2016-09-16 17 views
0

我有以下型号:Django的子查询过滤器从现场

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是这样的:

domains = Domain.objects.filter(
       Q(
        PlainDetails.objects.filter(plan = Domain.plan).aggregate(Sum('accounts')) 
        <= 
        Mailbox.objects.filter(domain = Domain).count() 
       ) 
      ) 

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这样的尝试

但不起作用,它会引发关于Domain.plan的错误,有没有办法在子查询中引用父查询中的字段值?这个查询集是有效的还是有另一种(更好)的方法?或者我应该只使用原始的sql,在这种情况下最好的选择是什么?

+0

什么是paret查询?也是完全可以使用原始查询,当你必须 – e4c5

+0

对不起,我的意思是**家长**查询 – Peter

回答

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_setmailbox_set与适当的related name,如果你明确指定任何在ForeignKey领域Plan。如果没有指定,这两个就是默认值。

UPDATE 对于非常复杂的查询,最好使用光标运行实际的SQL。 Django ORM通常足够好,但根据需要,这可能还不够。请查看docs

+0

感谢您的回答,实际上邮箱没有关系,既不计划与邮箱的计划,所以得到mailbox_count为你的代码不工作,拿你的代码我认为它可以工作,如果改变该部分的东西是这样的:'mailbox_count = Mailbox.objects.filter(domain = DomainFromParentQuery).count()',但我找不到如何引用'DomainFromParentQuery'或者即使它的posible – Peter

+0

哦对此感到抱歉。我误解了,并认为邮箱有一个外键“计划”。由于它具有fk到'Domain',只需使用'mailbox_set__id'而不是'plan__mailbox_set__id'。我编辑了我的帖子。 –

+0

好的,再次感谢您的更新,现在查询运行正常,但没有给出与原始sql相同的结果,它的总和和计数的givin错误值,似乎没有采取正确的相关记录,我正在研究该问题找到最新情况。 – Peter