一般情况下,我们在写Django项目需要操作QuerySet时一些常用的方法已经满足我们日常大多数需求,比如get、filter、exclude、delete神马的感觉就已经无所不能了,但随着项目但业务逻辑越来越复杂,这几个方法可能就不能很好但满足我们了,所以这时候,最好的办法是神马??对,读文档!这里的读文档不是有业务需求时去查文档,而是要为了阅读文档而阅读文档。以下也是作为我的文档阅读笔记,我记下了一些我以后可能会用到或者一些技巧性提升的东西,好,不废话,正文开始:

首先,我们假设有以下两个model:

class Entry(Model.models):
ip = models.CharField(max_length=20)
time = models.DateTimeField()
black = models.BooleanField(default=False)
class Blog(Model.models):
title = models.CharField(max_length=100)
content = models.CharField(max_length=500)
publish = models.BooleanField(default=False)
entry = models.ForeignField(Entry, relate_name='entrys')

1、annotate(args, **kwargs)

为queryset增加注解,神马是注解?就是你读出queryset可能会需要一些额外数据要添加进去的时候,你就可以用这个东东咯,使用方法看代码:

>>> q = Blog.objects.annotate(Count('entry'))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42

Blog model 类本身并没有定义 entry__count 属性,但可以使用注解函式的关系字参数,从而改变注解的命名:

>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42

2、aggregate(args, *kwargs)

这个参数有点像annotate的反义,annotate返回的是一个包含注解值的queryset,而aggregate则单独返回注解值,返回类型是一个dict,当然,这种方式在文档中叫做聚合查询,具体使用如下:

>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}

通过在 aggregate 指定关键字参数,你可以控制返回的聚合名称:

>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}

3、defer(*fields)

延后读取字段。啥意思?我读文档时就这感觉。。后来发现是酱紫滴,一个复杂滴model可能你从数据库中读出后根本不需要某些字段,读了又浪费时间浪费空间,怎么办?对!用defer,延后读取,你可以在defer中指定一个或多个字段,也可用链式方法使用defer,它返回对依然是个完整对queryset但其中defer指定但字段并没有真但从数据库读出来,只有当你访问这些延后字段时django才会从数据库读取这些数据,感觉在数据量变大后用这个方法很nice,具体用法如下:

Blog.objects.defer("content").filter(publish=True).defer("title")

不过要注意的是,不能用defer过的字段进行order_by操作,这样做木有作用滴,如果需要清楚defer,只要加个defer(None)就ok啦。

你还阔以defer model中的外键,但是你需要提使用 select_related() 载入关联 model,具体用法:

Blog.objects.select_related().defer("entry__ip", "entry__time")

4、only(*fields)

我想你已经猜到了,一定是defer相反的咯,是啊是啊,没错。only会立即查询指定的字段,但是要注意了,这有坑,only只返回指定的字段,其他木有指定的默认就给defer了哟,所以以下写法是等价滴:

Entry.objects.only('ip')
Entry.objects.defer('time', 'black')

当你使用链式方法调用only时只有最后一个only内的参数会立即返回,其他参数都会被defer,注意这里only的覆盖性~

5、create(**kwargs)

创建并保存对象。一般我们要新建一个model对象时直接使用他的构造函数或者使用.语法赋值,最后调用.save()方法保存。那么在我们已经知道新建这个对象所有必须数据的情况下,其实用create会更快捷,代码看着更干净,起使用方法与构造方法类似,只是不需要调用.save()啦, 例子如下:

p = Entry.objects.create(ip='127.0.0.1', time=<a datetime type object>, black=False)

6、get_or_create(kwargs) 和 update_or_create(kwargs)

嗯,看看就知道这个是create的升级版,没错,他们俩一个是在查无此数据后新建一个是更新不存在数据时新建,具体用法同createget_or_create等效如下过程

try:
obj = Blog.objects.get(title='test', content='test')
except Blog.DoesNotExist:
obj = Blog(title='test', content='test')
obj.save()

注意这两个方法的返回值,他们返回两个东东:

created, obj = get_or_create(**kwargs)

其中created是个bool值,当此方法生成了一个新的model object,此值为True,反之为False,obj则是生成的object或者查到的object实例。

7、latest(field_name=None) 和 earliest(field_name=None)

分别返回指定字段的最新数据与最早数据。

8、first() 和 last()

分别返回queryset的第一项与最后一项,具体用法如下:

p = Blog.objects.order_by('title').first()

等同于:

try:
p = Blog.objects.order_by('title')[0]
except IndexError:
p = None

9、update(**kwargs)

用于更新一组数据,但要注意,它不能更新外键, 不能更新切片过的queryset以及不能再被切片的set,用法如下:

Entry.objects.filter(black=False).update(ip='0.0.0.0')

10、delete()

有人肯定要说了,博主你再逗我,这个方法抬头不见低头见,还用你说?!是啊是啊,删除普通数据的时候当然木有什么,但是如果删除外健关系很复杂的object时有木有想过细节?是不是细思极恐 啊#_#
比如,以我们开头的model为例,我删了一个entry实例,那么与它有外健关联的blog实例会怎样?一同被删了?还是保留?保留的话那他对应的entry外健是神马?WTF!
嗯,实话告诉你,默认情况下调用delete()是会删除所有有关的外键对象的(是不是突然感觉自己之前代码里有坑了)所以我们需要详细说说这个方法,如何做才能让他不删除对应的外键或者说按照我们想象的方式进行删除呢?

