python框架django书籍_【2020Python修炼记】web框架之 Django的ORM语法
【目录】
一、单表查询(增删改查)
二、常见的十几种查询方法
三、神奇的双下划线查询
四、外键字段的增删改查
五、跨表查询(重点)
(一)子查询
(二)联表查询
六、聚合查询
七、分组查询
八、F与Q查询
九、Django中如何开启事务
十、orm中常用字段及参数
十一、数据库查询优化 (only与defer、select_related与prefetch_related)
一、单表查询(增删改查)
#django自带的sqlite3数据库对日期格式不是很敏感 处理的时候容易出错#增
#res = models.User.objects.create(name='jason',age=18,register_time='2002-1-21')
#print(res)
#import datetime
#ctime = datetime.datetime.now()
#user_obj = models.User(name='egon',age=84,register_time=ctime)
#user_obj.save()
#删
#res = models.User.objects.filter(pk=2).delete()
#print(res)
"""pk会自动查找到当前表的主键字段 指代的就是当前表的主键字段
用了pk之后 你就不需要指代当前表的主键字段到底叫什么了
uid
pid
sid
..."""
#user_obj = models.User.objects.filter(pk=1).first()
#user_obj.delete()
#修改
#models.User.objects.filter(pk=4).update(name='egonDSB')
#user_obj = models.User.objects.get(pk=4)
#user_obj = models.User.objects.filter(pk=6)
"""get方法返回的直接就是当前数据对象
但是该方法不推荐使用
一旦数据不存在该方法会直接报错
而filter则不会
所以我们还是用filter"""
#user_obj.name = 'egonPPP'
#user_obj.save()
二、常见的十几种查询方法
(一)必知必会13条
#必知必会13条
#1.all() 查询所有数据
#2.filter() 带有过滤条件的查询
#3.get() 直接拿数据对象 但是条件不存在直接报错
#4.first() 拿queryset里面第一个元素
#res = models.User.objects.all().first()
#print(res)
#5.last()
#res = models.User.objects.all().last()
#print(res)
#6.values() 可以指定获取的数据字段 select name,age from ... 列表套字典
#res = models.User.objects.values('name','age') #
#print(res)
#7.values_list() 列表套元祖
#res = models.User.objects.values_list('name','age') #
#print(res)
#"""
## 查看内部封装的sql语句
#上述查看sql语句的方式 只能用于queryset对象
#只有queryset对象才能够点击query查看内部的sql语句
# #"""
#8.distinct() 去重
#res = models.User.objects.values('name','age').distinct()
#print(res)
"""去重一定要是一模一样的数据
如果带有主键那么肯定不一样 你在往后的查询中一定不要忽略主键"""
#9.order_by()
#res = models.User.objects.order_by('age') # 默认升序
#res = models.User.objects.order_by('-age') # 降序
# #print(res)
#10.reverse() 反转的前提是 数据已经排过序了 order_by()
#res = models.User.objects.all()
#res1 = models.User.objects.order_by('age').reverse()
#print(res,res1)
#11.count() 统计当前数据的个数
#res = models.User.objects.count()
#print(res)
#12.exclude() 排除在外
#res = models.User.objects.exclude(name='jason')
#print(res)
#13.exists() 基本用不到因为数据本身就自带布尔值 返回的是布尔值
#res = models.User.objects.filter(pk=10).exists()
#print(res)
(二)测试脚本
"""当你只是想测试django中的某一个py文件内容 那么你可以不用书写前后端交互的形式
而是直接写一个测试脚本即可
脚本代码无论是写在应用下的tests.py还是自己单独开设py文件都可以"""
#测试环境的准备 去manage.py中拷贝前四行代码 然后自己写两行
importosimportsysif __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")importdjango
django.setup()#在这个代码块的下面就可以测试django里面的单个py文件了
(三)查看内部sql语句的方式
#方式1
res = models.User.objects.values_list('name','age')
#
print(res.query)
queryset对象才能够点击query查看内部的sql语句#方式2:所有的sql语句都能查看#去配置文件中配置一下即可
LOGGING ={'version': 1,'disable_existing_loggers': False,'handlers': {'console':{'level':'DEBUG','class':'logging.StreamHandler',
},
},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level':'DEBUG',
},
}
}
三、神奇的双下划线查询
#神奇的双下划线查询
#1 年龄大于35岁的数据
#res = models.User.objects.filter(age__gt=35)
#print(res)
#2 年龄小于35岁的数据
#res = models.User.objects.filter(age__lt=35)
#print(res)
#大于等于 小于等于
#res = models.User.objects.filter(age__gte=32)
#print(res)
#res = models.User.objects.filter(age__lte=32)
#print(res)
#年龄是18 或者 32 或者40
#res = models.User.objects.filter(age__in=[18,32,40])
#print(res)
#年龄在18到40岁之间的 首尾都要
#res = models.User.objects.filter(age__range=[18,40])
#print(res)
#查询出名字里面含有s的数据 模糊查询
#res = models.User.objects.filter(name__contains='s')
#print(res)
# #是否区分大小写 查询出名字里面含有p的数据 区分大小写
#res = models.User.objects.filter(name__contains='p')
#print(res)
#忽略大小写
#res = models.User.objects.filter(name__icontains='p')
#print(res)
#res = models.User.objects.filter(name__startswith='j')
#res1 = models.User.objects.filter(name__endswith='j')
# #print(res,res1)
#查询出注册时间是 2020 1月
#res = models.User.objects.filter(register_time__month='1')
#res = models.User.objects.filter(register_time__year='2020')
四、外键字段的增删改查
(一)一对多外键增删改查
#一对多外键增删改查
#增
#1 直接写实际字段 id
#models.Book.objects.create(title='论语',price=899.23,publish_id=1)
#models.Book.objects.create(title='聊斋',price=444.23,publish_id=2)
#models.Book.objects.create(title='老子',price=333.66,publish_id=1)
#2 虚拟字段 对象
#publish_obj = models.Publish.objects.filter(pk=2).first()
#models.Book.objects.create(title='红楼梦',price=666.23,publish=publish_obj)
#删
#models.Publish.objects.filter(pk=1).delete() # 级联删除
#修改
#models.Book.objects.filter(pk=1).update(publish_id=2)
#publish_obj = models.Publish.objects.filter(pk=1).first()
#models.Book.objects.filter(pk=1).update(publish=publish_obj)
(二)多对多外键增删改查
#如何给书籍添加作者?
book_obj = models.Book.objects.filter(pk=1).first()#print(book_obj.authors) # 就类似于你已经到了第三张关系表了
#book_obj.authors.add(1) # 书籍id为1的书籍绑定一个主键为1 的作者
#book_obj.authors.add(2,3)
#author_obj = models.Author.objects.filter(pk=1).first()
#author_obj1 = models.Author.objects.filter(pk=2).first()
#author_obj2 = models.Author.objects.filter(pk=3).first()
#book_obj.authors.add(author_obj)
#book_obj.authors.add(author_obj1,author_obj2)
"""add给第三张关系表添加数据
括号内既可以传数字也可以传对象 并且都支持多个"""
#删
#book_obj.authors.remove(2)
#book_obj.authors.remove(1,3)
#author_obj = models.Author.objects.filter(pk=2).first()
#author_obj1 = models.Author.objects.filter(pk=3).first()
#book_obj.authors.remove(author_obj,author_obj1)
"""remove
括号内既可以传数字也可以传对象 并且都支持多个"""
#修改
#book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象
#book_obj.authors.set([3]) # 括号内必须给一个可迭代对象
#author_obj = models.Author.objects.filter(pk=2).first()
#author_obj1 = models.Author.objects.filter(pk=3).first()
#book_obj.authors.set([author_obj,author_obj1]) # 括号内必须给一个可迭代对象
"""set
括号内必须传一个可迭代对象,该对象内既可以数字也可以对象 并且都支持多个"""
#清空
#在第三张关系表中清空某个书籍与作者的绑定关系
book_obj.authors.clear()"""clear
括号内不要加任何参数"""
(三)正反向的概念
#正向#反向
外键字段在我手上那么,我查你就是正向
外键字段如果不在手上,我查你就是反向
book>>>外键字段在书那儿(正向)>>>publish
publish>>>外键字段在书那儿(反向)>>>book
一对一和多对多正反向的判断也是如此"""正向查询按字段
反向查询按表名小写
_set
..."""
五、跨表查询(重点)
(一)子查询(基于对象的跨表查询)
#1.查询书籍主键为1的出版社
#book_obj = models.Book.objects.filter(pk=1).first()
## 书查出版社 正向
#res = book_obj.publish
#print(res)
#print(res.name)
#print(res.addr)
#2.查询书籍主键为2的作者
#book_obj = models.Book.objects.filter(pk=2).first()
## 书查作者 正向
## res = book_obj.authors # app01.Author.None
#res = book_obj.authors.all()
# , ]>
# #print(res)
#3.查询作者jason的电话号码
#author_obj = models.Author.objects.filter(name='jason').first()
#res = author_obj.author_detail
#print(res)
#print(res.phone)
#print(res.addr)
"""在书写orm语句的时候跟写sql语句一样的
不要企图一次性将orm语句写完 如果比较复杂 就写一点看一点
正向什么时候需要加.all()
当你的结果可能有多个的时候就需要加.all()
如果是一个则直接拿到数据对象
book_obj.publish
book_obj.authors.all()
author_obj.author_detail"""
#4.查询出版社是东方出版社出版的书
#publish_obj = models.Publish.objects.filter(name='东方出版社').first()
#出版社查书 反向
#res = publish_obj.book_set # app01.Book.None
#res = publish_obj.book_set.all()
#print(res)
#5.查询作者是jason写过的书
#author_obj = models.Author.objects.filter(name='jason').first()
#作者查书 反向
#res = author_obj.book_set # app01.Book.None
#res = author_obj.book_set.all()
#print(res)
#6.查询手机号是110的作者姓名
#author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
#res = author_detail_obj.author
#print(res.name)
"""基于对象
反向查询的时候
当你的查询结果可以有多个的时候 就必须加_set.all()
当你的结果只有一个的时候 不需要加_set.all()
自己总结出 自己方便记忆的即可 每个人都可以不一样"""
(二)联表查询(基于双下划线的跨表查询)
#基于双下划线的跨表查询
#1.查询jason的手机号和作者姓名
#res = models.Author.objects.filter(name='jason').values('author_detail__phone','name')
#print(res)
#反向
#res = models.AuthorDetail.objects.filter(author__name='jason') # 拿作者姓名是jason的作者详情
#res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__name')
#print(res)
#2.查询书籍主键为1的出版社名称和书的名称
#res = models.Book.objects.filter(pk=1).values('title','publish__name')
#print(res)
#反向
#res = models.Publish.objects.filter(book__id=1).values('name','book__title')
#print(res)
#3.查询书籍主键为1的作者姓名
#res = models.Book.objects.filter(pk=1).values('authors__name')
#print(res)
#反向
#res = models.Author.objects.filter(book__id=1).values('name')
#print(res)
#查询书籍主键是1的作者的手机号
#book author authordetail
#res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
#print(res)
"""你只要掌握了正反向的概念
以及双下划线
那么你就可以无限制的跨表"""
六、聚合查询—— aggregate
聚合函数就是五个聚合函数的使用,通常都是配合【分组】一起使用的
首先应导入这五个聚合函数模块 :
from django.db.models import Max,Min,Sum,Count,Avg
#聚合查询 aggregate
"""聚合查询通常情况下都是配合分组一起使用的
只要是跟数据库相关的模块
基本上都在django.db.models里面
如果上述没有那么应该在django.db里面"""
from app01 importmodelsfrom django.db.models importMax,Min,Sum,Count,Avg#1 所有书的平均价格
#res = models.Book.objects.aggregate(Avg('price'))
#print(res)
#2.上述方法一次性使用
res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('pk'),Avg('price'))print(res)
七、分组查询
#分组查询 annotate
"""MySQL分组查询都有哪些特点
分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取了
严格模式
ONLY_FULL_GROUP_BY"""
from django.db.models importMax, Min, Sum, Count, Avg#1.统计每一本书的作者个数
#res = models.Book.objects.annotate() # models后面点什么 就是按什么分组
#res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
"""author_num是我们自己定义的字段 用来存储统计出来的每本书对应的作者个数"""
#res1 = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
#print(res,res1)
"""代码没有补全 不要怕 正常写
补全给你是pycharm给你的 到后面在服务器上直接书写代码 什么补全都没有 颜色提示也没有"""
#2.统计每个出版社卖的最便宜的书的价格(作业:复习原生SQL语句 写出来)
#res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
#print(res)
#3.统计不止一个作者的图书
#1.先按照图书分组 求每一本书对应的作者个数
#2.过滤出不止一个作者的图书
#res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
#"""
#只要你的orm语句得出的结果还是一个queryset对象
#那么它就可以继续无限制的点queryset对象封装的方法
# #"""
#print(res)
#4.查询每个作者出的书的总价格
#res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
#print(res)
"""如果我想按照指定的字段分组该如何处理呢?
models.Book.objects.values('price').annotate()
后续BBS作业会使用
你们的机器上如果出现分组查询报错的情况
你需要修改数据库严格模式(去掉严格模式)"""
八、F与Q查询
#F查询
#1.查询卖出数大于库存数的书籍
#F查询
"""能够帮助你直接获取到表中某个字段对应的数据"""
from django.db.models importF#res = models.Book.objects.filter(maichu__gt=F('kucun'))
#print(res)
#2.将所有书籍的价格提升500块
#models.Book.objects.update(price=F('price') + 500)
#3.将所有书的名称后面加上爆款两个字
"""在操作字符类型的数据的时候 F不能够直接做到字符串的拼接"""
from django.db.models.functions importConcatfrom django.db.models importValue
models.Book.objects.update(title=Concat(F('title'), Value('爆款')))#models.Book.objects.update(title=F('title') + '爆款') # 所有的名称会全部变成空白
#Q查询
#1.查询卖出数大于100或者价格小于600的书籍
#res = models.Book.objects.filter(maichu__gt=100,price__lt=600)
"""filter括号内多个参数是and关系"""
from django.db.models importQ#res = models.Book.objects.filter(Q(maichu__gt=100),Q(price__lt=600)) # Q包裹逗号分割 还是and关系
#res = models.Book.objects.filter(Q(maichu__gt=100)|Q(price__lt=600)) # | or关系
#res = models.Book.objects.filter(~Q(maichu__gt=100)|Q(price__lt=600)) # ~ not关系
#print(res) #
#Q的高阶用法 能够将查询条件的左边也变成字符串的形式
q =Q()
q.connector= 'or'q.children.append(('maichu__gt',100))
q.children.append(('price__lt',600))
res= models.Book.objects.filter(q) #默认还是and关系
print(res)
九、Django中如何开启事务
"""事务
ACID
原子性
不可分割的最小单位
一致性
跟原子性是相辅相成
隔离性
事务之间互相不干扰
持久性
事务一旦确认永久生效
事务的回滚
rollback
事务的确认
commit"""
#目前你只需要掌握Django中如何简单的开启事务#事务
from django.db importtransactiontry:
with transaction.atomic():#sql1
#sql2
...#在with代码快内书写的所有orm操作都是属于同一个事务
exceptException as e:print(e)print('执行其他操作')
十、orm中常用字段及参数
AutoField
主键字段 primary_key=True
CharField varchar
verbose_name 字段的注释
max_length 长度
IntegerField int
BigIntegerField bigint
DecimalField
max_digits=8decimal_places=2EmailFiled varchar(254)
DateField date
DateTimeField datetime
auto_now:每次修改数据的时候都会自动更新当前时间
auto_now_add:只在创建数据的时候记录创建时间后续不会自动修改了
BooleanField(Field)-布尔值类型
该字段传布尔值(False/True) 数据库里面存0/1TextField(Field)-文本类型
该字段可以用来存大段内容(文章、博客...) 没有字数限制
后面的bbs作业 文章字段用的就是TextField
FileField(Field)-字符类型
upload_to= "/data"给该字段传一个文件对象,会自动将文件保存到/data目录下然后将文件路径保存到数据库中/data/a.txt
后面bbs作业也会涉及#更多字段
直接参考博客:https://www.cnblogs.com/Dominic-Ji/p/9203990.html#django除了给你提供了很多字段类型之外 还支持你自定义字段
classMyCharField(models.Field):def __init__(self,max_length,*args,**kwargs):
self.max_length=max_length#调用父类的init方法
super().__init__(max_length=max_length,*args,**kwargs) #一定要是关键字的形式传入
defdb_type(self, connection):"""返回真正的数据类型及各种约束条件
:param connection:
:return:"""
return 'char(%s)'%self.max_length#自定义字段使用
myfield = MyCharField(max_length=16,null=True)#外键字段及参数
unique=True
ForeignKey(unique=True) ===OneToOneField()#你在用前面字段创建一对一 orm会有一个提示信息 orm推荐你使用后者但是前者也能用
db_index
如果db_index=True 则代表着为此字段设置索引
(复习索引是什么)
to_field
设置要关联的表的字段 默认不写关联的就是另外一张的主键字段
on_delete
当删除关联表中的数据时,当前表与其关联的行的行为。"""django2.X及以上版本 需要你自己指定外键字段的级联更新级联删除"""
十一、数据库查询优化 (only与defer、select_related与prefetch_related)
only与defer
select_related与prefetch_related"""orm语句的特点:
惰性查询
如果你仅仅只是书写了orm语句 在后面根本没有用到该语句所查询出来的参数
那么orm会自动识别 直接不执行"""
#only与defer#res = models.Book.objects.all()
#print(res) # 要用数据了才会走数据库
#想要获取书籍表中所有数的名字
#res = models.Book.objects.values('title')
#for d in res:
#print(d.get('title'))
#你给我实现获取到的是一个数据对象 然后点title就能够拿到书名 并且没有其他字段
#res = models.Book.objects.only('title')
#res = models.Book.objects.all()
#print(res) # , , , , ]>
#for i in res:
#print(i.title) # 点击only括号内的字段 不会走数据库
#print(i.price) # 点击only括号内没有的字段 会重新走数据库查询而all不需要走了
res= models.Book.objects.defer('title') #对象除了没有title属性之外其他的都有
for i inres:print(i.price)"""defer与only刚好相反
defer括号内放的字段不在查询出来的对象里面 查询该字段需要重新走数据
而如果查询的是非括号内的字段 则不需要走数据库了"""
#select_related与prefetch_related#select_related与prefetch_related 跟跨表操作有关
#res = models.Book.objects.all()
#for i in res:
#print(i.publish.name) # 每循环一次就要走一次数据库查询
#res = models.Book.objects.select_related('authors') # INNER JOIN
"""select_related内部直接先将book与publish连起来 然后一次性将大表里面的所有数据
全部封装给查询出来的对象
这个时候对象无论是点击book表的数据还是publish的数据都无需再走数据库查询了
select_related括号内只能放外键字段 一对多 一对一
多对多也不行"""
#for i in res:
#print(i.publish.name) # 每循环一次就要走一次数据库查询
res= models.Book.objects.prefetch_related('publish') #子查询
"""prefetch_related该方法内部其实就是子查询
将子查询查询出来的所有结果也给你封装到对象中
给你的感觉好像也是一次性搞定的"""
for i inres:print(i.publish.name)
参考阅读:
python框架django书籍_【2020Python修炼记】web框架之 Django的ORM语法相关推荐
- python框架django书籍_有Python基础,刚接触web框架的Django初学者。
本文面向:有Python基础,刚接触web框架的Django初学者. 环境:windows7 python3.5.1 pycharm Django 1.10版 pip3 一.Django简介 百度百科 ...
- 使用双标记写html代码时如何进行嵌套,【2020Python修炼记】前端开发之 前端基础和HTML入门...
发表于:2020-11-12 18:21 阅读: 119次 这篇教程主要讲解了[2020Python修炼记]前端开发之 前端基础和HTML入门,并附有相关的代码样列,我觉得非常有帮助,现在分享出来大家 ...
- 学习python最好的书籍_最好的Python书籍
学习python最好的书籍 Python is an amazing programming language. It can be applied to almost any programming ...
- python 数据科学书籍_您必须在2020年阅读的数据科学书籍
python 数据科学书籍 "We're entering a new world in which data may be more important than software.&qu ...
- python django 动态网页_Django-手撸简易web框架-实现动态网页-wsgiref初识-jinja2初识-python主流web框架对比-00...
自己动手实现一个简易版本的web框架 在了解python的三大web框架之前,我们先自己动手实现一个. 备注: 这部分重在掌握实现思路,代码不是重点 代码中也有许多细节并未考虑,重在实现思路 手撸一个 ...
- python金融量化书籍_超强干货 | Python金融数据量化分析教程+机器学习电子书
如今Python语言的学习已经上升到了国家战略的层面上.Python语言是人工智能的基础语言,国家相关教育部门对于"人工智能普及"格外重视,不仅将Python列入到小学.中学和高中 ...
- Python自动化开发学习的第十一周----WEB框架--Django基础
WEB框架的本质 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf-8imp ...
- 自学python的经典书籍_有哪些 Python 经典书籍?
内容太长,完整内容请访问原文: python 3.7极速入门教程9最佳python中文工具书籍下载 筛选了2年内优秀的python书籍,个别经典的书籍扩展到5年内. python现在的主流版本是3.7 ...
- python接口自动化测试书籍_干货丨Python接口测试自动化实战及代码示例:含get、post等方法...
引言:年初参与到一个后台系统开发的项目中,里面涉及了很多接口,我做为项目组测试人员,需要对这些接口进行测试,一开始使用 postman 工具测试,很是方便.但随着接口数量的增加,不光要执行手动点击测试 ...
最新文章
- buffers和cache的区别
- java springmvc mybatis mysql
- mybatis实现反向工程
- MacOS中Elasticsearch的安装「借助Homebrew」
- Oracle中通过游标执行带参数的存储过程实现解析CLOB字段内的xml字符串:
- 【BZOJ3956】Count,单调栈+ST表维护区间最大值
- 知识图谱之WordNet
- 知钱俱乐部 php,知钱俱乐部
- 全智通A+常见问题汇总解答—A+打印本次派工单,结果显示所派工项目
- js splice的三个用法
- java开发程序员培训班,成功跳槽阿里!
- 【案例分享】某银行用这20件事,实现数字化转型
- Java 8 Stream 总结
- 《关于组织申报2017年度高新技术企业的通知》
- 图神经网络基础--图结构数据
- 关于“ROS2 Topic-Statistics-Tutorial编译出错”的思考2
- 设备异常状态检测相关内容(一)
- php多用户修改头像源码,PHP 针对多用户 实现头像更换
- 2017年电气报价软件排名!评分最高的是它
- nonebot2聊天机器人插件3:计算器calculator