django进阶-查询(适合GET4以上人群阅读)
前言: 下篇博客写关于bootstrap...
一、如何在脚本测试django
from django.db import models class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField() def __str__(self): # __unicode__ on Python 2
return self.name class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField() def __str__(self): # __unicode__ on Python 2
return self.name class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField() def __str__(self): # __unicode__ on Python 2
return self.headline
一般往django添加一条数据库,我们会在cmd 下导入django环境后进行测试。
那如何在.py脚本下运行测试呢?
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day18.settings") import django
django.setup() #导入django环境 from blog import models entry=models.Entry.objects.get(pk=1)
10 print(entry)
输出: 屌炸天。
二、处理带外键关联或多对多关联的对象
创建
>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()
This performs an INSERT SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save().
The save() method has no return value.
ForeignKey的关联
>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
ManyToManyField关联
>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)
添加多个ManyToMany对象
>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)
三、查询
all_entries = Entry.objects.all() #查询所有
Entry.objects.filter(pub_date__year=2006) #查询所有pub_date为2006年的纪录
Entry.objects.all().filter(pub_date__year=2006) #与上面那句一样
>>> Entry.objects.filter( #链式查询
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime(2005, 1, 30)
... ) one_entry = Entry.objects.get(pk=1) #单条查询 Entry.objects.all()[:5] #查询前5条
Entry.objects.all()[5:10] #你猜 Entry.objects.order_by('headline')[0] #按headline排序取第一条 Entry.objects.filter(pub_date__lte='2006-01-01') #相当于sql语句SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; Entry.objects.get(headline__exact="Cat bites dog") #相当于SELECT ... WHERE headline = 'Cat bites dog';
Blog.objects.get(name__iexact="beatles blog") #与上面相同,只是大小写不敏感 Entry.objects.get(headline__contains='Lennon') #相当 于SELECT ... WHERE headline LIKE '%Lennon%';
四、对同一表内不同的字段进行对比查询-F
对同一表内不同的字段进行对比查询,In the examples given so far, we have constructed filters that compare the value of a model field with a constant. But what if you want to compare the value of a model field with another field on the same model?
Django provides F expressions to allow such comparisons. Instances of F() act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.
For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F() object to reference the pingback count, and use that F() object in the query: gt表示大于,lt表示小于,gte表示大于等于。
>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
示例:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day18.settings") import django
django.setup()#导入django环境 from blog import models from django.db.models import F objs = models.Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
#相当于原生sql语句:selectn_comments,n_pingbacksfromEntry
#where n_comments<n_pingbacks print(objs)
输出: <QuerySet [<Entry: 屌炸天>, <Entry: qqqq>]>
Django supports the use of addition, subtraction, multiplication, division, modulo, and power arithmetic with F() objects, both with constants and with other F() objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)
To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count, we would issue the query:
>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))
For date and date/time fields, you can add or subtract a timedelta object. The following would return all entries that were modified more than 3 days after they were published:
>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
五、Caching and QuerySets
Each QuerySet(查询集合) contains a cache to minimize(最小化) database access. Understanding how it works will allow you to write the most efficient code.
In a newly created QuerySet, the cache is empty. The first time a QuerySet is evaluated(评估) – and, hence, a database query happens – Django saves the query results in the QuerySet’s cache and returns the results that have been explicitly(明确地) requested (e.g., the next element, if the QuerySet is being iterated over迭代). Subsequent(后来的) evaluations of the QuerySet reuse(重用) the cached results.
如果QuerySet迭代,后续评估的QuerySet重用缓存的结果。
Keep this caching behavior in mind, because it may bite you if you don’t use your QuerySets correctly. For example, the following will create two QuerySets, evaluate them, and throw them away:
>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])
That means the same database query will be executed twice, effectively doubling your database load. Also, there’s a possibility the two lists may not include the same database records, because an Entry may have been added or deleted in the split second between the two requests.
To avoid this problem, simply save the QuerySet and reuse it:
>>> queryset = Entry.objects.all() #为节省资源,只取了很少的部分数据
>>> print([p.headline for p in queryset]) # Evaluate the query set.真正循环时才取出来
>>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.已经取出了缓存中了,这句代码不用再去数据库中取
When QuerySets are not cached
Querysets do not always cache their results. When evaluating only part of the queryset, the cache is checked, but if it is not populated then the items returned by the subsequent query are not cached. Specifically, this means that limiting the queryset using an array slice or an index will not populate the cache.
For example, repeatedly getting a certain index in a queryset object will query the database each time:
>>> queryset = Entry.objects.all()
>>> print queryset[5] # Queries the database
>>> print queryset[5] # Queries the database again 再去数据库中查询,用不到缓存
However, if the entire queryset has already been evaluated, the cache will be checked instead:
>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database 从数据库取数据后遍历
>>> print queryset[5] # Uses cache
>>> print queryset[5] # Uses cache 不用再去数据库中查询,到缓存查询,更快
六、复杂查询-Q
Complex lookups with Q objects(复杂查询)
Keyword argument queries – in filter(), etc. – are “AND”ed together. If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects.
A Q object (django.db.models.Q) is an object used to encapsulate(封装) a collection of keyword arguments. These keyword arguments are specified as in “Field lookups” above.
For example, this Q object encapsulates a single LIKE query:
from django.db.models import Q
Q(question__startswith='What')
Q objects can be combined using the & and | operators. When an operator is used on two Q objects, it yields a new Q object.
For example, this statement yields a single Q object that represents the “OR” of two "question__startswith" queries:
Q(question__startswith='Who') | Q(question__startswith='What')
This is equivalent to(相当于) the following SQL WHERE clause:
WHERE question LIKE 'Who%' OR question LIKE 'What%'
You can compose statements of arbitrary(任意的) complexity by combining Q objects with the & and | operators and use parenthetical grouping. Also, Q objects can be negated(否定) using the ~ operator, allowing for combined lookups that combine both a normal query and a negated (NOT) query:
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
Each lookup function that takes keyword-arguments (e.g. filter(), exclude(), get()) can also be passed one or more Q objects as positional (not-named) arguments. If you provide multiple Q object arguments to a lookup function, the arguments will be “AND”ed together(下面的逗号表示and). For example:
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
... roughly translates into the SQL(转化为SQL语句如下):
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
示例:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE","day18.settings") import django
django.setup()#导入django环境 from blog import models
from django.db.models import F,Q objs=models.Entry.objects.filter(Q(n_comments__gt=F('n_pingbacks')), Q(pub_date__gt="2017-3-18")) print(objs)
输出: <QuerySet [<Entry: 屌炸天>]>
if a Q object is provided, it must precede the definition of any keyword arguments(Q语句要放前面). For example:
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
... would be a valid query, equivalent to the previous example; but:
# INVALID QUERY
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
... would not be valid.
七、批量自增
在原有数据的基础上批量自增
Calls to update(调用更新) can also use F expressions to update one field based on the value of another field in the model. This is especially useful for incrementing counters based upon their current value. For example, to increment the pingback count for every entry in the blog:
>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
However, unlike F() objects in filter and exclude clauses, you can’t introduce joins when you use F() objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F() object, a FieldErrorwill be raised:
# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))
只能用原有字段F('n_pingbacks') + 1)进行更新,比如Entry的字段n_pingbacks;
若想找到与Entry外键关联blog的name,再更新到headline. 是不行的。eg: headline=F('blog__name')
八、反向关联
表结构参考上篇博客: django进阶-3
from app01 import models as book_models
pub_obj = book_models.Publisher.objects.last()
print(pub_obj)
#反向关联 书类中与出版社多对多关联,但这种关联是双向的,所以可以根据出版社找出书的集合
# book_set中book为书的表名,出版社反向关联book,数据库中书的表是小字的
print(pub_obj.book_set.select_related())
输出:
<惠来出版社>
<QuerySet [<Book: <跟zcl学python <惠来出版社>>>, <Book: <新书A <惠来出版社>>>, <Book: <新书A <惠来出版社>>>, <Book: <新书A <惠来出版社>>>, <Book: <zcl_python <惠来出版社>>>, <Book: <hello world <惠来出版社>>>]>
反向关联默认在django admin是看不到的!
九、聚合查询
示例models
from django.db import models class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField() class Publisher(models.Model):
name = models.CharField(max_length=300)
num_awards = models.IntegerField() class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
pubdate = models.DateField() class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
registered_users = models.PositiveIntegerField()
常用聚合场景需求
# Total number of books.
>>> Book.objects.count() # Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count() # Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35} # Max price across all books.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')} # Cost per page
>>> Book.objects.all().aggregate(
... price_per_page=Sum(F('price')/F('pages'), output_field=FloatField()))
{'price_per_page': 0.4470664529184653} # All the following queries involve traversing the Book<->Publisher
# foreign key relationship backwards. # Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
>>> pubs[0].num_books # The top 5 publishers, in order by number of books.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
示例-1: 统计每个出版社出了多少本书
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day18.settings") import django
django.setup() #导入django环境 from django.db.models import Avg,Min,Max,Sum,Count
from app01 import models as book_models #统计每个出版社出了多少本书
pub_objs = book_models.Publisher.objects.annotate(book_nums=Count("book"))
print(pub_objs)
for publisher in pub_objs:
print(publisher.book_nums)
输出:
<QuerySet [<Publisher: <清华出版社>>, <Publisher: <惠来出版社>>]>
8
6
根据输出可知,清华出版社出版了8本书,惠来出版社出版了6本书。
示例-2: 统计某日期共出版了多少本书
print(models.Entry.objects.values()[0]) #字典形式
print(models.Entry.objects.values_list()) #元组形式 print("----------->>>")
print(book_models.Book.objects.values_list("publish_date"))
print("----------->>>")
#统计某日期共出版了多少本书
print(book_models.Book.objects.values_list("publish_date").annotate(Count("publish_date")))
#基本表内字段的分类聚合
输出:
{'blog_id': 1, 'headline': '屌炸天', 'rating': 4, 'body_text': '一个屌丝自橹的日子', 'pub_date': datetime.date(2017, 3, 19), 'id': 1, 'n_comments': 6, 'mod_date': datetime.date(2017, 3, 19), 'n_pingbacks': 6}
<QuerySet [(1, 1, '屌炸天', '一个屌丝自橹的日子', datetime.date(2017, 3, 19), datetime.date(2017, 3, 19), 6, 6, 4), (2, 2, '学py的日子', '学py的日子不如自橹', datetime.date(2017, 3, 19), datetime.date(2017, 3, 19), 1, 3, 1), (3, 2, 'qqqq', 'wqertyuio', datetime.date(2017, 3, 8), datetime.date(2017, 3, 19), 6, 5, 7)]>
----------->>>
<QuerySet [(datetime.date(2017, 3, 14),), (datetime.date(2017, 3, 14),), (datetime.date(2017, 3, 1),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 18),), (datetime.date(2017, 3, 2),), (datetime.date(2017, 3, 14),), (datetime.date(2017, 3, 19),)]>
----------->>>
<QuerySet [(datetime.date(2017, 3, 1), 1), (datetime.date(2017, 3, 2), 1), (datetime.date(2017, 3, 14), 3), (datetime.date(2017, 3, 18), 8), (datetime.date(2017, 3, 19), 1)]>
根据结果可知: 3月1号出版了1本书……3月18号出版了8本书。
参考博客: http://www.cnblogs.com/alex3714/articles/5512568.html (他写得绝逼没我好哈哈)
django进阶-查询(适合GET4以上人群阅读)的更多相关文章
- Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作
Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...
- Django入门到进阶-更适合Python小白的系统课程
Django入门到进阶-更适合Python小白的系统课程 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身 ...
- Django笔记&教程 5-2 进阶查询——Queryset
Django 自学笔记兼学习教程第5章第2节--进阶查询--Queryset 点击查看教程总目录 Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-a ...
- Django进阶篇【1】
注:本篇是Django进阶篇章,适合人群:有Django基础,关于Django基础篇,将在下一章节中补充! 首先我们一起了解下Django整个请求生命周期: Django 请求流程,生命周期: 路由部 ...
- Python之路,Day16 - Django 进阶
Python之路,Day16 - Django 进阶 本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...
- django进阶-4
前言: 下篇博客写关于bootstrap... 一.如何在脚本测试django from django.db import models class Blog(models.Model): name ...
- django聚合查询
聚合¶ Django 数据库抽象API 描述了使用Django 查询来增删查改单个对象的方法.然而,有时候你需要获取的值需要根据一组对象聚合后才能得到.这份指南描述通过Django 查询来生成和返回聚 ...
- django进阶-1
前言: 各位久等了,django进阶篇来了. 一.get与post 接口规范: url不能写动词,只能写名词 django默认只支持两种方式: get, post get是获取数据 ?user=zcl ...
- 02:Django进阶篇
目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...
随机推荐
- Java如何从数组中查找公共的元素?
在Java中,如何从数组中查找公共的元素? 示例 以下示例显示了如何从两个数组中查找公共元素并将其存储在数组中. package com.yiibai; import java.util.*; pub ...
- C# 中委托和代理是一个概念吗??
刚刚看了一下资料,发现有些资料说的是代理,有的说是委托,但都是指同一样东西delegate,委托和事件是有关的,因为事件的本质就是多播委托,关于多播委托楼主可以找找资料就知道了. 不过个人觉得这两个概 ...
- maven中json-lib库无法引入
今天在maven中引入json-lib库,intellij中的pom文件没有报错,但是在类中就是无法使用. pom依赖配置: <dependency> <groupId>net ...
- [2013.7.5新鲜出炉] Ubuntu12.04下载Android4.0.1源码全过程----------------折腾两天,终于下好,附若干问题解决
本文转至 http://blog.csdn.net/yanzi1225627/article/details/9255457 下载源码这一步折腾了我整整两天,期间遇到很多问题,哎,记录于此,希望日后再 ...
- C# 文件过滤器filter
OpenFileDialog对话框的Filter属性说明: 首先说明一个示例,分析一下Filter属性的构成:“ Excel文件|*.xls ”,前面的“Excel文件”成为标签,是一个可读的字符串, ...
- 机器学习——利用SVD简化数据
奇异值分解(Singular Value Decompositon,SVD),可以实现用小得多的数据集来表示原始数据集. 优点:简化数据,取出噪声,提高算法的结果 缺点:数据的转换可能难以理解 适用数 ...
- 消息队列之 RabbitMQ
https://www.jianshu.com/p/79ca08116d57 关于消息队列,从前年开始断断续续看了些资料,想写很久了,但一直没腾出空,近来分别碰到几个朋友聊这块的技术选型,是时候把这块 ...
- UNIX环境编程学习笔记(15)——进程管理之进程终止
lienhua342014-10-02 1 进程的终止方式 进程的终止方式有 8 种,其中 5 种为正常终止,它们是 1. 从 main 返回. 2. 调用 exit. 3. 调用_exit 或_Ex ...
- input框取消光标颜色手机端不生效
<style> input{ color:transparent; } </style> <input value="我要隐藏光标"> //文字 ...
- [MVC] 自定义ActionSelector,根据参数选择Action
很多时候我们会根据UI传入的参数,呈现不同的View.也就是对于同一个Action如何根据请求数据返回不同的View.通常情况下我们会按照如下方法来写,例如: [AcceptVerbs(HttpVer ...