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

 

 

  

posted @ 2018-07-04 11:05  ︻◣_蝸犇り~  阅读(150)  评论(0编辑  收藏  举报