一、Django终端打印SQL语句

如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看

在Django项目的settings.py文件中,在最后复制粘贴如下代码:

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}

查看内部sql语句配置

补充:

除了配置外,还可以通过一点.query即可查看查询语句,具体操作如下:

二、测试环境

我们测试的时候不想一直通过网络请求,可以用app里面的test文件也可以自己新建test测试文件来直接测试,配置如下:

三、单表查询

1.单表增删改查

    # 增
# 方式1: create(这个有返回值,返回对象本身)
# book_obj = models.Book.objects.create(title='三国',price=19.99,create_time='2019-11-11')
# print(book_obj.title)
# 方式2:对象点save()方法
# from datetime import datetime
# ctime = datetime.now()
# book_obj = models.Book(title='金色梅',price=96.66,create_time=ctime)
# book_obj.save() # 查
# print(models.Book.objects.all())
# print(models.Book.objects.get(pk=1)) #不存在会立刻报错,测试使用
# print(models.Book.objects.filter(pk=2))
"""
pk会自动查找到当前数据的主键字段,无论你是id、tid、sid都能找到
""" # 改
# 1.update
# models.Book.objects.filter(pk=1).update(title='三国演义') #批量更新,指哪打哪
# 2.对象.save()
# book_obj = models.Book.objects.get(pk=1)
# book_obj.price = 666.66
# book_obj.save() #这个效率极低,会将此对象所有属性从头到尾更新一遍 # 删除 delete()
# models.Book.objects.filter(pk=2).delete()
   #

2.必会13种方法

   # < 1 > all(): 查询所有结果

    # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
# < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
# < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
# print(models.Book.objects.exclude(pk=1)) # 只要pk不是1的数据全部查询出来 # < 5 > order_by(*field): 对查询结果排序('-id') / ('price')
# print(models.Book.objects.order_by('price')) # 默认是升序
# print(models.Book.objects.order_by('-price')) # 加负号就是降序 # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
# print(models.Book.objects.order_by('price').reverse()) # < 7 > count(): 返回数据库中匹配查询(QuerySet)
# print(models.Book.objects.count()) # 对查询出来的结果进行一个计数 # 的对象数量。
# < 8 > first(): 返回第一条记录
# print(models.Book.objects.filter(pk=1).first())
# < 9 > last(): 返回最后一条记录
# print(models.Book.objects.all().last()) # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False,没毛用
# print(models.Book.objects.filter(pk=1000))
# print(models.Book.objects.filter(pk=1000).exists()) # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
# model的实例化对象,而是一个可迭代的字典序列
# print(models.Book.objects.values('title','price')) # 得到的结果是列表套字典 # < 12 > values_list(*field): 它与values()非常相似,他返回列表套元祖,values返回列表套字典
# print(models.Book.objects.values_list('title','price')) # 得到的结果是列表套元组   # < 13 > distinct(): 从返回结果中剔除重复纪录
#去重的前提是 一定要有完全重复的数据 才能去重
# print(models.Book.objects.filter(title='三国演义').distinct())
# print(models.Book.objects.values('title','price','create_time').distinct())

3.神奇的双下方法

            价格大于 小于 大于等于  小于等于   在什么之间  或好几个选择
price__gt
price__lt
price__gte
price__lte
price__in
price__range 书籍名称中包含
title__contains='p'
title__icontains='p' 创建的年份
create_time__year
"""神奇的双下滑查询"""
# 查询价格大于200的书籍
# res = models.Book.objects.filter(price__gt=200)
# 查询价格小于200的书籍
# res = models.Book.objects.filter(price__lt=200) # 查询价格大于等于200.22的书籍
# res = models.Book.objects.filter(price__gte=200.22)
# 查询价格小于等于200.22的书籍
# res = models.Book.objects.filter(price__lte=200.22) # 查询价格要么是200,要么是300,要么是666.66
# res = models.Book.objects.filter(price__in=[200,300,666.66])
# 查询价格在200到800之间的
# res = models.Book.objects.filter(price__range=(200,800)) # 两边都包含 # 查询书籍名字中包含p的 (mysql中才有效,自带小库不行)
"""原生sql语句 模糊匹配
like 关键字
% 匹配任意
_ 匹配一个
"""
# res = models.Book.objects.filter(title__contains='p') # 仅仅只能拿小写p
# res = models.Book.objects.filter(title__icontains='p') # 忽略大小写 # 查询书籍是以三开头的
# res = models.Book.objects.filter(title__startswith='三')
# res1 = models.Book.objects.filter(title__endswith='p') # 查询出版日期是2017的年(******)
#res = models.Book.objects.filter(create_time__year='2017')

四、多表操作(图书管理系统)

图书管理系统表创建
一对多:ForeignKey
一对一:OnoToOneField 可以用ForeignKey代替,ForeignKey(unique=True)
上面两个关键字所创建出来的字段会自动加上_id后缀 多对多:ManyToManyFiled
该字段并不会真正的在表中展示出来 它仅仅是一个虚拟字段
1.告诉orm自动创建第三种表
2.帮助orm跨表查询

models.py

