表查询
配置测试脚本
当你想单独测试django中某一个py文件 你需要手动配置测试脚本
如何配置测试脚本
第一种
直接在某一个应用下的tests文件中书写下面内容(去manage.py拷贝前四行代码)
然后自己写两行代码即可
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
import django
django.setup()
# 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
from app01 import models
第二种
直接新建一个任意名称的py文件 在里面也写上面的配置 也可以配置
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
import django
django.setup()
# 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
from app01 import models
创建数据
1.用create创建数据
传时间的时候除了手动写,也可以传入日期
from datetime import date
ctime = date.today()
book_obj = models.Books.objects.create(title='红楼梦',price=333,publish_data=ctime)
2.用对象的绑定方法
book_obj = models.Books(title='西游记',price='666',publish_data='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语句
print(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获取到的直接就是数据对象本身
当条件不存在的情况下
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()
在配置文件中添加:可以直接根据orm返回出对应的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', }, } }
13条查询
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) 3. get() 筛选 获取的是数据对象本身 条件不存在直接报错 并且查询条件必须是唯一的 数据对象 res = models.Books.objects.get(title='西游记') res1 = models.Books.objects.filter(title='西游记') # print(res,res1) print(res1) 4. first() 取queryset中第一个数据对象 数据对象 res = models.Books.objects.filter(title='西游记').first() print(res.price) 5. last() 取queryset中最后一个数据对象 数据对象 res = models.Books.objects.filter(title='西游记').last() print(res.price) 6. count() 统计数据的个数 数字 num = models.Books.objects.count() print(type(num)) 7. 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')}]> 8. 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() 颠倒顺序 前提是颠倒的对象必须有顺序(提前排序之后才能颠倒)和order_by连用 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=500) print(res)
查询价格小于等于500的书籍 res = models.Books.objects.filter(price__lte=500) print(res) 查询价格是222或者444或者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)
auto_now:每次修改的数据的时候 都会自动更新修改书籍(展示最新的一次修改时间)
auto_now_add:当数据创建出来的时候 会自动将创建时间记录下来
class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) publish_date = models.DateField(auto_now_add=True)#会自动写入时间
一对多字段的增删改查
传实际数字,或者传对象
增 第一种 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) # 同时传两个 传对象 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()#把书籍为2的所有记录都清除了 """ clear清空书籍相关所有记录 括号内不需要传递参数 """
基于对象的跨表查询
""" 正反向查询 关系字段在谁哪 由谁查谁就是正向 如果关系字段不在 就是反向 正向查询按字段 .all() authors.all() 多个情况下 反向查询按表名小写+ _set .all() book_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()即可 """ 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)