- 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()# 返回布尔值 判断数据对象是否存在
- 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')
-
- # 多对多外键表是第三方表\
- # 增
- 方法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()括号内不加任何参数
- '''
- # 正向
- 外键字段在我手上,我查你就是正向
- # 反向
- 外键字段不在我手上,我查你就是反向
- 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()
- '''
-
- # 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',
- },
- }
- }
- # 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')
- # 聚合查询 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查询
- 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)
- '''
- 事物
- ACID
- 原子性:不可分割的最小单位
- 一致性:跟原子性相辅相成
- 隔离性:事物之间互相不干扰
- 持久性:事物一旦确定永久生效
- 事物的回滚 rollback
- 事物的确认 commit
- # 目前你只需要简单的开启事物
- from django.db import transaction
- transaction.atomic():
- sql语句
- 在with代码块内书写的所有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该方法内部就是子查询
- 将子查询出来的所有结果也给你封装到对象中
- 给你的感觉也好像是一次性搞定
- '''