Django之ORM連表操作

lcc發表於2021-09-11

Django之ORM連表操作

ORM連表操作

我們在學習django中的orm的時候,我們可以把一對多,多對多,分為正向和反向查詢兩種方式。

正向查詢:ForeignKey在 UserInfo表中,如果從UserInfo表開始向其他的表進行查詢,這個就是正向操作,反之如果從UserType表去查詢其他的表這個就是反向操作。

(1)一對多:models.ForeignKey(其他表)

(2)多對多:models.ManyToManyField(其他表)

(3)一對一:models.OneToOneField(其他表)

正向連表操作總結:

所謂正、反向連表操作的認定無非是Foreign_Key欄位在哪張表決定的,

Foreign_Key欄位在哪張表就可以哪張表使用Foreign_Key欄位連表,反之沒有Foreign_Key欄位就使用與其關聯的小寫表名;

1對多:物件.外來鍵.關聯表欄位,values(外來鍵欄位__關聯表欄位)

多對多:外來鍵欄位.all()

反向連表操作總結:

透過value、value_list、fifter 方式反向跨表:小寫表名__關聯表欄位

透過物件的形式反向跨表:小寫表面_set().all()

前端ajax需要攜帶的引數 

根據前端引數,返回不同資料庫結果

應用場景:

(1)一對多:當一張表中建立一行資料時,有一個單選的下拉框(可以被重複選擇)

例如:建立使用者資訊時候,需要選擇一個使用者型別【普通使用者】【金牌使用者】【鉑金使用者】等。

(2)多對多:在某表中建立一行資料是,有一個可以多選的下拉框。

例如:建立使用者資訊,需要為使用者指定多個愛好。

a.png

