Django ORM如何在多对多字段的两个条件下左连接

2024-09-26 22:53:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两种型号:

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查询

^{pr2}$

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

我需要一些类似FilteredRelated的东西:

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

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


Tags: nametruemodelismodelssubscriptionsmaillength
1条回答
网友
1楼 · 发布于 2024-09-26 22:53:41

根本不需要使用FilteredRelation执行此操作,您可以这样写:

Subscription.objects.filter(
    email__id=mail_id
)

对于mail_id要筛选的Email对象的id。在

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

^{pr2}$

反正不需要使用LEFT OUTER JOIN,因为您要检查mail_id是否是一个特定的id,因此INNER JOIN将产生相同的集。在

请注意,您使用了ManyToManyField,Django在两个实体之间创建了一个表,但是您不能访问该表,除非您使用^{} [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=email_id
        )
    )
)

这将导致如下查询:

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

相关问题 更多 >

    热门问题