一、查询集QuerySet
1、概念
Django的ORM中存在查询集的概念
查询集,也称查询结果集–QuerySet,表示从数据库中获取的对象集合,
当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表)
- all() : 返回所有的数据
- filter() :返回满足条件的数据
- exclude() :返回满足条件之外的数据
- order_by() :对结果进行排序
对查询集可以再次调用过滤器进行过滤,如
>>> books = BookInfo.objects.filter(readcount__gt=30).order_by('pub_date')
>>> books
<QuerySet[<BookInfo:天龙八部>,<BookInfo:雪山飞狐>]>
也就意味着查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果,从SQL的角度讲,查询集与select语句等价,过滤器像where、limit、order by字句
exists() :判断查询集中是否有数据,如果有则返回True,没有则返回False
2、两大特性
(1)惰性执行
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括:迭代、序列化、与if合用
例如,当执行以下语句时,并非进行数据库查询,只是创建了一个查询集books
books = BookInfo.objects.all()
继续执行迭代操作后,才真正的进行了数据库的查询:
for book in books:
print(book,name)
(2)缓存
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询结果集时会使用缓存的数据,减少了数据库的查询次数,提升性能。
# 以下代码查询时,每执行一次都会查询一次数据库,增加了数据库的负担
from book.models import BookInfo
[book.id for book in BookInfo.objects.all()] # 查询数据库
[book.id for book in BookInfo.objects.all()] # 再次查询数据库
# 缓存优化--将查询集付给变量
books = BookInfo.objects.all()
# 执行时,只在第一次调用时查询数据库,数据就会存入内存,再次执行时,只从内存中读取数据
[book.id for book in books] # 第一次查询 查询数据库读取数据,放入内存
[book.id for book in books] # 第二次查询 读取缓存数据
[book.id for book in books] # 第三次查询 读取缓存数据 。。。。
(3)限制查询结果集
可以对查询集进行取下标或切片操作,等同于sql中的limit和offset字句,但是不支持负数索引
对查询集进行切片后返回一个新的查询集,不会立即执行查询
如果获取一个对象,直接使用[0],等同于[0,1].get(),但如果没有数据,[0]引发IndexError异常,[0,1].get()如果没有数据引发DoseNotExist异常
>>> from book.models import BookInfo
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> BookInfo.objects.all()[0]
<BookInfo: 射雕英雄传>
>>> BookInfo.objects.all()[0:2]
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>]>
>>> BookInfo.objects.all()[:2]
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>]>
>>>
二、分页
##############################分页###############################
from django.core.paginator import Paginator
book6 = BookInfo.objects.all()
# Paginator(object_list ,per_page)
# object_list 结果集/列表
# per_page 每页多少条记录
p = Paginator(book6 ,2)
# 获取第几页的数据
book6_page = p.page(1)
>>> from django.core.paginator import Paginator
>>> book6 = BookInfo.objects.all()
>>> # Paginator(object_list ,per_page)
>>> # object_list 结果集/列表
>>> # per_page 每页多少条记录
>>> p = Paginator(book6 ,2)
<console>:1: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class 'book.models.BookInfo'> QuerySet.
>>>
>>> # 获取第几页的数据
>>> book6_page = p.page(1)
>>> book6_page
<Page 1 of 2>
>>>
三、视图
1、allowed_hosted
主工程中settings.py
# ALLOWED_HOSTS 允许以哪种主机形式访问后端,默认是127.0.0.1
# 可添加ip/域名 是一种安全机制,只能使用罗列的ip访问
ALLOWED_HOSTS = ['192.168.227.134','127.0.0.1']
1、路由命名与reverse反解析(逆向)
(1)路由命名
在定义路由的时候,可以为路由命名,方便查找特定视图的具体路径信息
- a、在使用include函数定义路由时,可以使用namespace参数定义路由的命名空间,如
path('', include('book.urls',namespace = 'book')),
命名空间表示,凡是book.urls中定义的路由,均属于namespace指明的book名下,
命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开
- b、在定义普通路由时,可以使用name参数指明路由的名字,如:
(1)reverse反解析
使用reverse函数,可以根据路由名称,返回具体的路径如
from django.shortcuts import reverse
from django.http import HttpRequest,HttpResponse
def testproject(request):
return HttpResponse('OK')
# 定义视图:提供书籍列表信息
def bookList(request):
# 返回book子应用中的名称为test的路由
url = reverse('book:test')
print(url)
return HttpResponse('index')
- 对于未指明namespace的,reverse(路由name)
- 对于指明namespace的,reverse(命名空间namespace:路由name)