Django模型层
Django操作数据库
pycharm链接MySQL
"""
三个位置查找数据库相关
右侧上方database
左下方database
配置里面的plugins插件搜索安装
再没有卸载pycharm重新装
pycharm可以充当很多款数据库软件的客户端
参考截图和视频操作即可
需要提前创建好库
"""
Django链接MySQL
# 默认用的是sqkite3
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# django链接MySQL
1.第一步配置文件中配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day60',
'USER':'root',
'PASSWORD':'',
'HOST':'127.0.0.1',
'PORT':3306,
'CHARSET':'utf8'
}
}
2.代码声明
django默认用的是mysqldb模块链接MySQL
但是该模块的兼容性不好 需要手动改为用pymysql链接
你需要告诉django不要用默认的mysqldb还是用pymysql
# 在项目名下的init或者任意的应用名下的init文件中书写以下代码都可以
import pymysql
pymysql.install_as_MySQLdb()
模型层
Django ORM
ORM:对象关系映射
- 作用:能狗让一个不会SQL语句的小白也能通过Python 面向对象的代码简单快捷的操作数据库
- 不足:封装程度太高,有事SQL语句的效率偏低,需要自己写SQL语句
# 类 ---> 表
# 对象 ---> 记录
# 对象属性 ---> 记录某个字段对应的值
# 先去 models.py 中写一个类
class User(models.Model):
id = models.AutoField(primary_key=True) # id int primary_key auto_increment
username = models.CharField(max_length=32) # username varchar(32)
password = models.IntegerField() # password int
### 数据库迁移命令
python3 manage.py makemigrations # 将操作记录记录到migration文件夹里
python3 manage.py migrate # 将操作真正的同步到数据库中
# 只要修改了models.py 中跟数据相关的代码,就必须重新执行上述两条命令
#CharField必须要指定max_length参数 不指定会直接报错
#verbose_name该参数是所有字段都有的 就是用来对字段的解释
# 由于一张表中必须要有一个主键字段 并且一般情况下都叫id字段
# 所以orm当你不定义主键字段的时候 orm会自动帮你创建一个名为id主键字段
# 也就意味着 后续我们在创建模型表的时候如果主键字段名没有额外的叫法 那么主键字段可以省略不写
id = models.AutoField(primary_key=True,verbose_name='主键')
字段的增删查改
# 字段的增加
直接在models.py的代码中加字段的语句,在有记录的情况下不设置默认值的话,终端会提示无法直接添加字段,需要进行选择
1. 在终端里设置字段的默认值
2. 退出终端操作,去代码中设置默认值
# 字段的修改
直接修改代码后执行数据库迁移的两条命令即可!
# 字段的删除
直接注释或删除代码中对应字段设置的代码后执行数据库迁移代码,执行完毕后字段对应的数据也没了
# 注意事项
在操作model.py的时候一定一定细心,千万不要不小心的注释了字段的代码
数据的增删查改
# 查
models.Userinfo.objects.all()
models.Userinfo.objects.filter(**{...})
# 增
models.Userinfo.objects.create(**{...})
# 第二种增
user_obj = models.User(username=username,password=password)
user_obj.save() # 保存数据
# 改
models.Userinfo.objects.update(**{...})
# 删
models.Userinfo.objects.delete(...)
表外键字段创建
一对一models.OneToOneField(to='')
一对多 models.ForeignKey(to='')
多对多models.ManyToManyField(to='')
'''
1. ORM 在帮我们建外键时会自动加上_id的后缀
2. 在建立多对多的外键时,我们只需要在任意一张表中建立外键字段,ORM会在自动帮我们建立第三张表,并且表中有自动生成的主键和两张关系表的主键三个字段
3. 在建立多对多的外键时,这个外键字段是虚拟字段,并不会在建立字段的表中暂时出来
4.django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常:TypeError: __init__() missing 1 required positional argument: 'on_delete'
'''
表关系:一对多;多对多;一对一
图书管理系统表设计
图书表
出版社表
作者表
作者详情表
表关系
图书表 与 出版社表
一对多,外键字段建立在多的一方,也就是图书表里
models.ForeignKey(to='Publish')
图书表 与 作者表
多对多,外键字段建立在第三张表上
authors = models.ManyToManyField(to='Author')
作者表 与 作者详情表
一对一,外键字段建立在查询评率高的那张表上,也就是作者表
author_detail = models.OneToOneField(to='AuthorDetail')
# 书籍表
class Book(models.Model):
title = models.CharField(verbose_name='书名', max_length=32)
price = models.DecimalField(verbose_name='单价', max_digits=8, decimal_places=2)
# 书与出版社的关系是一对多,外键建立在书的这张表中
publish = models.ForeignKey(to='Publish')
# 书与作者的关系是多对多,ORM不需要自己建第三张表,它会自动建
# 只需要告诉ORM是哪两张表有关系
# 这个字段是一个虚拟字段,并不会在这张表中展示,用于ORM自动创建第三种表
authors = models.ManyToManyField(to='Author')
# 出版社表
class Publish(models.Model):
name = models.CharField(validators='出版社名称', max_length=32)
addr = models.CharField(validators='出版社地址', max_length=64)
# 作者表
class Author(models.Model):
name = models.CharField(verbose_name='姓名', max_length=32)
addr = models.CharField(verbose_name='地址', max_length=64)
# 作者表和作者详情表是一对一关系,外键字段建立咋作者表中
author_detail = models.OneToOneField(to='AuthorDetail')
# ORM 在建立外键字段时会自动加上_id 后缀,并不会自动识别我们自己有没有加
# 作者详情表
class AuthorDetail(models.Model):
age = models.IntegerField(verbose_name='年龄')
phone = models.BigIntegerField(verbose_name='手机号')
Django的on_delete参数
on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为
on_delete=models.CASCADE, # 删除关联数据,与之关联也删除
on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做
on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError
# models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)
# models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)
on_delete=models.SET, # 删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
多对多外键字段三种创建方式
第一种(全自动)
class Books(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_lengrh=32)
# 第三张表的扩展性极差,无法添加额外的字段
第二种(纯手动)
class Books(models.Model):
title = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_lengrh=32)
class BooksToAuthor(models.Model):
book_id = models.ForeingKey(to='Author')
author_id = models.Foreingkey(to='Books')
desc = models.CharField(max_length=32)
# 第三张表可以自定义,但ORM查询不方便
第三种(半自动)
class Books(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author',through='BooksToAuthor',
through_fields=('book_id','author_id'))
class Author(models.Model):
name = models.CharField(max_lengrh=32)
authors = models.ManyToManyField(to='Books',through='BooksToAuthor',
through_fields=('author_id','book_id'))
class BooksToAuthor(models.Model):
book_id = models.ForeingKey(to='Author')
author_id = models.Foreingkey(to='Books')
desc = models.CharField(max_length=32)
# 自己设置第三张表,在定义外键字段时添加两个参数,第一个是外键表名,第二个是一个元组,元组第一个是当前表在外键表中的外键字段名,第二个是对方表在外键表中的外键字段名
# 这种方式设立的外键,无法使用add/set/remove/clear,其他不受影响
数据库正向反向迁移
正向迁移(将Django中的类导入到数据库中变成表):
python3 mange.py makemigration
python3 mange.py migrate
反向迁移:
inspectdb
Django脚本环境
Django默认情况下不允许单独使用某个功能部分(models.py)
要么自己新建一个py文件
要么使用自带的tests文件
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day47.settings")
import django
django.setup()
# 测试代码
关键字查询
# 增 create()
# 查 查询的结果大多是QuerySet对象,可以用query方法查看对应的MySQL语句操作
all()
filter() # 参数pk特指当前表的主键字段(无论主键取啥名)
first() # 查看列表中第一个数据
last() # 查看列表中最后一个数据
values() # 根据参数显示查询结果的字段,查询结果可以看成列表套字典
values_list() # 根据参数显示查询结果的字段,查询结果可以看成列表套元组
get() # 类似于filter,但查询不到会报错
exclude() # 取反
order_by() # 排序,默认是升序(asc,字段前面加负号是降序(desc)
reverse() # 反转,必须现有顺序才能反转
distinct() # 去重
count() # 计数,返回int类型
exists() # 判断是否有数据,返回布尔类型
# update()
# delete()
# 增 1.create()
# models.Books.objects.create(title='三国演义',price=456.23)
# models.Books.objects.create(title='水浒传',price=876.45)
# models.Books.objects.create(title='聊斋志异',price=123.69)
# models.Books.objects.create(title='草堂笔记',price=456.96)
# 查 2.all()
# res = models.Books.objects.all()
# print(res) # QuerySet对象
# print(res.query) # 只要是QuerySet对象就可以点query查看内部SQL语句
# 查 3.filter()
# res1 = models.Books.objects.filter() # pk特指当前表的主键字段
# print(res1) # QuerySet对象
# print(res1.query)
# print(res1.first()) # 获取列表中第一个数据对象
# print(res1.last()) # 获取列表中最后一个数据对象
# 4.values与5.values_list
# res2 = models.Books.objects.values('title','price')
# print(res2) # QuerySet对象 可以看成列表套字典
# print(res2.query)
# res3 = models.Books.objects.values_list('title','price')
# print(res3) # QuerySet对象 可以看成列表套元祖
# print(res3.query)
# 6.查 get() 不推荐使用
# res4 = models.Books.objects.get(pk=1)
# print(res4) # 数据对象
# res5 = models.Books.objects.get(pk=100)
# print(res5) # 数据对象
# res6 = models.Books.objects.filter(pk=100)
# print(res6) # 数据对象
# 7.取反 exclude()
# res7 = models.Books.objects.exclude(pk=1)
# print(res7) # QuerySet
# print(res7.query)
# 8.排序 order_by() 默认是升序(asc) 字段前面加负号降序(desc)
# res8 = models.Books.objects.order_by('price')
# res8 = models.Books.objects.order_by('-price')
# select * from books order by price desc,price asc;
# res8 = models.Books.objects.order_by('-price','price')
# print(res8) # QuerySet对象
# print(res8.query)
# 9.反转 reverse() 必须先有顺序才可以反转
# res9 = models.Books.objects.all()
# res9 = models.Books.objects.order_by('price').reverse()
# print(res9)
# 10.去重 distinct()
# res10 = models.Books.objects.all().distinct()
# res10 = models.Books.objects.values('title','price').distinct()
# print(res10)
# 11.计数 count()
# res11 = models.Books.objects.count()
# print(res11) # 6
# 12.判断是否有数据 exists()
# res12 = models.Books.objects.filter(pk=999).exists()
# print(res12) # False
# 13.update()
# 14.delete()
双下划线查询
__gt 大于
__lt 小于
__gte 大于等于
__lte 小于等于
__in 成员运算
__range 范围查询
__contains 模糊查询,区分大小写
__icontains 模糊查询,忽略大小写
日期相关
_time__month
_time__year
外键字段的增删改查
# 增
# 加数据时外键字段有两种方式,一种直接放外键值,一种放虚拟字段,放查询出来的对象
models.Book.objects.create(title='三国演义',price=345.43,publish_id=1)
models.Book.objects.create(title='红楼梦',price=678.31,publish_id=2)
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='三国演义',price=345.43,publish=publish_obj)
models.Book.objects.create(title='七龙珠',price=908.43,publish=publish_obj)
# 改
models.Book.objects.filter(pk=2).update(publish_id=1)
models.Book.objects.filter(pk=2).update(publish=publish_obj)
# 删 级联更新级联删除
models.BOok.objects.filter(pk=1).delete()
# 多对多 先查询到一张表中要建立关系的记录,再点另外一张表进行相应的操作
book_obj = models.Book.objects.filter(pk=3).first()
# 绑定关系
book_obj.authors.add(1) # 去书与作者的关系表中绑定关系
book_obj.authors.add(1,2) # 去书与作者的关系表中绑定关系
book_obj.authors.add(author_obj1)
book_obj.authors.add(author_obj1,author_obj2)
# 修改关系
book_obj.authors.set([1,])
book_obj.authors.set([1,2])
book_obj.authors.set([author_obj,])
book_obj.authors.set([author_obj1,author_obj2])
# 移除关系
book_obj.authors.remove(1)
book_obj.authors.remove(1,2)
book_obj.authors.remove(author_obj,)
book_obj.authors.remove(author_obj1,author_obj2)
# 清空关系 删除这条记录在外键表里的有关记录
book_obj.authors.clear()
多表查询
重要概念
- 正向查询
- 反向查询
当前查询对象是否含有外键字段
- 如果有就是正向
- 如果无则是反向
口诀:
- 正向查询按外键字段
- 多对多需要额外再加一个.all()
- 一对一和一对多不需要加
- 反向查询按表名小写
- 一对多和多对多需要加_set.all()
- 一对一不需要加
基于对象的跨表查询
# 子查询:将一张表的查询结果当做另外一条SQL语句的条件
# 1、查询书籍主键字段为4的出版社名称
# 先查询数据对象
book_obj = models.Book.objects.filter(pk=4).fitst()
# 外键字段在书籍表中,所以是正向查询
res = book_obj.publish
print(res)
# 2、查询数据主键为3的作者姓名
# 先查询书籍对象
book_obj = models.Book.objects.filter(pk=3).first()
# 外键字段在书籍表中,所以是正向查询
# res = book_obj.authors
# print(res) # app01.Author.None
res = book_obj.authors.all() # 多对多查询,要加上all
print(res) # <QuerySet [<Author: Author object>]>
# 3.查询作者jason的地址
# 先查询jason数据对象
author_obj = models.Author.objects.filter(name='jason').first()
# 外键字段在作者这里 所以是正向查询
res = author_obj.author_detail
print(res)
print(res.addr)
print(res.phone)
# 4.查询东方出版社出版的书籍
# 先查询出版社对象
publish_obj = models.Publish.objects.filter(title='东方出版社').first()
# 外键字段在书那里自己没有 所以是反向
# res = publish_obj.book_set
# print(res) # app01.Book.None
res = publish_obj.book_set.all()
print(res)
# 5.查询jason写过的书籍
# 先查询jason数据对象
# author_obj = models.Author.objects.filter(name='jason').first()
# 外键字段在书那里自己没有 所以是反向
# res = author_obj.book_set
# print(res) # app01.Book.None
res = author_obj.book_set.all()
print(res) # app01.Book.None
# 6.查询电话是120的作者
# 先查询120数据对象
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
# 外键字段在作者那里本身没有 所以是反向
res = author_detail_obj.author
print(res)
print(res.name)
print(res.age)
基于双下划线的跨表查询
# 1.查询书籍主键为4的出版社名称
res = models.Book.objects.filter(pk=4).values('publish__title','publish__addr','title')
print(res)
# 2.查询书籍主键为3的作者姓名
res = models.Book.objects.filter(pk=3).values('authors__name')
print(res)
# 3.查询作者jason的地址
res = models.Author.objects.filter(name='jason').values('author_detail__addr','name','age')
print(res)
# 4.查询北方出版社出版的书籍名称
res = models.Publish.objects.filter(title='北方出版社').values('book__title')
print(res)
# 5.查询jason写过的书籍
res = models.Author.objects.filter(name='jason').values('book__title','name','age')
print(res)
# 6.查询电话是120的作者
res = models.AuthorDetail.objects.filter(phone=120).values('author__name','author__age','addr')
print(res)
进阶操作
# 1.查询书籍主键为4的出版社名称
res = models.Book.objects.filter(pk=4).values('publish__title','publish__addr','title')
print(res)
# 反向查询高阶部分
res = models.Publish.objects.filter(book__pk=4)
print(res)
# 2.查询书籍主键为3的作者姓名
res = models.Book.objects.filter(pk=3).values('authors__name')
print(res)
# 反向查询高阶部分
res = models.Author.objects.filter(book__pk=3)
print(res)
# 3.查询作者jason的地址
res = models.Author.objects.filter(name='jason').values('author_detail__addr','name','age')
print(res)
# 反向查询高阶部分
res = models.AuthorDetail.objects.filter(author__name='jason')
print(res)
# 查询书籍主键为3的作者的电话号码
res = models.Book.objects.filter(pk=3).values('authors__author_detail__phone')
print(res)
res = models.AuthorDetail.objects.filter(author__book__pk=3).values('phone')
print(res)
res = models.Author.objects.filter(book__pk=3).values('author_detail__phone')
print(res)
分组聚合
# 聚合查询,关键字:aggregate
'''max min sum count avg'''
from django.db.models import Max,Min,Sum,Avg,Count
# 求书的最高价格
res = models.Book.objects.aggregate(Max('price'))
print(res)
res1 = models.Book.objects.aggregate(Min('price'),Sum('price'),Avg('price'),Count('pk'))
print(res1)
# 分组查询,关键字:annotate
# 1.统计每一本书的作者个数
res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('title','author_num')
print(res)
res1 = models.Book.objects.annotate(author_num=Count('authors')).values('title', 'author_num')
print(res1)
# 2.统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(not_expensive=Min('book__price')).values('title','not_expensive')
print(res)
# 3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('title','author_num')
print(res)
# 4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
print(res)
'''如果你按照表里面某个指定的字段分组'''
res = models.Book.objects.values('publish_time').annotate()
res1 = models.Book.objects.annotate()
F与Q查询
F查询
from django.db.models import F
# 1.查询库存数大于卖出数的书籍
res = models.Book.objects.filter(kucun__gt=F('maichu'))
print(res)
# 2.将所有的书籍价格上涨100块
res = models.Book.objects.update(price=F('price') + 100)
print(res)
# 3.将所有的书籍名称加上"爆款"后缀
'''针对字符串不能直接拼接 需要额外导入模块操作'''
models.Book.objects.update(title=F('title') + '爆款')
from django.db.models.functions import Concat
from django.db.models import Value
ret3 = models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
Q查询
from django.db.models import Q
# 查找出书名为三国演义爆款或库存为100的书
res = models.Book.objects.filter(title='三国演义爆款',kucun=100)
# filter()括号内可以写多个参数 逗号隔开 默认只支持and连接
rint(res)
res1 = models.Book.objects.filter(Q(title='三国演义爆款'),Q(kucun=100)) # and
res2 = models.Book.objects.filter(Q(title='三国演义爆款')|Q(kucun=100)) # or
res3 = models.Book.objects.filter(~Q(title='三国演义爆款')|Q(kucun=100)) # not
print(res1.query)
# Q进阶用法:根据不同的查询条件查询想要的书
condition = input('请输入你需要按照什么字段查询数据>>>:')
data = input('请输入你需要查询的数据名称>>>:')
q = Q() # 生成一个Q对象
q.children.append((condition,data))
res = models.Book.objects.filter(q)
print(res)
q = Q()
q.connector = 'or' # 可以修改连接条件
q.children.append(('title__contains','三'))
q.children.append(('price__gt',200)) # 可以添加多个条件 并且也是and关系
res = models.Book.objects.filter(q)
print(res)
print(res.query)
事务
- 事务的四大特性 ACID
- 原子性(atomicitty):一个事务是一个不可分割的工作单位,事务中包括的诸多操作要么都做,要么都不做
- 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性密切相关
- 独立性(隔离性,isolation):一个事务的执行不能被其他事务干扰,每个事务相互之间是独立的。
- 持久性(durability,也称永久性 permanence):事务对数据库的改变是永久的,
- 数据库设计三大范式
- 第一范式
- 第二范式
- 第三范式
MySQL中的事务:
start transcation
commit
rollback
Django中的事务:
from django.db import transaction
try:
with transaction.atomic():
# 创建一条订单数据
models.Order.objects.create(num="110110111", product_id=1, count=1)
# 能执行成功
models.Product.objects.filter(id=1).update(kucun=F("kucun") - 1, maichu=F("maichu") + 1)
except Exception as e:
print(e)
执行原生MySQL语句
res = models.Book.objects.raw('select * from app01_book')
for i in res:
print(i)
模型层字段
models.AutoField(primary_key=True) # 自增主键
models.CharField(max_length=) # varchar(21)
models.IntergeField() # int()
models.DataField() # data
models.DataTimeField() # datatime
auto_now # 每次修改数据时都会自动更新时间
auto_now_add # 只在第一次添加数据时会更新时间
models.DecimalField() # float()
models.BooleanField()
给这个字段传布尔值会自动转成数字0和1
models.TextField()
存储大段文本时使用(BBS项目中会用到)
models.EmailField()
存储邮箱格式数据
models.FileField()
存储数据路径
# 自定义字段
from django.db.models import Field
class MyCharField(Field):
def __init__(self,max_length,*args,**kwargs):
self.max_length = max_length
super().__init__(max_length=max_length,*args,**kwargs)
def db_type(self, connection):
return 'char(%s)'%self.max_length
模型层参数
max_length # 数据长度,一般用在字符类型中
varbose_name # 给该字段起一个名字,方便后期查看
default # 默认值
mull # 是否为空
auto_now # 时间字段中自动更新
auto_now_add # 时间字段中第一次修改数据时更新
to # 要关联的表
to_field # 要关联的表的字段,一般默认是主键字段,该参数可不写
unique # 是否唯一
db_index # 是否为该字段设置索引
choices # 设置一一对应的关系
# choices 参数,用于像性别,婚姻,在职状态等这类值是有限个数的,在存入数据库是用对应关系存入数字会节省储存控件
# 例如用户表中的性别,婚姻,在职状态
class User(models.Model):
name = models.CharField(max_length=32)
gender_choices = (
(1, '男'),
(2, '女'),
)
gender = models.IntegerField(choices=gender_choices)
marriage_choices = (
(1, '已婚'),
(2, '未婚'),
)
marriage = models.IntegerField(choices=marriage_choices)
# 获得对应关系
.get_字段名_display()
其他补充
测试环境一:在tests.py文件中,自己拷贝四行代码,添加代码
测试环境二:pycharm自带的,Python Console
配置文件查看所有的ORM内部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',
},
}
}
ORM查询优化
# 惰性查询
用不到查询结果的ORM查询语句即是写了也不会执行
1.only 和 defer
2. select_related 和 prefech_related
# only和defer的用法和value一样,不过value查询结果是列表套字典,而only和defer是列表套对象
# only括号内写了什么字段,那生成的对象就包含有对应字段,在后面查找该字段就不再走数据库查询了,而查找的字段不是括号里有的,那每次都会走一下数据库查询
# defer与only的相反,defer括号里有什么字段,那生成的对象里就没有什么字段,需要这个字段的值就需要重新走一遍数据库查询
# 2. select_related 和 prefech_related
# select_related 相当于连表操作,现将models后面的表和括号内外键字段关联起来,之后一次性把所有的数据查到对象中
# prefech_relate 相当于没有将多步操作合并的子查询,先查询到models后面的表的所有数据,然后将括号内关联的表的数据全部查询到对象里
# 1.only与defer
# res = models.Book.objects.values('title') # 列表套字典
# res1 = models.Book.objects.only('title') # 列表套对象
# print(res1)
# for i in res1:
# # print(i.title)
# print(i.price)
"""
only括号内写什么字段
生成的对象就含有对应的属性 在查找该属性的时候不再走数据库查询
但是一旦查找括号内没有的字段属性 则每次都会走数据库查询
"""
# res1 = models.Book.objects.defer('title')
# # print(res1) # 列表套对象
# for i in res1:
# print(i.title)
"""
defer与only刚好相反
生成的对象就不含有对应的属性 在查找该属性的时候需要每次走数据库查询
但是一旦查找括号内没有的字段属性 则不需要走数据库查询
"""
# 2. select_related 和 prefech_related
# res = models.Book.objects.filter(pk=3).first()
# print(res.publish.title)
# res = models.Book.objects.select_related('publish')
# for i in res:
# print(i.publish.title)
"""
select_related相当于连表操作
先将models后面的表和括号内外键字段关联的表连接起来
之后一次性把所有的数据封装到数据对象中
"""
res = models.Book.objects.prefetch_related('publish')
for i in res:
print(i.publish.title)
"""
prefetch_related相当于子查询
先查询models后面的表的所有的数据
然后将括号内关联的表的数据全部查询出来
之后整合到一起
"""
数据日期字段截取
from django.db.models.functions import TruncMonth
date_menu = models.Article.objects.filter(blog=blog)
.annotate(month=TruncMonth('create_time'))
.values('month')
.annotate(c=Count('pk'))
.values_list('month','c')
将日期截取到月份
create_time month
2020-11-11 2020-11
2020-11-1 2020-11
2020-11-22 2020-11
2020-11-23 2020-11
TruncMonth 截取到月份 几年几月
TruncYear 截取到年 几年
TrunDay 截取到日 几年几月几日
批量插入数据
.bulk_create() # 可以批量插入数据,大大加快的存储速度
def home(request):
# 一条条插入,效率极低
for i in range(1,10001):
models.Book.objects.create(title=f'第{i}本书')
# 批量插入
book_list = []
for i in range(1,10001):
book_list.append(models.Book(title=f'第{i}本书'))
models.Book.objects.bulk_create(book_list)
终端打印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',
},
}
}

浙公网安备 33010602011771号