Django 07

今日考题

1.必知必会N条都有哪些,每个都是干啥使的

models.User.objects.all() # 查询所有数据
models.User.objects.filter() # 带有过滤条件的查询
models.User.objects.get() # 直接拿数据对象,条件不存在直接报错
models.User.objects.all().first() # 拿queryset里面的第一个元素
models.User.objects.all().last() # 拿queryset里面的最后一个元素
models.User.objects.values('name') # 可以指定获取数据字段 相当于select name from ...
models.User.objects.values('name','age').distinct() # 去重一定要去除一模一样的数据,如果带有主 
                                                       键那么一定不一样数据
models.User.objects.order_by('age') # 默认升序
models.User.objects.order_by('-age') # 降序
models.User.objects.order_by('age').reverse()# 反转的前提一定是已经排过序
models.User.object.count() # 统计当前数据的个数
models.User.object.exclude(name='jaosn')# 排除在外
models.User.object.filter(pk=1).exist()# 返回布尔值 判断数据对象是否存在

2.简述神奇的双下划线查询都有哪些方法,作用是什么

1、年龄大于35岁的数据
res = models.User.objects.filter(age__gt=35)
2、年龄小于35岁的数据
res = models.User.objects.filter(age__lt=35)
3、大于等于 小于等于
res = models.User.objects.filter(age__gte=35)
res = models.User.objects.filter(age__lte=35)
4、年龄是18 或者32 或者40
res = models.User.objects.filter(age__in=[18,32,40])
5、年龄在18到40岁之间 首位都要
res = models.User.objects.filter(age__range=[18,40])
6、查询名字带有s的数据 模糊查询 区分大小写
res = models.User.objects.filter(name__contains='s')
不区分大小写
res = models.User.object.filter(name__icontains='s')
7、查询名字开头结尾是否带有J
res = models.User.objects.filter(name__startswith='j')
res = models.User.objects.filter(name__endswith='j')
8、查新注册时间是2002年1月
res = models.User.objects.filter(register_time__year='2002')
res = models.User.object.filter(register_time__month='1')

3.针对多对多外键字段的增删改查方法有哪些,各有什么特点?

# 多对多外键表是第三方表\
# 增
方法1:直接给定绑定编号
book_obj = models.Book.objects.filter(pk=1).first() # 主键值为1的book对象
book_obj.authors # 进入第三个虚拟表中
book_obj.authors.add(1) # 给主键值为1的book对象绑定主键值为1的作者 (一本书一个作者)
book_obj.authors.add(1,2)# 给主键值为1的book对象绑定主键值为1,2的作者(一本书两个作者)
方法二:虚拟字段,绑定对象
author_obj = models.Author.objects.filter(pk=1).first() # 主键值为1的author对象
book_obj.authors.add(author_obj)
'''
add() 给第三方表传数字也可以是对象,并且都支持多个

'''
# 删
book_obj.authors.remove(1) # 删除给book对象绑定的单个作者
book_obj.authors.remove(1,2) # 删除给book对象绑定的多个作者
'''
remove()就可以传对象 也可以传数字
'''
# 修改
book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象
虚拟对象方式
author_obj = models.Author.objects.filter(pk=2).first()
book_obj.authors.set([author_obj]) 
'''
括号内必须传一个可迭代对象,该对象既可以是数字,也可以是对象,并且都支持多个

'''
# 清空
清空第三方表中书籍与某些作者的第三方关系
book_obj.authors.clear() # 清空主键字段为1的书籍与作者的绑定关系
'''
clear()括号内不加任何参数
'''

4.什么是正反向的概念,及查询口诀,你能否总结一下正反向查询不同情况下点击不同字段的规律

# 正向
外键字段在我手上,我查你就是正向
# 反向
外键字段不在我手上,我查你就是反向
eg:
Book 外键字段在书在(正向)>> Publish
Publish 外键字段是书(反向)>>> Book
'''
一对一和多对多的正反向查询也是如此
口诀:正向查询按字段 反向查询按表明小写 --set
'''

上周内容回顾

单表的增删改查

# 增
1.create()
2.对象.save()
# 查
1. all() 查所有
2. 筛选条件,括号内多个参数之间逗号隔开 并且默认是and关系
3. get()  条件不存在直接报错 不推荐使用
# 改
 update()  queryset对象帮你封装的批量更新
对象.save()
# 删
delete() queryset对象帮你封装的批量删除
对象.delete()
'''
在实际项目中数据是不可能真正删除的 一般情况下都用一个字段来标记是否删除
'''

测试环境准备

# 你如果只想测试django某一py文件(大部分情况下就是models.py)
# 在应用下的tests.py或者自己新建一个py文件
'''
1.去manage.py拷贝前四行
2.自己书写两行
    import django
    django.setup()
'''

如何查看ORM内部的sql语句

# 1.queryset对象可以直接点query查看
queryset对象.query
# 2.配置文件配置日志相关代码即可(不用记,直接复制粘贴)
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

必知必会N多条

