Django 一對多/多對多 跨關聯關係的查詢

總結

1.過濾的條件是 一對多/多對多 關係裏多的一方時

過濾的數據可能出現重複數據

 

filter(**kwargs) , kwargs 表示 且 的邏輯關係

filter(**kwargs1).filter(**kwargs2) , kwargs1 和 kwargs2 表示 或 的邏輯關係

exclude 是和 filter 的邏輯相反,即

exclude(**kwargs) , kwargs 表示 或 的邏輯關係

exclude(**kwargs1).exclude(**kwargs2) , kwargs1 和 kwargs2 表示 且 的邏輯關係

 

2.過濾的條件是 一對一/一對多 關係裏一的一方時

filter(**kwargs) , kwargs 表示 且 的邏輯關係

filter(**kwargs1).filter(**kwargs2) , kwargs1 和 kwargs2 也表示 且 的邏輯關係

 

與第一條的 exclude 一樣,即

exclude(**kwargs) , kwargs 表示 或 的邏輯關係

exclude(**kwargs1).exclude(**kwargs2) , kwargs1 和 kwargs2 表示 且 的邏輯關係

 

創建 models

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Base(models.Model):
    name = models.CharField(max_length=6, blank=True, null=True)
    code = models.CharField(max_length=6, blank=True, null=True)
    class Meta:
        abstract = True
    def __str__(self):
        return self.name
############################
#      one to one          #
############################
class A(Base):
    pass
class B(Base):
    a = models.OneToOneField(A, related_name='b', blank=True, null=True)
############################
#      one to many         #
############################
class C(Base):
    pass
class D(Base):
    c = models.ForeignKey(C, related_name='ds', blank=True, null=True)
############################
#      many to many        #
############################
class E(Base):
    pass
class F(Base):
    es = models.ManyToManyField(E, related_name='fs')

 

一對一查詢(查詢條件爲一的一方)

filter

# 滿足 b__name='B1' 且 滿足 b__code='B1'
A.objects.filter(b__name='B1', b__code='B1')
SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         INNER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE ("stu_models_b"."name" = "B1" AND "stu_models_b"."code" = "B1")

 

# 滿足 b__name='B1' 且 滿足 b__code='B1'
A.objects.filter(b__name='B1').filter(b__code='B1')

 

SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         INNER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE ("stu_models_b"."name" = "B1" AND "stu_models_b"."code" = "B1")

filter 使用 Q

from django.db.models import Q
# 滿足 b__name='B1' 且 滿足 b__code='B1'
A.objects.filter(Q(b__name='B1') & Q(b__code='B1'))

 

SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         INNER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE ("stu_models_b"."name" = B1 AND "stu_models_b"."code" = B1)

 

# 滿足 b__name='B1' 或 滿足 b__code='B1'
A.objects.filter(Q(b__name='B1') | Q(b__code='B1'))

 

SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         INNER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE ("stu_models_b"."name" = B1 OR "stu_models_b"."code" = B1)

 

# 滿足 b__name='B1' 且 滿足 b__code='B1'
A.objects.filter(Q(b__name='B1')).filter(Q(b__code='B1'))

 

SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         INNER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE ("stu_models_b"."name" = B1 AND "stu_models_b"."code" = B1)

 

exclude

# 不滿足 b__name='B1' 或 不滿足 b__code='B1'
A.objects.exclude(b__name='B1', b__code='B1')                     

 

-- not (a and b) == not a or not b
SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         LEFT OUTER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE NOT (
           "stu_models_b"."name" = B1 AND "stu_models_b"."name" IS NOT NULL 
           AND 
           "stu_models_b"."code" = B1 AND "stu_models_b"."code" IS NOT NULL
           )

 

# 不滿足 b__name='B1' 且 不滿足 b__code='B1'
A.objects.exclude(b__name='B1').exclude(b__code='B1')

 

-- not a and not b
SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         LEFT OUTER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE (
       NOT ("stu_models_b"."name" = B1 AND "stu_models_b"."name" IS NOT NULL) 
       AND
       NOT ("stu_models_b"."code" = B1 AND "stu_models_b"."code" IS NOT NULL)
       ) 

exclude 使用 Q

# 不滿足 b__name='B1' 且 不滿足 b__code='B1'
A.objects.exclude(Q(b__name='B1') | Q(b__code='B1'))  

 

