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)

事务

  1. 事务的四大特性 ACID
    • 原子性(atomicitty):一个事务是一个不可分割的工作单位,事务中包括的诸多操作要么都做,要么都不做
    • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性密切相关
    • 独立性(隔离性,isolation):一个事务的执行不能被其他事务干扰,每个事务相互之间是独立的。
    • 持久性(durability,也称永久性 permanence):事务对数据库的改变是永久的,
  2. 数据库设计三大范式
    • 第一范式
    • 第二范式
    • 第三范式
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',
        },
    }
}
posted @ 2021-06-30 20:32  zheng-sn  阅读(70)  评论(0)    收藏  举报