Dan*_*iel 6 django django-queryset
我在减少特定视图的查询数量方面遇到了麻烦.这是一个相当沉重的,但我相信它可以减少:
Profile:
name = CharField()
Officers:
club= ManyToManyField(Club, related_name='officers')
title= CharField()
Club:
name = CharField()
members = ManyToManyField(Profile)
Election:
club = ForeignKey(Club)
elected = ForeignKey(Profile)
title= CharField()
when = DateTimeField()
Run Code Online (Sandbox Code Playgroud)
俱乐部有会员和官员(总裁,比赛总监).人们可以是多个俱乐部等的成员......官员在选举中当选,其结果被存储.
鉴于一名球员,我怎样才能找到每个球员俱乐部最近当选的官员?
目前我有
clubs = Club.objects.filter(members=me).prefetch_related('officers')
for c in clubs:
officers = c.officers.all()
most_recent = Elections.objects.filter(club=c).filter(elected__in=officers).order_by('-when')[:1].get()
print(c.name + ' elected ' + most_recent.name + ' most recently')
Run Code Online (Sandbox Code Playgroud)
问题是循环查询,如果你是1个俱乐部的成员,那么它很好而且速度很快,但是如果你加入50个数据库我的数据库就会爬行.
编辑: Nil的回答做我想要的但没有得到对象.我真的不需要这个对象,但我确实需要另一个字段以及日期时间.如果查询有用:
Club.objects.annotate(last_election=Max('election__when'))
Run Code Online (Sandbox Code Playgroud)
生成原始SQL
SELECT "organisation_club"."id", "organisation_club"."name", MAX("organisation_election"."when") AS "last_election"
FROM "organisation_club"
LEFT OUTER JOIN "organisation_election" ON ( "organisation_club"."id" = "organisation_election"."club_id" )
GROUP BY "organisation_club"."id", "organisation_club"."name"
Run Code Online (Sandbox Code Playgroud)
如果可能的话(或者主要是'ORM答案),我真的很喜欢ORM答案.
我相信这就是你要找的东西:
from django.db.models import Max, F
Election.objects.filter(club__members=me) \
.annotate(max_date=Max('club__election_set__when')) \
.filter(when=F('max_date')).select_related('elected')
Run Code Online (Sandbox Code Playgroud)
可以在一个声明中再次向前和向后关注关系,允许您为与当前选举的俱乐部相关的任何选举注释max_date.本F
类允许您根据SQL选择的领域,包括任何额外的字段筛选查询集通过添加注释,聚集,连接等.
您想要的内容在 SQL 术语中定义:查询Election
表,将其分组Club
并仅保留每个俱乐部的最后一次选举。
现在,我们如何在 Django ORM 中翻译它?查看文档,我们了解到可以通过注释来完成此操作。诀窍是你需要逆向思考。您想要对每个俱乐部的上次选举进行注释(添加新数据)。这给了我们:
Club.objects.annotate(last_election=Max('election__when'))
# Use it in a for loop like that
for club in Club.objects.annotate(last_election=Max('election__when')):
print(club, club.last_election)
Run Code Online (Sandbox Code Playgroud)
遗憾的是,这仅添加了日期,并不能回答您的问题!您想要名称或完整的Club
对象。我搜索过,但仍然不知道如何正确执行。如果一切都失败了,您仍然可以在 Django 中使用原始 SQL 查询,使用第一个链接中的查询。
归档时间: |
|
查看次数: |
1213 次 |
最近记录: |