-- not ((a or b)) == not (a or b) == not a and not b
SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         LEFT OUTER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE NOT ((("stu_models_b"."name" = B1 AND "stu_models_b"."name" IS NOT NULL) OR
            ("stu_models_b"."code" = B1 AND "stu_models_b"."code" IS NOT NULL)))

 

# 不滿足 b__name='B1' 或 不滿足 b__code='B1'
A.objects.exclude(Q(b__name='B1') & Q(b__code='B1'))

 

-- not ((a and b)) == not (a and b) == not a or not b
SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         LEFT OUTER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE NOT ("stu_models_b"."name" = B1 AND "stu_models_b"."name" IS NOT NULL AND "stu_models_b"."code" = B1 AND
           "stu_models_b"."code" IS NOT NULL)

 

# 不滿足 b__name='B1' 且 不滿足 b__code='B1'
A.objects.exclude(Q(b__name='B1')).exclude(Q(b__code='B1'))

 

-- not a and not b
SELECT "stu_models_a"."id", "stu_models_a"."name", "stu_models_a"."code"
FROM "stu_models_a"
         LEFT OUTER JOIN "stu_models_b" ON ("stu_models_a"."id" = "stu_models_b"."a_id")
WHERE (NOT ("stu_models_b"."name" = B1 AND "stu_models_b"."name" IS NOT NULL) AND
       NOT ("stu_models_b"."code" = B1 AND "stu_models_b"."code" IS NOT NULL))

 

一對多查詢(查詢條件爲多的一方)

filter

# 滿足 ds__name='D1' 且 滿足 ds__code='D1'
C.objects.filter(ds__name='D1', ds__code='D1')

 

SELECT "stu_models_c"."id", "stu_models_c"."name", "stu_models_c"."code"
FROM "stu_models_c"
         INNER JOIN "stu_models_d" ON ("stu_models_c"."id" = "stu_models_d"."c_id")
WHERE ("stu_models_d"."name" = D1 AND "stu_models_d"."code" = D1)

 

# 滿足 ds__name='D1' 或 滿足 ds__code='D1'
C.objects.filter(ds__name='D1').filter(ds__code='D1')

 

SELECT "stu_models_c"."id", "stu_models_c"."name", "stu_models_c"."code"
FROM "stu_models_c"
         INNER JOIN "stu_models_d" ON ("stu_models_c"."id" = "stu_models_d"."c_id")
         INNER JOIN "stu_models_d" T3 ON ("stu_models_c"."id" = T3."c_id")
WHERE ("stu_models_d"."name" = D1 AND T3."code" = D1)
-- 第一個內聯和第二個內聯是 兩個 數據相同 的表
-- where 裏過濾的是 第一個內聯裏 name 等於 D1 的數據 和 第二個內聯裏 code 等於 D1 的數據,本質上是在做過濾掉 stu_models_d 表裏 name 等於 D1 或者 code 等於 D1 的數據
-- 所以 where 裏的過濾是在做 或 操作

 

# c1 {name=C1}, C 反向關聯名稱爲 ds
# d1 {name=D1, c =c1}, d2 {name=D2, c=c2}

 
# 滿足 ds__name='D1' 或 滿足 ds__name__contains='D'
# 出現數據重複,結果爲兩個c1, QuerySet [<C: C1>, <C: C1>]>
C.objects.filter(ds__name='D1').filter(ds__name__contains='D')

 

SELECT "stu_models_c"."id", "stu_models_c"."name", "stu_models_c"."code"
FROM "stu_models_c"
         INNER JOIN "stu_models_d" ON ("stu_models_c"."id" = "stu_models_d"."c_id")
         INNER JOIN "stu_models_d" T3 ON ("stu_models_c"."id" = T3."c_id")
