Django ORM

ORM执行查看原生SQL的两种方法

1.在setting中配置

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

2.如果查询的结果是queryset对象可以.query查看命令

只要是queryset对象就可以无限制的点queryset对象的方法,queryset.filter().filter().filter()

搭建django-ORM测试环境

from django.test import TestCase
import os
# Create your tests here.
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zx1.settings")
import django django.setup()
from app01 import models
# 你就可以在下面测试django任何的py文件

res1=models.Book.objects.get(title='步天歌') 研究objects

不知道你有没有发现,objects和Queryset方法有很多是一样的,Queryset有的方法objects都会有,而且他们还有一个相似的地方,设置方法是返回值都是一样,都是返回Queryset对象

查看objects源码
发现底层是c实现的,看不了,但是这里出现了熟悉的东西,它继承的类中有个QUerySet
class Manager(BaseManager.from_queryset(QuerySet)):
pass 查看from_queryset源码,看它到底干了啥
@classmethod
def from_queryset(cls, queryset_class, class_name=None):
#class为空执行if内的内容
if class_name is None:
#这里拼接了字符串
class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
class_dict = {
'_queryset_class': queryset_class,
}
#这一步很可疑,到底向这个字典里放了什么,看下一段代码,使用了BaseManager._get_queryset_methods();
class_dict.update(cls._get_queryset_methods(queryset_class))
#创建了一个新的类对象,继承BaseManager
return type(class_name, (cls,), class_dict) 查看_get_queryset_methods源码
#可以发现这部分代码比较难,还好它有官方的注释,只要看注释就大概知道这部分代码大概干了啥
只复制缺少的方法。
只复制公共方法或具有属性的方法
将方法复制到管理器上。
根据注释知道这部分就是把queryset中的方法提取出来的部分,最后把方法放入字典
@classmethod
def _get_queryset_methods(cls, queryset_class):
#这里的queryset_class其实就是Queryset类对象
def create_method(name, method):
def manager_method(self, *args, **kwargs):
return getattr(self.get_queryset(), name)(*args, **kwargs)
manager_method.__name__ = method.__name__
manager_method.__doc__ = method.__doc__
return manager_method new_methods = {}
# Refs http://bugs.python.org/issue1785.
predicate = inspect.isfunction if six.PY3 else inspect.ismethod
for name, method in inspect.getmembers(queryset_class, predicate=predicate):
# Only copy missing methods.
if hasattr(cls, name):
continue
# Only copy public methods or methods with the attribute `queryset_only=False`.
queryset_only = getattr(method, 'queryset_only', None)
if queryset_only or (queryset_only is None and name.startswith('_')):
continue
# Copy the method onto the manager.
new_methods[name] = create_method(name, method)
return new_methods

objects总结

根据上面的研究objects其实就是一个由Manager创建的一个实例对象,而且它有QuerySet的方法,所以它和QuerySet是没有继承一类的关系的

接下来就是下一个问题了:既然objects和QuerySet的方法是一样的,那QuerySet是不是也可以查询数据库呢?

其实我们没创建一个model,比如Book他就会默认创建一个objects,那么objects有表的一些信息也就不奇怪了,但是单独创建一个QuerySet对象,它是没有这些信息的,那么它是缺少数据的。

QuerySet特性

由此可见QuerySet对象的强大,我看了部分源码发现其实惰性查询也是它实现的,它的功能非常强大。

queryset切片

queryset的切片不是对结果集的切片而是直接对sql进行limit和offset

res = models.Article.objects.all()[5:10] # (OFFSET 5 LIMIT 5)

queryset惰性查询

res = models.Article.objects.all()[5:10]
不去打印或者使用res的话,数据是还没有的,只有使用res才会去执行sql语句拿到查询的数据
print(res)的时候才会去查询数据

queryset缓存机制

下面的案例sql只查询了一次

    res = models.Article.objects.all()
for i in res:
print(i.title)
for i in res:
print(i.desc)

但是这样的话,是执行了两次

    res = models.Article.objects.all()
print(res)
print(res)

什么时候会触发缓存,什么时候不会触发?

https://www.jb51.net/article/169274.htm

get-first-last

get

因为框架默认返回的就是一个数据,如果条件是多个的就会报错

get方法并不是惰性查询,而且返回的是表模型的实例,可以这样理解它并不是QuerySet对象,不是惰性就很正常

res1=models.Book.objects.get(title='步天歌')

first-last

通过sql可以发现,如果拿第一个数据和最后一个数据,其实就是按主键进行排序,然后通过limit拿值

(0.001) SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date`, `app01_book`.`publish_id` FROM `app01_book` ORDER BY `app01_book`.`id` ASC LIMIT 1; args=()

(0.000) SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date`, `app01_book`.`publish_id` FROM `app01_book` ORDER BY `app01_book`.`id` DESC LIMIT 1; args=()

filter

惰性查询,我执行下面的代码的时候查询并没有执行,sql代码存在Queryset的内部了,这个时候我们可以看到sql是啥了

res=models.Book.objects.filter(title='步天歌')
print(type(res))
print(res.query) <class 'django.db.models.query.QuerySet'>
(0.001) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date`, `app01_book`.`publish_id` FROM `app01_book` WHERE `app01_book`.`title` = 步天歌

QuerySet内部的SQL优化

下面我打印了每一个阶段的sql语句,安装我们一般的思路,如果打印了res2的话,这两条sql都会执行

    res=models.Book.objects.filter(title='步天歌')
print(res.query)
res2 = res.values("id")
print(res2.query) (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date`, `app01_book`.`publish_id` FROM `app01_book` WHERE `app01_book`.`title` = 步天歌
(0.000) SELECT VERSION(); args=None
SELECT `app01_book`.`id` FROM `app01_book` WHERE `app01_book`.`title` = 步天歌

