单表操作
DateField里面的参数:
auto_now:每次更新的时候,都会重新记录时间 (=True)
auto_now_add:创建数据时,自动将当前时间记录下来 =(True)
测试test创建
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm.settings")
import django
django.setup()
from app01 import models
##前三行去manage.py中复制
##特别需要注意的是 后面三句的顺序一定要写在__main__中,而且模型层导入放在最后,然后就可以开始测试了
单表操作:(强调:只要是queryset对象就可以无限制的点queryset的方法)
models.Book.objects.filter().filter.filter.filter.filter.filter
单表操作实战-增删改查
#新增数据
#方法1
obj=models.Book.objects.create(name='三国演义',price='10',publish='北方出版社',author='linxiao')
#方法2
obj1=models.Book(name='红楼梦',price='20',publish='南方出版社',author='lindaxian')
obj1.save()
#查询
#方法1
book_obj=models.Book.objects.all()
book_obj1=models.Book.objects.filter(name='三国演义',price='10').first()
#取到的是queryset对象 filter中的,是and的关系,.first获得的是一个Book的对象
#方法2
book_obj2=models.Book.objects.get(name='三国演义1')
#获得的直接是对象 但是数据不存在直接报错
#修改
#方法1
models.Book.objects.filter(price='20').update(price='15')
#方法2
book_obj=models.Book.objects.filter(name='三国演义').first()
book_obj.name='西游记'
book_obj.save()
#直接使用queryset.xxx可以直接修改保存 如果获得的是一个对象 然后对象.属性修改 必须使用save()保存
#删除
models.Book.objects.filter(name='西游记').delete()
#删除的值不存在 不会报错
单表操作实战-补充
<1> all(): 查询所有结果
<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
<4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
<5> order_by(*field): 对查询结果排序('-id')/('price')
<6> reverse(): 对查询结果反向排序 >>>前面要先有排序才能反向
<7> count(): 返回数据库中匹配查询(QuerySet)的对象数量。
<8> first(): 返回第一条记录
<9> last(): 返回最后一条记录
<10> exists(): 对查询出来的QuerySet进行有无数据的判断,有就返回True,否则返回False
<11> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
<12> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<13> distinct(): 从返回结果中剔除重复纪录
单表操作实战-补充-双下划线的用法
#双下划线的用法
#查询价格大于30的数据
res=models.Book.objects.filter(price__gt='30')
#查询价格小于30的数据
res = models.Book.objects.filter(price__lt='30')
#查询价格大于等于30的数据
res = models.Book.objects.filter(price__gte='30')
#查询价格是否在列表中
res=models.Book.objects.filter(price__in=['20','10'])
#查询价格在某个区间范围内
res=models.Book.objects.filter(price__range=('0','50’))
#查询名称中含有’三’的书籍
title__contains=‘三’
#查询书籍名称中有字母p的书籍,并忽略大小写
title__icontains=‘p’
返回QuerySet对象的方法有:
all()
filter()
exclude()
order_by()
reverse()
distinct()
特殊的QuerySet
values() 返回一个可迭代的字典序列
values_list() 返回一个可迭代的元祖序列
返回具体对象的
get()
first()
last()
多表操作
如何判断表关系:一方能否有多个另一方,另一方能否有多个一方
一对一:其实就是一张表被人为拆分成了两张表而已,主要是为了缓解查询压力
一对多:通常建立在多的那一方
多对多:多对多字段建立在哪张表都可以,但是通常建立在查询频率比较高的那张表里,为了后期的正向查询提高方便
多表关系的建立
#建立外键
publish=models.ForeignKey(to='Publish')
#建立多对多表 虚拟字段,只是告诉orm新建第三表表示book跟author多对多的关系
authors=models.ManyToManyField(to='Author’)
#一对一表
authordetail=models.OneToOneField(to='AuthorDetail')
多表操作实战-一对多增删改查
#书籍表一对多字段的增删改查
#创建图书的两种方式
#publish_id直接传入出版社的id即可
models.Book.objects.create(name='金不梅',price=10,publish_id=1)
#publish直接传入出版社对象
publish_obj=models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(name='封神榜',price=100,publish=publish_obj)
#修改图书的两种方式
#方法一
models.Book.objects.filter(name='三国演义').update(publish_id=2)
#方法二
publish_obj=models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(name='金不梅').update(publish=publish_obj)
多表操作实战-多对多增删改查
多对多字段数据的增删改查
多对多字段新增 add()里面可以直接传id值,并且可以传多个,也可以传对象,也支持多个
remove()删除
clear()清空该图书的所有数据 不支持传参
set()先清空 再添加 参数必须是可迭代对象
多表操作实战-多对多增删改查代码
#数据多对多字段的增删改查
#给书籍对象添加作者
book_obj=models.Book.objects.filter(name='金不梅').first()
book_obj.authors.add(1) #给当前数据对象添加id为1的作者
book_obj.authors.add(1,2) #给当前对象添加id为1,2的作者
author_obj=models.Author.objects.filter(id=3).first()
author_obj2=models.Author.objects.filter(id=2).first()
author_obj3=models.Author.objects.filter(id=1).first()
author_queryset=models.Author.objects.all()
book_obj.authors.add(author_obj) #给当前数据对象添加作者
book_obj.authors.add(*author_queryset) #给当前数据对象添加作所有者
book_obj.authors.add(author_obj,author_obj2) #给当前数据对象添加作者1,2
#删除数对象与作者的绑定关系
book_obj=models.Book.objects.filter(pk=5).first()
book_obj.authors.remove(1,2) #支持传多个id 也支持传多个对象参数
#修改数据与作者的绑定关系
book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.set([1,]) #先清空再添加 参数必须是一个可迭代的对象 既可以传id值也可以传对象
#一次性清空作者的绑定关系
book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.clear() #不支持传参,调用就意味清空所有
跨表查询:
正向查询按字段 反向查询按表名小写
只要是查询结果是多的 要加个all()
补充知识点
补充一个知识点概念
正向查询按字段,反向查询按表名小写
正向与反向
# 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写
# 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写
# 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写
反向:
一对多 反向后面要加_set.all() 查出来是queryset本身
一对一不用加_set 查出来是对象本身
多对多 反向后面要加_set.all() 查出来是queryset本身
基于对象的跨表查询
#正向查询
#查询书籍是金不梅的出版社的地址
book_obj=models.Book.objects.filter(name='金不梅').first()
res=book_obj.publish.addr #一本书只能有一个出版社
#查询书籍金不梅的作者名字
book_obj=models.Book.objects.filter(name='金不梅').first()
res=book_obj.authors.all() #一本书可能有多个作者 要.all()
#反向查询
#查询东方出版社出版的书籍
#一对多 正向按字段 反向按表名小写加_set
publish_obj=models.Publish.objects.filter(name='东方出版社').first()
res=publish_obj.book_set.all() #只要不是一对一 都要.all()
#多对多
#查询所有林霄写过的书
author_obj=models.Author.objects.filter(name='林霄').first()
res=author_obj.book_set.all()
#一对一
#作者电话是110的作者的姓名
author_detail=models.AuthorDetail.objects.filter(phone='110').first()
res=author_detail.author.name
基于双下划线的多表查询
#作者姓名是林霄写过书的价格 反向
res=models.Author.objects.filter(name='林霄').values('book__price')
#查询书籍id为1的出版社的addr 正向的
res=models.Book.objects.filter(id=1).values('publish__addr') # 这里的publish不是表名小写而是字段
#查询书籍是金不梅的作者的电话号码
res=models.Book.objects.filter(name='金不梅').values('authors__authordetail__phone').first()
# 查询林霄作者的手机号
# 正向
res=models.Author.objects.filter(name='林霄').values('authordetail__phone')
# 反向
res=models.AuthorDetail.objects.filter(author__name='林霄').values('phone')
# 查询东方出版社出版的价格大于30的书
res=models.Publish.objects.filter(name='东方出版社',book__price__gt='30').values('book__name')
在控制台打印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',
},
}
}
聚合查询
#聚合查询
from django.db.models import Avg,Sum,Max,Min,Count
res=models.Book.objects.all().aggregate(Avg('price'))
res=models.Book.objects.all().aggregate(Sum('price'))
res=models.Book.objects.all().aggregate(Max('price'))
res=models.Book.objects.all().aggregate(Min('price'))
res=models.Book.objects.all().aggregate(Count('price'))
分组查询
#给数据库设置严格模式 会报错
from django.db.models import Count,Min
# 统计出每个出版社买的最便宜的书的价格
publisher_list = models.Publish.objects.annotate(min_price=Min("book__price"))
F与Q查询
F查询
查询的条件左右两边都来自数据库 而非手动输入
#F查询 查询的条件左右两边都来自于数据库而非你自己定义的值
from django.db.models import Q,F
res=models.Book.objects.filter(maichu__gt=F('kuchu')).values('name')
#讲商品的价格全部提高50
models.Book.objects.update(price=F('price')+50)
Q查询
将filter内部默认的and关系转换成与或非
与 &
或 |
非 ~
#Q查询能够将filter内部默认的and关系转化成或与非 或& 与| 非~
from django.db.models import Q
res=models.Book.objects.filter(Q(name='三国演义')|Q(name='水浒传')).values('name')
Q的另一种用法
q=Q()
q.children.append(’name’,'金不梅’)
models.Book.objects.filter(q)