一對多
models.py
from django.db import models # Create your models here. # 數據庫:一對多。它指的是兩個表之間的關系,一指的是主表中的一條數據,多指的是從表中的多條數據。 # 兩個表: # 班級表(1班,2班,3班) # 學生表(張三-1班, 李四-1班, 王五-1班,趙六-2班,麻子-3班,小明-2班) # 這兩個表:班級表就是主表,因為班級表的一條數據(比如1班)對應了學生表的多條數據(張三-1班, 李四-1班, 王五-1班),所以學生表是從表。 class Classes(models.Model): """ 這是班級表,是主表; """ c_name = models.CharField(max_length=20) class Meta: db_table = 'classes' class Student(models.Model): """ 這是從表,學生表; 主表中的一條數據可以對應從表中的多條數據; 從表中的一條數據只能對應主表中的一條數據; """ s_name = models.CharField(max_length=20) # 如何在從表中關聯主表的ID? # ForeignKey()外鍵,在Student表中,關聯外部表Classes的主鍵,所以稱為外鍵。 # on_delete:必須設置。表示從表數據所關聯的主表數據被刪除以后,從表應該怎么辦。 # 1. CASCADE:如果主表數據刪除,從表對應的數據也全部刪除; # 比如:張三、李四、王五關聯的都是1班,如果1班這條數據被刪除了,那么,對應的張三、李四、王五也全部刪除; # 2. SET_NULL:如果主表數據刪除,從表數據保留,但是這種外鍵的關聯關系classes_id設置為NULL。 # 從表關聯兩個主表的外鍵。 # related_name指定外鍵的關聯名稱,這個名稱是用於將來查詢數據使用的。只在主表查從表時會用到。 classes_one = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name='cls_one') classes_two = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name='cls_two') class Meta: db_table = 'student'
views.py
from django.shortcuts import render from django.views.generic import View from .models import Classes, Student # 通用視圖類的用法: # 1. 主要作用還是用於配置url路由,只不過形式和視圖函數的寫法不一樣,但是功能是一樣的;視圖函數區分GET和POST主要是通過request.method,而通用視圖將GET和POST請求封裝成了類中的兩個方法; class Home(View): def get(self, request, id): print('------', id) """ self和request是固定的兩個參數,這兩個參數后面如果還有參數,那就是url傳遞的參數; :param request: :return: """ return render(request, 'index.html') def post(self, request, id): print('=======', id) a = request.POST.get('a') b = request.POST.get('b') return render(request, 'index.html', {'result': int(a)+int(b)}) class DataHandler(View): def get(self, request): # 數據庫中要先存在主表的數據,然后才能創建從表的數據。 # c1 = Classes(c_name='1班') # c1.save() # c2 = Classes(c_name='2班') # c2.save() # c3 = Classes(c_name='3班') # c3.save() # 關聯主表id:通過classes(表面)或者classes_id(核心)都可以進行綁定; # s1 = Student(s_name="張三", classes_one=c1, classes_two=c1) # s1.save() # s2 = Student(s_name="李四", classes_id=c1.id) # s2.save() # s3 = Student(s_name="王五", classes=c2) # s3.save() # s4 = Student(s_name="趙六", classes_id=c3.id) # s4.save() # return render(request, 'index.html') # 如何根據主表的一條數據查詢所有從表的數據? c1 = Classes.objects.get(id=1) # 語法:主表數據.從表名稱_set # student_set就是一個查詢結果集,所有的學生數據都在里面。 # stus = c1.student_set.all() # 如果從表出現,多個關聯同一個主表的外鍵,就不能再使用student_set了,無法區分是classes_one還是classes_two。 stus = c1.cls_two.all() # 如何根據從表的一條數據查詢對應的一條主表的數據? s1 = Student.objects.get(id=1) # classes就是s1對象的屬性,是在Student類中聲明的一個屬性。 classes_name = s1.classes_two.c_name return render(request, 'index.html', {'stus': stus})
一對一
models.py
from django.db import models # Create your models here. # ORM數據庫的一對一關系:一個表中的一條數據對應着另外一個表中的一條數據。 # 例如: 一個賬戶只對應着一個聯系人,一個聯系人只能有一個賬戶。身份證。 class Account(models.Model): """ 一個賬戶類 """ # 賬戶名稱 a_name = models.CharField(max_length=20) # 賬戶密碼 a_pwd = models.CharField(max_length=100) # 賬戶激活的時間 # DateField()參數為空,這個字段的值需要自己添加。 # auto_now=True: 當這個Account這個對象的屬性被修改了,在保存的時候,這個a_register_date這個時間會自動更新為保存時間;(強調更新時間) # auto_now_add=True: 含義就是這個時間字段,不會隨着對象的修改而更新這個時間,只在這個對象被第一次創建的時候自動填充創建的時間。以后也不會再變動了。(強調創建時間) # auto_created=True: 表示使用當前時間作為值,自動創建這個字段的值。默認是False。當創建對象的時候就不需要給這個字段賦值了,會自動創建。 a_register_date = models.DateTimeField(auto_now_add=True, auto_created=True) a_update_date = models.DateTimeField(auto_now=True) class Meta: db_table = 'account' class Contact(models.Model): """ 一個賬戶的擁有人。 """ # 所有人的姓名 c_name = models.CharField(max_length=20) # 所有人的住址 c_address = models.TextField() # 所有人的聯系方式 c_phone = models.CharField(max_length=20) # 添加賬戶和所有人的一對一關系。 # models.CASCADE:當account表中的一條數據刪除時,對應的contact表中的數據也要刪除。 account = models.OneToOneField(Account, on_delete=models.CASCADE) class Meta: db_table = 'contact' # 將models.OneToOneField寫在哪一個表中,哪一個表就是從表;OneToOneField()的第一個參數就是主表; # OneToOneField不強調位置關系,兩個表中任選一個作為主表,另一個作為從表; # 一對多:一必須是主表,多是從表,強調位置關系。
views.py
from django.shortcuts import render from .models import Account, Contact from datetime import datetime def add(request): # 添加主表數據 a1 = Account(a_name='1@qq.com', a_pwd='123', a_register_date=datetime.now(), a_update_date=datetime.now()) a1.save() a2 = Account(a_name='2@qq.com', a_pwd='456', a_register_date=datetime.now(), a_update_date=datetime.now()) a2.save() # 添加從表數據 c1 = Contact(c_name='張三', c_address='北京', c_phone='111', account=a1) c1.save() c2 = Contact(c_name='李四', c_address='鄭州', c_phone='222', account_id=a2.id) c2.save() return render(request, 'index.html', {'result': '數據添加成功'}) def select(request): # 根據主表的一條數據,查詢從表的一條數據。也就是查詢該賬戶的擁有人。 account = Account.objects.get(id=2) contact = account.contact.c_name # 根據從表的一條數據,查詢主表的一條數據。也就是查詢這個人的賬戶。 contact = Contact.objects.get(id=2) account = contact.account.a_name return render(request, 'index.html', {'data': account}) def update(request): account = Account.objects.get(id=1) account.a_pwd = '111' account.save() return render(request, 'index.html', {'result': '數據修改成功'}) def delete(request): Account.objects.get(id=1).delete() return render(request, 'index.html', {'result': '數據刪除成功'})
多對多
models.py
from django.db import models # Create your models here. # 多對多:一個表中的一條數據對應另外一個表中的多條數據;另外一個表中的一條數據對應着前一個表中的多條數據; class Publication(models.Model): """ 出版社(主表) """ p_name = models.CharField(max_length=50) class Article(models.Model): """ 文章(從表) """ a_name = models.CharField(max_length=50) pub = models.ManyToManyField(Publication) # 一對多:ForginKey一定要設置在從表。 # 一對一和多對多:關系可以設置在任意一個表中。
views.py
from django.shortcuts import render from .models import * from django.http import HttpResponse # Create your views here. def index(request): # 添加 # 一對一和一對多:先添加主表的數據,再添加從表的數據; # 多對多:先分別添加兩個表的數據,然后再進行關聯; # p1 = Publication(p_name='新華出版社') # p1.save() # p2 = Publication(p_name='東方出版社') # p2.save() # # a1 = Article(a_name='個稅改革') # a1.save() # a2 = Article(a_name='大橋通車') # a2.save() # 關聯文章和出版社的關系 # a1這個文章關聯的出版社是p1和p2,意思就是p1和p2兩個出版社都出版了a1這個文章。 # a1.pub.add(p1, p2) # a2.pub.add(p2) # 查詢: # 1-根據主表數據查詢從表數據; # 查詢 "東方出版社" 出版過的所有文章; p1 = Publication.objects.get(id=2) articles = p1.article_set.all() for article in articles: print(article.a_name) # 2-根據從表數據查詢主表數據; # 查詢 "個稅改革" 這個文章,共有幾個出版社出版; a1 = Article.objects.get(id=1) pubs = a1.pub.all() for p in pubs: print(p.p_name) return HttpResponse('數據添加成功')