gpt4 book ai didi

python - Django ORM - 如何在具有多对多字段的两个条件下加入

转载 作者:太空宇宙 更新时间:2023-11-04 04:11:28 24 4
gpt4 key购买 nike

我有两个模型:

class Subscription(models.Model):
name = models.CharField(max_length=100, unique=True)

class Email(models.Model):
email = models.EmailField(unique=True)
subscriptions = models.ManyToManyField(Subscription)
is_confirmed = models.BooleanField(default=False)

我需要通过django orm模拟sql查询

select * from newsletter_subscription ss
left join newsletter_mail_subscriptions ms
on ss.id = ms.subscription_id and ms.mail_id = <mail_id>;

所以我可以通过获取可用订阅的完整列表来查看邮件是否订阅了每个订阅

我需要类似 FilteredRelated 的东西:

q = Subscription.objects.annotate(
is_subscribe=FilteredRelation(
'mail_subscriptions', condition=Q(mail_subscriptions__mail_id=10)
)
)

但是FilteredRelation不支持跨越关系字段的条件

最佳答案

对于 FilteredRelation 根本不需要这样做,您可以这样写:

Subscription.objects.filter(
<b>email__id=</b><i>mail_id</i>
)

使用 mail_id 您希望过滤的 Email 对象的 ID。

Django 将构造一个如下所示的查询:

SELECT subscription.id, subscription.name
FROM subscription
INNER JOIN email_subscriptions
ON subscription.id = email_subscriptions.subscription_id
WHERE email_subscriptions.email_id = <i>email_id</i>

无论如何都不需要使用 LEFT OUTER JOIN,因为您检查 mail_id 是否是特定的 id,因此 code>INNER JOIN 将产生相同的集合。

请注意,您使用了 ManyToManyField,并且 Django 在两个实体之间创建了一个表,但您无法访问该表,除非您指定一个带有 through [Django-doc] 的模型。参数。

您还可以使用 is_subscribed 注释 Subscription,例如:

from django.db.models import Exists, OuterRef

Subscription.objects.annotate(
is_subscribed=Exists(
Email.subscriptions.through.objects.filter(
subscription_id=OuterRef('id'),
mail_id=<i>email_id</i>
)
)
)

这会产生如下查询:

SELECT subscription.*,
<b>EXISTS(</b>
SELECT U0.id, U0.email_id, U0.subscription_id
FROM email_subscriptions U0
WHERE U0.subscription_id = subscription.id AND U0.mail_id = <i>email_id</i>
<b>) AS is_subscribed</b>
FROM subscription

关于python - Django ORM - 如何在具有多对多字段的两个条件下加入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56209156/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com