那么情况到底如何呢?

最后只执行了最后的代码,说明QuerySet内部还进行了Sql代码的优化

print(res2)

(0.001) SELECT `app01_book`.`id` FROM `app01_book` WHERE `app01_book`.`title` = '步天歌' LIMIT 21; args=('步天歌',)

filter和values

我发现filter和values其实和sql中最简单的查询非常的相似

filter就类似

select * from modle.book where filter()

values就类似

select vlaues() from modle.book

filter和values一起用就是这样了

select values() from modle.book where filter()

filter和values_list

filter和values_list其实查询数据的sql语句是一样的,差别就是对拿来的数据进行了不同的处理,一个把记录包装成对象,另一个单纯把数据拿出来放在元组里面

(0.000) SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date`, `app01_book`.`publish_id` FROM `app01_book` LIMIT 21; args=()

(0.001) SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish_date`, `app01_book`.`publish_id` FROM `app01_book` LIMIT 21; args=()

queryset方法详解

https://www.jianshu.com/p/13d2ce796770

Django ORM-objects-QuerySet的更多相关文章

  1. Django ORM之QuerySet

    Django ORM用到三个类:Manager.QuerySet.Model.Manager定义表级方法(表级方法就是影响一条或多条记录的方法),我们可以以models.Manager为父类,定义自己 ...

  2. Django ORM之QuerySet方法大全

    ################################################################## # PUBLIC METHODS THAT ALTER ATTRI ...

  3. Python Django orm操作数据库笔记之QuerySet API

    什么时候Django会将QuerySet转换为SQL去执行: 根据Django的数据库机制,对于QuerySet来说,当QuerySet被第一次构建,然后又调用他的filter方法,接着在对其进行切片 ...

  4. django orm总结[转载]

    django orm总结[转载] 转载地址: http://www.cnblogs.com/linjiqin/archive/2014/07/01/3817954.html 目录1.1.1 生成查询1 ...

  5. Django ORM - 001 - 外键表查询主表信息

    开始用Django做web开发,我想大家都会遇到同样的问题,那就是如何高效快速的查询需要的数据,MVC都很简单,但是ORM折腾起来就有些费时间,我准备好好研究下Django ORM,所以会有一个系列的 ...

  6. Django ORM 查询管理器

    Django ORM 查询管理器 ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言 ...

  7. Django ORM模型的一点体会

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载. 使用Python的Django模型的话,一般都会用它自带的ORM(Object-relational ma ...

  8. Django ORM那些相关操作

    一般操作 https://docs.djangoproject.com/en/1.11/ref/models/querysets/         官网文档 常用的操作 <1> all() ...

  9. django orm 及常用参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

  10. Django ORM中常用字段和参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

随机推荐

  1. windows下搭建开发环境

    PHP集成开发环境有很多,如XAMPP.AppServ......只要一键安装就把PHP环境给搭建好了.但这种安装方式不够灵活,软件的自由组合不方便,同时也不利于学习.所以我还是喜欢手工搭建PHP开发 ...

  2. AutoCad 二次开发 .net 之相同块的自动编号

    主要步骤: 一.获取一个块的id: 其中oId就是了. 二.通过次oId获取块引用blkRef: 三.通过它获取所有相同的块引用的id集合: 四.通过步骤三的集合得到所有的块引用得到集合listBr: ...

  3. AtCoder Grand Contest 038

    目录 \(\bf A - 01 \ Matrix\) \(\bf B- Sorting \ a \ Segment\) \(\bf C-LCMs\) \(\bf D-Unique \ Path\) 这 ...

  4. Spring Cloud gateway 五 Sentinel整合

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  5. 精心整理(含图版)|你要的全拿走!(R数据分析,可视化,生信实战)

    本文首发于“生信补给站”公众号,https://mp.weixin.qq.com/s/ZEjaxDifNATeV8fO4krOIQ更多关于R语言,ggplot2绘图,生信分析的内容,敬请关注小号. 为 ...

  6. Vue+element UI实现分页组件

    介绍 这是一个是基于element-UI的分页组件基础上,进行了二次封装的分页组件,在展示数据时,该分页组件采用了每显示一页数据,只请求当前页面的数据的请求策略,从而避免了一次性将数据全部请求所造成的 ...

  7. 一个类GraphQL的ORM数据访问框架发布

    Zongsoft.Data 发布公告 很高兴我们的 ORM 数据访问框架(Zongsoft.Data)在历经两个 SaaS 产品的应用之后,今天正式宣布对外推广! 这是一个类 GraphQL 风格的  ...

  8. Python项目开发公用方法--excel生成方法

    在实际开发中,我们有时会遇到数据导出的需求.一般的,导出的文件格式为Excel形式. 那么,excel的生成就适合抽离出一个独立的公用方法来实现: def generate_excel(excel_n ...

  9. ffmpeg centos yum安装

    CentOS 6&7安装ffmpeg   CentOS 6和7安装方法是不一样的,下面分别说明: 安装前都需要先安装epel扩展源 yum -y install epel-release ce ...

  10. nyoj 813-对决 (i*j == k)

    813-对决 内存限制:64MB 时间限制:1000ms 特判: No 通过数:11 提交数:23 难度:0 题目描述: Topcoder 招进来了 n 个新同学,Yougth计划把这个n个同学分成两 ...