一对多
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 renderfrom django.views.generic import Viewfrom .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 renderfrom .models import Account, Contactfrom datetime import datetimedef 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 renderfrom .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('数据添加成功')