模型02
一、关联关系
1、概述
关联关系指的是数据表之间的数据是相互依赖和影响,表之间有从属关系。比如:有一个用户表,用户又有一个订单表,用户表和订单表之间有就从属关系。
# 部门表和员工表
# 部门表:
部门id 部门名称 部门的职责
id title note
1 教学部 日常教学
2 品保部 学生管理Mrs.king
# 员工表:
员工id 员工姓名 年龄 薪水 所在的部门的id
id name age salary dept_id
1 Tom 18 3000 1
# 员工表和部门表之间存在关联关系 MySQL中通过外键来搭建(加强)两个表之间的关系
# foreign key(dept_id) references t_department(id) -- 人和狗
2、关联关系的种类
1. 一对一
一个人一本护照
2. 一对多
一个部门有多个员工
3. 多对多
一个学生有多门课,一门课有多个学生
3、Model类中的关联关系
在ORM中搭建关联关系-使用外键
在ORM中所有的表都是通过Model产生的,要让表与表之间有关联关系,此时就需要让Model类之间产生关联
class Department(models.Model):
xxx
class Employee(models.Model):
xxx
# dept_id -> 声明为类中的属性,同时要把它作为外键
dept_id = models.ForeignKey()
# 1. ForeignKey(to=对方的类名,on_delete=models.CASCADE) -- 一对多
# 2. OneToOneField(to=对方的类名,on_delete=models.CASCADE) -- 一对一
# 3. ManyToManyField(to=对方的类名) -- 多对多 没有删除选项
二、关联关系Model类的搭建
1、一对多
1:*
class Category(models.Model):
title = models.CharField(max_length=20)
note = models.CharField(max_length=20)
class Meta:
db_table = 't_category'
class Goods(models.Model):
title = models.CharField(max_length=20)
price = models.FloatField()
cate = models.ForeignKey(to=Category,on_delete=models.CASCADE)
class Meta:
db_table = 't_goods'
2、一对一
1:1
class Person(models.Model):
name = models.CharField(max_length=20)
age = models.SmallIntegerField()
class Meta:
db_table = 't_person'
class Passport(models.Model):
country = models.CharField(max_length=20)
expire = models.SmallIntegerField()
per = models.OneToOneField(to=Person,on_delete=models.CASCADE)
class Meta:
db_table = 't_passport'
3、多对多
*:*
class Student(models.Model):
name = models.CharField(max_length=20)
age = models.SmallIntegerField()
class Meta:
db_table = 't_student'
class Course(models.Model):
title = models.CharField(max_length=20)
duration = models.SmallIntegerField()
stu = models.ManyToManyField(to=Student)
class Meta:
db_table = 't_course'
三、关联关系的查询
1、一对一查询
ps = Person.objects.all()
print(ps)
ps = Person.objects.filter(age__gt=18).values()
print(ps)
pts = Passport.objects.all()
print(pts)
pt = Passport.objects.get(country='中国')
print(pt.per)
pn = Person.objects.get(name='Tom')
print(pn.passport)
pn = Person.objects.filter(passport__country='中国').values()
print(pn)
pt = Passport.objects.filter(per__name='Tom').values()
print(pt)
pn = Person.objects.filter(passport__country='中国').values('id','name','age','passport__id','passport__country','passport__expire')
print(pn)
pt = Passport.objects.filter(country='中国').values('id','country','expire','per__name','per__age')
print(pt)
pt = Passport.objects.filter(per__name='Tom').values('id','country','expire','per__name','per__age')
print(pt)
pn = Person.objects.filter(name='Tom').values('id','name','age','passport__country','passport__expire')
print(pn)
2、一对多查询
cs = Category.objects.values()
print(cs)
gs = Goods.objects.values()
print(gs)
g = Goods.objects.get(title='电视')
print(g.cate)
c = Category.objects.get(title='家电')
print(c.goods_set)
print(c.goods_set.all())
print(c.goods_set.values())
c = Category.objects.filter(goods__title='电视')
print(c)
g = Goods.objects.filter(cate__title='家电')
print(g)
result = Category.objects.filter(goods__title='电视').values('title','note','goods__title','goods__price')
print(result)
result = Goods.objects.filter(title='电视').values('title','price','cate__title','cate__note')
print(result)
result = Goods.objects.filter(cate__title='家电').values('title','price','cate__title','cate__note')
print(result)
result = Category.objects.filter(title='家电').values('title','note','goods__title','goods__price')
print(result)
# 查询商品价格大于5000的分类信息 -- 会出现重复的数据 cs = Category.objects.filter(goods__price__gt=5000) print(cs) print(set(cs)) # 去重 print(list(set(cs)))
3、多对多查询
四、增删改操作
1、增加数据
# 1. 增加主表方数据 (和单表增加无差异) c = Category(title='水果',note='含水分和糖分较多的植物果实') c.save()# 2. 添加从表方数据 情况一: 为已存在的主表附加从表数据 - 方式一:使用等号关联 c = Category.objects.get(title='水果') Goods.objects.create(title='苹果',price=6.88,cate=c) - 方式二:将新的商品添加到分类的商品集里 c = Category.objects.get(title='水果') g = Goods.objects.create(title='香蕉',price=3.3) # 要允许外键为空 -- cate属性可以为空 c.goods_set.add(g) - 方式三:使用商品集的manager调用create创建一个新的商品 c = Category.objects.get(title='水果') c.goods_set.create(title='梨',price=3) 情况二: 同时添加主从数据 也分三种方式,就是主表数据create创建出来,而不是get获取 c = Category.objects.create(title='生鲜',note='xxx') c.goods_set.create(title='虾',price=30)
2、删除数据
# 1. 删除从表数据(和单表无差异) g = Goods.objects.get(title='虾') g.delete()# 2. 删除主表数据 删除主表数据,需要看从表方的级联(删除)设置 - on_delete 删除选项: - (1)models.CASCADE 级联删除:删除主表数据时,从表数据一起被删除 - (2)model.SET_NULL 外键置空:删除主表数据时,将从表的外键置空NULL(需要允许外键为空) - (3)models.SET_DEFAULT 设置为默认值:当删除主表数据时,将从表的外键置为默认值(需要添加一个default参数 default=100 100必须是一个合法/存在的值) - (4)models.SET(值) 设置为某个值:当删除主表数据时,将外键设置为该值(不需要配合default使用) - (5)models.PROTECT 不允许删除主表数据 - (6)models.DO_NOTHING django什么也不做,由数据库来决定是否合法 -- 一般不用
3、修改数据
1. 先获取某个数据-主表或从表 g = Good.objects.get(title='电视')2. 给属性赋值 g.price = 68003. 保存到数据库 g.save() # 修改主和修改从是一样
五、懒加载Lazy-load
QuerySet在查询数据时,是延迟执行,只有真正用到了数据,才会发起查询 ps = Person.objects.all() # 查询所有人的信息,但实际上它并没有执行select print(ps) # 验证方法: 给mysql配置日志文件1. 找到mysql的安装目录下的my.ini文件2. 在[mysqld]的下面添加如下配置: log='D:/mysql.log'3. 重启mysql服务 方式一:任务管理器的服务中,找到mysql右键重启 方式二:使用管理员身份打开cmd,执行net stop mysql 和 net start mysql
作业:
练习上课代码 周一上来写代码