天天看點

Django關聯關系查詢

一對一Model ,有外鍵即設定關聯關系的一方為從表,從表查主表為正向查詢,反之。這裡護照為從表,人為主表。

class Passport(models.Model): # 護照(從表)

note = models.CharField(max_length=20)

person = models.OneToOneField(to="Person",on_delete=models.CASCADE,null=True) #關系屬性

class Meta:

db_table="t_passport"

class Person(models.Model): # 人(主表)

name = models.CharField(max_length=20)

age = models.IntegerField()

class Meta:

db_table="t_person"

注:不需要手動設定 person字段唯一,自動會設定為唯一

一對一 一個人一本護照

# 1.隻查 單方資料 (與單表資料查詢一緻)

# 隻查人的資訊

ps = Person.objects.filter(name='Tom').values() # 自己查自己

print(ps)

# 隻查 護照的資訊

p1 = Passport.objects.all().values()

print(p1)

ps = Person.objects.filter(passport='1').values()

print(ps)

# 2.通過一方查另一方資料 (先擷取一方資料,再通過它查詢另一方)

# 查詢 名字為tom的護照資訊

p1 = Person.objects.get(name='Tom')

print(p1.passport.note) #反向查詢 基于對象 類名小寫

# 查詢護照為美國的人的資訊

ps = Passport.objects.get(note='美國')

print(ps.per_id, ps.per.name,ps.per.age) #正向查詢 基于對象 直接調用外鍵

# 3.通過一方 查另一方 (查詢條件是對方)

# 查詢名字為tom的護照資訊

p1 = Passport.objects.filter(per__name='Tom').values() #正向查詢 基于字段 外鍵__字段

print(p1)

# 查詢護照為美國的人的資訊

p1 = Person.objects.filter(passport__note='美國').values() #反向查詢 基于字段 類小寫__字段

print(p1)

print(Person.objects.filter(passport__note='美國')) # QuerySet集合對象

# 4.保留雙方資料 ()

# 查詢名字為Tom的人資訊 和 護照的資訊

p1 = Person.objects.filter(name='Tom').values('name','age','passport__note') #反向查詢 基于字段 類小寫__字段

print(p1)

p1 = Passport.objects.filter(per__name='Tom').values('note','per__name','per__age','per_id') #正向查詢 基于字段 外鍵__字段

print(p1)

一對一查詢總結:

正向查詢時,基于對象,對象.直接調用外鍵;基于字段 外鍵__字段

反向查詢時,基于對象,對象.類名小寫;基于字段 類小寫__字段

感覺從表和主表查起來差不多。

一對多Model 貨物為從表,種類為主表

class Category(models.Model): #種類(主表)

title = models.CharField(max_length=20)

note = models.CharField(max_length=20)

class Meta:

db_table="t_category"

class Goods(models.Model): #貨物(從表)

title = models.CharField(max_length=20,unique=True)

price = models.FloatField()

cate = models.ForeignKey(to=Category,on_delete=models.CASCADE) #關系屬性 主表删除後,從表中使用主表中資料的也會跟随一起删除

class Meta:

db_table = "t_goods"

# 1對多關系 Category(1):沒有關系屬性 Goods(*):其中有關系屬性cate

# 一對多 查詢 category主表 goods從表

# 1.隻查詢一方資料

# 隻查 主表

c1 = Category.objects.filter(name='服裝').values()

print(c1)

g1 = Goods.objects.filter(price=5000).values()

print(g1)

# 2.通過一方查詢另一方 (先查詢到一方資料,再通過它查詢另一方)

# 查詢服裝類别為男裝的 商品名稱

c1 = Category.objects.get(name='服裝')

print(c1.goods_set) # 查詢也是一個集合 #反向查詢 基于對象 對象.表名_set

print(c1.goods_set.all()) # 查詢也是一個集合

# 查詢 商品沙發所屬的類别

g1 = Goods.objects.get(title='沙發')

print(g1.cate.name, g1.cate.note) #正向查詢 基于對象 對象.外鍵.字段

# 3.通過一方查詢另一方(查詢條件是另一方)

# 查詢 床 商品的 類别資訊

c1 = Category.objects.filter(goods__title='床').values() #反向查詢 基于字段 表名__字段

print(c1)

# 查詢分類為 家居 類别的 商品資訊

g1 = Goods.objects.filter(cate__name='家居').values() #正向查詢 基于字段 外鍵__字段