# 1.all() 查看所有数据
# 2.filter() 我们在利用主键字段筛选数据的时候,可以不考虑主键字段叫什么,直接使用pk代替
# 3.get() 筛选条件不存在直接报错
# 4.values() 获取指定字段的数据 返回结果是一个queryset对象(列表套字典的形式)
# 5.values_list() 获取指定字段对应的数据 返回结果是一个queryset对象(列表套元组的形式)
# 6.count() 统计查询出来的数据个数
# 7.first()
# 8.last()
# 9.order_by() 默认是升序 你可以在字段前面加一个-变成降序
# 10.reverse() 前面已经是排序过了 之后在反转
# 11.exclude() 排除...在外
# 12.distinct() 去重(主键一定不要忘记)
# 13.exists() 判断数据值是否有值 返回布尔值



神奇的双下划线查询

# 价格大于 小于 大于等于 小于等于
prince__gt
prince__lt
prince__gte
prince__lte


# 成员运算
prince__in

# 范围查询
prince__range

# 模糊查询
title__contains 默认是区分大小写
title__icontains 忽略大小写

# 只按照年份或者月份或者
create_time__yaer
cretae_time__month

外键字段的增删改查

# 一对多
publish_id = 1
publish = publish_obj

# 多对多
add
remove
上述两个方法括号内既可以传对象也可以传数字并且都支持多个
set 括号内必须传一个可迭代对象 可迭代对象里面可以是数字也可以是对象并且都支持传多个
clear 括号内无需给任何参数 直接清空对应的数据关系

多表查询

# 正反向概念
正向 外键字段就在我手中
反向 外键字段不在我手中
#小口诀
正向查询按外键字段 反向查询按表明小写
_set
.all()

# 温馨提示
书写sql语句和orm语句一样 不要试图一次性写完 可以分步写
'''
多表操作
1.子查询
2.联表操作
inner join
left join
right join
union


Django orm中
1 基于对象的跨表查询
    子查询
        先拿到一个数据对象 然后点点点
2 基于双下划线的跨表查询
    联表查询


'''
1.基于对象的跨表查询
book_obj.publish
book_obj.authors.all()
author_obj.author_detail


publish_obj.book_set.all()
author_obj.book_set.all()

2.基于上下划线的跨表查询
models.Book.objects.filter(pk=1).values('title','publish__name')
models.Publish.objects.filter(pk=1).values('book_title','name')
# 利用双下划线的跨表查询可以帮助你跨n多张表 只要有外键字段
models.Book.objects.filter(pk=1).values('authors__author_detail__phone')

今日内容概要

  • 聚合查询(聚合函数的使用)
  • 分组查询的使用
  • F与Q查询
  • django中如何开启事物
  • orm中常用字段及参数
  • 数据库查询优化(only与defer、select_related与prefetch_related)
  • 图书管理系统作业讲解

今日内容详细

聚合查询

# 聚合查询 aggregrate
'''
聚合查询通常情况下都是配合分组一起使用的
只要是跟数据库相关的模块基本上都在django.db.models
如果没有也应该在django.db里面
'''
from app01 import models
    from django.db.models import Max,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('price'),Avg('price'))
    print(res)

分组查询

# 分组查询 annotate
'''

mysql分组查询有那些特点
分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取
严格模式
    ONLY_FULL_GROUP_BY

'''
# 1、统计每一本书的作者个数
    res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
    print(res)
models后面点书就按照书分组,author_num是我们自己定义的字段 用来存储统计出来的每本书对应的作者个数
'''
代码没有补全不要怕正常写 补全是pycharm给你的 后面到服务器上面直接书写代码 什么补全都没有
'''
 # 2.统计每个出版社卖的最便宜的书的价格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
    print(res)

    # 3.统计不止一个作者的图书(先按照图书分组,求每一本书对应的作者个数,过滤出不止一个作者的图书)
    res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
    print(res)

'''
只要你的orm语句结果还是一个queryset对象那么他就可以无限制的点queryset对象封装的方法
'''

# 4.查询每个作者出的书的总价格
    res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    print(res)

'''
如果我想要按照指定的字段如何处理呢?
models.Book.objects.values('price').annotate()
'''

F与Q查询

# F查询
    from django.db.models import F
'''
能帮助你直接获取表中的某个数据
在操作字符类型数据的时候 F不能够做到字符串的拼接
'''

    # 1、查询卖出数大于库存数的书籍
    res = models.Book.objects.filter(maichu__gt=F('kucun')).first()
    print(res.title)

    # 2.将所有的书籍价格提高500元
     res = models.Book.objects.update(price=F('price')+500)

    # 3.将所有书的后面名称都加上爆款两字
    from django.db.models.functions import Concat
    from django.db.models import Value

     res = models.Book.objects.update(title=Concat(F('title'),Value('爆款')))

     res = models.Book.objects.update(title=F('title')+'爆款') #所有名称都会变成空白
