Django中model之間關係(一對多,一對一,多對多)

  • ForeignKey

ForeignKey(to, on_delete, related_name=None, related_query_name=None,
                 limit_choices_to=None, parent_link=False, to_field=None,
                 db_constraint=True, **kwargs)

to : 要關聯的表名。

on_delete : 當刪除關聯表中的數據時,當前表與其關聯的行的行爲。

related_name : 用於反向操作時,代替表名_set,related_name == 表名_set。

to_field :  表示需要關聯的表的字段,  默認情況下會關聯表的主鍵。

related_query_name : 用於反向操作時,代替表名   即 表名_set ==  related_query_name_set。也可用於連表查詢。

db_constraint : 表示是否在數據庫中創建外建約束。

limit_choices_to: 在Admin或ModelForm中顯示關聯數據時,提供的條件。

parent_link: 在Admin中是否顯示關聯數據。(不常用)

  • OneToOneField

OneToOneField(to, on_delete, related_name=None, related_query_name=None,
                 limit_choices_to=None, parent_link=False, to_field=None,
                 db_constraint=True, **kwargs)

to : 要關聯的表名。

on_delete : 當刪除關聯表中的數據時,當前表與其關聯的行的行爲。

related_name : 用於反向操作時,代替表名_set,related_name == 表名_set。

to_field :  表示需要關聯的表的字段,  默認情況下會關聯表的主鍵。

related_query_name : 用於反向操作時,代替表名   即 表名_set ==  related_query_name_set。也可用於連表查詢

db_constraint : 表示是否在數據庫中創建外建約束。

limit_choices_to: 在Admin或ModelForm中顯示關聯數據時,提供的條件。

parent_link: 在Admin中是否顯示關聯數據。(不常用)

  • ManyToManyField

ManyToManyField(to, related_name=None, related_query_name=None,
                 limit_choices_to=None, symmetrical=None, through=None,
                 through_fields=None, db_constraint=True, db_table=None,
                 swappable=True, **kwargs)

注意:在多對多關係中,django默認會創建第三個表,來存儲對應表的關係。你也可以通過through來指定存放映射關係的表。

symmetrical: 僅用於多對多自關聯時,指定內部是否創建反向操作的字段。默認爲True。

through:手動指定中間關聯表。(需要在models.py中創建一個Model,並且其中包含兩個相關聯模型的外鍵)

through_fields:在中間表中,有多個關聯對象的外建。django需要知道使用哪兩個關聯,through_fields = (field1,field2),注意field1應該是有ManyToManyField字段的關聯模型外鍵名。

db_constraint:是否在數據庫中創建外建約束

db_table:指定表名

舉例詳解:

from django.db import models

# Create your models here.


class UserInfo(models.Model):
    username = models.CharField(max_length=16,unique=True,null=True)
    pwd = models.CharField(max_length=32,null=True)
    addresss = models.CharField(max_length=32,default='sdaf')
    signup_time = models.DateField(auto_now_add=True)


class OrderInfo(models.Model):
    order_time = models.DateField(auto_now_add=True)
    order_status = models.BooleanField()
    order_content = models.CharField(max_length=32)
    key = models.ForeignKey(UserInfo, on_delete=models.CASCADE, default=1, related_name='Info',related_query_name='query')


class UserSalary(models.Model):
    money = models.IntegerField()
    user = models.ManyToManyField(UserInfo, related_name='salary')


class UserAge(models.Model):
    age = models.IntegerField()
    user_age = models.OneToOneField(UserInfo,on_delete=models.CASCADE)

一共有五張表。

OneToOne(一對一的增刪改查)

a = UserAge.objects.get(id=1)
d = UserInfo.objects.get(id=1) # 也可以使用filter,但是注意filter查出的是QuerySet集合。
a.age
# 12
d.username
# xiao1

# 正向查
a.user_age.username
# 'xiao1'

# 反向查    注意這個和多對一和多對多不一樣。一個對象只對一個對象。
d.userage.age
# 12

#注意反向查的時候,不需要在model名後加set
# 直接刪
a.delete()
# 或者
d.userage.delete()
# 兩個表達式都返回值 (1, {'myapp.UserAge': 1})
# 先在主表中新建一個對象(或者查找一個對象,注意這個對象不能是已關聯過的)
# e = UserInfo.objects.get(id=4)
e = UserInfo.objects.create(username = 'first')
# 然後創建從表對象,將要關聯的主表對象賦值給從表中的OneToOne字段。
UserAge.objects.create(age=121,user_age=e)

# 在主表或者從表中隨便修改。然後用save()保存
a.age = 122
a.save()
d.username = "zhangzhang"
d.save()
# get()出的數據不是quertset,因此不可以使用update方法。如果想要用的話,可以使用filter查

 

 多對多和一對多

正向操作和反向操作

注意:正反向操作時,起始必須是model中一個對象,不可以是QuerySet集合。

# 正向操作(根據從表查主表中數據)
OrderInfo.objects.get(id=1).key.username

# 反向操作(根據主表中數據查從表中數據)
UserInfo.objects.get(id=1).Info.all() 
# 注意:由於設置了related_name , 所以上面語句中 Info ==  orderinfo_set
# 正向操作時,對於ForeignKey,由於查到的是一個對象,因此無法使用.all()方法。

常用的是add和create方法。

add(*objsbulk=Truethrough_defaults=None) # 將指定的模型對象添加到關聯對象集合中。

a = OrderInfo.objects.get(id=2)
UserInfo.objects.get(id=3).Info.add(a)  # related_name爲Info

add中可以是多個對象,也可以是關聯對象主鍵值

# 多個對象
>>> lists = OrderInfo.objects.filter(order_status=0)
>>> UserInfo.objects.get(id=4).Info.add(*lists)

create(through_defaults=None**kwargs)

創建一個新對象,保存並將其放入相關對象集中。返回新創建的對象.

 # 一般都是從主表出發,
UserInfo.objects.get(id=3).Info.create(order_status=1,order_content="success")

也就相當於

u = UserInfo.objects.get(id=3)
o = OrderInfo(order_status=1,order_content="success",key=u)
o.save()

remove(*objsbulk=True)

從相關對象集中刪除指定的模型對象:(這也是從主表出發)

>>> b = Blog.objects.get(id=1) #主表對象
>>> e = Entry.objects.get(id=234) # 從表對象
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.

#注意,對於ForeignKey,必須要外建字段選項null=True,纔可以使用remove方法,否則不行。ManyToMany無所謂

 # 除此以外,刪除操作後,只是把存放映射關係的第三張表的中的數據刪除了。並沒有刪除從表中的數據

clear(bulk=True)

#注意,對於ForeignKey,必須要外建字段選項null=True,纔可以使用clear方法,否則不行。ManyToMany無所謂

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()

set()方法

set(objsbulk=Trueclear=Falsethrough_defaults=None)

重置關聯關係。

該方法有一個clear 參數。如果clear=False ,則將不再objes 中的元素使用remove()方法移除。如果clear=True,則首先調用clear()方法將之前的元素全部刪除掉,再將集合中的元素整個刪除。

最重要的是 :對於多對多如果你使用了中間模型(保存多對多的關係),則add,create,remove,set方法都不能調用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章