print(g1)

# 4.保留雙方資料

# 查詢商品名稱為 電視 的分類資訊 和 商品資訊

c1 = Category.objects.filter(goods__title='電視').values('name','note','goods__title','goods__price') #反向查詢 基于字段 表名__字段

print(c1)

# 查詢商品價格大于5000的商品的分類資訊

c1 = Category.objects.filter(goods__price__gt=5000) #反向查詢 基于字段 表名__字段

print(c1)

print(set(c1))

#注意在進行聯合查詢時,可能會由重複資料出現,解決:

list(set(Category.objects.filter(goods__price__gt=200)))

一對多總結:

正向查詢時,基于對象,對象.外鍵.字段;基于字段,外鍵__字段

反向查詢時,基于對象,對象.表名_set;基于字段,表名__字段

多對多Model

class Student(models.Model): #學生(主表)

name = models.CharField(max_length=20)

age = models.IntegerField()

class Meta:

db_table="t_student"

class Course(models.Model): #課程(從表)

title = models.CharField(max_length=30)

expire = models.SmallIntegerField()

stu = models.ManyToManyField(to=Student) #關系屬性

class Meta:

db_table="t_course"

# 多對多關系 Course:有對方關系屬性students, Student:沒有對方關系屬性

# 1.隻查詢一方

# 查詢學生 linda 學生資訊

s1 = Student.objects.filter(name='Linda').values()

print(s1)

# 查詢mysql課程資訊

c1 = Course.objects.filter(title__icontains='MYSQL').values()

print(c1)

# 2.查詢一方,通過它查詢另一方

# 查詢 學習mysql的學生資訊

c1 = Course.objects.get(title='DJANGO')

print(c1.stu.all()) #正向查詢 基于對象 對象.外鍵

# 查詢 學生 linda 課程資訊

s1 = Student.objects.get(name='Linda')

print(s1.course_set.all()) #反向查詢 基于對象 對象.表名_set

print(s1.course_set.values())

# 3.通過一方 查詢 另一方 (查詢條件為對方)

# 查詢 學生 linda 課程資訊

c1 = Course.objects.filter(stu__name='Linda').values() #正向查詢 基于字段 外鍵__字段

print(c1)

# 查詢 學習mysql的學生資訊

s1 = Student.objects.filter(course__title='PYTHON').values() #反向查詢 基于字段 表名__字段

print(s1)

# 4.保留雙方資料

# 查詢學習django的學生資訊 和 課程資訊

s1 = Student.objects.filter(course__title='DJANGO').values('name','age','course__title','course__expire') #反向查詢 基于字段 表名__字段

print(s1)

# 查詢jack學習的課程資訊 和 學生資訊

c1 = Course.objects.filter(stu__name='Jack').values('title','expire','stu__age','stu__name') #正向查詢 基于字段 外鍵__字段

print(c1)

#關聯查詢

Student.objects.filter(course__title__contains="h") #标題中含有"h"的課程中的學生 #反向查詢 基于字段 表名__字段

Course.objects.filter(stu__name="zzz") #姓名為zzz的學生參加的課程 #正向查詢 基于字段 外鍵__字段

Course.objects.filter(stu__age__gt=18) #年齡大于18的學生參加的課程 #正向查詢 基于字段 外鍵__字段

坑:不能查具體某個字段

多對多總結:

正向查詢時,基于對象,對象.外鍵;基于字段,外鍵__字段

反向查詢時,基于對象,對象.表名_set;基于字段,表名__字段

最後3個總結寫在一起比較:

一對一查詢總結:

正向查詢時,基于對象,對象.直接調用外鍵;基于字段 外鍵__字段

反向查詢時,基于對象,對象.類名小寫;基于字段 類小寫__字段

一對多總結:

正向查詢時,基于對象,對象.外鍵.字段;基于字段,外鍵__字段

反向查詢時,基于對象,對象.表名_set;基于字段,表名__字段

多對多總結:

正向查詢時,基于對象,對象.外鍵;基于字段,外鍵__字段

反向查詢時,基于對象,對象.表名_set;基于字段,表名__字段

最後總結,

基于對象的情況下,正向查詢時基本一緻,直接調用外鍵就好;反向查詢時一對多和多對多,需要對象.表名_set調用。

基于字段的情況下,正向查詢時,外鍵__字段;反向查詢時,表名__字段。一對一可能為類名小寫__字段。