# Q查询

 # 1.查询卖出数大于800 价格小于800的书籍
    # res = models.Book.objects.filter(maichu__gt=800,price__lt=900)
    # print(res)
    '''
    filter括号内多个参数之间是and关系
    
    '''
    from django.db.models import Q
    # res = models.Book.objects.filter(Q(maichu__gt=800),Q(price__lt=900)) #Q包裹逗号分割 还是and关系
    # res = models.Book.objects.filter(Q(maichu__gt=800)|Q(price__lt=900)) #| or关系
    # res = models.Book.objects.filter(~Q(maichu__gt=800)Q(price__lt=900)) #~ not关系
    # print(res)
    # Q的高阶用法 能够将查询条件的左边也变成字符串的形式
    q = Q()
    # q.connector = ’or‘ 修改默认关系变成or
    q.children.append(('maichu__gt',800))
    q.children.append(('price__lt',900))
    res = models.Book.objects.filter(q) # 默认是and关系
    print(res)

django中如何开启事物

'''
事物
ACID
原子性:不可分割的最小单位
一致性:跟原子性相辅相成
隔离性:事物之间互相不干扰
持久性:事物一旦确定永久生效

事物的回滚  rollback
事物的确认 commit
# 目前你只需要简单的开启事物
from django.db import transaction
transaction.atomic():
sql语句
在with代码块内书写的所有orm操作都属于同一个事物

orm中常用字段及参数

AutoFiled int自增列 必须填入参数 primary_key=True。当model中没有自增列,则自动会创建一个列名为id的列

InterField   int
BigInterField  bigint

CharField 字符类型varchar  必须提供max_length参数,表示长度

DateField 日期字段
DateTimeField 日期时间字段 
参数:auto_now每次修改数据的时候都会更新时间
auto_now_add 只在创建数据的时候记录创建时间后续不会自动修改

BooleanField(Field) 布尔值类型
该字段传布尔值(False/True) 数据库里面存1或0

TextField(Field)  文本类型
该字段可以用来存大段文本内容 没有字数限制

FileField(Field) 字符类型
upload_to = '/data'
给该字段传一个文件对象,会自动将文件保存到/data目录下然后将文件路径保存到数据库中
/data/a.txt

#django除了给你提供很多字段类型之外 还支持你自定义字段类型


# 字段参数
null 用于表示某个字段可以为空

unique 如果设置unique=True 表示该字段再此表中是唯一的

db_index 如果db_index=True 则代表着为此字段设置索引

default 为该字段设置默认值

# 关系字段
ForeignKey
外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多'中'多'的一方。

ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。
字段参数
to 设置要关联的表
to_field 设置要关联表的字段
on_delete 当删除关联表中的数据时
db_constrains 是否在数据库中创建外键的约束,默认为True
class MyModel(models.Model):
    user = models.ForeignKey(
        to="User",
        to_field="id",
        on_delete=models.SET(func)
    )

OneToOneFiled
一对一字段。

通常一对一字段用来扩展已有字段。(通俗的说就是一个人的所有信息不是放在一张表里面的,简单的信息一张表,隐私的信息另一张表,之间通过一对一外键关联)



数据库查询优化

only 与 defer
select_related与prefetch_related
'''
orm语句的特点
惰性查询
如果你仅仅只书写了orm语句 在后面根本没有用到该语句查询出来的参数 那么orm会自动识别 不执行
'''
# 想要获取书籍表中所有书的名字
    # res = models.Book.objects.values('title')
    # for d in res:
    #     print(d.get('title'))
    # 你给我实现获取到的是一个数据对象,然后点title就能拿到书名 并且没有其他字段
    # res = models.Book.objects.only('title')
    # print(res)
    # for i in res:
    #     print(i.title) # 点击only括号内的字段不会走数据库
        # print(i.price) # 点击only括号外的字段会重新走数据库查询

    # res = models.Book.objects.defer('title') #对象除了没有title属性其他都有
    # print(res)
    # for i in res:
    #     print(i.title) # 点击defer括号内的字段重新走数据库查询
        # print(i.price) # 点击defer括号外的字段不会走数据库
    '''
    defer与only刚好相反
    defer括号内放的字段不在查询出来的对象里面 查询该字段需要重新走数据库
    而如果查询非括号内的字段不需要走数据库
    '''
    # res = models.Book.objects.all() # 每循环一次就要走一次数据库查询
    # for i in res:
    #     print(i.publish.name)
    # res = models.Book.objects.select_related('publish')
    '''
    select_related内部现将book与publish连起来 然后将大表里面的所有数据对象全部封装给查询出来的对象
    这个时候对象无论是点击book表中的数据还是publish表中的数据都无需再走数据库查询 网络请求越少延迟越低 也就是优化数据库查询
    select_related括号内只能放外键字段 一对一 一对多 多对多也不行
    '''
    # print(res)
    # for i in res:
    #     print(i.publish.name)
    res = models.Book.objects.prefetch_related('publish')
    for i in res:
        print(i.publish.name)
    '''
    prefetch_related该方法内部就是子查询
    将子查询出来的所有结果也给你封装到对象中
    给你的感觉也好像是一次性搞定
    '''

你可能感兴趣的:(Django,django,python,后端)