版本控制 django缓存 跨域 redis
一、版本控制:
1、内置的类:
QueryParameterVersioning, # 基于get传参的方式 eg:/users?version=v1 AcceptHeaderVersioning,# 基于请求头的 eg:Accept: application/json; Accept为关键字 NamespaceVersioning, # 基于名称空间的 eg:v1.example.com URLPathVersioning # 基于正则的方式(推荐) eg:/v1/users/
2、局部使用:
在视图类中配置
如:versioning_class=URLPathVersioning #单个项目只能设置一种方法 所以此处非列表
3、全局使用:在settings中配置:
REST_FRAMEWORK = { 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.QueryParameterVersioning', 'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值) 'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本 'VERSION_PARAM': 'version' # URL中获取值的key }
二、django缓存
1、目的:为了提高网站的并发量
2、djago缓存的三种粒度六种缓存方式
2.1、六种缓存方式:
a、开发调试缓存
b、内存缓存
c、文件缓存
d、数据库缓存
e、Memcache缓存(使用python-memcached模块)
f、Memcache缓存(使用pylibmc模块)
经常使用的有文件缓存和Mencache缓存
2.2、三种粒度:
a、全站缓存
b、单页面缓存
c、页面中局部缓存
3、缓存是的使用:(文件缓存举例:)
其他缓存配置请参考:https://www.cnblogs.com/liuqingzheng/articles/9803351.html
3.1 在settings中配置(缓存方式:文件)
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) } } }
3.2、使用缓存:
3.2.1、使用单页面缓存(使用装饰器):
视图:
from django.views.decorators.cache import cache_page import time from .models import * @cache_page(15) #超时时间为15秒 def index(request): t=time.time() #获取当前时间 bookList=Book.objects.all() return render(request,"index.html",locals())
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3>当前时间:-----{{ t }}</h3> <ul> {% for book in bookList %} <li>{{ book.name }}--------->{{ book.price }}$</li> {% endfor %} </ul> </body> </html>
3.2.2、页面局部缓存:
视图:
from django.views.decorators.cache import cache_page import time from .models import * def index(request): t=time.time() #获取当前时间 bookList=Book.objects.all() return render(request,"index.html",locals())
html:
{% load cache %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3 style="color: green">不缓存:-----{{ t }}</h3> {% cache 2 'name' %} <h3>缓存:-----:{{ t }}</h3> {% endcache %} </body> </html>
3.2.3、全站缓存:
通过中间件控制,判断缓存是否存在,若不存在,则通过中间件将其全部缓存到django的缓存中
MIDDLEWARE_CLASSES = ( 'django.middleware.cache.UpdateCacheMiddleware', #响应HttpResponse中设置几个headers 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', #用来缓存通过GET和HEAD方法获取的状态码为200的响应 ) CACHE_MIDDLEWARE_SECONDS=10 # 用来控制时间的配置 单位为s
视图函数:
from django.views.decorators.cache import cache_page import time from .models import * def index(request): t=time.time() #获取当前时间 bookList=Book.objects.all() return render(request,"index.html",locals()) def foo(request): t=time.time() #获取当前时间 return HttpResponse("HELLO:"+str(t))
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h3 style="color: green">当前时间:-----{{ t }}</h3> <ul> {% for book in bookList %} <li>{{ book.name }}--------->{{ book.price }}$</li> {% endfor %} </ul> </body> </html>
4、补充,缓存存储的数据格式:
-缓存存储的数据格式 unique-snowflake={ index:asdfafasfasf, test:aerafdgerytwrega, 'ttt':saefasfaefqwe, 'yyy':asdfasfdsad, }
三、跨域问题:
IP 端口 协议三者有一个不同就是跨域
解决方法:跨域资源共享
1、跨域资源共享(CORS)简介:
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
2、CORS基本流程
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
3、CORS两种请求详解:
(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预检请求,预检请求同意我发,我再发起第二次真实请求,一次是真实的请求
以后处理跨域问题(可以用第三方的django-cors-headers),即在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。 * 关于“预检” - 请求方式:OPTIONS - “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息 - 如何“预检” => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过 Access-Control-Request-Method => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过 Access-Control-Request-Headers
支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'
支持跨域,复杂请求
由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
- “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
- “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
例:
class MyMiddleware(MiddlewareMixin): def process_response(self,request,response): #处理了简单请求 response['Access-Control-Allow-Origin'] = '*' #处理非简单请求 if request.method=='OPTIONS': response['Access-Control-Allow-Headers']='*' # response['Access-Control-Allow-Methods']='PUT,PATCH' response['Access-Control-Allow-Methods']='*' return response
四、redis数据库:
1、数据库的安装:https://www.cnblogs.com/liuqingzheng/p/9831331.html
2、redis,mongodb:非关系型数据库/nosql
-redis存储在内存中
-mongodb存储在硬盘上
3、redis一般用来
a、做缓存
b、session数据
c、游戏排行榜
d、对速度要求比较高的数据的存储
e、做消息队列
4、redis是key-value的存储,支持持久化,像py中的字典,有5大数据类型:
a、字符串
b、列表
c、字典
d、集合
e、有序集合
redis={
k1:'123', 字符串
k2:[1,2,3,4], 列表/数组
k3:{1,2,3,4} 集合
k4:{name:lqz,age:12} 字典/哈希表
k5:{('lqz',18),('egon',33)} 有序集合
}
5、比较redis和Memcached
a、redis 支持5大数据类型
b、redis支持持久化
c、单线程,单进程,速度是非常快
d、Memcached不能持久化,只支持字符串
6、string操作:
set(name, value, ex=None, px=None, nx=False, xx=False) #在Redis中设置值,默认,不存在则创建,存在则修改 参数: # ex,过期时间(秒) # px,过期时间(毫秒) # nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果 # xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值 setnx(name, value) #设置值,只有name不存在时,执行设置操作(添加),如果存在,不会修改 setex(name, time, value) # 设置值 # 参数: # time,过期时间(数字秒 或 timedelta对象) psetex(name, time_ms, value) # 设置值 # 参数: # time_ms,过期时间(数字毫秒 或 timedelta对象 mset(*args, **kwargs) #批量设置值 #如: # mset(k1='v1', k2='v2') #或 # mget({'k1': 'v1', 'k2': 'v2'}) get(name) #获取值 mget(keys, *args) #批量获取 #如: #mget('k1', 'k2') # 或 #r.mget(['k3', 'k4']) getset(name, value) #设置新值并获取原来的值 getrange(key, start, end) # 获取子序列(根据字节获取,非字符) # 参数: # name,Redis 的 name # start,起始位置(字节) # end,结束位置(字节) # 如: "刘清政" ,0-3表示 "刘" setrange(name, offset, value) # 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加) # 参数: # offset,字符串的索引,字节(一个汉字三个字节) # value,要设置的值 setbit(name, offset, value) # 对name对应值的二进制表示的位进行操作 # 参数: # name,redis的name # offset,位的索引(将值变换成二进制后再进行索引) # value,值只能是 1 或 0 # 注:如果在Redis中有一个对应: n1 = "foo", 那么字符串foo的二进制表示为:01100110 01101111 01101111 所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1, 那么最终二进制则变成 01100111 01101111 01101111,即:"goo" getbit(name, offset) # 获取name对应的值的二进制表示中的某位的值 (0或1) bitcount(key, start=None, end=None) # 获取name对应的值的二进制表示中 1 的个数 # 参数: # key,Redis的name # start,位起始位置 # end,位结束位置 bitop(operation, dest, *keys) # 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值 # 参数: # operation,AND(并) 、 OR(或) 、 NOT(非) 、 XOR(异或) # dest, 新的Redis的name # *keys,要查找的Redis的name # 如: bitop("AND", 'new_name', 'n1', 'n2', 'n3') # 获取Redis中n1,n2,n3对应的值,然后讲所有的值做位运算(求并集),然后将结果保存 new_name 对应的值中 strlen(name) # 返回name对应值的字节长度(一个汉字3个字节) incr(self, name, amount=1) # 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。 # 参数: # name,Redis的name # amount,自增数(必须是整数) # 注:同incrby incrbyfloat(self, name, amount=1.0) # 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。 # 参数: # name,Redis的name # amount,自增数(浮点型) decr(self, name, amount=1) # 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。 # 参数: # name,Redis的name # amount,自减数(整数) append(key, value) # 在redis name对应的值后面追加内容 # 参数: key, redis的name value, 要追加的字符串
7、django中使用redis
方式一:(通过导入模块来实现单例)
--redis_pool.py
import redis POOL = redis.ConnectionPool(host='127.0.0.1', port=6379,password='1234',max_connections=1000)
视图函数中使用:
import redis from django.shortcuts import render,HttpResponse from utils.redis_pool import POOL def index(request): conn = redis.Redis(connection_pool=POOL) conn.hset('kkk','age',18) return HttpResponse('设置成功') def order(request): conn = redis.Redis(connection_pool=POOL) conn.hget('kkk','age') return HttpResponse('获取成功')
方式二:
安装django-redis模块
settings中
# redis配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "123", } } }
视图函数:
from django_redis import get_redis_connection conn = get_redis_connection('default') print(conn.hgetall('xxx'))
附:https://www.cnblogs.com/liuqingzheng/articles/9833534.html#_label3