目录
一 .缓存
定义:缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存
意义:视图渲染有一定成本,数据库的频繁查询过高;所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数;用户拿到响应的时间成本会更低
优化的思想:
1.在Django中设置缓存
有多种缓存方法,这里使用将缓存的数据存储在数据库中
说明:
尽管存储介质没有更换,但是当把一次负责查询的结果直接存储到表里,比如多个条件的过滤查询结果,可避免重复进行复杂查询,提升效率;
settings.py中的配置
CACHES={
'default':{
'BACKEND':'django.core.cache.backends.db.DatabaseCache',
'LOCATION':'my_cache_table',
'TIMEOUT':300,#缓存保存时间 单位秒,默认值为300,
'OPTIONS':{
'MAX_ENTRIES':300,#缓存最大数据条数
'CULL_FREQUENCY':2,#缓存条数达到最大值时删除1/x的缓存数据
}
}
}
然后手动执行
python3 manage.py createcachetable
python3 manage.py migrate
2.使用
a)整体缓存
#在视图中
from django.views.decorators.cache import cache_page
@cache_page(30)
def my_views(request):
...
#在路由中
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo/',cache_page(60)(my_view)),
]
b)局部缓存(缓存api)
#方法一
from django.core.cache import caches
cache1=caches['key1']
cache2=caches['key2']
#key是在settings.py中的自定义cache
#方法二
from django.core.cache import cache
#调用defalut项
cache.set(key,value,timeout)#存储缓存
#返回值None,value可以是任意对象
cache.get(key)#获取缓存
#返回value,不存在返回None
cache.add(key,add)#存储缓存,只有在key不存在时生效
#返回True或False
cache.get_or_set(key,value,timeout)#若未获取到数据则执行set
#返回value
cache.set.many(dict,timeout)#批量存储缓存
#返回插入失败的数组
cache.get_many(key_list)#批量获取
#返回字典
cache.delete(key)#删除key的数据
#返回None
cache.delete_many(key_list)#批量删除
#返回None
c)浏览器缓存策略
强缓存:
不会向服务器发送请求,直接从缓存中读取资源
1,响应头-Expires
定义:缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点样例:Expires:Thu,02 Apr 2030 05:14:08 GMT
2,响应头-Cache-Control
在HTTP/1.1中,Cache-Control主要用于控制网页缓存。比如当Cache-Control:max-age=120 代表请求创建时间后的120秒,缓存失效
说明:目前服务器都会带着这两个头同时响应给浏览器,浏览器优先使用Cache-Control
注:cache_page自带强缓存
协商缓存:
大图片这类比较费带宽且不易变化的数据,强缓存时间到期后,浏览器会去跟服务器协商,当前缓存是否可用,如果可用,服务器不必返回数据,浏览器继续使用原来缓存的数据,如果文件不可用,则返回最新数据,所以协商缓存必须基于强缓存
1, Last-Modified响应头和If-Modified-Since请求头
Last-Modified为文件的最近修改时间,浏览器第一次请求静态文件时,服务器如果返回Last-Modified响应头,则代表该资源为需协商的缓存
当缓存到期后,浏览器将获取到的Last-Modified值做为请求头If-Modified-Since的值,与服务器发请求协商,服务端返回304响应码[响应体为空],代表缓存继续使用,200响应码代表缓存不可用[响应体为最新资源]
2,ETag响应头和If-None-Match请求头
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成;
缓存到期后,浏览器将ETag响应头的值做为If-None-Match请求头的值,给服务器发请求协商;服务器接到请求头后,比对文件标识,不一致则认为资源不可用,返回200响应码[响应体为最新资源];可用则返回304响应码
二.中间件
官网介绍:中间件是Django请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件”系统,用于全局改变Django的输入或输出,中间件以类的形式体现,每个中间件负责特定功能
中间件的理解:
1.编写中间件
中间件类须继承自django.utils.deprecation.MiddlewareMixin
中间件类须实现下列五个方法中的一个或多个:
#在项目目录下创建middleware文件夹,创建文件mymiddleware
class MYMW(MiddlewareMixin):
def process_request(self, request):
...
#执行路由之前被调用,在每个请求上调用,返回None或HttpResponse对象
def process_view(self, request, callback, callback_args,callback_kwargs):
...
#调用视图之前被调用,在每个请求上调用,返回None或HttpResponse对象
def process_response(self, request,response):
...
#所有响应返回浏览器 被调用,在每个请求上调用,返回HttpResponse对象
def process_exception(self,request,exception):
...
#当处理过程中抛出异常时调用,返回一个HttpResponse对象
def process_template_response(self, request, response):
...
#在视图函数执行完毕且试图返回的对象中包含render方法时被调用;该方法需要返回实现了render方法的响应对象
注:中间件中的大多数方法在返回None时表示忽略当前操作进入下一项事件,当返回HttpResponese对象时表示此请求结束,直接返回给客户端
2.注册中间件
#settings.py中
MIDDLEWARE = [
...
'middleware.mymiddleware.MYMW'
]
3.中间件的调用顺序
进入视图函数之前,从上到下按照注册顺序执行,进入之后,由下至上
4.CSRF攻击
某些恶意网站上包含链接、表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的认证信息试图在你的网站上完成某些操作,这就是跨站请求伪造(CSRF,CrossSite Request Forgey)。
防范:django采用‘比对暗号‘机制 防范攻击,Cookies中存储暗号1,模板中表单里藏着 暗号2,用户只有在本网站下提交数据,暗号2才会随表单提交给服务器,django对比两个暗号,对比成功,则认为是合法请求,否则是违法请求-403响应码
配置:
首先在settings.py中确认
MIDDLEWARE中
django.middleware.csrf.CsrfViewMiddleware是否打开
然后再模板中,form标签下添加如下标签
{% csrf_ token %}
特殊说明:
如果某个视图不需要django进行csrf保护,可以用装饰器关闭对此视图的检查
样例:from django.views.decorators.csrf import csrf_exempt @csrf_exempt def my_view(request): return HttpResponse('Hello world')
三.分页
分页是指在web页面有大量数据需要展示,为了方便阅读在每个页面至展示部分数据
1.Paginator对象
负责分页整体数据的管理,对象的构造方法:
from dajngo.core.paginator import Paginator
paginator =Paginator(object_list, per_page)
-参数
- object_list 需要分类数据的对象列表
-per_page每页数据个数
- 返回值:
-Paginator的对象
Paginator属性:
- count:需要分页数据的对象总数
-num_pages:分页后的页面总数
- page_range:从1开始的range对象,用于记录当前面码数-per_page 每页数据的个数
Paginator方法:
paginator对象.page(number)
-参数 number为页码信息(从1开始)
-返回当前number页对应的页信息
-如果提供的页码不存在,抛出InvalidPage异常
InvalidPage:总的异常基类,包含以下两个异常子类
- PageNotAnInteger:当向page()传入一个不是整数的值时抛
- EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出
2.Page对象
负责具体某一页的数据的管理
创建对象
Paginator对象的page()方法返回Page对象
page = paginator.page(页码)
Page对象属性:
- object _list:当前页上所有数据对象的列表
-number:当前页的序号,从1开始
paginator:当前page对象相关的Paginator对象
Page对象方法:
has_next().如果有下一贝返回True
has_previous():如果有上一页返回True
has_other_pages():如果有上一页或下一页返回True
next_page_number():返回下一页的页码,如果下一页不存在,抛出InvalidPage异常
previous_page_number():返回上一页的页码,如果上一页不存在,抛出InvalidPage异常
四.CSV文件
逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)
说明:可被常见制表工具,如excel等直接进行读取
1.操作CSV
Python提供了内建库-csv;可直接通过该库操作csv文件案例如下:
import csv
with open('eggs.csv','w', newline=")as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['a', 'b', 'c'])
2.实现下载CSV
在网站中,实现下载CSV,注意如下:
-响应Content-Type类型需修改为text/csv。这告诉浏览器该文档是CSV文件,而不是HTML文件
- 响应会获得一个额外的 Content-Disposition标头,其中包含CSV文件的名称。它将被浏览器用于开启 “另存为..”对话框
import csv
from django.http import HttpResponse
from .models import Book
def make_csv_view(request):
response= HttpResponse(content_type='text/csv');response['content-Disposition']='attachment; filename="mybook.csv"'
a1l_book = Book.objects.all()
writer = csv.writer(response)
writer.writerow(['id', 'title'])
for b in all_book:
writer.writerow([b.id, b.title])
return response