欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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