Python 学习第二十二天 django知识(四)

一,django session知识

  (1)session与cookies

          session是保存在服务器端的键值对,而cookies是保存在客户浏览器端的特定文件中的键值对

  (2)在用session时,django必须执行两步python manage.py makemigrations,python manage.py migrate 生成相关的session表

  (3)request.session['username']=user 在session中设置值,requset.session['username']在session中获取值

  (4)session 的数据全都保存在服务器端,只给客户端发一份随机字符串,并通过这个随机字符串做验证,session依赖于cookie

  (5)session的配置和操作

         1,数据库session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
  
a. 配置 settings.py
  
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
      
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
  
  
  
b. 使用
  
    def index(request):
        # 获取、设置、删除Session中数据
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在则不设置
        del request.session['k1']
  
        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
  
  
        # 用户session的随机字符串
        request.session.session_key
  
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
  
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
  
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
  
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。

     2,缓存session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
a. 配置 settings.py
  
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
  
  
    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
  
  
  
b. 使用
  
    同上

     3,文件session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a. 配置 settings.py
  
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
  
  
    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
  
b. 使用
  
    同上

     4,缓存+数据库session

1
2
3
4
5
6
7
8
9
数据库用于做持久化,缓存用于提高效率
  
a. 配置 settings.py
  
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
  
b. 使用
  
    同上

    5,加密cookies

1
2
3
4
5
6
7
a. 配置 settings.py
      
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
  
b. 使用
  
    同上

 二,CSRF知识

  1,CSRF原理

   先访问页面时设置一个随机的字符串,当提交的时候带着生成的随机字符串去提交,则通过CSRF的验证

  2,设置CSRF

    (1)form表单提交,不仅在cookie中生成一个csrftoken,而且在cookie中也会生成一个cerftoken

1
2
3
4
5
6
<form action="/login/" method="POST">
       {% csrf_token %}                                                           #会在html页面自动生成一个input框,并且包含一个随机的字符串    
       <input type="text" name="user" />
       <input type="text" name="pwd" />
       <input type="submit" value="提交" />
</form>

    (2)通过ajax请求提交,访问后端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
    <script><br>    
        $(function(){
            $.ajaxSetup({
                beforeSend: function(xhr,settings){
                    xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
                }
            });
 
            $('#btn1').click(function () {
                $.ajax({
                    url: '/login/',
                    type:"POST",
                    data: {'user': 'root', 'pwd': '123'},
                    // headers: {'X-CSRFtoken': $.cookie('csrftoken')},
                    success:function(arg){
 
                    }
                })
            });
        })
 </script>

   (3)views函数设置CSRF

1
2
3
4
5
6
7
8
9
10
全局:
 
  中间件 django.middleware.csrf.CsrfViewMiddleware
 
局部:
 
    @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
 
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

   (4)官网提供的CSRF的ajax提交设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
<script src="/static/plugin/jquery/jquery.cookie.js"></script>
<script type="text/javascript">
        var csrftoken = $.cookie('csrftoken');
   
        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));      #只对于某个方式的提交添加CSRF
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        function Do(){ 
            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
   
        }
</script>

 三,django中间件

 (1)django中间件原理:

  在django的settings.py中的MIDDLEWARE模块中写入某个类的以及类中的方法,并且在这个方法中已process_request做为请求的传递,经过每个中间件函数,最终将请求发送到django的url中,再经过url匹配views函数处理,最终将结果返回,并且返回时需要经过每个中间件的proess_response

(2)中间件可以对所有的请求做一个统一的操作,例如:IP请求过滤,公共校验

(3)自定义中间件

  1,在django 工程中创建任意的目录,例如middle

  2,在目录中创建.py文件,例如:m1.py

  3,m1.py中编写Python类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from django.utils.deprecation import MiddlewareMixin
class row1(MiddlewareMixin):
    def process_request(self,request):                                    #必须是process_request或者process_response函数
        print("1111")
    def process_response(self,request,response):
        print("aaaa")
        return response
class row2(MiddlewareMixin):
    def process_request(self,request):
        print("2222")
    def process_response(self,request, response):
        print("bbbbb")
        return response
class row3(MiddlewareMixin):
    def process_request(self,request):
        print("3333")
    def process_response(self,request, response):
        print("ccccc")
        return response

  4,在django的settings.py文件中添加中间件

1
2
3
4
5
6
7
8
9
10
11
12
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'middle.m1.row1',
    'middle.m1.row2',
    'middle.m1.row3',
]

   5,中间件其它方法

1
2
process_view(self, request, view_func, view_func_args, viws_func_kwargs)  #增加一个中间件处理流程
process_exception(self, request, exception)                               #捕捉view函数中的异常,并进行处理,返回给用户

 四,django 缓存

   1,配置

  (1)开发调试配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