from django.db import models

# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True) #auto_now_add只会在创建的时候创建日期,auto_now会在每一次修改数据时创建新日期 # 库存数
kucun = models.IntegerField(null=True) #表已经创建好后新增字段必须设置default=xxx或者null=True
# 卖出数
maichu = models.IntegerField(null=True) publish = models.ForeignKey(to='Publish') # 默认是跟publish的主键字段做的一对多外键关联
authors = models.ManyToManyField(to='Author')
# 虚拟字段 1.自动创建第三张表 2.帮助orm跨表查询 def __str__(self):
return self.title class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
# email = models.EmailField() # 就是varchar(254) def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail') def __str__(self):
return self.name
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=64)
"""
models.py中的模型类__str__方法 必须返回一个字符串形式数据!!! """
def __str__(self):
return self.addr

1.外键字段的增删改查

# 一对多的字段的增删改查

    # 增
# publish_id传数字
models.Book.objects.create(title='三国演义',price=189.99,publish_id=1)
# publish直接传出版社对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj) # 改
# 传数字的
models.Book.objects.filter(pk=1).update(publish_id=3)
# 传对象的
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj) # 删
# models.Publish.objects.filter(pk=2).delete() # 默认都是级联更新 级联删除

# 多对多字段的增删改查

在多对多表关系并且这一张多对多的关系表是由Django自动帮你建的情况下,下面的方法才可使用

    # 增
# 要给主键为1的书籍添加两个作者
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.add(1)
# book_obj.authors.add(2,3) # author_obj = models.Author.objects.filter(pk=1).first()
# author_obj1 = models.Author.objects.filter(pk=2).first()
# author_obj2 = models.Author.objects.filter(pk=3).first()
# book_obj.authors.add(author_obj)
# book_obj.authors.add(author_obj1,author_obj2)
"""
add()
是给书籍添加作者 括号内既可以传数字也可以传对象
并且支持一次性传多个 逗号隔开即可
""" # 改
# 将主键为1的书籍对象 作者修改为2,3
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.set([2,])
# book_obj.authors.set([2,3]) # author_obj = models.Author.objects.filter(pk=1).first()
# author_obj1 = models.Author.objects.filter(pk=2).first()
# author_obj2 = models.Author.objects.filter(pk=3).first()
# book_obj.authors.set([author_obj,])
# book_obj.authors.set([author_obj, author_obj1, author_obj2])
"""
set()括号内 需要传一个可迭代对象
可迭代对象中 可以是多个数字组合
也可以是多个对象组合
但是不要混着用!!!
""" # 删
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.remove(3)
# book_obj.authors.remove(1,2) # author_obj = models.Author.objects.filter(pk=1).first()
# author_obj1 = models.Author.objects.filter(pk=2).first()
# author_obj2 = models.Author.objects.filter(pk=3).first()
# book_obj.authors.remove(author_obj)
# book_obj.authors.remove(author_obj1,author_obj2)
"""
remove()括号内既可以传数字 也可以传对象
并且支持传对个 逗号隔开即可
""" # 将某本书跟所有作者的关系全部清空
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.clear() # 清空当前书籍与所有作者的所有关系 """
add()
set()
remove()
上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象 clear()
clear括号内不需要传任何参数
"""

2.ORM跨表查询(******)

2.1 正向与反向的概念

# 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写 # 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书 # 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书 总结:如果手上有关联字段就是正向,如果没有就是反向
    正向查询按外键字段
    反向查询按表名小写

2.2基于对象跨表查询

    """基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)"""
"""
强调:在书写orm语句的时候 跟写sql语句一样
不要尝试着 一次性写完 应该做到写一点看一点再一点
"""
# 1.查询书籍id是1 的出版社名称
# book_obj = models.Book.objects.filter(pk=1).first()
# print(book_obj.publish.name)
# print(book_obj.publish.addr) # 2.查询书籍id是2 的作者姓名
# book_obj = models.Book.objects.filter(pk=2).first()
# print(book_obj.authors) # app01.Author.None 有多个对象时必须加all
# print(book_obj.authors.all())
# res = book_obj.authors.all()
# for r in res:
# print(r.name) # 3.查询作者是jason的家庭住址
# author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.author_detail.addr) # 4.查询出版社是东方出版社出版的书籍
# publish_obj = models.Publish.objects.filter(name='东方出版社').first()
# # print(publish_obj.book_set) # app01.Book.None
# print(publish_obj.book_set.all()) #反向多个时,必须加_set.all # 5.查询作者是jason的写过的所有的书籍
# author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set) # app01.Book.None
# print(author_obj.book_set.all()) #反向多个 # 6.查询电话号码是130的作者姓名
# author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
# print(author_detail_obj.author.name)
# print(author_detail_obj.author.age) #反向一个不需要加set
"""
   当你查询结果是多个时需要加all
   否则直接外键字段即可
当你反向查询的结果是多个的时候 还需要加_set
否则直接表名小写即可
"""
# 7.查询书籍id为1 的作者的电话号码 (可以连续跨表查)
# book_obj = models.Book.objects.filter(pk=1).first()
# author_list = book_obj.authors.all()
# for author_obj in author_list:
# print(author_obj.author_detail.phone)

2.3基于双下划线的查询

 """基于双下划线的跨表查询(连表操作)
