django 模型层
Posted angle6-liu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django 模型层相关的知识,希望对你有一定的参考价值。
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="北京")
1 一对一
# 添加一对一关系记录方式一 models.Author.objects.create(name=‘alex‘,age=‘8‘,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=‘[email protected]‘) 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)
反向:表名小写
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)
给关联表添加记录的方法
#以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="151") .values_list("title","publish__name") # 方式2: ret=Author.objects .filter(authordetail__telephone__startswith="151") .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"
(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 模型层的主要内容,如果未能解决你的问题,请参考以下文章