2016-09-16 118 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