复习settar和getattr
getattr(对象,属性,默认值)对象中取出属性的值
setattr(对象,属性,属性的值)为对象添加新的属性
CBV的源码截图
django settings源码
importilb模块
第二节课
一、双下划线查询
1.1打印orm内部sql语句的两种方法?
1.如果是queryset对象 那么可以点query直接查看该queryset的内部sql语句
# 不是
2.在django项目的配置文件中 配置一下参数即可实现所有的orm在查询的时候自动打印对应的sql语句
django配置文件(settings)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
修改数据库的两行代码:
makemigrations
migrate
在django中你可以写一个单独测试某一个py文件的测试脚本不需要再频繁的走web请求
在根目录下建立test.py
import os
import sys
if __name__ == "__main__":
# django在启动的时候 就会往全局的大字典中设置一个键值对 值是暴露给用户的配置文件的路径字符串
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings")
import django
django.setup()
from app01 import models
LIMIT的作用:
这个是为了避免数据库的压力,防止数据特别巨大
使用该,来复习原生sql语句!
双下查询:
总结:双下查询等于是封装了原生sql语句,变成其他另一个语法。简单易用!值得推荐
"""神奇的双下滑查询"""
# 查询价格大于200的书籍
# res = models.Book.objects.filter(price__gt=200) #查询结果不包括200!
# print(res)
# 查询价格小于200的书籍
# res = models.Book.objects.filter(price__lt=200)
# print(res)
# 查询价格大于等于200.22的书籍
# res = models.Book.objects.filter(price__gte=200)
# print(res)
# 查询价格小于等于200.22的书籍
# res = models.Book.objects.filter(price__lte=200.22)
# print(res)
# 查询价格要么是200,要么是300,要么是666.66
# res = models.Book.objects.filter(price__in=[200,300,666.66])
# print(res)
# 查询价格在200到800之间的
# res = models.Book.objects.filter(price__range=(200,800)) # 两边都包含
# print(res)
# 查询书籍名字中包含p的
"""在打印的原生sql语句 模糊匹配出现
like
%
_
"""
#拿到价格里包含数字0的
注意!!只在mysql生效
注意!!只在mysql生效
注意!!只在mysql生效
res = models.Book.objects.filter(price__contains=0) # 仅仅只能拿小写p
res = models.Book.objects.filter(title__icontains='p') # 忽略大小写
#
print(res)
# 查询书籍是以三开头的
# res = models.Book.objects.filter(title__startswith='三')
# res1 = models.Book.objects.filter(title__endswith='p')
# print(res)
# print(res1)
# 查询出版日期是2017的年(******)
# res = models.Book.objects.filter(create_time__year='2017')
# print(res)
图书管理系统表的创建
数据库切换为mysql的操作步骤:
1.新建一个数据库
2.settings中修改ATABASES的数据
3.init文件写入两句话:
import pymysql
pymsql.install_as_MySQLdb()
更换操作:1
2
现在models创建三张表,并设置好外键关系,数据库生效的两条命令是?!
pycharm中
makemigrations产生表记录
migrate保存到数据库
现在录入数据库数据
tests脚本,就不用再浏览器点击了。这是针对某一py文件的测试代码
二、多表操作
外键字段的增删改查
2.1一对多的字段的增删改查
2.1.1增create():
publish参数有两个选项:1publish_id传数字 ;2publish直接传出版社对象
# **一对多的字段的增删改查**
# 增:
# 1.publish_id传数字
models.Book.objects.create(title='三国义',price=189.99,publish_id=1)
# 2.publish直接传出版社对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='梦',price=999.99,publish=publish_obj)
2.1.2改update()
同样,外键字段也可以传两种:1.传数字的;2.传对象的
# 改update()
# 1.传数字的
res= models.Book.objects.filter(pk=1).update(publish_id=3)
print(res)
# 2.传对象的
publish_obj = models.Publish.objects.filter(pk=2).first()
print(publish_obj)
models.Book.objects.filter(pk=1).update(publish=publish_obj)
# 删
models.Publish.objects.filter(pk=2).delete() # 默认都是级联更新 级联删除
2.2多对多字段的增删改查
add()
set()
remove()
上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象
clear()
clear括号内不需要传任何参数
增add()
# 要给主键为1的书籍添加两个作者
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.authors) # 对象点击多对多虚拟字段 会直接跨到多对多的第三张表
#支持同时添加多个
# book_obj.authors.add(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()
是给书籍添加作者 括号内既可以传数字也可以传对象
并且支持一次性传多个 逗号隔开即可
"""
改set([])
# 将主键为1的书籍对象 作者修改为2,3
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.set([2,])
# book_obj.authors.set([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.set([author_obj,])
# book_obj.authors.set([author_obj, author_obj1, author_obj2])
"""
set()括号内 需要传一个可迭代对象
可迭代对象中 可以是多个数字组合
也可以是多个对象组合
但是不要混着用!!!
"""
删
1.remove()# 一个一个删
2.clear() # 清空所有
# book_obj = models.Book.objects.filter(pk=1).first()
# # book_obj.authors.remove(3)
# book_obj.authors.remove(1,2)
# 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.remove(author_obj)
# book_obj.authors.remove(author_obj1,author_obj2)
"""
remove()括号内既可以传数字 也可以传对象
并且支持传对个 逗号隔开即可
"""
# 将某本书跟作者的关系全部清空
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.clear() # 清空当前书籍与作者的所有关系
"""
add()
set()
remove()
上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象
clear()
clear括号内不需要传任何参数
"""
跨表查询(重点)
诀窍:正向查询按外键字段,反向查询按表名小写
正向与反向的概念(******)
诀窍:正向查询按外键字段,反向查询按表名小写
1基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)
2基于双下划綫的跨表查询(连表操作)
left join
inner join
right join
union
# 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写
# 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书
# 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书
一、基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)
强调:在书写orm语句的时候 跟写sql语句一样
不要尝试着 一次性写完 应该做到写一点看一点再一点
# 1.查询书籍id是1 的出版社名称
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.publish.name)
# print(book_obj.publish.addr)
book_obj.publish。现在就跨表了,现在就可以.publish的字段了。比如:book_obj.publish.name
# 2.查询书籍id是2 的作者姓名
# book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors:app01.Author.None。多对多的关系要加.all()
# print(book_obj.authors)
# print(book_obj.authors.all())
id为2的书籍对应多个作者,通过.all()拿到所有作者对象,for循环依次取出对象
# res = book_obj.authors.all()
# for r in res:
# print(r.name)
书籍和作者是多对多的关系。
正向.字段后得出的结果是app01.Author.None。多对多的关系要加.all()
# 3.查询作者是jason的家庭住址
# author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.author_detail.addr)
# 4.查询出版社是东方出版社出版的书籍
# publish_obj = models.Publish.objects.filter(name='东方出版社').first()
# # print(publish_obj.book_set) # app01.Book.None
反向,当获取多个对象的时候:加_set
# print(publish_obj.book_set.all())
# 5.查询作者是jason的写过的所有的书籍
# author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set) # app01.Book.None
# print(author_obj.book_set.all())
# 6.查询电话号码是130的作者姓名
# author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
# print(author_detail_obj.author.name)
"""
当你反向查询的结果是多个的时候 就需要加_set
否则直接表明小写即可
"""
# 7.查询书籍id为1 的作者的电话号码
# book_obj = models.Book.objects.filter(pk=1).first()
# author_list = book_obj.authors.all()
# for author_obj in author_list:
# print(author_obj.author_detail.phone)
二、基于双下划綫的跨表查询(连表操作)
left join
inner join
right join
union
正向
正向 __字段
models.Book.objects.filter(name='jason').values('publish__name')
# 1.查询jason作者的手机号
# res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
# print(res)
# res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
# print(res1)
# 查询jason这个作者的年龄和手机号
# 正向
# res = models.Author.objects.filter(name='jason').values('age','author_detail__phone')
# print(res)
# 反向
# res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
# print(res1)
# 查询手机号是130的作者年龄
# 正向
# res = models.AuthorDetail.objects.filter(phone=130).values('author__age')
# print(res)
# # 反向
# res1 = models.Author.objects.filter(author_detail__phone=130).values('age')
# print(res1)
# 查询书籍id是1 的作者的电话号码
只要表中有外键字典就可以无限制的跨表
# res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
# res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段')
# print(res)
"""只要表里面有外键字段 你就可以无限制跨多张表"""
# 1.查询出版社为北方出版社的所有图书的名字和价格
# res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
# print(res)
# 2.查询北方出版社出版的价格大于19的书
# res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
# print(res)
# 聚合查询(aggregate)
# 1.统计所有书的总价格
# from django.db.models import Max,Min,Count,Avg,Sum
#
# # res = models.Book.objects.aggregate(Sum('price'))
# res1 = models.Book.objects.aggregate(Avg('price'))
# res2 = models.Book.objects.aggregate(Count('price'))
# res3 = models.Book.objects.aggregate(Max('price'))
# res4 = models.Book.objects.aggregate(Min('price'))
# res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))
# print(res5)
# print(res)
# print(res1)
# print(res2)
# 分组查询
# 统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
# res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
# print(res)
# 统计出每个出版社卖的最便宜的书的价格
# res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
# print(res)
# 统计不止一个作者的图书
# res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
# print(res)
"""
只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选
"""
# 查询各个作者出的书的总价格
# res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
# print(res)
书籍有多个出版社要.all()
拿到这个结果就说明,写的没错,只是少东西!
反向查
_没有set,则报错
分组查询:models点啥就按啥分组
F查询和Q查询
F查询从数据库获取字段对应的值
增加字段kucun和maichu
看题目:
之前这个数是我们自己指定的,现在是数据库里的数据,怎么写?F查询
F查询就是来解决这一问题的。
需要导入模块:
F查询的本质就是从数据库中获取某个字段的值
# 查询库存数大于卖出数的书籍
"""之前查询等号后面的条件都是我们认为输入的
现在变成了需要从数据库中获取数据放在等号后面
"""
from django.db.models import F
# res = models.Book.objects.filter(kucun__gt=F('maichu'))
# print(res)
# 将书籍库存数全部增加1000
# models.Book.objects.update(kucun=F('kucun')+1000)
# 把所有书名后面加上'新款'
# from django.db.models.functions import Concat
# from django.db.models import Value
#
# ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
# models.Book.objects.update(title = F('title')+'新款') # 不能这么写
Q查询
看题目:使用Q查询来修改条件
也需要导入模块:
from django. db. models import Q
filter()括号内,逗号是and的关系
Q查询:Q()
from django.db.models import Q
# 查询书籍名称是三国演义或者价格是444.44
与
# res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系
或 |
# res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))
非 ~
# res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))
# print(res2)
Q的高级用法
Q高级用法
q = Q()
q.connector = 'or' # 修改查询条件的关系 默认是and
q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件
# q.children.append(('price__gt',444)) # 往列表中添加筛选条件
# res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系
# print(res)