我想用一个有趣的值来扩充我的模特管理员之一。鉴于这样的模型:
class Participant(models.Model):
pass
class Registration(models.Model):
participant = models.ForeignKey(Participant)
is_going = models.BooleanField(verbose_name='Is going')
现在,我想显示Registration
Participant
is_going
False
的其他SELECT reg.*, COUNT(past.id) AS not_going_num
FROM registrations AS reg, registrations AS past
WHERE past.participant_id = reg.participant_id AND
past.is_going = False
的数量。所以,类似于这个SQL查询:
Admin
我想我可以根据Django Admin, Show Aggregate Values From Related Model扩展queryset()
的{{1}}方法,并使用额外的Count
进行注释,但我仍然无法弄清楚如何处理自我加入并过滤到这个。
我查看了Self join with django ORM和Django self join , How to convert this query to ORM query,但前者正在进行SELECT *
而后者似乎有数据模型问题。
有关如何解决此问题的任何建议?
答案 0 :(得分:4)
请参阅以前版本答案的编辑历史记录。
下面的管理员实施将为每个Registration
模型显示“Not Going Count”。 “Not Going Count”是注册is_going=False
的{{1}}计数。
participant
以下是对QuerySet的更全面的解释:
@admin.register(Registration)
class RegistrationAdmin(admin.ModelAdmin):
list_display = ['id', 'participant', 'is_going', 'ng_count']
def ng_count(self, obj):
return obj.not_going_count
ng_count.short_description = 'Not Going Count'
def get_queryset(self, request):
qs = super(RegistrationAdmin, self).get_queryset(request)
qs = qs.filter(participant__registration__isnull=False)
qs = qs.annotate(not_going_count=Sum(
Case(
When(participant__registration__is_going=False, then=1),
default=0,
output_field=models.IntegerField())
))
return qs
过滤器使Django执行两个连接 - qs = qs.filter(participant__registration__isnull=False)
到参与者表,以及INNER JOIN
到注册表。
LEFT OUTER JOIN
这是一个标准聚合,用于qs = qs.annotate(not_going_count=Sum(
Case(
When(participant__registration__is_going=False, then=1),
default=0,
output_field=models.IntegerField())
)
))
计算SUM
。这转换为SQL
is_going=False
为每个注册模型生成总和,并且总和属于注册的参与者。
答案 1 :(得分:0)
我可能会误解,但你可以为单个参与者做的事情:
participant = Participant.objects.get(id=1)
not_going_count = Registration.objects.filter(participant=participant,
is_going=False).count()
对于所有参与者,
from django.db.models import Count
Registration.objects.filter(is_going=False).values('participant') \
.annotate(not_going_num=Count('participant'))
关于aggregating for each item in a queryset的Django doc。