【发布时间】:2017-10-02 04:10:28
【问题描述】:
如何在单个表达式中从 多对一 关系的 过滤 结果中获取 最新 值注释 Django QuerySet?
鉴于这个玩具架构:
from django.db import models
class Lorem(models.Model):
""" Lorem ipsum, dolor sit amet. """
class LoremStatusEvent(models.Model):
""" A status event change on a given `ipsum` for a `lorem`. """
created = models.DateTimeField(auto_now_add=True)
lorem = models.ForeignKey(Lorem)
ipsum = models.CharField(max_length=200)
status = models.CharField(max_length=10)
为了在 Django LoremAdmin(对于 Lorem 模型)中制作自定义 QuerySet,我需要:
- 将
foo_status和bar_status分别从单独的 JOIN 子句派生到LoremStatusEvent模型:lorem.loremstatusevent_set__status。 - 过滤每个连接以仅包含那些对应
Ipsum值的事件:foo_status_events=LoremStatusEvent.filter(ipsum='foo')。 - 将状态事件集聚合为每个对应连接的最新状态事件:
foo_status=LoremStatusEvent.objects.filter(ipsum='foo').latest('created').status。 - 用几个额外的值注释结果,
foo_status和bar_status:queryset = queryset.annotate(foo_status=???).annotate(bar_status=???)。
如果我发明一些函数来完成这一切——get_field、latest_by、filter_by、loremstatus_set_of_every_corresponding_lorem——我可以这样写管理员:
from django.contrib import admin
class LoremAdmin(admin.ModelAdmin):
""" Django admin for `Lorem` model. """
class Meta:
model = Lorem
def get_queryset(request):
""" Get the `QuerySet` of all instances available to this admin. """
queryset = super().get_queryset(request)
queryset.annotate(
foo_status=(
get_field('status')(
latest_by('created')(
filter_by(ipsum='foo')(
loremstatusevent_set_of_every_corresponding_lorem)))),
bar_status=(
get_field('status')(
latest_by('created')(
filter_by(ipsum='bar')(
loremstatusevent_set_of_every_corresponding_lorem)))),
)
return queryset
哪些实际函数应该替换这些占位符名称?
-
loremstatus_set_of_every_corresponding_lorem,相当于Lorem.loremstatusevent_set。 -
filter_by,用于过滤右侧的连接。 -
latest_by,聚合结果集,按字段排序,获取单个最新实例。我没有看到任何这样的documented aggregation function。 -
get_field,从结果实例中引用一个字段。
请记住,所有这些都需要在 Lorem 实例的查询集上完成,通过 Lorem.loremstatusevent_set 访问相关实例;我当时没有LoremStatusEvent 实例,所以我不能直接使用LoremStatusEvent 的属性。
那么,上述占位符中应该包含哪些实际的 Django 功能?
【问题讨论】:
标签: django join django-models annotations