django基础知识(五)
文章目录
缓存
定义:
缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存
意义:
视图渲染有一定成本,数据库的频繁查询过高;
所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数;
用户拿到响应的时间成本会更低
缓存场景特点:
缓存的地方,数据变动频率较少
Django中设置缓存
-
数据库缓存
-
将缓存的数据存储在数据库中
-
说明:尽管存储介质没有更换,但是当把一次负责查询的结果直接存储到表里,比如多个条件的过滤查询结果,可避免重复进行复杂查询,提升效率;
-
配置:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'my_cache_table', #初始化表:python manage.py createcachetable 'TIMEOUT': 300,#缓存保存时间单位秒,默认值为300, 'OPTIONS':{ 'MAX_ENTRIES': 300,#缓存最大数据条数 'CULL_FREQUENCY':2,#缓存条数达到最大值时删除1/x的缓存数据 } } }
-
-
本地存储缓存
-
数据缓存到服务器内存中
-
配置样例:
CACHES = { 'default': { 'BACKEND': 'django. core.cache.backends . locmem. LocMemcache ' , 'LOCATION': 'unique-snowflake' #雪花算法 } }
-
-
文件系统缓存
-
将缓存的数据存储到本地文件中
-
配置样例:
CACHES = { 'default': { 'BACKEND':'django.core.cache.backends.filebased.FileBasedcache ', 'LOCATION': '/var/tmp/django_cache ',#这个是文件夹的路径 # 'LocATION': 'c : \ test\cache ' ,#windows下示例 } }
-
Django缓存策略:
-
整体缓存策略:
-
视图函数中:
from django.views.decorators.cache import cache_page @cache_page(30) ->单位s #当前缓存存储时间 def my_view(request): ...
-
路由中:
from django.views.decorators.cache import cache_page ur1patterns = [ path( 'foo/', cache_page(60)(my_view) ), ]
-
-
局部缓存策略:
-
缓存api的使用
先引入cache对象
方式1∶使用caches[ 'CACHE配置key]导入具体对象 from django.core.cache import caches cache1- caches ['myalias'] cache2 = caches ['myalias_2'] 方式2∶ from django.core.cache import cache 相当于直接引入 CACHES配置项中的'default'项
-
cache.set(key, value, timeout)-存储缓存
- key:缓存的key,字符串类型
- value:Python对象
- timeout:缓存存储时间(s),默认为CACHES中的TIMEOUT值
- 返回值:None
-
cache.get(key)- 获取缓存
- key:缓存的key
- 返回值:为key的具体值,如果没有数据,则返回None
-
cache.add(key,value)-存储缓存,只在key不存在时生效
- 返回值: True[存储成功] or False[存储失败]
-
cache.get_or_set(key, value, timeout)- 如果未获取到数据则执行set操作
- 返回值: value
-
cache.set_many(dict,timeout)-批量存储缓存
- dict: key和value的字典
- timeout:存储时间(s)
- 返回值:插入不成功的key的数组
-
cache.get_many(key_list)-批量获取缓存数据
- key_list:包含key的数组
- 返回值:取到的key和value的字典
-
cache.delete(key) -删除key的缓存数据
- 返回值: None
-
cache.delete_many(key_list)-批量删除
- 返回值: None
-
-
浏览器缓存策略
-
强缓存
不会向服务器发送请求,直接从缓存中读取资源
- 响应头- Expires
- 定义:缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点
- 样例: Expires:Thu, 02 Apr 2030 05:14:08 GMT
- 响应头- Cache-Control
- 在HTTP/1.1中,Cache-Control主要用于控制网页缓存。
- 比如当
Cache-Control:max-age=120‘
代表请求创建时间后的120秒,缓存失效 - 说明:目前服务器都会带着这两个头同时响应给浏览器,浏览器优先使用Cache-Control
- 响应头- Expires
-
协商缓存
强缓存的数据过期后,还需要跟服务器进行通信,从而获取最新数据;
如果强缓存的数据是一些静态文件,大图片等这类比较费带宽且不易变化的数据,强缓存时间到期后,浏览器会去跟服务器协商,当前缓存是否可用,如果可用:服务器不必返回数据,浏览器继续使用原来缓存的数据;如果不可用:则返回最新数据
-
Last-Modified响应头和If-Modified-Since请求头说明:
(1) Last-Modified为文件的最近修改时间,浏览器第一次请求静态文件时,
服务器如果返回Last-Modified响应头,则代表该资源为需协商的缓存
(2) 当缓存到期后,浏览器将之前获取到的Last-Modified值做为请求头 -
lf-Modified-Since的值,与服务器发请求协商,服务端返回304响应码[响应体为空],代表缓存继续使用,200响应码代表缓存不可用[响应体为最新资源]
-
ETag响应头和If-None-Match请求头
(1) Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化, Etag就会重新生成;
(2) 缓存到期后,浏览器将ETag响应头的值做为lf-None-Match请求头的值,给服务器发请求协商;服务器接到请求头后,比对文件标识,不一致则认为资源不可用,返回200响应码[响应体为最新资源];可用则返回304响应码**对比:**Last-Modified VS Etag
精度不一样 – Etag准确率更高
性能上 - Last-Modified高,Etag需要计算文件标识
优先级 – Etag 高;两个头同时出现,浏览器优先取Etag
-
-
中间件
定义:
- 中间件是 Django请求/响应处理的钩子框架。它是一个轻量级的、低级的“插件"系统,用于
全局改变 Django的输入或输出。
- 中间件以类的形式体现
- 每个中间件组件负责做一些特定的功能。例如,Django包含一个中间件组件AuthenticationMiddleware,
它使用会话将用户与请求关联起来。
编写中间件:
- 中间件类须继承自django,utils.deprecation.MiddlewareMixin类
- 中间件类须实现下列五个方法中的一个或多个:
- process_request(self,request)
执行路由之前被调用,在每个请求上调用,返回None或HttpResponse对象
- process_view(self, request, callback, callback_args,callback_kwargs)
调用视图之前被调用,在每个请求上调用,返回None或HttpResponse对象
- process_response(self, request, response)
所有响应返回浏览器被调用,在每个请求上调用,返回HttpResponse对象
- process_exception(self, request, exception)
当处理过程中抛出异常时调用,返回一个HttpResponse对象
- process_template_response(self,request, response)
在视图函数执行完毕且试图返回的对象中包含render方法时被调用;该方法需要返回实现了render方法的响应对象
注: 中间件中的大多数方法在返回None时表示忽略当前操作进入下一项事件,当返回HttpResponese对象时表示此请求结束,直接返回给客户端
注册中间件
settings.py中需要注册一下自定义的中间件
MIDDLEWARE = [
...
'middleware.mymiddleware.MyMW2',
]
**注意:**配置为数组,中间件被调用时以‘先上到下’,进入视图后再‘由下到上’的顺序调用
练习1:
用中间件实现强制某个IP地址只能向/test开头的地址发送5次请求提示:
class VisitLimit(MiddlewareMixin):
visit_times = {}
def process_request(self,request):
ip_address = request.META['REMOTE_ADDR'] #远程客户端的IP地址
path_url = request.path_info #客户端访问的请求路由信息
if not re.match('^/test',path_url):
return
times = self.visit_times.get(ip_address,0)
print('ip',ip_address,'已经访问',times)
self.visit_times[ip_address] = times + 1
if times < 5:
return
return HttpResponse('您已经访问过' + str(times) + '次,访问被禁止')
中间件执行总流程
-
CSRF攻击 - 跨站伪造请求攻击
- 定义:某些恶意网站上包含链接、表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的
- 认证信息试图在你的网站上完成某些操作,这就是跨站请求伪造(CSRF,即Cross-Site Request Forgey)。
-
CSRF防范:
-
django采用’比对暗号’机制防范攻击
-
Cookies中存储暗号1,模板中表单里藏着暗号2,用户只有在本网站下提交数据,暗号2才会随表单提交给服务器, django对比两个暗号,对比成功,则认为是合法请求,否则是违法请求-403响应码
-
配置步骤:
1. settings.py中确认MIDDLEWARE django.middleware.csrf.CsrfViewMiddleware是否打开 2. 模板中, form标签中添加如下标签:{% csrf_token %}
-
特殊说明:
-
如果某个视图不需要django进行csrf保护,可以用装饰器关闭对此视图的检查
-
样例:
from django.views.decorators.csrf import csrf_exempt @csrf_exempt def my_view(request): return HttpResponse('He1lo wor1d')
-
-
分页
定义:
分页是指在web页面有大量数据需要显示,为了阅读方便在每个页页中只显示部分数据。
优点:
- 方便阅读
- 减少数据提取量,减轻服务器压力。
django中分页的实现:
Django提供了Paginator类可以方便的实现分页功能
Paginator类位于django.core.paginator
模块中。
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页对应的页信息
- 如果提供的页码不存在,抛出lnvalidPage异常
- lnvalidPage:总的异常基类,包含以下两个异常子类:
- PageNotAnInteger:当向page()传入一个不是整数的值时抛出
- EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出
- lnvalidPage:总的异常基类,包含以下两个异常子类:
Page对象
- 定义:负责具体某一页的数据的管理
- 创建对象:
- Paginator对象的page()方法返回
Page对象page = paginator.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():返回下一页的页码,如果下一页不存在,抛出lnvalidPage异常
- previous_page_number():返回上一页的页码,如果上一页不存在,抛出InvalidPage异常
生成csv文件
csv文件定义:
逗号分隔值(Comma-Separated Values,CSv,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)
说明:
可被常见制表工具,如excel等直接进行读取
python中生成csv文件:
-
Python提供了内建库– csv; 可直接通过该库操作csv文件
-
案例如下:
import csv with open('eggs.csv', 'w', newline=") as csvfile: writer = csv.writer(csvfile) writer.writerow(['a', 'b','c'])
-
csv文件下载:
在网站中,实现下载CSv,注意如下:
-
响应Content-Type类型需修改为text/csv。这告诉浏览器该文档是CSV文件,而不时HTML文件
-
响应会获得一个额外的Content-Disposition标头,其中包含CSv文件的名称。它将被浏览器用于开启“另存为…"对话框
import csv from django.http import HttpResponse from .mode1s import Book def make_csv_view(request): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment;filename="mybook.csv"' a11_book = Book.objects.a11() writer = csv.writer(response) writer.writerow(['id','title']) for b in a11_book : writer.writerow( [b.id,b.title]) return response
-