day4_关联关系
程序员文章站
2022-03-08 11:54:02
...
模型2
一、关联关系
1、概述
关联关系指的是数据表之间的数据是相互依赖和影响关系,。表之间有从属关系,对数mysql中的表之间的关系。
2、种类
- 一对一
- 一对多
- 多对多
3、Model中的关联关系
OneToOneField(to=关联的类名,on_delete=级联选项) 一对一
ForeignKey(to=关联的类名,on_delete=级联选项) 一对多
ManyToManyField(to=关联的类名) 多对多
4、例子
一对一
class Person(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
class Meta:
db_table="t_person"
class Passport(models.Model):
note = models.CharField(max_length=20)
per = models.OneToOneField(to="Person",on_delete=models.CASCADE,null=True) #关系属性
class Meta:
db_table="t_passport"
一对多
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,unique=True)
price = models.FloatField()
cate = models.ForeignKey(to=Category,on_delete=models.CASCADE) #关系属性
class Meta:
db_table = "t_goods"
多对多
class Student(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
class Meta:
db_table="t_student"
class Course(models.Model):
title = models.CharField(max_length=30)
expire = models.SmallIntegerField()
stu = models.ManyToManyField(to=Student) #关系属性
class Meta:
db_table="t_course"
5、关联关系查询
一对一查询
Person.objects.filter(passport__id=1)#护照的id是1的Person
查主表信息时,直接从表(双下划线) passport__id
Passport.objects.filter(per_id=1) #id为1的person的Passport
查从表信息时,直接用关联对象 per_id=1
保留双方的数据
Person.objects.filter(passport__country='USA').values('id','name','age','passport__country')
一对多查询
查主表
Category.objects.filter(goods__pk__gt=1)#id大于1的商品的类别
查从表
Goods.objects.filter(cate__pk__gte=1) # 类别id大于1的商品
保留双方的数据
Goods.objects.filter(cate__title__contains="s").values("cate__title","pk","price")
cs = Category.objects.all()
gs = Goods.objects.all()
cs[0].goods_set # 没有多方的关系属性,通过"多方类名_set"获得多方
# 此时只是返回一个RelatedManger,不支持遍历和限制获取子集 而且并没有数据,可以调用QuerySet的方法
注意(__set)只是model对象的方法
cs[0].goods_set.filter(price_gt=200)
多对多查询
和一对多一样,先查询一个
stus = Student.objects.all()
stus[0].course_set.filter(title__contains='s') #获得第一个学生的 标题中含有"s"的课程
Student.objects.filter(course__title__contains="h") #标题中含有"h"的课程中的学生
Course.objects.filter(stu__name="zzz") #姓名为zzz的学生参加的课程
6、增加数据
- 为已存在的主表添加从表的数据
# 方式一: 先取某一个类别,再通过该类别创建一个商品
c = Category.objects.get(pk=1) # 获取类别一对象
c.goods_set.create(title = 'abc',price=139.99) # 不需要再save
# 方式二:先取某个类别,单独创建商品并关联类别
c = Category.objects.get(pk=1)
g = Goods.objects.create(title='abc',price=213,cate=c) #为商品的关系属性赋值
# 注意:如果是1:1,则只能使用方式二
- 为不存在的主表添加
c = Category(title="类别1",note="xx")
g = Goods(title="zzz6",price=100)
g.save() #此时,外键的值为null
c.save()
c.goods_set.add(g) #会同步数据库,补充外键值
或
c = Category(title="类别1",note="xx")
c.save()
g = Goods(title="zzz6",price=100,cate9=c)
g.save() #此时,good是有外键值的
#注意如果是1:1只能用第二种
7、删除数据
Goods.objects.get(pk=1).delete()
注意级联选项
参数 | 作用 |
---|---|
CASCADE | 主表删,从表删 |
SET_NULL | 主表删,从表为空 |
PROTECT | 不允许直接删除主表 |
SET_DEFAULT | 删除主表,为从表设置默认值,需要加default |
SET | 同上,不需要default,set() |
DO_NOTHING | 删除主表,从表什么也不做 |
8、修改数据
查找对象,直接对象.属性改,注意得保存
cs = Category.objects.all()
c = cs[0]
c.title="new_title"
c.save()
懒加载Lazy-load
QuerySet在查询数据时,是延迟执行,直到真正使用了数据,才发起查询
- 测试方式
找到mysql的安装目录下的my.ini文件,添加配置:
# SERVER SECTION
[mysqld]
.....
log = "E:/mysql_log.log" #设置日志文件,记录sql语句执行
或
general-log=1
general_log_file=E:/mysql_log.log 安装目录
#需要重启Mysql服务 net stop/start mysql
上一篇: postgresql是什么?
推荐阅读
-
mysql中如何将几个没有关系的结果集放在一起_MySQL
-
请问关于PHP中关联多表相关字段,并做分页处理的SQL语句写法
-
thinkphp四级关联查询如何写
-
ThinkPHP采用原生query实现关联查询left join实例
-
Mybatis动态sql、if与where的使用、sql片段、foreach遍历、Mybatis的关联查询一对一、一对多、多对多、Mybatis的延时加载
-
np.ogrid(),np.mgrid()和meshgrid()函数的关系
-
fireworks怎么调整图形上下层关系?
-
Eloquent ORM 查询数据的关联扩展
-
PHP和cms的关系
-
JavaScript 以对象为索引的关联数组_javascript技巧