以相親關系表舉例,男女生信息表都放在一個數據表中,男生可以看到相親過的女生,同理女生也可以看到相親過的男生
1.前戲:通過外鍵表引出:
- 所有的信息都整合在一張表里,通過另一張按照自定義規則設置的外鍵表,實現連表操作查詢的功能。
建立外鍵表:
- 由於是對同一張表操作,django框架此時就沒有那么智能,此時就需要我們自定義約束規則,以規范使用!
PS:補充一點內容:ForeignKey()中的參數:
- to="表名"
- to_field="列名" #建立外鍵關系的列名,默認是id列
- related_query_name="自定義名" #定義一個反向操作的名稱,保留了反向連表操作中_set的屬性
- related_name="自定義名" #定義一個反向操作的名稱,直接通過自定義名即可反向操作
related_query_name和related_name都是定義的反向操作的屬性,一般常用於related_name.
舉例說明:-外鍵表中,反向操作的名字,女生為a,男生為b!
# related_query_name
obj對象男.b_set.all()
obj對象女.a_set.all()
# related_name
obj對象男.a.all()
obj對象女.b.all()
1)models.py文件中,ORM利用類創建表的代碼:
#創建用戶信息表
class Userinfo(models.Model):
nickname = models.CharField(max_length=32) #昵稱
username = models.CharField(max_length=32) #用戶名
password = models.CharField(max_length=64) #密碼
gender_choices = (
(1,"男"),
(2,"女"),
)
gender = models.IntegerField(choices=gender_choices) #性別
#外鍵關聯表
class U2U(models.Model):
g = models.ForeignKey("Userinfo",related_name="boys") #設置與女生關聯的外鍵,及反向操作的名稱
b = models.ForeignKey("Userinfo",related_name="girls")#設置與男生關聯的外鍵,及反向操作的名稱
2)給兩張表添加數據:
- 信息表就不用多說了,就是平常添加的順序,此除多說說關聯表,關聯表添加數據的方式有兩種:
#第一種:知道ID直接添加:
models.U2U.objects.create(b_id=1,g_id=4)
#第二種:先從信息表中,獲取相對應的對象,然后在關聯表中直接添加這個對象,內部會做轉換操作,拿取用戶的id。
boy = models.Userinfo.objects.filter(gender=1,id=2).first()
gril = models.Userinfo.objects.filter(gender=2,id=5).first()
models.U2U.objects.create(b=boy,g=gril)
3)表和數據都有了,那就剩下操作了,怎么獲取相對應的信息!
- 此處再次普及一下正反向操作的定義:
正反向操作是以外鍵為標志,從當前有外鍵的表,通過外鍵獲取對應表的數據操作稱為正向操作;反之,從數據表反向獲取關聯表的操作,稱為反向操作。
注意一點:不管是正反向操作,獲取的對象(數據)都是跨表之后的另一張表的對象(信息)!
root = models.Userinfo.objects.filter(id=1).first() #先獲取一個信息表的對象
result = root.girls.all() #通過定義的反向關聯的名字,反向查找與當前對象有關系的對象,注意:此處獲取的是 U2U表的對象!
for u in result:
print(u.g.nickname) #通過拿到的對象,在通過外鍵關系,正向獲取有關系對象的昵稱。
2.正題:
- 既然上邊的操作可以實現信息的整合,那么建立聯系的外鍵是否也可以寫在一張表里呢?答案是肯定的。這種創建關聯的方式就叫做自關聯。
本質:把所有的信息都在一張表上創建,雖然只有一張表,但是我們可以再想象着生成一張一模一樣的表,這兩個表之間通過外聯建立關系。
雖然是叫做自關聯,實質上還是兩張表的操作!
- M2M自關聯特性:(多對多)
#創建自關聯的整合表
class Userinfo(models.Model):
nickname = models.CharField(max_length=32) #昵稱
username = models.CharField(max_length=32) #用戶名
password = models.CharField(max_length=64) #密碼
gender_choices = (
(1,"男"),
(2,"女"),
)
gender = models.IntegerField(choices=gender_choices) #性別
m = models.ManyToManyField('Userinfo')
#ManyToManyField有一特性,就是會自動生成一張關系表,我們設置的這個自關聯表中,會生成三列,id,from_userinfo_id,to_userinfo_id
自增id不用說,from_userinfo_id,to_userinfo_id,從列名上就能看出來,分別代表着userinfo表的不同id,一個是從哪兒來,一個是去哪里。
obj = models.Userinfo.objects.filter(id=1).first()
# from_userinfo_id #正向操作 sql語句
obj.m => select xx from xx where from_userinfo_id = 1
# to_userinfo_id #反向操作 sql語句
obj.userinfo_set => select xx from xx where to_userinfo_id = 1
- 關系表內自定義規則:記住定義了規則之后,一定要嚴格遵守!!!
定義:
# 前面列:男生ID
# 后面列:女生ID
應用:
# 男生對象
obj = models.UserInfo.objects.filter(id=1).first()
# 根據男生ID=1查找關聯的所有的女神
obj.m.all()
# 女生
obj = models.UserInfo.objects.filter(id=4).first()
# 根據女生ID=4查找關聯的所有的男生
obj.userinfo_set.all()