首页 > 解决方案 > 当使用具有多个 order by 和 distinct 的 Q 过滤器时,Django order by issue

问题描述

我正在开发一个照片项目,用户可以在其中下载喜欢照片(也可以进行其他操作)。我有两个模型来跟踪这些信息。以下是使用的模型(使用的数据库Postgres)。

# Photo model stores photos
# download_count, like_count is stored in the same model as well for easier querying
class Photo(models.Model):
        name = models.CharField(max_length=100, null=True, blank=True)
        image = models.ForeignKey(Image, null=True, on_delete=models.CASCADE)
        download_count = models.IntegerField(default=0)
        like_count = models.IntegerField(default=0)
        views = GenericRelation(
            'Stat', related_name='photo_view',
            related_query_name='photo_view', null=True, blank=True)
        downloads = GenericRelation(
            'Stat', related_name='photo_download',
            related_query_name='photo_download', null=True, blank=True)
    
    
# Stat has generic relationship with photos. So that it can store any stats information
class Stat(models.Model):
        VIEW = 'V'
        DOWNLOAD = 'D'
        LIKE = 'L'
        STAT_TYPE = (
            (VIEW, 'View'),
            (DOWNLOAD, 'Download'),
            (LIKE, 'Like'),
        )
        user = models.ForeignKey(
            User, null=True, blank=True, on_delete=models.SET_NULL)
        content_type = models.ForeignKey(
            ContentType, on_delete=models.CASCADE, default=0)
        object_id = models.PositiveIntegerField()
        content_object = GenericForeignKey()
        stat_type = models.CharField(max_length=2, choices=STAT_TYPE, default=VIEW)
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)

我的要求是获取本周流行的照片。人气分数应该考虑点赞数、下载数

我写了下面的查询来获取本周流行的照片,检查本周创建的喜欢或下载。

# week number
current_week = date.today().isocalendar()[1]

photos = Photo.objects.filter(Q(likes__created_at__week=current_week) | Q(downloads__created_at__week=current_week))\
            .order_by('id', 'download_count', 'like_count')\
            .distinct('id')

问题:对于上述查询,即使提到了其他字段,结果集也始终按id排序。

要求:图片按总点赞数和下载量排序,按热度排序。

考虑到数据库性能,请建议我一种方法来实现这一点。

谢谢你

标签: djangodatabasepostgresqldjango-modelsdjango-filter

解决方案


对于这种情况,您可以使用annotate()F 对象:

photos = Photo.objects.filter().annotate(like_download=F('download_count') + F('like_count')).order_by('like_download').distinct()

推荐阅读