(3)一對一:在某表中建立一行資料時,有一個單選的下拉框(下拉框中的內容被用過一次就消失了。

例如:原有含10列資料的一張表儲存相關資訊,經過一段時間之後,10列無法滿足需求,需要為原來的表再新增5列資料。

1對多

如果A表的1條記錄對應B表中N條記錄成立,兩表之間就是1對多關係;在1對多關係中 A表就是主表,B表為子表,ForeignKey欄位就建在子表;

如果B表的1條記錄也對應A表中N條記錄,兩表之間就是雙向1對多關係,也稱為多對多關係;

在orm中設定如果 A表設定了外來鍵欄位user=models.ForeignKey('UserType')到B表(注意外來鍵表名加引號)

就意味著 寫在寫A表的B表主鍵, (一列),代表B表的多個(一行)稱為1對多,

查詢

總結:利用orm獲取 資料庫表中多個資料

獲取到的資料型別本質上都是 queryset型別,

類似於列表,

內部有3種表現形式(物件,字典,列表)

modle.表名.objects.all()

modle.表名.objects.values()

modle.表名.objects.values()

跨表

正操作

所以表間只要有外來鍵關係就可以一直點下去。

所以可以透過obj.外來鍵.B表的列表跨表操作(注意!!orm連表操作必須選拿單個物件,不像SQL中直接表和表join就可以了)

print(obj.cls.title)

foreignkey欄位在那個表裡,那個表裡一個"空格"代表那個表的多個(一行)

class UserGroup(models.Model):
            """
            部門 3
            """
            title = models.CharField(max_length=32)
        class UserInfo(models.Model):
            """
            員工4
            """
            nid = models.BigAutoField(primary_key=True)
            user = models.CharField(max_length=32)
            password = models.CharField(max_length=64)
            age = models.IntegerField(default=1)
            # ug_id 1
            ug = models.ForeignKey("UserGroup",null=True)

1. 在取得時候跨表

q = UserInfo.objects.all().first()

q.ug.title

2. 在查的時候就跨表了 

UserInfo.objects.values('nid','ug_id') 

UserInfo.objects.values('nid','ug_id','ug__title')    #注意正向連表是  外來鍵__外來鍵列 反向是小寫的表名

3. UserInfo.objects.values_list('nid','ug_id','ug__title')

反向連表:

反向操作無非2種方式:

(1)透過物件的形式反向跨表:小寫表面_set().all()

(2)透過value和value_list方式反向跨表:小寫表名__欄位

1. 小寫的表名_set 得到有外來鍵關係的物件

obj = UserGroup.objects.all().first()

result = obj.userinfo_set.all() [userinfo物件,userinfo物件,]

2. 小寫的表名 得到有外來鍵關係的列 #因為使用values取值取得是字典的不是物件,所以需要 小寫表名(外來鍵表)__

v = UserGroup.objects.values('id','title') 

v = UserGroup.objects.values('id','title','小寫的表名稱') 

v = UserGroup.objects.values('id','title','小寫的表名稱__age') 

3. 小寫的表名 得到有外來鍵關係的列

v = UserGroup.objects.values_list('id','title') 

v = UserGroup.objects.values_list('id','title','小寫的表名稱') 

v = UserGroup.objects.values_list('id','title','小寫的表名稱__age')

1對多自關聯( 由原來的2張表,變成一張表! )

想象有第二張表,關聯自己表中的行

s.png

d.png

相關推薦:《》

程式碼

    class Comment(models.Model):
                """
                評論表
                """
                news_id = models.IntegerField()            # 新聞ID
                content = models.CharField(max_length=32)  # 評論內容
                user = models.CharField(max_length=32)     # 評論者
                reply = models.ForeignKey('Comment',null=True,blank=True,related_name='xxxx') #回覆ID

多對多:

1、自己寫第3張關係表

ORM多對多查詢:

女士表:

a.png

男生表:

s.png

男女關係表

d.png

多對跨表操作

#獲取方少偉有染的女孩
    obj=models.Boy.objects.filter(name='方少偉').first()
    obj_list=obj.love_set.all()
    for row in obj_list:
        print(row.g.nike)
    # 獲取和蒼井空有染的男孩
    obj=models.Girl.objects.filter(nike='蒼井空').first()
    user_list=obj.love_set.all()
    for row in  user_list:
        print(row.b.name)

多對多關係表   資料查詢思路

(1)找到該物件

(2)透過該物件 反向操作 找到第三張關係表

(3)透過第三張關係表 正向操作 找到 和該物件有關係物件

總結

只要物件1和物件2 中間有關係表建立了關係; 物件1反向操作 到關係表 ,關係表正向操作到物件2,反之亦然。

2、第3張關係表不用寫(m=models.ManyToManyField(' 要關聯的表') 自動生成)

1562035302215495.png

由於 DjangoORM中一個類名對應一張表,要想操作表就modles.類直接操作那張表,但使用ManyToManyField欄位生成 “第三張”關係表怎麼操作它呢?

答案:透過單個objd物件 間接操作

class Boy(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField('Girl',through="Love",through_fields=('b','g',))
class Girl(models.Model):
    nick = models.CharField(max_length=32)
    m = models.ManyToManyField('Boy')

正向操作: obj.m.all()

obj = models.Boy.objects.filter(name='方少偉').first()
    print(obj.id,obj.name)
    obj.m.add(2)
    obj.m.add(2,4)
    obj.m.add(*[1,])
    obj.m.remove(1)
    obj.m.remove(2,3)
    obj.m.remove(*[4,])
    obj.m.set([1,])
    q = obj.m.all()
    # [Girl物件]
    print(q)
    obj = models.Boy.objects.filter(name='方少偉').first()
    girl_list = obj.m.all()
    obj = models.Boy.objects.filter(name='方少偉').first()
    girl_list = obj.m.all()
    girl_list = obj.m.filter(nick='小魚')
    print(girl_list)
    obj = models.Boy.objects.filter(name='方少偉').first()
    obj.m.clear()

反向操作 :obj.小寫的表名_set

多對多和外來鍵跨表一樣都是 小寫的表名_set

3、既自定義第三張關係表 也使用ManyToManyField('Boy')欄位(雜交型別)

ManyToManyField()欄位建立第3張關係表,可以使用欄位跨表查詢,但無法直接操作第3張表,

自建第3表關係表可以直接操作,但無法透過欄位 查詢,我們可以把他們結合起來使用;

作用:

(1)既可以使用欄位跨表查詢,也可以直接操作第3張關係表

(2)obj.m.all() 只有查詢和清空方法

外來鍵反向查詢別名(方便反向查詢)

在寫ForeignKey欄位的時候,如果想要在反向查詢時不使用預設的 小寫的表名_set,就在定義這個欄位的時間加related引數!

related_name、related_query_name 欄位=什麼別名 反向查詢時就使用什麼別名!

反向查詢:

設定了related_query_name 反向查詢時就是obj.別名_set.all()保留了_set

related_query_name

related_name

反向查詢:

設定了relatedname就是 反向查詢時就說 obj.別名.all()  

多對多自關聯(由原來的3張表,變成只有2張表)

把兩張表透過 choices欄位合併為一張表

‘第三張關係表’ 使用models.ManyToManyField('Userinfo')生成

特性:

obj = models.UserInfo.objects.filter(id=1).first()  獲取物件

(1)查詢第三張關係表前面那一列:obj.m

select xx from xx where from_userinfo_id = 1

(2)查詢第三張關係表後面那一列:obj.userinfo_set

select xx from xx where to_userinfo_id = 1

多對多自關聯特性:

x.png

ManyToManyField生成的第三張表

cc.png

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2331/viewspace-2837325/,如需轉載,請註明出處,否則將追究法律責任。

相關文章