Django表關係與表查詢
1、一對多
首先來說說一對多,這個關聯關係經常用到,多的一方通過models.ForeignKey進行關聯。如下示例:
class Department(models.Model): name = models.CharField(max_length=20) create_data = models.DateField(auto_now_add=True) is_delete = models.BooleanField(default=False) # default=False,在資料庫中表現為0 class Meta: # 這裡定義了db_table的話,那麼遷移後表名就是department這個了,不會是應用名_類名小寫(例如:framework_department) db_table = "department" class Employee(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() gender = models.IntegerField(default=0) # decimal_place = 2表示兩位小數,max_digits表示8個數字,包括小數的兩位 salary = models.DecimalField(max_digits=8,decimal_places=2) # null=True 表示可以為空,blank=True表示django後臺管理輸入這個欄位可以為空 comment = models.CharField(max_length=300,null=True,blank=True) hire_data = models.DateField(auto_now_add=True) department = models.ForeignKey("Department") # department = models.ForeignKey("Department", related_name = 'employee') # 加了related_name = 'employee'後,在進行查詢一個部門的全部員工時就不用employee_set了,直接使用employee即可。其餘方法和使用employee_set一致。 class Meta: db_table = "employee"
以上定義了兩個模型,員工和部門是一對多關係,員工屬於多的一方,所以使用了models.ForeignKey來與部門進行關聯。關聯的模型如果是定義在一個py檔案裡的話,那麼可以直接寫模型名稱即可,例如:Department就可以直接使用,但是如果要關聯不在一個py檔案裡的模型,那麼就要通過:應用名.模型名使用(例如:user.User)。
以上都是關於模型的定義和使用,當然,最重要的是使用模型相關方法進行增刪查改。
1.1、新增資料
新增Department:
Department.objects.create(name="生產部")
新增Employee:
Employee.objects.create(name="小明", age=18, gender=0, salary=8000.50, comment="新入職員工", department=1)
當然這樣新增會報錯:
ValueError: Cannot assign “1”: “Employee.department” must be a “Department” instance.
因為新增employee時,department需要傳入一個例項物件,而不是單純的一個ID。正確新增如下:
Employee.objects.create(name="小明", age=18, gender=0, salary=8000.50, comment="新入職員工", department=Department.objects.get(id=1)) Employee.objects.create(name="小張", age=18, gender=0, salary=9000.50, comment="新入職員工", department=Department.objects.filter(id=2)[0])
1.2、更新一個員工所屬的部門:
Employee.objects.filter(id=1).update(department=3)
這裡要注意的是,更新就不用傳一個例項物件了,只需要傳入部門id即可。傳入例項物件會報錯。
1.3、根據條件刪除:
刪除指定部門下的所有員工:
Employee.objects.filter(department=2).delete()
1.4、查詢資料
一個員工所屬的部門:
employee = Employee.objects.get(id=1)
employee_belong_department=employee.department
employee_belong_department_name= employee_belong_department.name
一個部門的全部員工:
department = Department.objects.get(id=1)
all_employee= department.employee_set.all()/a.employee_set.values()/a.employee_set.values_list()
使用外來鍵時,一般都會定義一個刪除的關聯操作。什麼意思呢?如下:
department = models.ForeignKey("Department", on_delete=models.CASCADE)
如果一個模型使用了外來鍵。那麼在對方那個模型被刪掉後,該進行什麼樣的操作。可以通過on_delete來指定。可以指定的型別如下:
CASCADE:級聯操作。如果外來鍵對應的那條資料被刪除了,那麼這條資料也會被刪除。
PROTECT:受保護。即只要這條資料引用了外來鍵的那條資料,那麼就不能刪除外來鍵的那條資料。如果我們強行刪除,Django就會報錯。
SET_NULL:設定為空。如果外來鍵的那條資料被刪除了,那麼在本條資料上就將這個欄位設定為空。如果設定這個選項,前提是要指定這個欄位可以為空。
SET_DEFAULT:設定預設值。如果外來鍵的那條資料被刪除了,那麼本條資料上就將這個欄位設定為預設值。如果設定這個選項, 前提是要指定這個欄位一個預設值 。
SET():如果外來鍵的那條資料被刪除了。那麼將會獲取SET函式中的值來作為這個外來鍵的值。SET函式可以接收一個可以呼叫的物件(比如函式或者方法),如果是可以呼叫的物件,那麼會將這個物件呼叫後的結果作為值返回回去,可以不用指定預設值 。
DO_NOTHING:不採取任何行為。一切全看資料庫級別的約束。
2、多對多
class Student(models.Model):
name = models.CharField(max_length=16, verbose_name=u'名字')
age = models.IntegerField(verbose_name=u'年齡')
class Club(models.Model):
name = models.CharField(max_length=16)
members = models.ManyToManyField("Student")
2.1、新增資料
1、首先,多對多關係表在遷移時會生成三張表,雖然我們只定義了兩張表,但是由於有ManyToManyField欄位存在,會使得第三張表名字為:有ManyToManyField欄位的模型名_欄位名(例如:club_members)。這第三張表是自動生成的,當然,我們是可以控制這第三張表,稍後會說到
新增student:
Student.objects.create(name="小張", age=19)
Student.objects.create(name="小明", age=18)
Student.objects.create(name="小銘", age=19)
Student.objects.create(name="小林", age=17)
新增club:
Club.objects.create(name="跑步")
Club.objects.create(name="跳遠")
Club.objects.create(name="跳高")
Club.objects.create(name="跳河")
club因為存在ManyToManyField欄位,所以新增資料時,不能直接將該欄位拿來使用
新增club_members:
先查詢student資料
student = Student.objects.get(name="小林")
再查詢club資料
club = Club.objects.get(name="跑步")
新增到關聯表
club.members.add(student)
注意:add()這個方法接收的是一個物件,所以,如果要進行批量新增的話,如下:
students = Student.objects.all()
club = Club.objects.get(name="跑步")
club.members.add(*students)
2.2、查詢資料
查詢一個社團的全部成員
c = Club.objects.get(name="跑步")
c.members.all()/c.members.values()/c.members.values_list()
查詢一個成員的全部社團
s = Student.objects.filter(id=1)
s.club_set.all()/s.club_set.values()/s.club_set.values_list() # 類名的小寫+_set
2.3、更新資料
更新一個club下所有成員名字為1
b=Club.objects.get(name="ww")
b.members.update(name="1") # 返回更新條數,例如:3
2.4、刪除資料
1、ManyToManyField是預設級聯刪除的,例如,如果要刪除所有club下的某個student,那麼就很簡單了。
club=Club.objects.get(id=1) # 先查club
club.members.filter(name="ss").delete() # 再查student,name欄位是關聯的Student表的name
返回資料為:(6, {u’framework.Student’: 1, u’framework.Club_members’: 5}),表示Student表刪除了一條資料,Club_members表刪除了5條資料。如果沒有該student,那麼返回為(0, {})。從上面可以看出如果使用以上方法不僅會刪除Student表中資料,還會刪除Club表資料。
2、有時候我們不想刪除那麼多資料,例如只想刪除某個club下的所有資料而不影響Student表中資料,那麼可以使用如下方法:
club=Club.objects.get(id=1) # 先查要刪除的那個club
club.members.clear() # 呼叫clear()方法刪除所有關於該club的資料
3、有時候我們還想只刪除某個club下的某個student資料,那麼可以使用如下方法:
club=Club.objects.get(id=2) # 先查club
stu=Student.objects.get(id=2) # 再獲取要刪除的student
club.members.remove(stu) # 呼叫remove方法刪除
3、自定義多對多表
前面說了多對多會自動建立一張關聯表,這張表是可以自定義的。
class Student(models.Model):
name= models.CharField(max_length=16)
age = models.IntegerField()
class Club(models.Model):
name= models.CharField(max_length=16)
class Membership(models.Model):
student = models.ForeignKey("Student")
club = models.ForeignKey("Club")
這種多對多關聯是自己定義的第三張關聯關係表,所以操作起來會較前面簡單。
3.1、新增資料
Membership.objects.create(student_id=1, club_id=1)
因為兩個欄位都是外來鍵關聯,所以操作時需要使用欄位名_id的形式進行操作。
3.2、查詢資料
查詢一個學生所有的club
a=Student.objects.get(id=1)
b=a.membership_set.all()
查詢一個club下的所有學生
a=Club.objects.get(id=1)
b=a.membership_set.all()
3.3、刪除資料
Membership.objects.filter(student_id=1, club_id=1).delete()
返回值:(1, {u’framework.Membership’: 1})/(0, {u’framework.Membership’: 0})
好啦,文章到這裡結束啦,謝謝瀏覽呀,祝各位看官老爺天天開心!