如何使用 django ORM 模拟 Python 设置?

发布于 2024-09-12 14:31:38 字数 1674 浏览 7 评论 0原文

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

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

I am working on a membership application. I would like to make a membership reminder. (member during a period of time which is not member for another period of time).

Currently, I am using set for making this calculation. See the code below.

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)

I would like to know of I can do it only by using the django ORM (filter, exclude, annotate, distinct ...)?

Thanks in advance for your help

UPDATE

In fact, my model is a bit more complex. I also have newspaper foreign key.

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)

I want to have the reminder for a given newspaper. In this case, the working query is

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)

I think that this a more verbose version of the answer given Ghislain Leveque which is also working well for me.

Thanks to S.Lott and KillianDS for very valuable answers and sorry for not so clear question :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

余罪 2024-09-19 14:31:38

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

顺便注意,对于简单的与和基本查找,你不需要 Q 对象,就像我用前两个查找参数。 Anding 仅通过传递多个参数来进行,需要 Q 对象来进行否定和 OR'ing 查找。

Isn't it simply negating the second expression and putting it in the same filter? So you have something like !(a&b), which equals to (!a)|(!b), in this case:

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

note by the way that for simple anding and basic lookups you need no Q objects, like I showed with the first two lookup parameters. Anding happens just by passing multiple arguments, Q objects are needed for negating and OR'ing lookups.

拥抱我好吗 2024-09-19 14:31:38

根据定义,关系数据库表一个集合。 Set-在SQL中是where not办法,在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)
)

A relational database table is a set -- by definition. Set - is where not exists in SQL, which is exclude in Django's ORM.

It seems (without testing) that you're doing this.

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)
)
¢蛋碎的人ぎ生 2024-09-19 14:31:38

你应该尝试:

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

You should try :

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')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文