复制代码
 
    # 此为开始调试用,实际内部不做任何操作
    # 配置:
        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)
                },
                'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
                'VERSION': 1,                                                 # 缓存key的版本(默认1)
                'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
            }
        }
 
 
    # 自定义key
    def default_key_func(key, key_prefix, version):
        """
        Default function to generate keys.
 
        Constructs the key used by all other methods. By default it prepends
        the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
        function with custom key making behavior.
        """
        return '%s:%s:%s' % (key_prefix, version, key)
 
    def get_key_func(key_func):
        """
        Function to decide which key function to use.
 
        Defaults to ``default_key_func``.
        """
        if key_func is not None:
            if callable(key_func):
                return key_func
            else:
                return import_string(key_func)
        return default_key_func
 
复制代码

    (2)内存缓存

1
2
3
4
5
6
7
8
9
10
11
12
# 此缓存将内容保存至内存的变量中
# 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }
 
    # 注:其他配置同开发调试版本
 
复制代码

   (3)文件缓存

1
2
3
4
5
6
7
8
9
10
# 此缓存将内容保存至文件
# 配置:
 
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': '/var/tmp/django_cache',
            }
        }
 # 注:其他配置同开发调试版本

    (4)数据库缓存

1
2
3
4
5
6
7
8
9
10
11
# 此缓存将内容保存至数据库
 
# 配置:
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
            'LOCATION': 'my_cache_table', # 数据库表
        }
    }
 
# 注:执行创建表命令 python manage.py createcachetable

     (5)memcache缓存,python-memcached模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 此缓存使用python-memcached模块连接memcache 
 
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }
 
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': 'unix:/tmp/memcached.sock',
        }
    }  
 
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }

     (6)memcache缓存(pylibmc模块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 此缓存使用pylibmc模块连接memcache
 
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '127.0.0.1:11211',
    }
}
 
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': '/tmp/memcached.sock',
    }
}  
 
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    }
}

   2,应用

    (1)某个view函数做缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
方式一:
    from django.views.decorators.cache import cache_page
 
    @cache_page(60 * 15)
    def my_view(request):
        ...
 
方式二:
    from django.views.decorators.cache import cache_page
 
    urlpatterns = [
        url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
    ]

   (2)对某个html内容进行缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% load cache %}                                      #先进行load
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>{{ ctime }}</h1>
    <h1>{{ ctime }}</h1>
 
     {% cache 10 c1 %}                              #10为10秒,c1为缓存的key
        <h1>{{ ctime }}</h1>
     {% endcache %}
</body>
</html>

    (3)全站使用

1
2
3
4
5
6
7
8
9
10
11
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
 
    MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',
        # 其他中间件...
        'django.middleware.cache.FetchFromCacheMiddleware',
    ]
 
    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""

     3,缓存优先级,(1)全局的缓存(2)views函数定义的缓存(3)模板语言的缓存

 五,django 信号

  1,django 内置信号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Model signals
    pre_init                    # django的modal执行其构造方法前,自动触发
    post_init                   # django的modal执行其构造方法后,自动触发
    pre_save                    # django的modal对象保存前,自动触发
    post_save                   # django的modal对象保存后,自动触发
    pre_delete                  # django的modal对象删除前,自动触发
    post_delete                 # django的modal对象删除后,自动触发
    m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
    pre_migrate                 # 执行migrate命令前,自动触发
    post_migrate                # 执行migrate命令后,自动触发
Request/response signals
    request_started             # 请求到来前,自动触发
    request_finished            # 请求结束后,自动触发
    got_request_exception       # 请求异常后,自动触发
Test signals
    setting_changed             # 使用test测试修改配置文件时,自动触发
    template_rendered           # 使用test测试渲染模板时,自动触发
Database Wrappers
    connection_created          # 创建数据库连接时,自动触发

   2,django信号的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception
 
from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate
 
from django.test.signals import setting_changed
from django.test.signals import template_rendered
 
from django.db.backends.signals import connection_created
 
 
def callback(sender, **kwargs):
    print("xxoo_callback")
    print(sender,kwargs)
 
xxoo.connect(callback)

   3,不在wiews.py文件中的信号导入

  (1)编写信号.py文件

      (2)将信号.py文件导入到django app的__init__.py中,启动app就会将信号.py加载到内存中

      4,自定义信号

  (1)定义信号

1
2
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

     (2)注册信号

1
2
3
4
5
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
  
pizza_done.connect(callback)

    (3)触发信号

1
2
3
from 路径 import pizza_done
  
pizza_done.send(sender='seven',toppings=123, size=456)

 

posted @   niu_x  阅读(321)  评论(0编辑  收藏  举报
编辑推荐:
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
阅读排行:
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
· MQ 如何保证数据一致性?
点击右上角即可分享
微信分享提示