Django 之 模型层ORM操作
2019-10-24 22:24 在上海的日子里 阅读(205) 评论(0) 编辑 收藏 举报目 录
-
ORM查询配置文件和测试环境搭建
-
- 配置文件(打印orm操作时显示sql语句) Django测试环境搭建
- 配置文件(打印orm操作时显示sql语句) Django测试环境搭建
-
-
单表查询
-
- 必知必会13条 神奇的双下划线查询
-
-
多表查询
- 子查询和连表查询 外键字段的增删改查 表与表之间的关联查询
一、ORM查询相关配置文件和django测试环境配置
1、想要在打印orm操作时显示原生的SQL语句,需要在settings.py 文件中添加如下代码:
""" 如果你向查看orm语句内部真正的sql语句有两种方式 1.如果是queryset对象 可以直接点query查看 2.配置文件中 直接配置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level': 'DEBUG', }, }} """
ORM查询语句中显示原生的SQL语句有两种方法:
一种是如上配置文件;
一种就是QuerySet对象,直接点Query查看,
只要是queryset对象就可以无限制的点queryset对象的方法
queryset.filter().filter().filter()
2、Django测试环境搭建
从manage.py 文件中拷如下代码,并添加 import django 和 django.setup() 两行代码
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_search.settings") import django django.setup() # 你就可以在下面测试django任何的py文件
二、单表查询
必知必会13 条, 神奇的双下划线查询
from django.test import TestCase # Create your tests here. import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_search.settings") import django django.setup() from app01 import models # res = models.Book.objects.all() # print(res) # 单表操作 # 增删改查 # 增 # models.Book.objects.create(title='金瓶霉',price=123.23,publish_date='2019-10-24') # from datetime import date # ctime = date.today() # book_obj = models.Book(title='三国演义',price=666.66,publish_date=ctime) # book_obj.save() # 改 # models.Book.objects.filter(pk=1).update(price=999.66) # book_obj = models.Book.objects.filter(pk=1).first() # book_obj.title = '不符合社会主义核心价值观' # book_obj.save() # 删除 # models.Book.objects.filter(pk=1).delete() # 查 # 1.all() 查询所有 QuerySet # res = models.Book.objects.all() # 惰性查询 # print(res) # for i in res: # print(i.title) # 2.filter() QuerySet # res = models.Book.objects.filter(pk=2) # print(res) # 3.get() 数据对象本身 # 4.first() 拿第一个 # res = models.Book.objects.all() # print(res) # print(res.first()) #5. last() 拿最后一个 # res = models.Book.objects.all() # print(res) # print(res.last()) # 6.exclude 除此之外 QuerySet # res = models.Book.objects.exclude(pk=3).filter(pk=4).filter(pk=1).filter(pk=4) # # # <QuerySet []> # # print(res) # 7.values QuerySet 列表套字典 # res = models.Book.objects.values('title') # for r in res: # print(r.get('title')) # 8.values_list QuerySet 列表套元组 # res = models.Book.objects.values_list('title') # print(res) # 9.count() 统计数据的个数 # res = models.Book.objects.count() # res1 = models.Book.objects.all().count() # print(res,res1) # 10.distinct() 去重 """去重:数据必须是一模一样的情况下才能去重""" # res = models.Book.objects.all().distinct() # res1 = models.Book.objects.values('title','price').distinct() # print(res1) # 11.order_by() # res = models.Book.objects.order_by('price') # 默认是升序 # # res1 = models.Book.objects.order_by('-price') # 加负号就是降序 # print(res) # 12.reverse() 前面必须是先结果排序才可以反转 # res = models.Book.objects.order_by('price').reverse() # print(res) # 13.exists() 一点卵用没有 # res = models.Book.objects.filter(pk=1).exists() # print(res) """神奇的双下划线查询""" # 查询价格大于200的书籍 # res = models.Book.objects.filter(price__gt=200) # 查询价格小于200的书籍 # res = models.Book.objects.filter(price__lt=200) # print(res) # 查询价格大于或者等于200的书籍 # res = models.Book.objects.filter(price__gte=200) # res1 = models.Book.objects.filter(price__lte=200) # print(res,res1) # 价格是200 或者是123.23 或者666.66 # res = models.Book.objects.filter(price__in=[200,123.23,666.66]) # print(res) # 价格在200 到700之间的书籍 # res = models.Book.objects.filter(price__range=(200,666.66)) # 顾头不顾尾 # print(res) # 模糊匹配 """ like % _ """ # 查询书籍名称中包含p的 # res = models.Book.objects.filter(title__contains='p') # 区分大小写 # print(res) # 忽略大小写 # res = models.Book.objects.filter(title__icontains='p') # 忽略大小写 # print(res) # 查询书籍名称是以三开头的书籍 # res = models.Book.objects.filter(title__startswith='三') # res1 = models.Book.objects.filter(title__endswith='P') # print(res1) # 查询出版日期是2019年的书籍 # res = models.Book.objects.filter(publish_date__year='2019') # 查询出版日期是10月的书籍 # res = models.Book.objects.filter(publish_date__month='10')
三、多表查询
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "many_search.settings") import django django.setup() from app01 import models # 一对多字段增删改查 # models.Book.objects.create(title='三国演义',price=123.23,publish_id=1) # publish_id直接传出版社主键值 # publish_obj = models.Publish.objects.filter(pk=2).first() # models.Book.objects.create(title='水浒传',price=123.23,publish=publish_obj) # publish直接传出版社数据对象 # 查 # book_obj = models.Book.objects.filter(pk=1).first() # print(book_obj.publish) # 获取到当前所对应的出版社对象 # print(book_obj.publish_id) # 获取到的就是表中的实际字段 # 改 # 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() # 默认也是级联更新 级联删除 # 多对多字段的增删改查 # 给主键为3的书籍添加两个作者 1 2 # book_obj = models.Book.objects.filter(pk=3).first() # # print(book_obj.authors) # 就相当于 已经在书籍和作者的关系表了 # # 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() # # book_obj.authors.add(author_obj) # book_obj.authors.add(author_obj,author_obj1) """ add() 括号内既可以传数字也可以传数据对象 并且都支持传多个 """ # 修改关系 # book_obj = models.Book.objects.filter(pk=3).first() # # book_obj.authors.set([3,]) # # book_obj.authors.set([1,3]) # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # book_obj.authors.set((author_obj,)) # book_obj.authors.set((author_obj,author_obj1)) """ set() 括号内 既可以传数字也传对象 并且也是支持传多个的 但是需要注意 括号内必须是一个可迭代对象 """ # 删 # book_obj = models.Book.objects.filter(pk=3).first() # # book_obj.authors.remove(2) # # 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() 括号内 既可以传数字也传对象 并且也是支持传多个的 """ # 清空 # book_obj = models.Book.objects.filter(pk=3).first() # book_obj.authors.clear() """clear()括号内不需要传任何参数 直接清空当前书籍对象所有的记录""" """ ORM跨表查询 1.子查询 2.连表查询 正反向的概念 外键字段在谁那儿 由谁查谁就是正向 谁手里有外键字段 谁就是正向查 没有外键字段的就是反向 书籍对象 查 出版社 外键字段在书籍 正向查询 出版社 查 书籍 外键字段在书籍 反向查询 正向查询按字段 反向查询按表名小写 ... """ # 1.基于对象的跨表查询 子查询 # 1.查询书籍是python入门的出版社名称 # book_obj = models.Book.objects.filter(title='python入门').first() # # 正向查询按字段 # print(book_obj.publish.name) # print(book_obj.publish.addr) # 2.查询书籍主键是6的作者姓名 # book_obj = models.Book.objects.filter(pk=6).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.phone) # print(author_obj.author_detail.addr) """ 正向查询 按字段 当该字段所对应的数据有多个的时候 需要加.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()) # 6.查询手机号是110的作者 # author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first() # print(author_detail_obj.author) # print(author_detail_obj.author.name) # print(author_detail_obj.author.age) """ 反向查询按表名小写 什么时候需要加_set 当查询的结果可以是多个的情况下 需要加_set.all() 什么时候不需要加_set 当查询的结果有且只有一个的情况下 不需要加任何东西 直接表名小写即可 """ # 7.查询书籍是python入门的作者的手机号 # book_obj = models.Book.objects.filter(title='python入门').first() # print(book_obj.authors.all()) # 2.基于双下划綫的跨表查询 连表查询 """ MySQL left join inner join right join union """ # 1.查询书籍是python入门的出版社名称 # 正向 # res = models.Book.objects.filter(title='python入门').values('publish__name') # print(res) # 反向 # res = models.Publish.objects.filter(book__title='python入门').values('name') # print(res) # 2.查询作者是jason的手机号码 # 正向 # res1 = models.Author.objects.filter(name='jason').values('author_detail__phone') # print(res1) # 反向 # res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age') # print(res) # 3.查询手机号是120的作者姓名 # res2 = models.AuthorDetail.objects.filter(phone=120).values('author__name') # print(res2) # res = models.Author.objects.filter(author_detail__phone=120).values('name','author_detail__addr') # print(res) # 4.查询出版社是东方出版社出版的书籍名称 # res = models.Publish.objects.filter(name='东方出版社').values('book__title','addr') # print(res) # 5.查询作者是jason的写过的书的名字和价格 # res = models.Author.objects.filter(name='jason').values('book__title','book__price') # print(res) # 7.查询书籍是python入门的作者的手机号 # res = models.Book.objects.filter(title='python入门').values('authors__author_detail__phone') # print(res)
后记:知识梳理和相关笔记总结
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
表查询 基于django settings源码实现自己的项目 配置文件的可插拔式设计 dir() importlib 反射 单表查询 只要是queryset对象 就可以无限制的点击queryset对象的方法 13条 1.all() # 查所有 2.filter() # 根据条件过滤 多个条件之间是and关系 3.get() # 直接获取数据对象 查询条件不存在直接报错 4.first() # 取queryset的第一个数据对象 5.last() # 取queryset的最后一个数据对象 6.exclude() # 除此之外 7.values() # queryset 类似于列表套字典 8.values_list() # queryset 类似于列表套元组 9.count() # 统计数据个数 10.distinct() # 一定要是完全一样的数据才能去重 11.order_by() # 排序 默认是升序 加负号就变成降序 12.reverse() # 反转 排序之后才能反转 13.exists() # 判断queryset是否有值 结果是个布尔值 神奇的双下线的查询 price__gt price__lt price__gte price__lte price__in=[100,200,300] price__range=(200,800) title__contains 包含 模糊匹配 title__icontains 忽略大小写 publish_date__year 只针对年份 publish_date__month 只针对月份 title__startswith title__endswith 多表查询 前期表准备 图书管理系统 一对多 多对多 一对一 外键字段的增删改查 一对多字段 create(publish_id=1) create(publish=publish_obj) update(publish_id=2) update(publish=publish_obj1) models.Publish.objects.filter(pk=2).delete() # orm外键默认是级联更新 级联删除的 多对多字段 # 朝第三张关系表中添加数据 book_obj.authors.add(1) book_obj.authors.add(1,2,3,4) book_obj.authors.add(author_obj) book_obj.authors.add(author_obj,author_obj1,author_obj2) # 朝第三张表修改数据 book_obj.authors.set((1,)) book_obj.authors.set((1,2,3)) book_obj.authors.set((author_obj,)) book_obj.authors.set((author_obj,author_obj1)) # 朝第三张表删除关系 book_obj.authors.remove(1) book_obj.authors.remove(1,2,3,4) book_obj.authors.remove(author_obj) book_obj.authors.remove(author_obj,author_obj1) # 朝第三张表清空当前书籍对象所有的记录 book_obj.authors.clear() 跨表查询 正反向的概念: 外键字段在谁那儿 谁就是正向 没有外键字段的 就是反向 口诀: 正向查询按字段 反向查询按表名小写 基于对象 # 子查询 """ 步骤都是先获取一个数据对象 然后利用对象点点点的方式查到锁对应的数据 """ # 正向 book_obj.publish.name book_obj.authors.all() author_obj.author_detail.addr """ 外键字段所对应的数据 如果是单个 不需要加all 如果是多个 需要加all() """ # 反向 publish_obj.book_set.all() author_obj.book_set.all() author_detail_obj.author.name """ 反向查询 数据如果是多个 那么需要 表名小写_set.all() 如果是一个 直接表名小写即可 """ 基于双下划綫 # 连表查询 """ left join right join inner join union """ # 正向 models.Book.objects.filter(title='python').values('publish__name') # 写外键字段publish之后 就会跨到publish表中 你想要该表的哪个字段对应的数据 就加__字段名获取 models.Book.objecst.filter(pk=1).values('authors__name') models.Author.objects.filter(name='jason').values('author_detail__addr') models.Publish.objects.filter(pk=1).values('book__title') models.authors.objects.filter(pk=1).values('book__title') models.AuthorDetail.objects.filter(pk=1).values('author__name') # 反向 models.Publish.objects.filter(book__title='python').values('name') """查询书籍id为1 的作者的 手机号""" models.Book.objects.filter(pk=1).values('authors__author_detail__phone')