答案在这里:

django.models 的 on_delete参数,此参数有以下几个可选值:

    • CASCADE:这就是delete()的默认选项,也就是关联删除
    • PROTECT:如果删除的model obj含有外键则引起 ProtectedError
    • SET_NULL:就是把外键置空咯,当然前提是你得设置外键的null=True
    • SET_DEFAULT:就是把外键设为默认咯,当然前提是你得设置外键的default=xxx
    • SET():SET内应是一个函数,用来返回一个外键实例,用法如下:

 def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user))

11、fields lookups

强大滴django fields lookups,具体可选参数有:

iexact icontains in istartwith gt gte lt lte endwith iendwith range
year month day week_day hour minute second insole (ex: search) iregex

其中,首字母带“i”的意思就是不分大小写,如果需要大小写敏感就把“i”去掉啦~其他参数大体从字面意思就知道啦,改天补上详细的例子。

12、Avg、Count、Sum、Max、Min、StdDev、Variance

这些方法就是求数据的相应结果咯,比如avg就是平均值啦,嗯,基本都看得懂,除了后两个,一个是方差,一个是标准差,具体用法其实前文里有,我还是放一下:

q = Blog.objects.annotate(Count('entry'))

13、强大的Q查询与F查询:

嗯,这一部分先留着,总之告诉你很腻害就是了,可以做很复杂的查询,先放个例子:

q = Blog.objects.filter(Q(title='test')|Q(content='hahaha'))

这是一个或查询,满足其中一个条件的数据会被返回。

参考

Django学习笔记之Django QuerySet的方法的更多相关文章

  1. Django学习笔记之Django中间件

    准备 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装饰 ...

  2. Django学习笔记之Django Form表单

    Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...

  3. Django学习笔记之Django Form表单详解

    知识预览 构建一个表单 在Django 中构建一个表单 Django Form 类详解 使用表单模板 回到顶部 构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的 ...

  4. Django学习笔记之Django ORM Aggregation聚合详解

    在当今根据需求而不断调整而成的应用程序中,通常不仅需要能依常规的字段,如字母顺序或创建日期,来对项目进行排序,还需要按其他某种动态数据对项目进行排序.Djngo聚合就能满足这些要求. 以下面的Mode ...

  5. Django学习笔记之Django ORM相关操作

    一般操作 详细请参考官方文档 必知必会13条 <> all(): 查询所有结果 <> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <> ...

  6. Django学习笔记之Django的url反向解析

    0x00 URL反向解析和三种不同的反向解析方式 Django中提供了关于URL的映射的解决方案,可以做两个方向的使用: 1.普通解析过程:由客户端的浏览器发起一个url请求,Django根据URL解 ...

  7. Django学习笔记之Django视图View

    一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. ...

  8. Django学习笔记之Django模版系统

    官方文档 常用语法 只需要记两种特殊符号: {{  }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 {{ 变量名 }} 变量名由字母数字和下划线组成. 点(.)在模板语言中有特 ...

  9. Django 学习笔记之五 Django中数据库中ManyToManyField及ForeignKey

    1.model里面的代码: from __future__ import unicode_literalsimport django.utils.timezone as timezonefrom dj ...

随机推荐

  1. 扩展jquery scroll事件,支持 scroll start 和 scroll stop

    效果预览: github: https://besswang.github.io/webapp-scroll/ 参考地址: http://www.ghugo.com/special-scroll-ev ...

  2. index封装

    就是求元素在父级当中的位置: 思路: <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  3. HDU1536 S-Nim

    S-Nim Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. eclipse中的SVN文件还原到历史版本

    转载自:http://www.softown.cn/post/103.html 由于某些特殊原因,我们可能需要将SVN资源库中的某个文件回滚到以前的某个历史版本(准确地说,这不是"回滚&qu ...

  5. 160527、项目上线后session(远程session)

    import java.io.Serializable;import java.util.HashMap;import java.util.Map;import java.util.UUID;impo ...

  6. 可序列化对象和byte[]数组之间的互转

    /// <summary> /// 将可序列化对象转成Byte数组 /// </summary> /// <param name="obj">对 ...

  7. Python实现HMM(隐马尔可夫模型)

    1. 前言 隐马尔科夫HMM模型是一类重要的机器学习方法,其主要用于序列数据的分析,广泛应用于语音识别.文本翻译.序列预测.中文分词等多个领域.虽然近年来,由于RNN等深度学习方法的发展,HMM模型逐 ...

  8. perl 常用命令

    过滤重复字符 perl -e '$_=<STDIN>; @in = split; if (@in < 100){ @out = grep {! $hash{$_}++ } @in;  ...

  9. django之页面缓存

    一  全站缓存(全局缓存) 在settings中配置,主要就是两个中间件,需要注意的就是两个中间件的前后位置 MIDDLEWARE_CLASSES = ( ‘django.middleware.cac ...

  10. Servlet实现前后端交互的原理及过程解析

    在日常调试项目时,总是利用tomcat去启动项目,并进行前后端联调,但对于前后端的请求响应的交互原理及过程并不是特别清晰. 为什么在前端发出相应请求,就能跳转到后端通过程序得到结果再响应到前端页面呢? ...