使用 annotate 或 extra 将外键字段添加到查询集? (相当于 SQL“AS”?)
Posted
技术标签:
【中文标题】使用 annotate 或 extra 将外键字段添加到查询集? (相当于 SQL“AS”?)【英文标题】:Using annotate or extra to add field of foreignkey to queryset ? (equivalent of SQL "AS" ?) 【发布时间】:2015-11-03 04:12:07 【问题描述】:我已经合并了两个单独工作的查询集(qs1 和 qs2),如下所示:
qlist = [qs1, qs2]
results = list(chain(qs1, qs2))
到目前为止,一切都很好 - 以上工作。但现在我正在尝试使用以下命令对结果进行排序:
qlist = [qs1, qs2]
results = sorted(chain(qs1, qs2), key=attrgetter('monthly_fee'))
问题是第二个查询集(qs2)通过ForeignKey引用monthly_fee;而 qs1 有 'monthly_fee' 可用。这是qs2:
qs2 = Offer.objects.select_related('subscription')
qs2 = qs2.order_by(subscription__monthly_fee)
以及简化模型:
class Subscription(models.Model):
monthly_fee = models.IntegerField(null=False, blank=True, default=0)
name = models.CharField(max_length=120, null=True, blank=True)
class Offer(models.Model):
promotion_name = models.CharField(max_length=120, null=True, blank=True)
subscription = models.ForeignKey(Subscription)
discount = models.IntegerField(null=False, blank=True, default=0)
我尝试使用 .annotate() 和 .extra() 在查询 qs2 中重命名subscription__monthly_fee
,如下所示:
qs2 = Offer.objects.select_related('subscription').annotate(monthly_fee=subscription__monthly_fee)
然后得到错误
全局名称“订阅__monthly_fee”未定义
我只是通过重写模型的 .save() 方法来破解这个问题,以便在创建对象时手动将monthly_fee 添加到每个 Offer 实例。但只是想检查是否有更好的方法?
谢谢你,
迈克尔
【问题讨论】:
【参考方案1】:我以前使用 F 表达式来实现这种重命名。试试这个:
from django.db.models import F
qs2 = Offer.objects.select_related('subscription').annotate(monthly_fee=F('subscription__monthly_fee'))
【讨论】:
谢谢马克。以前从未使用过 F 表达式。尝试添加它但得到以下错误:'F' object has no attribute 'lookup' 这可能在 Django 1.8 中已修复。请参阅文档:You can also use the double underscore notation to span relationships in an F() object
(docs.djangoproject.com/en/1.8/topics/db/queries/…)。【参考方案2】:
好的,我找到了一种方法来做到这一点。
qs2 = Offer.objects.select_related('subscription').extra(select='monthly_fee':'mobile_subscription.monthly_fee')
其中“mobile”是 Django 应用程序的名称。我没有意识到 .extra 允许您遵循外键,但您实际上必须指定实际的数据库表并使用 SQL 点表示法。
以上是我们应该做的实际正确的方法吗? (即删除原始 SQL 表名/字段)
我一直在尝试使用 Django 语法,例如 .extra(select='monthly_fee':'subscription__monthly_fee')
,但它不起作用!
【讨论】:
这不是 Django 风格。更喜欢Mark Galloway's answer的方法。以上是关于使用 annotate 或 extra 将外键字段添加到查询集? (相当于 SQL“AS”?)的主要内容,如果未能解决你的问题,请参考以下文章