一、缓存
介绍:
在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面.
当一个网站的用户访问量很大的时候,每一次的的后台操作,都会消耗很多的服务端资源,所以必须使用缓存来减轻后端服务器的压力.
缓存是将一些常用的数据保存内存或者memcache中,在一定的时间内有人来访问这些数据时,则不再去执行数据库及渲染等操作,而是直接从内存或memcache的缓存中去取得数据,然后返回给用户.
几种缓存方式:
1、开发调试缓存
2、内存缓存
3、文件缓存
4、数据库缓存
5、缓存到redis
1、开发调试(此模式为开发调试使用,实际上不执行任何操作)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 缓存后台使用的引擎
'TIMEOUT': 300, # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
},
}
}
2、内存缓存(将缓存内容保存至内存区域中)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', # 指定缓存使用的引擎
'LOCATION': 'unique-snowflake', # 写在内存中的变量的唯一值
'TIMEOUT':300, # 缓存超时时间(默认为300秒,None表示永不过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
}
}
}
3、文件缓存(把缓存数据存储在文件中)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', #指定缓存使用的引擎
'LOCATION': '/var/tmp/django_cache', #指定缓存的路径
'TIMEOUT':300, #缓存超时时间(默认为300秒,None表示永不过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
}
}
}
4、数据库缓存
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache', # 指定缓存使用的引擎
'LOCATION': 'cache_table', # 数据库表
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
}
}
}
需要注意:创建缓存的数据库表使用的语句:
python manage.py createcachetable
缓存的粒度:
全站缓存 来的请求所需要的所有数据全部缓存
单页面缓存 单独一个页面所需的数据缓存起来
局部缓存 页面中某个位置的数据缓存起来
缓存的使用:
1.1、单页面的缓存:在视图函数上加上一个装饰器即可
from django.views.decorators.cache import cache_page
import time
@cache_page(10) # 设置超时时间
def test(request):
ctime = time.time()
return render(request,'test.html',locals())
需要注意,在settings里配置一下:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', # 指定缓存使用的引擎
'LOCATION': 'C:\cache_location', # 指定缓存的路径
'TIMEOUT': 300, # 缓存超时时间(默认为300秒,None表示永不过期)
'OPTIONS': {
'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
}
}
}
1.2 cbv下实现单页面缓存
from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_page import time @method_decorator(cache_page(5),name='dispatch') class ShowTime(APIView): def get(self,request): ctime = time.strftime('%Y-%m-%d %H:%M:%S') return render(request,'show_time.html',{'ctime':ctime})
2、局部缓存
from django.core.cache import cache
import time
def test(request):
ctime = time.time()
return render(request,'test.html',{'time':ctime})
虽然与单页面的settings配置是一样的,但在模板文件里存在一定的差异性。
模板层:
{% load cache %}
{{ time }} #这部分的内容没有被缓存
{% cache 5 'test'%} #第一个参数表示缓存时间,第二个参数是key值(取缓存的时候,需要根据key值取)
当前时间:{{ time }} # 这部分的数据被缓存
{% endcache %}
3、全站缓存
需要在settings里配置两个中间件,一个在最上方,一个在最下方
'django.middleware.cache.UpdateCacheMiddleware', # 重写了process_response
''这里的是其他的中间件''
'django.middleware.cache.FetchFromCacheMiddleware' # 重写了process_request
同时还需要配置超时时间,同样在settings里配置
CACHE_MIDDLEWARE_SECONDS = 5 超时时间设定为5秒
需要注意:不需要配置CACHES了!
缓存的高级用法:
对于前后端分离的项目:
cache.set('test_data',{'name':'michael','age':18},5)
#对应的key为 test_data,数据位字典里的数据,超时时间为5秒
cache.get('test_data') # 取对应的缓存数据
二、跨域
跨域的产生是由于浏览器的同源策略,介绍下:
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
何为跨域:
通常情况下,A网页访问B服务器资源时,不满足以下三个条件其一就是跨域访问
1. 协议不同
2. 端口不同
3. 主机不同
跨域时,后端其实已经拿到前端发送的请求了,只是在返回数据时被拦截了!!!
解决方案:CORS(跨域资源共享)
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
基本流程:
览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
两种请求详解:
只要满足以下两大请求的,就是简单请求:
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
只要不满足上面两个条件的,就属于非简单请求
浏览器对这两种请求的处理,是不一样的。
二者的区别:
简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
* 关于“预检”
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'
支持跨域,复杂请求
由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
“预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
“预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
简单请求:
视图层:
from django.shortcuts import HttpResponse
def test1(request):
print(request.method)
bon = HttpResponse('ok')
return bon
中间件:
class CorsMiddleWare(MiddlewareMixin):
def process_response(self,request,response):
if request.method == 'GET':
response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8001"
return response
另外一个端口的django下的模板层:
<script>
$('#btn').click(function () {
alert(111)
$.ajax({
url:'http://127.0.0.1:8000/test1/',
type:'get',
data:{'name':'micahel'},
{#contentType:'application/json',#}
success:function (datas) {
console.log(datas)
}
})
})
</script>
非简单请求:
视图层:
在简单的函数下:
from django.shortcuts import HttpResponse
def test1(request):
print(request.method) # 会打印两次 一次为OPTIONS,另一次为前端的请求方式
bon = HttpResponse('ok')
return bon
中间件:
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
def process_response(self, request, response):
if request.method == 'OPTIONS':
print(request) # <WSGIRequest: OPTIONS '/test1/'>
print(response) # <HttpResponse status_code=200, "text/html; charset=utf-8">
response["Access-Control-Allow-Headers"] = "Content-Type"
if request.method == 'POST':
print(request) # <WSGIRequest: POST '/test1/'>
print(request.POST) # <QueryDict: {}> 因为我传过来的数据是json类型的
print(request.body) # b'name=micahel' json类型的数据在request.body里面
response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8001"
return response
另外一个端口下的模板层:
<script>
$('#btn').click(function () {
alert(111)
$.ajax({
url:'http://127.0.0.1:8000/test1/',
type:'post',
data:{'name':'micahel'},
contentType:'application/json',
success:function (datas) {
console.log(datas)
}
})
})
</script>
待续:在cbv下实现跨域 !!! 因为走了一次预检,所以第一次的method = options ,第二次为 post ,所以可考虑到cbv继承view,在其内部定义一个options方法即可! 不过在实际操作开发过程中,在视图类中不会写options方法,而是直接在中间件里完成即可!
-redis的安装和简单使用 -内存数据库 -Redis-x64-3.2.100---》mysql -redis-desktop-manager-0.9.3.817----》navcate -安装完后 -redis-server 服务端 -redis-cli 客户端
|