我正在处理会员申请。我想提出会员提醒。 (成员在一段时间内不是另一段时间的成员)。
目前,我正在使用set
进行此计算。请参阅下面的代码。
class Member(models.Model):
...
class Membership(models.Model):
member = models.ForeignKey(Member, verbose_name=_("Member"))
start_date = models.DateField(_("Start date"))
end_date = models.DateField(_("End date"))
x = Member.objects.filter(Q(membership__start_date__lte=dt1) & Q(membership__end_date__gte=dt1))
y = Member.objects.filter(Q(membership__start_date__lte=dt2) & Q(membership__end_date__gte=dt2))
result = set(x) - set(y)
我想知道我只能通过使用django ORM(filter,exclude,annotate,distinct ...)来实现它?
提前感谢您的帮助
事实上,我的模型有点复杂。我也有报纸外键。
class Member(models.Model):
...
class Newspaper(models.Model):
...
class Membership(models.Model):
member = models.ForeignKey(Member, verbose_name=_("Member"))
start_date = models.DateField(_("Start date"))
end_date = models.DateField(_("End date"))
newspaper = models.ForeignKey(Newspaper)
我希望得到一份特定报纸的提醒。在这种情况下,工作查询是
sin = models.Membership.objects.filter(start_date__lte=dt1,
end_date__gte=dt1,
newspaper__id=2)
sout = models.Membership.objects.filter(start_date__lte=dt2,
end_date__gte=dt2,
newspaper__id=2)
result = models.Member.objects.filter(membership__in=sin).exclude(membership__in=sout)
我认为这个答案更加冗长,Ghislain Leveque对我来说也很好。
感谢S.Lott和KillianDS提供了非常有价值的答案,并对不太明确的问题表示抱歉:)
答案 0 :(得分:6)
是不是简单地否定了第二个表达式并将其放在同一个过滤器中?所以你有类似的东西!(a& b),等于(!a)|(!b),在这种情况下:
result = Member.objects.filter(membership__start_date__lte=dt1, membership__end_date__gte=dt1, ~Q(membership__start_date__lte=dt2) | ~Q(membership__end_date__gte=dt2))
请注意,对于简单的anding和基本查找,您不需要Q对象,就像我使用前两个查找参数一样。 Anding只是通过传递多个参数来实现,需要Q对象来否定和OR'ing查找。
答案 1 :(得分:3)
关系数据库表 是一个集合 - 按定义。在SQL中设置-
为where not exists
,在Django的ORM中为exclude
。
似乎(没有测试)你正在这样做。
result = Member.objects.filter(
Q(membership__start_date__lte=dt1) & Q(membership__end_date__gte=dt1)
).exclude(
Q(membership__start_date__lte=dt2) & Q(membership__end_date__gte=dt2)
)
答案 2 :(得分:1)
你应该尝试:
result = Member.objects.\
filter(
membership__start_date__lte = dt1,
membership__end_date__gte=dt1).\
exclude(
pk__in = \
Member.objects.filter(
membership__start_date__lte = dt2,
membership__end_date__gte = dt2).\
values_list('pk')