我有以下模特:
class Domain(models.Model):
name = models.CharField(...)
plan = models.ForeignKey(Plan, ....)
class Plan(models.Model):
name = models.CharField(...)
num_ex_accounts = models.IntegerField(...)
class PlanDetails(models.Model):
accounts = models.IntegerField()
plan = models.ForeignKey(Plan, ....)
class Mailbox(models.Model):
domain = models.ForeignKey(Domain, ...)
任何域都有一个计划,任何计划都有N个计划详细信息,其中包含使用域创建邮箱的帐户值,我想进入一个超过帐户值的查询集域,使用原始sql,sql就像:
SELECT domain
FROM domain, plan
WHERE plan.id = domain.plan_id
AND (
SELECT SUM(accounts)
FROM plandetails WHERE plandetails.plan_id=plan.id
)
<=
(
SELECT COUNT(*)
FROM mailbox WHERE mailbox.domain_id=domain.id
)
我在django中试过这样的事情:
domains = Domain.objects.filter(
Q(
PlainDetails.objects.filter(plan = Domain.plan).aggregate(Sum('accounts'))
<=
Mailbox.objects.filter(domain = Domain).count()
)
)
但是不起作用,它会抛出关于Domain.plan的错误,有没有办法在子查询中从父查询引用该字段值?这个查询集有效还是有另一个(更好的)方法?或者我应该只使用原始sql,在这种情况下最好的选择是什么?
答案 0 :(得分:1)
如果您使用的是Django 1.8及更高版本,请尝试以下操作:
Domain.objects.annotate(
account_sum=Sum('plan__plandetails_set__accounts'),
mailbox_count=Count('mailbox_set__id'))
).filter(
account_sum__lte=F('mailbox_count')
)
如果您在plandetails_set
字段中明确指定任何mailbox_set
,则将related name
和ForeignKey
替换为相应的Plan
。如果没有指定,那么这两个只是默认值。
<强>更新强> 对于非常复杂的查询,使用游标运行实际SQL可能更好。 Django ORM通常足够好,但根据需要,它可能还不够。请查看docs。