一、一对一关系
1、我们在models中创建一个新的模型,叫做StudentInfo
点击查看代码
class StudentInfo(BaseModel):
"""学生信息附加表"""
address = models.CharField(max_length=255,verbose_name="家庭地址")
# 当设置字段为外键时,ORM会自动根据当前外键属性名拼接上_id作为数据表中的字段名
# 例如,外键为student,则数据表中的真是字段名为student_id
student = models.OneToOneField(Student,related_name="info",on_delete=models.DO_NOTHING,verbose_name="外键")
class Meta:
db_table = 'db_student_info'
verbose_name = "学生信息附加表"
verbose_name_plural = verbose_name
# 3.模型操作方法
def __str__(self):
return f'<UserInfo {self.student.name}>'
2、在视图中创建一个新的类,RelationView,记得去绑定路由
点击查看代码
from .models import StudentInfo
class RelationView(View):
"""关联查询:通过表与表之间的关系进行数据库连接,这个在ORM中叫关联查询"""
def get(self,request):
"""
1.一对一关系:主表中的一条记录,在从表中只对应最多一条记录,同理,附加表中的一条记录最多对应主表中的一条记录
用户表和用户附加表,商品表和商品详情表......
"""
# 添加测试数据
# 1.直接从数据库层面设置id的数值
# student_info = StudentInfo.objects.create(student_id=2,address="北京市中心广场")
# print(student_info)
# 2.直接按主模型添加
# student = Student.objects.get(pk=5)
# student_info = StudentInfo.objects.create(student=student,address = "北京市")
# print(student_info)
"""关联查询"""
# 正向查询,从Student---->StudentInfo方向查询
# student = Student.objects.get(pk=2)
# # 在外键中声明了related_name的情况下使用related_name的值可以直接获取外键对象
# print(student.info)
# print(student.info.address)
# 逆向查询,从StudentInfo--->Student方向
# student_info = StudentInfo.objects.get(pk=2)
# print(student_info.student.name)
"""更新和删除"""
# 先获取主模型,然后从主模型中获取附加模型对象,通过附加模型对象修改数据
# student = Student.objects.get(pk=2)
# print(student.info.address)
# # 修改操作
# student.info.address = "山西省"
# student.info.save()
# student = Student.objects.get(pk=2)
# print(student.info.address)
# 先获取附加模型,然后通过附加模型获取主模型对象,通过主模型对象修改数据
# student_info = StudentInfo.objects.get(pk=2)
# print(student_info.student.age)
# student_info.student.age = 20
# student_info.student.save()
# print(student_info.student.age)
"""删除操作"""
# 先删外键对应的记录,然后删除主键对应的记录
# student_info = StudentInfo.objects.filter(student_id=2).first() # on_delete=Do_NOTHING
# student_info.delete()
# student = Student.objects.get(pk=4)
# student.delete()
return HttpResponse("ok")
二、一对多关系
3、我们再创建一个模型
点击查看代码
class Achievement(BaseModel):
"""成绩表"""
# ForeignKey 一对多
student = models.ForeignKey(Student,related_name="score_list",on_delete=models.DO_NOTHING,verbose_name="外键",null=True)
# max_digits 总数值长度,不包含小数点
# decimal_places 小数位数的字符最多允许有几个
score = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="成绩")
class Meta:
db_table = 'db_student_achievement'
verbose_name = "学生成绩表"
verbose_name_plural = verbose_name
# 3.模型操作方法
def __str__(self):
return f'<UserInfo {self.student.name}>'
4、在视图中写一个视图
点击查看代码
from .models import Achievement
class RelationView(View):
def get(self,request):
"""
1对多:主表的一条记录,在表中只对应一条或多条记录,同理,附加表中的一条记录最多对应主表中的一条记录
表达的是业务中的一种从属关系
用户表和用户附加信息表,商品表和商品详情表,文章表和文章详情表
"""
"""添加数据"""
# student = Student.objects.get(pk=2)
# print(student.score_list) # 等同于 Achievement.objects
# print(student.score_list.all()) # 等同于 Achievement.objects.filter(student_id=2).all()
# student.score_list.create(student=student,score=66)
"""查询数据"""
# 正向查找
# student = Student.objects.get(pk=2)
# score_list = student.score_list.values()
# print(score_list)
# 不设置related_name,可以基于"外键模型小写_set"来获取外键模型
# student = Student.objects.get(pk=2)
# score_list = student.achievement_set.values()
# print(score_list)
# 反向查找
# achi = Achievement.objects.get(pk=3)
# print(achi.student)
# print(achi.score)
"""更新和删除数据,它们只能通过模型来完成"""
# 删除
# student = Student.objects.get(pk=2)
# score_list = student.score_list.all()
# for score in score_list:
# score.delete()
# 更新
# student = Student.objects.get(pk=2)
# # 遍历或者下标操作都可以
# score_list = student.score_list.first()
# score_list.score = 20
# score_list.save()
return HttpResponse("ok")
三、多对多关系
5、我们再在模型中创建两个模型
点击查看代码
class Teacher(models.Model):
name = models.CharField(max_length=15,verbose_name="老师")
class Meta:
db_table = "db_teacher"
verbose_name = "老师信息表"
verbose_name_plural = verbose_name
class Course(models.Model):
name = models.CharField(max_length=15,verbose_name="课程")
# 多对多,外键不需要设置on_delete属性
# 老师授课的课程:teacher.course_list
# 课程授课的老师:course.teacher_list
teacher_list = models.ManyToManyField(Teacher,related_name = "course_list")
class Meta:
db_table = "db_course"
verbose_name = "课程信息表"
verbose_name_plural = verbose_name
6、在视图中创建一个视图
点击查看代码
from .model import Course,Teacher
class RelationView(View):
def get(self,request):
"""
范式理论:
第一范式:不能有重复的属性
第二范式:必须唯一
第三范式:不能冗余
多对多:A表中的一条记录,在B表中有对应的信息表,反之,B表中的一条记录也可以在A表中找到多个对应的记录
课程和学生的之间关系,好友与好友之间关系,读者和文章之间的关系,购买者和商品之间的关系......
"""
"""添加数据"""
# teacher1 = Teacher.objects.create(name="龙老师")
# teacher2 = Teacher.objects.create(name="林老师")
# teacher3 = Teacher.objects.create(name="李老师")
# teacher4 = Teacher.objects.create(name="程老师")
#
# course1 = Course.objects.create(name="Python初级")
# course2 = Course.objects.create(name="Python中级")
# course3 = Course.objects.create(name="Python高级")
# 通过老师添加课程,反过来也是类似
# teacher = Teacher.objects.get(pk=1)
# 此处不仅可以添加课程,而且我们还可以完成老师和课程之间的绑定
# teacher.course_list.create(name="javascript入门")
# 添加已存在的课程信息渝老师绑定关系
# course = Course.objects.get(pk=3)
# teacher.course_list.add(course)
"""查找数据"""
# 查询老师授课的课程
# teacher = Teacher.objects.filter(name="龙老师").first()
# print(teacher.course_list.values())
# 查询课程的授课老师都有谁
# course = Course.objects.get(pk=3)
# print(course.teacher_list.values())
"""更新删除数据"""
# 当希望删除两个模型之间的一条关联关系时,我们使用remove
# course = Course.objects.get(pk=3)
# teacher = Teacher.objects.filter(name="龙老师").first()
# course.teacher_list.remove(teacher)
# 当希望删除两个模型之间的全部关联关系时,我们使用clear
# 删除对应模型的单个模型就调用单个模型对象来完成
return HttpResponse("ok")
7、创建一个新的模型:
点击查看代码
class Area(models.Model):
"""行政区划"""
name = models.CharField(max_length=20)
parent = models.ForeignKey("self",related_name="son_list",null=True,on_delete=models.DO_NOTHING)
class Meta:
db_table = "db_area"
verbose_name = "行政区划表"
verbose_name_plural = verbose_name
def __str__(self):
return f'<UserInfo {self.student.name}>'
8、创建一个新视图,请自行尝试
点击查看代码
from .models import Area
class RelationView(View):
def get(self,request):
"""自关联"""
# 查询顶级单位
province_list = Area.objects.filter(parent_id__isnull=True).all()
print(province_list)
province = province_list.filter(name="河南省").first()
print(province)
city_list = province.son_list.all()
print(city_list)
city = city_list.filter(name="郑州市").first()
print(city)
area_list = city.son_list.all()
print(area_list)
area = area_list[0]
print(area)
return HttpResponse("ok")