如何在Django Orm中获得每组的最新n条记录

时间:2018-01-04 12:38:47

标签: python django django-models orm django-rest-framework

我有3个模型,如

class Business(models.Model):
    name = models.CharField(max_length=30)
    ...

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    date = models.DatetimeField()
    business = models.ForeignKey(Business)

我想得到每个家伙的最后3个电话号码,这就是我实现它的方式;

response=list()
for dude in Dude.objects.all():
    temp_dude = dict()
    temp_dude['name_label'] = str(dude.name)
    temp_dude['phones'] = list()
    for phone_number in PhoneNumber.objects.filter(dude=dude).order_by("-date")[:3]:
        temp_phone = dict()
        temp_phone['date_added'] = phone_number.date.timestamp()
        temp_phone['business_label'] = str(phone_number.business.name)
        temp_dude['phones'].append(temp_phone)
    response.append(temp_dude)

但它为每个家伙打了至少两次数据库并消耗了大量的cpu。

使用django orm获得相同响应的最有效方法是什么?

P.S:我有3000万电话号码和170个老兄。

1 个答案:

答案 0 :(得分:1)

在这种情况下尝试的第一件事是select_related来获取每个家伙的phone_number。

dudes = Dude.objects.select_related('phone_number', 'phone_number__business').all()
for dude in dudes:
    do_the_thing()  

(请注意您正在查询的其他对象上的select_relatedphone_number.business

在这种情况下,如果每个phone_number有很多Dude s,那么这可能会比原始查询更糟糕,因为它会抓取每个Dude.phone_number。

不幸的是,正如评论所暗示的那样,没有ORM方法可以限制select_related。你需要编写一些SQL。您可以通过调出DB kogging,然后运行自己的custom SQL query来观察SQL Django为select_related查询生成的内容。