【问题标题】:How to mimic Python set with django ORM?如何用 django ORM 模拟 Python 集?
【发布时间】:2010-08-02 09:46:02
【问题描述】:

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

目前,我正在使用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 提供非常有价值的答案,很抱歉问题不是很清楚 :)

【问题讨论】:

  • 实际上,通过一些小的调整,您可以使我的答案仍然适用于这个更复杂的模型,如果 sin 和 sout 查询集变得非常大,则建议的解决方案效率极低。

标签: python django django-orm


【解决方案1】:

这不是简单地否定第二个表达式并将其放在同一个过滤器中吗?所以你有类似 !(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 查找。

【讨论】:

    【解决方案2】:

    关系数据库表一个集合——根据定义。设置-在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)
    )
    

    【讨论】:

      【解决方案3】:

      你应该试试:

      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')
      

      【讨论】:

        猜你喜欢
        • 2012-10-04
        • 2023-03-10
        • 1970-01-01
        • 2015-12-20
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多