WHERE ("stu_models_d"."name" = D1 AND T3."name" LIKE % D % ESCAPE '\')
-- 因爲該 SQL 做 或 操作,所以滿足條件的 D 有 d1 和 d2,又因爲 d1 和 d2 都關聯着 c1,所以出現了兩個 c1,最終導致出現 重複數據 

 

exclude

# 不滿足 ds__name='D1' 或 不滿足 ds__code='D1'
C.objects.exclude(ds__name='D1', ds__code='D1')     

 

-- not (a and b) == not a or not b
SELECT "stu_models_c"."id", "stu_models_c"."name", "stu_models_c"."code"
FROM "stu_models_c"
WHERE NOT (
           "stu_models_c"."id" IN (SELECT U1."c_id" AS Col1 FROM "stu_models_d" U1 WHERE (U1."name" = D1 AND U1."c_id" IS NOT NULL)) 
           AND
           "stu_models_c"."id" IN (SELECT U1."c_id" AS Col1 FROM "stu_models_d" U1 WHERE (U1."code" = D1 AND U1."c_id" IS NOT NULL))
           )

 

# 不滿足 ds__name='D1' 且 不滿足 ds__code='D1'                
C.objects.exclude(ds__name='D1').exclude(ds__code='D1')

 

-- not a and not b                   
SELECT "stu_models_c"."id", "stu_models_c"."name", "stu_models_c"."code"
FROM "stu_models_c"
WHERE (
       NOT ("stu_models_c"."id" IN (SELECT U1."c_id" AS Col1 FROM "stu_models_d" U1 WHERE (U1."name" = D1 AND U1."c_id" IS NOT NULL))) 
       AND
       NOT ("stu_models_c"."id" IN (SELECT U1."c_id" AS Col1 FROM "stu_models_d" U1 WHERE (U1."code" = D1 AND U1."c_id" IS NOT NULL)))
       )     

 

多對多查詢(查詢條件爲多的一方)

filter

# 滿足 ds__name='D1' 且 滿足 ds__code='D1'
F.objects.filter(es__name='E1', es__code='E1')

 

SELECT "stu_models_f"."id", "stu_models_f"."name", "stu_models_f"."code"
FROM "stu_models_f"
         INNER JOIN "stu_models_f_es" ON ("stu_models_f"."id" = "stu_models_f_es"."f_id")
         INNER JOIN "stu_models_e" ON ("stu_models_f_es"."e_id" = "stu_models_e"."id")
WHERE ("stu_models_e"."name" = E1 AND "stu_models_e"."code" = E1)

 

# 滿足 ds__name='D1' 或 滿足 ds__code='D1'
F.objects.filter(es__name='E1').filter(es__code='E1')

 

SELECT "stu_models_f"."id", "stu_models_f"."name", "stu_models_f"."code"
FROM "stu_models_f"
         INNER JOIN "stu_models_f_es" ON ("stu_models_f"."id" = "stu_models_f_es"."f_id")
         INNER JOIN "stu_models_e" ON ("stu_models_f_es"."e_id" = "stu_models_e"."id")
         INNER JOIN "stu_models_f_es" T4 ON ("stu_models_f"."id" = T4."f_id")
         INNER JOIN "stu_models_e" T5 ON (T4."e_id" = T5."id")
WHERE ("stu_models_e"."name" = E1 AND T5."code" = E1)

 

exclude

# 不滿足 ds__name='D1' 或 不滿足 ds__code='D1'
F.objects.exclude(es__name='E1', es__code='E1')                                                                                   

 

-- not (a and b) == not a or not b
SELECT "stu_models_f"."id", "stu_models_f"."name", "stu_models_f"."code"
FROM "stu_models_f"
WHERE NOT (
           "stu_models_f"."id" IN (SELECT U1."f_id" AS Col1 FROM "stu_models_f_es" U1 INNER JOIN "stu_models_e" U2 ON (U1."e_id" = U2."id") WHERE U2."name" = E1) 
           AND 
           "stu_models_f"."id" IN (SELECT U1."f_id" AS Col1 FROM "stu_models_f_es" U1 INNER JOIN "stu_models_e" U2 ON (U1."e_id" = U2."id") WHERE U2."code" = E1)
           )

 

# 不滿足 ds__name='D1' 且 不滿足 ds__code='D1'                                                                                                                                                                           
F.objects.exclude(es__name='E1').exclude(es__code='E1')

 

-- not a and not b    
SELECT "stu_models_f"."id", "stu_models_f"."name", "stu_models_f"."code"
FROM "stu_models_f"
WHERE (
       NOT ("stu_models_f"."id" IN (SELECT U1."f_id" AS Col1 FROM "stu_models_f_es" U1 INNER JOIN "stu_models_e" U2 ON (U1."e_id" = U2."id") WHERE U2."name" = E1)) 
       AND 
       NOT ("stu_models_f"."id" IN (SELECT U1."f_id" AS Col1 FROM "stu_models_f_es" U1 INNER JOIN "stu_models_e" U2 ON (U1."e_id" = U2."id") WHERE U2."code" = E1))
       )  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章