我正在寻找一种方法来获取所有资源的特定人员的最新评级。
目前我正在使用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')
我需要保留所有旧评级,因为其他功能需要能够记录事物如何“改变”。
答案 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来限制SQL请求(我的示例可能会为您节省一些请求,以及更优雅,但它不像使用原始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制作复杂的组,你正在进行比必要的更复杂的查询)。使用布尔字段还意味着您可以为用户的评级提供“前进/后退”/“撤消/重做”行为(如果相关)。