在django查询集中查找用户的最新评级

时间:2011-06-18 04:11:18

标签: django django-queryset

我正在寻找一种方法来获取所有资源的特定人员的最新评级。 目前我正在使用Rating.objects.filter(Person = person).order_by('-timestamp')之类的查询 然后通过unique_everseen通过资源和用户属性上的密钥传递它,然后使用Rating.objects.filter(id__in = uniquelist)重新查找。使用django queryset函数有更优雅的方法吗? 这些是相关的模型。

class Person(models.Model):
    pass

class Resource(models.Model):
    pass

class Rating(models.Model):
    rating = models.IntegerField()
    timestamp = models.DateField()
    resource = models.ForeignKey('Resource')
    user = models.ForeignKey('Person')

我需要保留所有旧评级,因为其他功能需要能够记录事物如何“改变”。

1 个答案:

答案 0 :(得分:1)

我不是100%明确你在这里寻找什么,你想找到用户对他们评定的所有资源的最新评级吗?如果您可以提供unique_everseen实际执行内容的详细信息,则有助于澄清您要查找的内容。

您宁愿从资源的角度来看:

resources = Resource.objects.filter(rating__user=person).order_by('-rating__timestamp')
resource_rating = [(resource, resource.rating_set.filter(person=person).get_latest('timestamp')) for resource in resources]

您可以使用Aggregate functions来获取每个资源的最新记录,或者使用Q object来巧妙地使用signal hook来限制SQ​​L请求(我的示例可能会为您节省一些请求,以及更优雅,但它不像使用原始SQL请求生成的那样简单)。在原始SQL中,您将使用内部SELECT或执行良好的GROUP BY来获取最新评级,因此模仿它将是理想的。

您还可以在评分模型上创建post_save {{3}}和'active'或'current'布尔字段,该字段将迭代与用户/资源匹配的其他评级,并将其“活动”字段设置为False。即post_save挂钩会使用以下内容将所有其他评级标记为对用户/资源无效:

if instance.active:
    for rating in Rating.objects.filter(user=instance.user,resource=instance.resource).exclude(id=instance.id):
        rating.active=False
        rating.save()

然后,您可以执行以下简单查询:

Rating.objects.filter(user=person,active=True).order_by('-timestamp')

这将是最经济的查询(即使你在原始SQL中通过/ inner select制作复杂的组,你正在进行比必要的更复杂的查询)。使用布尔字段还意味着您可以为用户的评级提供“前进/后退”/“撤消/重做”行为(如果相关)。