一、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)