gpt4 book ai didi

python - 在 Django 查询中收到 "missing FROM-clause"编程错误

转载 作者:行者123 更新时间:2023-11-29 12:07:20 24 4
gpt4 key购买 nike

我正在尝试编写一个查询,以检索其所有者应收到到期通知的所有订阅。

我想排除已通知的订阅和有较新订阅可用的订阅。

接下来是查询:

Subscription.objects.filter(
end_date__gte=timezone.now(),
end_date__lte=timezone.now() + timedelta(days=14),
).exclude(
Q(notifications__type=Notification.AUTORENEWAL_IN_14) | Q(device__subscriptions__start_date__gt=F('start_date'))
)

没有| Q(device__subscriptions__start_date__gt=F('start_date') 部分,查询完美运行。有了它,django (postgres) 会引发下一个错误:

django.db.utils.ProgrammingError: missing FROM-clause entry for table "u1"
LINE 1: ...ption" U0 INNER JOIN "orders_subscription" U2 ON (U1."id" = ...

我检查了 sql,它似乎不正确:

SELECT "orders_subscription"."id",
"orders_subscription"."months",
"orders_subscription"."end_date",
"orders_subscription"."start_date",
"orders_subscription"."order_id",
"orders_subscription"."device_id",
FROM "orders_subscription"
WHERE ("orders_subscription"."churned" = false
AND "orders_subscription"."end_date" >= '2019-04-05T13:27:39.808393+00:00'::timestamptz
AND "orders_subscription"."end_date" <= '2019-04-19T13:27:39.808412+00:00'::timestamptz
AND NOT (("orders_subscription"."id" IN
(SELECT U1."subscription_id"
FROM "notifications_notification" U1
WHERE (U1."type" = 'AUTORENEWAL_IN_2W'
AND U1."subscription_id" IS NOT NULL))
OR ("orders_subscription"."device_id" IN
(SELECT U2."device_id"
FROM "orders_subscription" U0
INNER JOIN "orders_subscription" U2 ON (U1."id" = U2."device_id")
WHERE (U2."start_date" > (U0."start_date")
AND U2."device_id" IS NOT NULL))
AND "orders_subscription"."device_id" IS NOT NULL)))) LIMIT 21

Execution time: 0.030680s [Database: default]

这是导致问题的部分:

INNER JOIN "orders_subscription" U2 ON (U1."id" = U2."device_id")
WHERE (U2."start_date" > (U0."start_date")
AND U2."device_id" IS NOT NULL))

U1 未在任何地方定义(它在 other 子句中本地定义,但这无关紧要。

关系模型非常简单,一个设备可以有很多订阅,一个订阅可以有很多(不同的)通知。

class Subscription(models.Model):
end_date = models.DateTimeField(null=True, blank=True)
start_date = models.DateTimeField(null=True, blank=True)

device = models.ForeignKey(Device, on_delete=models.SET_NULL, null=True, blank=True, related_name="subscriptions")
# Other non significatn fields

class Device(models.Model):
# No relational fields

class Notification(models.Model):
subscription = models.ForeignKey('orders.Subscription', related_name="notifications", null=True, blank=True, on_delete=models.SET_NULL)
# Other non significatn fields

所以我的问题是:我的查询是错误的还是 Django ORM 查询生成器中的错误?

最佳答案

ORM 显然无法将您的子句翻译成 SQL。即使单独使用该子句(没有前面的子句,即查询中的任何地方都没有 U1 别名),也会发生这种情况。

除了不存在的别名,ORM 似乎还错误地识别了 F('start_date') 的来源——它是主要的 orders_subscription(没有别名),而不是来自子选择的任何别名表。

您可以通过自己定义适当的子查询来帮助 ORM。

(下面的尝试基于这样的假设,即该条款的目的是排除具有较晚日期的兄弟订阅(= 相同父设备)的订阅。)

所以这是带有更正子句的排除过滤器:

from django.db.models import OuterRef, Subquery

qs.exclude(
Q(notifications__type=Notification.AUTORENEWAL_IN_14) |
Q(device_id__in=Subquery(Subscription.objects
.filter(
device_id=OuterRef('device_id'),
start_date__gt=OuterRef('start_date'))
.values('device_id')
))
)

但是,更仔细地查看过滤器,我们正在选择一个列 (device_id),我们刚刚将其值作为过滤条件传递。 Exists 更好地表达了这一点子查询:

from django.db.models import OuterRef, Exists

(qs.annotate(has_younger_siblings=Exists(Subscription.objects.filter(
device_id=OuterRef('device_id'),
start_date__gt=OuterRef('start_date'))))
.exclude(has_younger_siblings=True)
.exclude(notifications__type=Notification.AUTORENEWAL_IN_14)
)

关于python - 在 Django 查询中收到 "missing FROM-clause"编程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55537147/

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