• django 整理二


    跨站请求伪造

      django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。django中设置防跨站请求伪造功能有分为全局和局部

      html中设置Token: {csrf_token %}

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    局部:

    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

    from django.views.decorators.csrf import csrf_exempt,csrf_protect

    文件上传

    上传到代码目录

    1 <form action="/lx/upload/" method="post" enctype="multipart/form-data">
    2     {% csrf_token %}
    3     <input type="file" name="fafa">
    4     <input type="submit" value="go">
    5 </form>
    file.html
    1 def upload_file(request):
    2     if request.method == "POST":
    3         obj = request.FILES.get('fafa')
    4         print("obj.name:", obj.name)
    5         f = open(obj.name, 'wb')
    6         for chunk in obj.chunks():
    7             f.write(chunk)
    8         f.close()
    9     return render(request,'lx/file.html')
    views.py

    上传到数据库

     1 from django import forms
     2 from lx import models
     3 
     4 
     5 class FileForm(forms.Form):
     6     ExcelFile = forms.FileField()
     7 
     8 
     9 def upload(request):
    10     uf = FileForm(request.POST,request.FILES)
    11 
    12     if uf.is_valid():
    13         u_file = models.UploadFile()
    14         u_file.userid = 1
    15         u_file.file = uf.cleaned_data['ExcelFile']
    16         u_file.save()
    17         print(u_file.file)
    18     else:
    19         print('uf:', uf)
    20 
    21     return render(request, 'lx/file.html', {'uf': uf})
    views.py
    1 <form action="/lx/upload2/" method="post" enctype="multipart/form-data">
    2     {% csrf_token %}
    3     <p>{{ uf }}</p>
    4     <input type="submit" value="go">
    5 </form>
    file.html
    1 class UploadFile(models.Model):
    2     userid = models.CharField(max_length=30)
    3     file = models.FileField(upload_to='./upload2/')
    4     date = models.DateTimeField(auto_now_add=True)
    models.py

    Session

    Django中默认支持Session,内部提供了5种类型的Session供开发者使用:

    数据库(默认)
    缓存
    文件
    缓存 + 数据库
    加密cookie

    数据库Session

     1     SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
     2      
     3     SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
     4     SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
     5     SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
     6     #SESSION_COOKIE_DOMAIN = '.baidu.com'
     7     SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
     8     SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
     9     SESSION_COOKIE_AGE = 86400 * 14                             # Session的cookie失效日期(2周)(默认)
    10     SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    11     SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
    settings.py
    缓存Session
     1 CACHES = {
     2     'default': {       # 这个地方必须是'default',否则会报错
     3         'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
     4         'LOCATION': [
     5             '127.0.0.1:11211',
     6             '127.0.0.1:11212',
     7         ]
     8 
     9     }
    10 }
    11 
    12 SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    13 SESSION_CACHE_ALIAS = 'default'  # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
    14 
    15 SESSION_COOKIE_NAME = "sessionid"  # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    16 SESSION_COOKIE_PATH = "/"  # Session的cookie保存的路径
    17 SESSION_COOKIE_DOMAIN = None  # Session的cookie保存的域名
    18 SESSION_COOKIE_SECURE = False  # 是否Https传输cookie
    19 SESSION_COOKIE_HTTPONLY = True  # 是否Session的cookie只支持http传输
    20 SESSION_COOKIE_AGE = 1209600  # Session的cookie失效日期(2周)
    21 SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 是否关闭浏览器使得Session过期
    22 SESSION_SAVE_EVERY_REQUEST = False  # 是否每次请求都保存Session,默认修改之后才保存
    settings.py

    文件Session(文件路径必须存在)

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

    缓存+数据库Session

     1 CACHES = {
     2     # 'default': {
     3     #     'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
     4     #     'LOCATION': os.path.join(BASE_DIR, 'cache_file'),
     5     #     'TIMEOUT': 600,
     6     #     'OPTIONS': {
     7     #         'MAX_ENTRIES': 1000
     8     #     }
     9     # }
    10     'default': {
    11         'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
    12         'LOCATION': [
    13             '127.0.0.1:11211',
    14             '127.0.0.1:11212',
    15         ]
    16 
    17     }
    18 }
    19 
    20 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'   # 引擎
    settings.py

    加密cookies Session

    1 SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
    settings.py

    session操作如下:

     1 def index(request):
     2     # request.session['k1'] = 123   # 赋值
     3     #
     4     # v1 = request.session['k1']
     5 
     6     # v2 = request.session.get('k1',None)  # 不存在则为None
     7     #
     8     # v3 = request.session.setdefault('k1', 456)  # 存在则不设置
     9     # print(v2, v3)
    10     # del request.session['k1']
    11 
    12     # 所有键、值 、键值对, 以列表的形式返回
    13     # request.session.setdefault('k1', 456)
    14     # v1 = request.session.keys()
    15     # v2 = request.session.values()
    16     # v3 = request.session.items()
    17     # print(v1,v2,v3)
    18 
    19     # v1 = request.session.session_key    # 用户session的随机字符串
    20     # v2 = request.session.clear_expired()   # 将所有Session失效日期小于当前日期的数据删除
    21     # v4 = request.session.exists('7m1k9hervqps7l131x22tnu4hvz1bf9j')   # 检查 用户session的随机字符串 在数据库中是否
    22     # v5 = request.session.delete('session_key')   # 删除当前用户的所有Session数据
    23     # # request.session.set_expiry(value)
    24     # #     *如果value是个整数,session会在些秒数后失效。
    25     # #     *如果value是个datatime或timedelta,session就会在这个时间后失效。
    26     # #     *如果value是0, 用户关闭浏览器session就会失效。
    27     # #     *如果value是None, session会依赖全局session失效策略。
    28 
    29     # print(v1, v2, v3, v4, v5)
    30 
    31     return HttpResponse("OK")
    views.py

     django内置分页扩展

     1 from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
     2 
     3 
     4 class CustomPaginator(Paginator):
     5     def __init__(self, current_page, max_pager_num, *args, **kwargs):
     6         """
     7         :param current_page: 当前页
     8         :param max_pager_num: 最多显示的页码个数
     9         :param args:
    10         :param kwargs:
    11         """
    12         self.current_page = int(current_page)
    13         self.max_pager_num = max_pager_num
    14         super(CustomPaginator, self).__init__(*args, **kwargs)
    15 
    16     def page_num_range(self):
    17         # 当前页面
    18         # self.current_page
    19         # 总页数
    20         # self.num_pages
    21         # 最多显示的页码个数
    22         # self.max_pager_num
    23         print(1)
    24         if self.num_pages < self.max_pager_num:
    25             return range(1, self.num_pages + 1)
    26         print(2)
    27         part = int(self.max_pager_num / 2)
    28         if self.current_page - part < 1:
    29             return range(1, self.max_pager_num + 1)
    30         print(3)
    31         if self.current_page + part > self.num_pages:
    32             return range(self.num_pages + 1 - self.max_pager_num, self.num_pages + 1)
    33         print(4)
    34         return range(self.current_page - part, self.current_page + part + 1)
    35 
    36 
    37 L = []
    38 for i in range(999):
    39     L.append(i)
    40 
    41 
    42 def page(request):
    43     current_page = request.GET.get('p', 1)
    44     # paginator = Paginator(L,10)
    45     paginator = CustomPaginator(current_page, 11, L, 10)
    46         # per_page: 每页显示条目数量
    47         # count:    数据总个数
    48         # num_pages:总页数
    49         # page_range:总页数的索引范围,如: (1,10),(1,200)
    50         # page:     page对象
    51 
    52     try:
    53         print('current_page:', current_page)
    54         posts = paginator.page(current_page)
    55             # has_next              是否有下一页
    56             # next_page_number      下一页页码
    57             # has_previous          是否有上一页
    58             # previous_page_number  上一页页码
    59             # object_list           分页之后的数据列表
    60             # number                当前页
    61             # paginator             paginator对象
    62     except PageNotAnInteger:
    63         posts = paginator.page(1)
    64     except EmptyPage:
    65         posts = paginator.page(paginator.num_pages)
    66 
    67     print('posts:', posts, 'type posts:', type(posts))
    68 
    69     return render(request, 'lx/page.html', {'posts': posts})
    views.py
     1 <ul>
     2     {% for item in posts %}
     3     <li>{{ item}}</li>
     4     {% endfor %}
     5 </ul>
     6 
     7 <div class="pagination">
     8     <span class="step-links">
     9         {% if posts.has_previous %}
    10         <a href="?p={{ posts.previous_page_number }}">Previous</a>
    11         {% endif %}
    12 
    13         {% for i in posts.paginator.page_num_range %}
    14         <a href="?p={{ i }}">{{ i }}</a>
    15         {% endfor %}
    16 
    17         {% if posts.has_next %}
    18         <a href="?p={{ posts.next_page_number }}">Next</a>
    19         {% endif %}
    20     </span>
    21 
    22     <span class="current">
    23         Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
    24     </span>
    25 
    26 </div>
    page.html

     序列化

    Django为我们提供了一个强大的序列化工具serializers,支持三种序列化格式:xml、json、yaml
    serialize方法至少接收两个参数,
    	第一: 要序列化成为的数据格式,这里是‘xml’
    	第二: 要序列化的数据对象,数据通常是ORM模型的QuerySet,一个可迭代的对象
    	
    序列化数据:
    	from django.core import serializers
    	data = serializers.serialize("xml", models.UserType.objects.all())
    	
    序列化数据写入文件:
    	with open("file.xml", "w") as out:
    		xml_serializer.serialize(models.UserType.objects.all(), stream=out)
    		
    序列化指定字段:
    	from django.core import serializers
    	data = serializers.serialize('xml', models.UserType.objects.all(), fields=('name','size'))
    	
    序列化继承模型
    	class Place(models.Model):
    		name = models.CharField(max_length=50)
    
    	class Restaurant(Place):
    		serves_hot_dogs = models.BooleanField(default=False)
    	
    	############  序列化Restaurant中属性  ############
    	data = serializers.serialize('xml', Restaurant.objects.all())
    	
    	############  序列化Restaurant与Place中属性  ############
    	all_objects = list(Restaurant.objects.all()) + list(Place.objects.all())
    	data = serializers.serialize('xml', all_objects)
    	
    反序列化:
    	# deserialize()方法返回的是一个迭代器
    	for obj in serializers.deserialize("xml", data):
    		print(obj)

    json.dumps无法处理datetime日期,可以通过自定义处理器来做扩展。

     1 import json
     2 from datetime import date
     3 from datetime import datetime
     4 
     5 
     6 class JsonCustomEncoder(json.JSONEncoder):
     7     def default(self, field):
     8         if isinstance(field, datetime):
     9             return field.strftime('%Y-%m-%d %H:%M:%S')
    10         elif isinstance(field, date):
    11             return field.strftime('%Y-%m-%d')
    12         else:
    13             return json.JSONEncoder.default(self, field)
    14 
    15 
    16 d = date.today()
    17 d2 = datetime.now()
    18 print(d, d2)
    19 ds = json.dumps(d, cls=JsonCustomEncoder)
    20 ds2 = json.dumps(d2, cls=JsonCustomEncoder)
    21 # ds = json.dumps(d)
    22 print("ds:", ds)
    23 print('ds2:', ds2)
    View Code

     信号

     Django中提供了“信号调度”,用于在框架执行操作时解耦。就是一些动作发生的时候,去执行一些操作。

    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          # 创建数据库连接时,自动触发

    信号signal实例:

    方法一(通过receiver()装饰器进行注册):
    
        from django.core.signals import request_finished
        from django.dispatch import receiver
    
        @receiver(request_finished)
        def my_callback(sender, **kwargs):
            print("Resquest finished!")
            
    方法二(手动注册):
        
        from django.core.signals import request_finished
    
        def my_callback(sender, **kwargs):
            print("Resquest finished!")
    
        request_finished.connect(my_callback)
        
        # Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)[source]
        
            # receiver :当前信号连接的回调函数,也就是处理信号的函数。 
            # sender :指定从哪个发送方接收信号。 
            # weak : 是否弱引用
            # dispatch_uid :信号接收器的唯一标识符,以防信号多次发送。
    1 from django.db.models.signals import pre_save
    2 from django.dispatch import receiver
    3 from .models import UploadFile
    4 
    5 @receiver(pre_save, sender=UploadFile)
    6 def my_callback(sender, **kwargs):
    7     print("Resquest finished!")
    特定发送者信号

    防止重复信号

    	# 每个唯一的dispatch_uid值,接收器都只绑定到信号一次
    	from django.core.signals import request_finished
    
    	request_finished.connect(my_callback,dispatch_uid="my_unique_identifier")  

    自定义信号

     1 from django.shortcuts import HttpResponse
     2 import time
     3 import django.dispatch
     4 from django.dispatch import receiver
     5 
     6 work_done = django.dispatch.Signal(providing_args=['path', 'time'])
     7 
     8 def create_signal(request):
     9     url_path = request.path
    10     print("我已经做完了工作。现在我发送一个信号出去,给那些指定的接收器。")
    11 
    12     work_done.send(create_signal, path=url_path, time=time.strftime("%Y-%m-%d %H:%M:%S"))
    13     return HttpResponse("200, OK")
    14 
    15 
    16 @receiver(work_done, sender=create_signal)
    17 def my_callback(sender, **kwargs):
    18     print("我在%s时间收到来自%s的信号,请求url为%s" % (kwargs['time'], sender, kwargs["path"]))
    views.py

     

      

  • 相关阅读:
    puppeteer,新款headless chrome!
    圣诞快乐,而且写博客有两年了~
    es2015及es2017对我们的编程方式造成了什么影响?
    Redis的安装和部署
    ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息
    hsweb 企业后台管理基础框架
    通过Spring Session实现新一代的Session管理
    mod_pagespeed
    unusedjs
    apache模块 合并多个js/css 提高网页加载速度
  • 原文地址:https://www.cnblogs.com/sshcy/p/9243877.html
Copyright © 2020-2023  润新知