Skip to main content
 首页 » 编程设计

python之如何用 django ORM 模仿 Python 集

2025年05月04日20落叶无声

我正在处理成员(member)申请。我想做一个成员(member)提醒。 (一段时间内的成员(member),另一段时间的非成员(member))。

目前,我正在使用 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(过滤、排除、注释、不同......)来做到这一点吗?

预先感谢您的帮助

更新

事实上,我的模型有点复杂。我也有报纸外键。

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 提供了非常有值(value)的答案,对于不太清楚的问题深表歉意:)

请您参考如下方法:

不就是把第二个表达式取反,放在同一个过滤器里吗?所以你有类似 !(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 查找。