left join
inner join
right join
union
"""
# 1.查询jason作者的手机号
   # res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr') # 正向查 author_detail是外键字段
# print(res)
# res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone') #反向查 author是表名字小写
# print(res1) # 查询jason这个作者的年龄和手机号
# res = models.Author.objects.filter(name='jason').values('age','author_detail__phone')
# print(res)
# res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
# print(res1) # 查询手机号是130的作者年龄
# res = models.AuthorDetail.objects.filter(phone=130).values('author__age')
# print(res)
# res1 = models.Author.objects.filter(author_detail__phone=130).values('age')
# print(res1) # 查询书籍id是1 的作者的电话号码
# res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone') #authors带s的是字段名
# res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段')
# print(res)
"""只要表里面有外键字段 你就可以无限制跨多张表""" # 1.查询出版社为北方出版社的所有图书的名字和价格
# res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
# print(res) # 2.查询北方出版社出版的价格大于19的书
# res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title')
# print(res)

3.聚合查询(aggregate)

需要导入 Sum,Max,Min,Avg,Count
from django.db.models import Sum,Max,Min,Avg,Count
# 1.统计所有书的总价格
# # res = models.Book.objects.aggregate(Sum('price'))
# res1 = models.Book.objects.aggregate(Avg('price'))
# res2 = models.Book.objects.aggregate(Count('price'))
# res3 = models.Book.objects.aggregate(Max('price'))
# res4 = models.Book.objects.aggregate(Min('price'))
# res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))

4.分组查询(annotate)

    from django.db.models import Max, Min, Count, Avg, Sum
# 统计每一本书的作者个数
# res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
# print(res) # 统计出每个出版社卖的最便宜的书的价格
# res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
# print(res) # 统计不止一个作者的图书
# res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
# print(res) # 查询各个作者出的书的总价格
# res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
# print(res)
"""
只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选 """

5.F查询

需要导入F模块

#F查询的本质就是从数据库中获取某个字段的值

    """之前查询等号后面的条件都是我们认为输入的
现在变成了需要从数据库中获取数据放在等号后面
"""
from django.db.models import F

  #查询库存数大于卖出数的书籍
  # res = models.Book.objects.filter(kucun__gt=F('maichu'))
# print(res) # 将书籍库存数全部增加1000
# models.Book.objects.update(kucun=F('kucun')+1000) # 把所有书名后面加上'新款' (了解即可)
   #先导入下面两个模块
# from django.db.models.functions import Concat
# from django.db.models import Value # ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
# models.Book.objects.update(title = F('title')+'新款') # 不能这么写,会报错还会破坏数据库原有名字

6.Q查询

或 与 非就用Q

from django.db.models import Q
# 查询书籍名称是三国演义或者价格是444.44
# res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系,不支持或关系
# res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系 # res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) #或 # res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) #取反

Q高级用法(了解)

   
#支持用户输入字符串来查询
   q = Q()
q.connector = 'or' # 修改查询条件的关系 默认是and
q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件
q.children.append(('price__gt',444)) # 往列表中添加筛选条件
res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系
print(res)

7.事务

事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则里面回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对于事务则是部分支持)

django使用事务:

from django.db import transaction

with transaction.atomic():
"""数据库操作
在该代码块中书写的操作 同属于一个事务
"""
models.Book.objects.create()
models.Publish.objects.create()
# 添加书籍和出版社 就是同一个事务 要么一起成功要么一起失败
print('出了 代码块 事务就结束')

最新文章

  1. windows防火墙命令
  2. Python文件使用“wb”方式打开,写入内容
  3. 如何在CentOS 7中禁止IPv6
  4. python入门练习题1
  5. java 集合(set)
  6. ansible服务模块和组模块使用
  7. ccflow学习下载网址
  8. C语言 处理文件
  9. java项目测试log4j
  10. Craig可能是个冲浪爱好者
  11. React-Native入门
  12. sublimit 编辑器 设置默认的编码
  13. Spark笔记-repartition和coalesce
  14. 关于Django Ajax CSRF 认证
  15. 一、JAVA变量类型:②局部变量
  16. Docker技术综述
  17. C#实体类对象修改日志记录
  18. poj 2284 That Nice Euler Circuit 解题报告
  19. Ubuntu 上更新 Flash 插件
  20. jemter多种方式查看结果树及正则的使用

热门文章

  1. javascript 入门 之 bootstrap 第一个程序
  2. MODIS系列之NDVI(MOD13Q1)二:modis数据相关信息
  3. C与C++的函数声明中省略参数的不同意义
  4. git获取特定的commit
  5. HttpClient之Get请求和Post请求示例
  6. 如何利用 githob 上传自己的网站
  7. Ubuntu安装Elasticsearch6.3
  8. golang方法详解
  9. 关于“xxx”object is not callable的异常
  10. deepin下深度终端使用ssh-agent(xshell中的xagent功能)