测试orm语句方法
在add下test文件内或者自创一个文件下,写上
from django.test import TestCase
Create your tests here.
当你想单独测试django中某一个py文件 你需要手动配置测试脚本
import os
if name == "main":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
import django
django.setup()
from app01 import models
orm日志设置
在settings文件下粘贴日志模块,在执行orm语句时就可以显示原生sql语句
orm方法
先创建数据
1.create方法
book_obj = models.Books.objects.create(title='三国演义',price=123.23,publish_date='2019-11-11')
print(book_obj)
from datetime import date
ctime = date.today()
book_obj = models.Books.objects.create(title='红楼梦', price=888.99, publish_date=ctime)
print(book_obj)
2.利用对象的绑定方法
book_obj = models.Books(title='西游记',price=666.66,publish_date='2000-1-21')
book_obj.save()
修改数据
res = models.Books.objects.filter(pk=1)
"""
pk会自动帮你查找到当前表的主键字段 所以后期我们都是用pk来指代主键字段
filter查询出来的结果是一个Queryset对象
1.只要是queryset对象就可以无限制的调用queryset的方法
res = models.Books.objects.filter(pk=1).filter().filter().filter().filter()
2.只要是queryset对象就可以点query查看当前结果内部对应的sql语句
res.query
SELECT app01_books.id, app01_books.title, app01_books.price, app01_books.publish_date FROM app01_books WHERE app01_books.id = 1
"""
方式1 利用queryset方法
models.Books.objects.filter(pk=1).update(price=444.66)
方式2 利用对象
book_obj = models.Books.objects.get(pk=1)
book_obj.price = 222.66
book_obj.save() # 该方法不推荐使用 推荐使用queryset方法
利用对象的修改 内部其实是重头到位将数据的所有字段都重新写一遍
"""
get和filter区别
1.filter获取到的是一个queryset对象 类似于一个列表
2.get获取的就是对象本shen
当条件不存在的情况下
filter不报错直接返回一个空 推荐使用filter方法
get直接报错 所以不推荐使用get方法
"""
删除数据
1.利用queryset方法 delete()
models.Books.objects.filter(pk=3).delete()
2,对象方法
book_obj = models.Books.objects.get(pk=3)
book_obj.delete()
查数据 13条
"""
如果你想查看所有的orm语句内部对应的sql语句
你可以直接在配置文件中配置相应的代码即可
"""
1. all() 查询所有 返回的结果QuerySet对象
res = models.Books.objects.all()
print(res)
"""
orm语句的查询默认都是惰性查询
只有当你真正要使用数据的时候才会执行orm语句
"""
2. filter() 筛选 相当于你原生sql语句里面的 where关键字 返回的结果QuerySet对象
res = models.Books.objects.filter(pk=1,title='三') # 支持多个参数 并且是and关系
print(res)
get() 筛选 获取的是数据对象本身 条件不存在直接报错 并且查询条件必须是唯一的 数据对象
res = models.Books.objects.get(title='西游记')
res1 = models.Books.objects.filter(title='西游记')print(res1)
first() 取queryset中第一个数据对象 数据对象
res = models.Books.objects.filter(title='西游记').first()
print(res.price)last() 取queryset中最后一个数据对象 数据对象
res = models.Books.objects.filter(title='西游记').last()
print(res.price)count() 统计数据的个数 数字
num = models.Books.objects.count()
print(type(num))values() 获取数据对象中指定的字段的值 可以有多个 queryset 列表套字典
res = models.Books.objects.values('title','price')
print(res)
<QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}, {'title': '西游记', 'price': Decimal('444.66')}, {'title': '西游记', 'price': Decimal('666.22')}]>values_list() 获取数据对象中指定的字段的值 可以有多个 queryset 列表套元祖
res = models.Books.objects.values_list('title','price')
print(res)
<QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
9.order_by() 按照指定的字段排序
res = models.Books.objects.order_by('price') # 默认是升序
res1 = models.Books.objects.all().order_by('price') # 默认是升序 两者等价 下面的方式 语义更明确
降序 字段前面加负号
res1 = models.Books.objects.all().order_by('-price')
print(res1)10.reverse() 颠倒顺序 前提是跌倒的对象必须有顺序(提前排序之后才能跌倒)
res = models.Books.objects.all()
res1 = models.Books.objects.all().reverse()
res2 = models.Books.objects.all().order_by('price')
res3 = models.Books.objects.all().order_by('price').reverse()
print(res2,res3)11.exclude() 排除什么什么之外 queryset对象
res = models.Books.objects.all().exclude(title='三国演义')
print(res)
<QuerySet [<Books: 红楼梦>, <Books: 西游记1>, <Books: 西游记2>]>12.exists() 判断查询结果是否有值 返回结果是一个布尔值
res = models.Books.objects.filter(pk=1).exists()
print(res)
该方法其实不需要使用 因为数据本身自带布尔值13.distinct() 对查询结果进行去重操作 去重的前提:数据必须是完全想要的情况下 才能够去重(你容易忽略主键)
res = models.Books.objects.values('title','price')
res = models.Books.objects.values('title','price').distinct()
print(res)
神奇的双下滑线查询
查询价格大于500的书籍
res = models.Books.objects.filter(price_gt=500)
print(res)
查询价格小于400 的书籍
res = models.Books.objects.filter(price_lt=400)
print(res)
查询价格大于等于500
res = models.Books.objects.filter(price_gte=444.66) 对数字精确度不敏感
res = models.Books.objects.filter(price_gte=500)
print(res)
查询价格小于等于500的书籍
res = models.Books.objects.filter(price_lte=500)
print(res)
查询价格是222.66或者444.22或者500的书籍
res = models.Books.objects.filter(price__in=[222,444,500])
print(res)
查询价格在200到800之间的书籍
res = models.Books.objects.filter(price__range=(200,800)) # 顾头顾尾
print(res)
查询出版日期是2019年的书籍
res = models.Books.objects.filter(publish_date_year='2019')
print(res)
查询出版日期是1月份的书籍
res = models.Books.objects.filter(publish_date__month='1')
print(res)
模糊查询
"""
MySQL中的模糊查询
关键字 like
模糊匹配的符号
%:匹配任何个数的任意字符
_:匹配一位任意的字符
"""
查询书籍是以三开头的书
res = models.Books.objects.filter(title_startswith='三')
print(res)
查询书籍是以义结尾的书
res = models.Books.objects.filter(title_endswith='1')
print(res)
查询书籍名称中包含游字的书籍
res = models.Books.objects.filter(title__contains='游')
print(res)
查询书籍名称中包含字母p的书籍
res = models.Books.objects.filter(title_contains='p') # 默认区分大小写
res = models.Books.objects.filter(title__icontains='p') # 忽略大小写 加i
print(res)
一对多字段增删改
增
第一种
models.Book.objects.create(title='三国演义',price=222.33,publish_id=1) # 直接传表里面的实际字段 跟数据主键值 publish_id
第二种
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj) 传虚拟字段 跟数据对象即可
改
第一种
models.Book.objects.filter(pk=1).update(publish_id=2)
第二种
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
删
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新
多对多字段数据的增删改
增
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish) # 点外键字段 可能会直接获取到外键关联的数据对象
给当前这一本书绑定作者
麻瓜做法 自己直接去操作第三张表
print(book_obj.authors) # 已经跨到第三张表了
book_obj.authors.add(1) # 在第三张表里面给书籍绑定一个主键为1的作者
book_obj.authors.add(1,2) # 在第三张表里面给书籍绑定一个主键为1的作者
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj,author_obj1)
"""
add方法 能够朝第三张关系表添加数据
即支持传数字
add(1,2)
也支持传对象
add(author_obj,author_obj1)
并且两者都可以是多个
"""
改
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set((1,3))
book_obj.authors.set([1,])
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj,author_obj1))
"""
set修改多对多关系表中的数据
既可以传数字也可以传对象
但是需要注意的是括号内必须是可迭代对象
都支持多个
set((1,3))
set((author_obj,author_obj1))
"""
删
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.remove(100)
book_obj.authors.remove(1,2)
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj,author_obj1)
"""
remove既可以传数字 也可以穿对象
并且都支持传多个 不需要迭代
remove(1,2)
remove(author_obj,author_obj1)
"""
清空 删除某个数据在第三张表中的所有记录
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear()
"""
clear清空书籍相关所有记录 括号内不需要传递参数
"""
跨表查询
"""
正反向查询
关系字段在谁哪 由谁查谁就是正向
如果关系字段 就是反向
正向查询按字段
反向查询按表名小写 + _set
"""
基于对象的跨表查询 子查询 分步操作
1.查询书籍主键为2的出版社名称
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish) # 出版社对象
print(book_obj.publish.name)
2.查询书籍主键为4的作者姓名
book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all())
3.查询作者是jason的手机号码
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.author_detail)
print(author_obj.author_detail.phone)
"""
什么时候需要加all
当正向查询点击外键字段数据有多个的情况下 需要.all()
app01.Author.None 一旦看到该结果 只需要加.all()即可
在写orm语句的时候跟你写sql语句一样 不要想着一次性写完
写一点查一点再写一点
"""
4.查询出版社是东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set) app01.Book.None
print(publish_obj.book_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()) # app01.Book.None
6.查询手机号是120的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author)
print(author_detail_obj.author.email)
"""
什么时候反向查询的时候表名小写需要加_set
一对多
多对多
一对一不需要加_set
"""
基于双下滑线的跨表查询 联表操作
"""
inner join
left join
right join
union
"""
1.查询书籍pk为2的出版社名称
正向
res = models.Book.objects.filter(pk=2).values('publish_name') # 写外键字段就相当于已经跨到外键字段所关联的表
你想要改表的哪个字段信息 你只需要加_获取即可
print(res)
反向
res = models.Publish.objects.filter(book__pk=2).values('name')
print(res)
2.查询书籍pk为2的作者姓名和邮箱
res = models.Book.objects.filter(pk=2).values('authors_name','authors_email')
print(res)
res = models.Author.objects.filter(book__pk=2).values('name','email')
print(res)
"""/
models后面点的谁 就以谁为基表
"""
3.查询作者是egon的家庭地址
res = models.Author.objects.filter(name='egon').values('author_detail_addr')
print(res)
res = models.AuthorDetail.objects.filter(author__name='egon').values('addr')
print(res)
4.查询出版社是东方出版社出版过的书的名字
res = models.Publish.objects.filter(name='东方出版社').values('book_title')
print(res)
res = models.Book.objects.filter(publish__name='东方出版社').values('title')
print(res)
查询书籍pk是2的作者的手机号
res = models.Book.objects.filter(pk=2).values('authors_author_detail_phone')
print(res)
res = models.Author.objects.filter(book_pk=2).values('author_detail__phone')
print(res)