Django Model层关联关系

模型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、一对一查询
# 1. 单独查询一方的数据(单表查询)
# (1)查询所有人的信息
	ps = Person.objects.all()
	print(ps)
# 查询年龄大于18的人的信息
	ps = Person.objects.filter(age__gt=18).values()
	print(ps)
# (2)查询所有的护照的信息
	pts = Passport.objects.all()
	print(pts)


# 2. 通过一方查询另一方
#(1)查询护照为中国的人的信息 -- 通过护照找人
	pt = Passport.objects.get(country='中国')
	print(pt.per)               # 类中有对方的属性时,直接`.该属性`即可

#(2)查询Tom的护照信息 -- 通过人找护照
	pn = Person.objects.get(name='Tom')
	print(pn.passport) # 如果在类中没有对方属性时,直接通过`.对方类名小写`即可


# 3. 通过一方查询另一方(加查询条件)
#(1)查询护照为中国的人的信息 -- 通过护照找人
	pn = Person.objects.filter(passport__country='中国').values()
	print(pn)

#(2)查询Tom的护照信息 -- 通过人找护照
	pt = Passport.objects.filter(per__name='Tom').values()
	print(pt)


# 4. 保留双方数据
#(1)查询护照为中国的人的信息和护照信息
	# 用人发起查询,条件为对方
	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)

#(2)查询Tom的护照信息和人的信息
	# 用护照发起查询,条件为对方
	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、一对多查询
# 1. 单独查询一方的数据(单表查询)
# (1)查询所有的分类信息
	cs = Category.objects.values()
	print(cs)

#(2)查询所有的商品信息
	gs = Goods.objects.values()
	print(gs)
 

 
# 2. 通过一方查询另一方
# (1)查询电视的分类信息
	g = Goods.objects.get(title='电视')
	print(g.cate)

#(2)查询分类为家电的商品信息
	c = Category.objects.get(title='家电')
	print(c.goods_set) #类型为Manager
	print(c.goods_set.all())
	print(c.goods_set.values())
 
# 3. 通过一方查询另一方(加查询条件)
# (1)查询电视的分类信息
	c = Category.objects.filter(goods__title='电视')
	print(c)

#(2)查询分类为家电的商品信息
	g = Goods.objects.filter(cate__title='家电')
	print(g)
 

# 4. 保留双方数据
# (1)查询电视的分类信息和商品信息
	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)

#(2)查询分类为家电的商品信息和分类信息
	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)查询所有的学生信息	stus = Student.objects.all()	print(stus)#(2)查询所有的课程信息	cs = Course.objects.all()	print(cs)# 2. 通过一方查询另一方# (1)查询选择了Python的学生信息	c = Course.objects.get(title='Python')	print(c.stu.all())#(2)查询Jack所选的课程信息	s = Student.objects.get(name='Jack')	print(s.course_set.all())# 3. 通过一方查询另一方(加查询条件)# (1)查询选择了Python的学生信息	stus = Student.objects.filter(course__title='Python')	print(stus)#(2)查询Jack所选的课程信息	cs = Course.objects.filter(stu__name='Jack')	print(cs)# 4. 保留双方数据# (1)查询选择了Python的学生信息和课程信息	result = Student.objects.filter(course__title='Python').values('name','age','course__title','course__duration')	print(result)	result = Course.objects.filter(title='Python').values('title','duration','stu__name','stu__age')	print(result)#(2)查询Jack所选的课程信息和学生信息	result = Course.objects.filter(stu__name='Jack').values('title','duration','stu__name','stu__age')	print(result)	result = Student.objects.filter(name='Jack').values('name','age','course__title','course__duration')	print(result)

四、增删改操作

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
作业:
练习上课代码   周一上来写代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值