django 模型层(2)
Django 模型层(2)
多表操作---模型之间的关系
- 1 一对一:作者----作者详细信息
- 2 一对多:书籍----出版社
- 3 多对多:书籍----作者
一 创建模型(主键(id)自动创建)
没有任何关系的一张表的创建
- class Emp(models.Model):
- name=models.CharField(max_length=32)
- age=models.IntegerField()
- salary=models.DecimalField(max_digits=8,decimal_places=2)
- dep=models.CharField(max_length=32)
- province=models.CharField(max_length=32)
单独一张表对应的模型类
1 一对一 OneToOneField
- models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)
参数to:表示与AuthorDetail绑定一对一关系
参数 null=True:表示允许为空;
参数on_delete:级联删除,表示当一对一关系的一方数据被删除了,其对应关系也删除了
- class Author(models.Model):
- '''
- ...其他字段省去
- '''
- # 作者与authordetail建立一对一关系
- authordetail=models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)
2一对多 ForeignKey (在多的一方(Book)绑定)
- 基本书写格式:
ForeignKey(to='被关联的表名’,null=True,on_delete=models.CASCADE)
- class Book(models.Model):
- '''
- 。。。
- '''
- # 创建一对多的关系:一个出版社可以对应多本书
- publish = models.ForeignKey(to='Publish', null=True, on_delete=models.CASCADE)
3 多对多 ManyToMany
注意:
1 自动创建关系表book_author;
- authors = models.ManyToManyField(to='Author')
- class Book(models.Model):
- '''
- ...
- '''
- # 书籍与作者创建多对多的关系
- authors = models.ManyToManyField(to='Author')
- from django.db import models
- # Create your models here.
- # 关系户:书籍------作者 多对多
- # 书籍------出版社 一对多
- # 作者------作者详细信息 一对一
- class Book(models.Model):
- '''
- 创建书籍表
- '''
- title = models.CharField(max_length=32)
- pub_date = models.DateField()
- price = models.DecimalField(max_digits=5, decimal_places=2)
- # 创建一对多的关系:一个出版社可以对应多本书
- publish = models.ForeignKey(to='Publish', null=True, on_delete=models.CASCADE)
- # 书籍与作者创建多对多的关系
- authors = models.ManyToManyField(to='Author')
- def __str__(self):
- return self.title
- class Publish(models.Model):
- '''
- 创建出版社表
- '''
- name = models.CharField(max_length=32)
- city = models.CharField(max_length=32)
- email = models.EmailField()
- def __str__(self):
- return self.name
- class Author(models.Model):
- '''
- 创建作者表
- '''
- name=models.CharField(max_length=32)
- age=models.IntegerField()
- # 作者与authordetail建立一对一关系
- authordetail=models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)
- def __str__(self):
- return self.name
- class AuthorDetail(models.Model):
- '''
- 创建作者详细信息表
- '''
- birthday=models.DateField()
- telephone=models.BigIntegerField()
- addr=models.CharField(max_length=64)
- def __str__(self):
- return self.addr
创建表模型类的完整代码
4 数据迁移
方法一
- python manage.py makemigrations
- python manage.py migrate
数据迁移代码
方法二
pycharm 中快捷启动方式
5 创建的表结果
二 添加记录
单表添加数据的两种基本方式
- models.AuthorDetail(id=1,birthday="1995-12-12",telephone=110,addr="北京")
方式一(类的是实例化)
- obj=models.AuthorDetail.objects.create(birthday="1995-12-12",telephone=110,addr="北京")
方式二(模型类objects管理器下的create方法)
1 一对一
- # 添加一对一关系记录方式一
- models.Author.objects.create(name='alex',age='',authordetail_id=1)
- # 添加一对一关系记录方式二
- wusir_d = models.AuthorDetail.objects.create(birthday="1999-8-12", telephone=666, addr="上海")
- wusir=models.Author.objects.create(name='wusir',age=18,authordetail=wusir_d) #接收记录对象
2 一对多
- # 绑定方式一
- python=models.Book.objects.create(title='python',pub_date='2015-10-8',price=120,publish_id=1)
- # 绑定方式二
- strawberry=models.Publish.objects.create(name='草莓出版社',city='武汉',email='999@eee')
- go=models.Book.objects.create(title='go',pub_date='2014-12-9',price=150,publish=strawberry)
3 多对多(如何给关系表添加数据)
正向:找关联属性
- # 正向绑定用字段 书籍找关系表通过Author属性
- python=models.Book.objects.filter(title='python').first()
- go=models.Book.objects.filter(title='go').first()
- alex=models.Author.objects.filter(name='alex').first()
- egon=models.Author.objects.filter(name='egon').first()
- print(python,alex,egon)
- print(python.publish.city)
给python书籍绑定两个作者信息
反向:表名小写
- linux = models.Book.objects.filter(title="linux").first()
- R = models.Book.objects.filter(title="R").first()
- wusir = models.Author.objects.filter(name="wusir").first()
- wusir.book_set.add(linux,R)
给egon绑定两本书
给关联表添加记录的方法
- #以python书籍对象为例
- python.authors.remove(alex)#移除作者信息 alex
- python.authors.clear() #清空作者信息
- python.authors.add(作者对象1,作者对象2) #添加作者信息
- python.authors.add(1,2) #添加作者信息
- python.authors.set([ 1,]) #先清空后设置值
关联表的方法
二 基于对象的跨表查询 ********
- 方法总结
- 正向查询:按照关系字段
- 对象1 -----------------------------------------> 对象2
- <----------------------------------------
- 反向查询:按照表名小写_set.all()
- 是否需要_set取决于结果的个数,
- 多个结果加_set.all()
1 一对一
- # 正向制作者--->作者详细信息
- #alex---->电话号码
- # alex=models.Author.objects.filter(name='alex').first()
- # result=alex.authordetail.telephone
正向查询
- # 反向查询作者<----作者详细信息
- #tel=110的作者是谁
- # ad=models.AuthorDetail.objects.filter(telephone=110).first()
- # result=ad.author.name
反向查询
2 一对多
- # 查询linux这本书籍的出版社信息地址(正向查询)
- linux=models.Book.objects.filter(title='linux').first()
- result=linux.publish.city
正向查询
- # 反向查询(出版社--->书籍)
- # 查询橘子出版社出版过的所有书籍
- publish=models.Publish.objects.filter(name='橘子出版社').first()
- print(publish)
- result=publish.book_set.all()
- print(result) #<QuerySet [<Book: java>]>
- for i in result:
- print(i.title)
反向查询
3 多对多
三 基于双下划线的跨表查询
- 模型类.objects.filter().values()
- 1 跨表操作在filter 和values使用__(双下划线)进行跨表操作;
- 2 正向查询按关联字段,反向查询按照表名小写;
1 一对一
- # 查询alex的手机号
- # 正向查询
- ret=Author.objects.filter(name="alex").values("authordetail__telephone")
- # 反向查询
- ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
2 一对多
- # 练习: 查询苹果出版社出版过的所有书籍的名字与价格(一对多)
- # 正向查询 按字段:publish
- queryResult=Book.objects
- .filter(publish__name="苹果出版社")
- .values_list("title","price")
- # 反向查询 按表名:book
- queryResult=Publish.objects
- .filter(name="苹果出版社")
- .values_list("book__title","book__price")
3 多对多
- # 练习: 查询alex出过的所有书籍的名字(多对多)
- # 正向查询 按字段:authors:
- queryResult=Book.objects
- .filter(authors__name="yuan")
- .values_list("title")
- # 反向查询 按表名:book
- queryResult=Author.objects
- .filter(name="yuan")
- .values_list("book__title","book__price")
4 进阶练习(连续跨表)
- # 练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名
- # 正向查询
- queryResult=Book.objects
- .filter(publish__name="人民出版社")
- .values_list("title","authors__name")
- # 反向查询
- queryResult=Publish.objects
- .filter(name="人民出版社")
- .values_list("book__title","book__authors__age","book__authors__name")
- # 练习: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
- # 方式1:
- queryResult=Book.objects
- .filter(authors__authorDetail__telephone__regex="")
- .values_list("title","publish__name")
- # 方式2:
- ret=Author.objects
- .filter(authordetail__telephone__startswith="")
- .values("book__title","book__publish__name")
双下划线跨表跨表巩固
四 聚合查询于分组
- emp-dep:
- id name age salary dep_id id name
- 1 alex 12 2000 1 1 销售部
- 2 egon 22 3000 2 2 人事部
- 3 wen 22 5000 2 2 人事部
- class Emp(models.Model):
- name=models.CharField(max_length=32)
- age=models.IntegerField()
- salary=models.DecimalField(max_digits=8,decimal_places=2)
- dep=models.CharField(max_length=32)
- province=models.CharField(max_length=32)
1 聚合 (aggregate) ---聚合函数 Sav, Max, Min, Avag
- 基本语法:
- 模型类.objects.aggregate(聚合函数( 字段 ))
结果:queryset类型,一个对象一个字典保存数据
- 实例1:
- # 计算所有图书的平均价格
- from django.db.models import Avg
- Book.objects.all().aggregate(Avg('price')) # {'price__avg': 34.35}
- 实例2:
- from django.db.models import Avg, Max, Min
- Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
- #{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
2 分组(annotate)
- key:
- 跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。
- 语法格式:
- (1)模型类.objects.all().value('分组条件').annotate('聚合函数')
- 结果是queryset对象,其中元素是字典
- <QuerySet [{..},{...}]>
- (2)模型类.objects.all().annotate('聚合函数') #以主键分组
- 结果是queryset对象,其中元素是对象
- #<QuerySet [<Book: java>,<Book: java>]>
3 练习
(1)统计每个出版社的最便宜的书
- publish_list=models.Publish.objects.annotate(min("book_price"))
- for publish_obj in publish_list:
- print(publish_obj.name,publish_obj.MinPrice)
- 简化代码:
- queryResult= Publish.objects
- .annotate(MinPrice=Min("book__price"))
- .values_list("name","MinPrice")
- print(queryResult)
- SELECT "app01_publish"."name", MIN("app01_book"."price") AS "MinPrice" FROM "app01_publish"
- LEFT JOIN "app01_book" ON ("app01_publish"."nid" = "app01_book"."publish_id")
- GROUP BY "app01_publish"."nid", "app01_publish"."name", "app01_publish"."city", "app01_publish"."email"
对应mysql语句
(2)统计每本书的作者个数
- models.Book.objects.annotate(authorsNum=Count('authors'))#待会检测
(3)统计每一本以py开头的书籍的作者个数
- models.Book.objects.filter(title_startswith='py')
.annocate(num_authors=Count('authors')
.values('title','c')
(4)统计不止一个作者的图书
- models.Book.objects
- .annocate( num_authors=Count('author'))
- .filter(num_authors__lg=1)
(5)根据一本图书作者数量的多少对查询集 QuerySet进行排序
- models.Book.objects
- .annotate(num_authors=Count('authors'))
- .order_by('num_authors')
(6)查询各个作者出的书的总价格
- models.author.objects
- .annotate(sum_price=sum('book__price'))
- .values('name','sum_price')
五 F查询与Q 查询
1 F查询 ---- F('字段名')
(1) 意义
- 1 在过滤条件中借助F查询,使得字段之间可以作比较;
- 2 在过滤条件中借助F查询,使得字段之间可以做四则运算;
(2) 字段之间的比较实例
- # 查询评论数大于收藏数的书籍
- from django.db.models import F
- models.objects.filter(commentNum__lg=F('keepNum'))
(3) 四则运算在过滤条件中的应用
- # 查询评论数大于收藏数2倍的书籍
- from django.db.models import F
- models.Book.objects.filter(commerntNum__lg=F('keepNum')*2)
- #修改操作也可以使用F函数,比如将每一本书的价格提高30元:
- models.Book.objects.update(price=F('price)+30)
2 Q 查询 ---- Q('字段名')
(1) 意义
- 使得过滤条件的方式不再是单一的 & (与)运算
- Q查询中的与|或|非
- 与: &
- 或: |
- 非: ~
(2)查询价格大于300或者名称以p开头的书籍 ( | 或运算)
- queryset=models.Book.objects.filter(price__lg=300|Q(title__startswith='p')).values('title')
(3)查询价格大于300或者不是2019年一月份的书籍
- models.Book.objects.filter(title__lg=300|~Q(Q(pub_date_year=2016)&Q(pub_date_mouth=1)))
django 模型层(2)的更多相关文章
- Django模型层(2)
<!DOCTYPE html><html lang="zh-cn"><head><meta charset="utf-8&quo ...
- {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...
- Django模型层之ORM
Django模型层之ORM操作 一 ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...
- Django模型层之单表操作
Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...
- Django模型层之更多操作
Django模型层之更多操作 一 .ORM字段 1.1 常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为 ...
- Django模型层(各种表及表数据的操作)
目录 一.Django模型层 0. django模型层的级联关系 1. 配置django测试脚本 (1)方式一 (2)方式二 2. orm表数据的两种增删改 (1)方式一: (2)方式二: 3. pk ...
- day 70 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- day 69 Django基础五之django模型层(一)单表操作
Django基础五之django模型层(一)单表操作 本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现 ...
- day 57 Django基础五之django模型层之关联管理器
Django基础五之django模型层之关联管理器 class RelatedManager "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器.它存在于下面两种情况 ...
随机推荐
- 【朝花夕拾】Android性能篇之(三)Java内存回收
在上一篇日志([朝花夕拾]Android性能篇之(二)Java内存分配)中有讲到,JVM内存由程序计数器.虚拟机栈.本地方法栈.GC堆,方法区五个部分组成.其中GC堆是一块多线程的共享区域,它存在的作 ...
- Android--拦截系统BroadcastReceiver
前言 上一篇博客,讲了BroadcastReceiver的一些基础内容,如何注册以及发送一个广播,那是基础,不清楚的可以先看看:Android--BroadcastReceiver.但是在实际开发当中 ...
- EF架构~Dapper.Contrib不能将Linq翻译好发到数据库,所以请不要用它
回到目录 对于Dapper是一个轻量级的数据访问框架,而需要使用者去自己做SQL,它,只是一个数据访问者! 对些,Dapper推出了Contrib扩展包,它可以友好的让开发人员使用linq,而不需要写 ...
- 阿里云Ubuntu安装图形界面与中文语言包
图形界面: http://blog.csdn.net/qq_37608398/article/details/78155568?locationNum=9&fps=1 安装中文: http:/ ...
- iOS逆向开发(8):微信自动添加好友
这一次,小程演示怎么让一个APP自动地运行,从而代替手工的操作.同样以"微信"以例,实现在一个微信群里面,对所有的成员,自动地一个一个地发出添加好友的请求. 知识点还是之前介绍的东 ...
- vue实用组件——圆环百分比进度条
因为所在公司临近年底突然宣布Game Over,导致我等小码农又要踏上一个艰辛的求职道路了.才眨眼功夫,年就过完了,快乐的时光总是很匆忙呀. 开年的第一个面试,面试官问我会不会自己写一个圆环进图圈,这 ...
- https 加密、http2.0、keep-alive
原文地址:https://ainyi.com/44 HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议 ...
- jquery父元素和子元素点击事件传递问题_不可把父元素的事件传递给子元素_事件无限循环传递
前述:jquery中: 当一个元素的点击事件被触发时,会自动将该事件向父级元素逐级专递. 但是实际场景当中,我们可能会遇到需要在父级元素中定义点击事件,来触发特定子元素的点击事件,我就遇到了这么一个问 ...
- 从零开始学安全(三十八)●cobaltstrike生成木马抓肉鸡
链接:https://pan.baidu.com/s/1qstCSM9nO95tFGBsnYFYZw 提取码:w6ih 上面是工具 需要java jdk 在1.8.5 以上 实验环境windows ...
- 【eclipse】eclipse报错:the resource is not on the build path of a java project
最近在eclipse中,使用svn导入svn上的一个maven项目,但是导入后类的包并没有以源码包的方式显示,而是以普通文件包的方式显示出来,在对类进行F3等操作时就报错:“the resource ...