版本控制 django缓存 跨域 redis

一、版本控制:

1、内置的类:

QueryParameterVersioning, # 基于get传参的方式
eg:/users?version=v1
AcceptHeaderVersioning,# 基于请求头的
eg:Accept: application/json;   Accept为关键字
NamespaceVersioning, # 基于名称空间的
eg:v1.example.com
URLPathVersioning   # 基于正则的方式(推荐)
eg:/v1/users/
View Code

 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
}
View Code

二、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)
                      }
                     }   
                    }
View Code

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())
View Code

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>
View Code

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())
View Code

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> 
View Code

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
View Code

视图函数:

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))
View Code

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>
View Code

4、补充,缓存存储的数据格式:

-缓存存储的数据格式
unique-snowflake={
    index:asdfafasfasf,
    test:aerafdgerytwrega,
    'ttt':saefasfaefqwe,
    'yyy':asdfasfdsad,
}                
View Code

三、跨域问题:

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    
View Code

四、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)
View Code

视图函数中使用:

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('获取成功')
View Code

方式二:

安装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",
        }
    }
}
View Code

视图函数:

from django_redis import get_redis_connection
conn = get_redis_connection('default')
print(conn.hgetall('xxx'))
View Code

附:https://www.cnblogs.com/liuqingzheng/articles/9833534.html#_label3

原文地址:https://www.cnblogs.com/peng-zhao/p/10638546.html