通过django中间件和python魔法方法实现自定义session(通过文件存储session)
Posted 耗油炒白菜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过django中间件和python魔法方法实现自定义session(通过文件存储session)相关的知识,希望对你有一定的参考价值。
思路:
# 首先设置一个继承dict的类MysessionDict(用来设置session,例如request.mysession) # 请求来的时候 # 1、生成一个空的MysessionDict对象;request.mysession = MysessionDict() # 2、过滤url,如果请求是"/login/","/register/"就直接通过,不用获取cookie # 3、获取请求的cookie,如果有随机字符串,则拿着这个随机字符串到存放session的文件中去匹配是否存在这个cookie,如果存着取出对应的值并赋值给request.mysession.data # 请求走的时候 # 首先判断请求的url如果是"/login/"并且mysession操作方式是修改,如果是"/login/"(不是则不做处理): # 生成随机字符串, # 获取request.POST中的用户名和密码信息存放在data变量中 # 将随机字符串和data通过方法将信息存放到文件中 # 将随机字符串赋值给cookie,键为"mysession_id"; # response.set_cookie(\'mysession_id\', random_str) # 如果是删除操作 # 删除文件中session,并删除cookie
代码:
设置字典的MysessionDict.py
class MysessionDict(dict): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.modified = False self.deleted = False @staticmethod def check_type_of_key(key): return isinstance(key, str) or False def __setattr__(self, key, value): if not self.check_type_of_key(key): raise TypeError( "The type of key must be \'str\' " ) if key not in [\'modified\', \'deleted\']: self[\'modified\'] = True super().__setattr__(key, value) def __getattr__(self, item): return self.__dict__.get(item) def __setitem__(self, key, value): if not self.check_type_of_key(key): raise TypeError( "The type of key must be \'str\' " ) if key not in [\'modified\', \'deleted\']: self.modified = True setattr(self, key, value) def __getitem__(self, item): return getattr(self, item, None) def flush(self): self.deleted = True
操作session文件的方法encrypt.py
import json import os # 保存session到文件中 def dump(data, random_str): with open("static/session.txt", "a") as f: json_data = json.dumps(data) all_data = "%s|%s" % (random_str, json_data) f.write("{}\\n".format(all_data)) # 从文件中取出session_id对应的session值 def load(random_str): with open("static/session.txt", "r") as f: for line in f: if random_str in line: line = line.strip("\\n") line_list = line.split("|")[1] data = json.loads(line_list) return data # 删除cookie def delete(random_str): with open("static/session.txt", "r") as f, \\ open("static/session.txt.swap", "w", encoding="utf-8") as fw: for line in f: if random_str in line: line = "" fw.write("{}".format(line)) os.remove("static/session.txt") os.rename("static/session.txt.swap", "static/session.txt")
中间件mysession.py
from django.utils.deprecation import MiddlewareMixin from app01.mymiddleware.utils.MysessionDict import MysessionDict from app01.mymiddleware.utils.encrypt import dump, load, delete from django.shortcuts import redirect import uuid IgnoreUrl = [\'/login/\', \'/register/\'] class MyMiddleware(MiddlewareMixin): def process_request(self, request): request.mysession = MysessionDict() target_url = request.get_full_path() if target_url not in IgnoreUrl: random_str = request.COOKIES.get("mysession_id") if not random_str: return redirect("login") data = load(random_str) request.mysession.data = data def process_response(self, request, response): if request.mysession.modified and request.get_full_path() == "/login/": random_str = str(uuid.uuid1()) data = { "username": request.POST.get(\'username\'), "password": request.POST.get(\'password\') } dump(data,random_str) response.set_cookie(\'mysession_id\', random_str) request.mysession["modified"] = False if request.mysession.deleted: random_str = request.COOKIES.get("mysession_id") delete(random_str) response.delete_cookie("mysession_id") return response
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r\'^admin/\', admin.site.urls), # 注册 url(r\'^register/\', views.register), # 登录 url(r\'^login/\', views.login,name="login"), url(r\'^logout/\', views.logout), url(r\'^index/\', views.index), ]
views.py
from django.shortcuts import render, HttpResponse, redirect from django.http import JsonResponse from app01.register_forms import RegisterForms from app01 import models import json # Create your views here. def register(request): form_obj = RegisterForms() if request.method == "POST": back_code = {"code": 200, "msg": ""} data = json.loads(request.body) form_obj = RegisterForms(data) if form_obj.is_valid(): clean_data = form_obj.cleaned_data clean_data.pop("re_password") models.Userinfo.objects.create(**clean_data) back_code["msg"] = "注册成功" back_code["url"] = "/login/" else: back_code["code"] = 300 back_code["msg"] = form_obj.errors return JsonResponse(back_code) return render(request, "register.html", locals()) def login(request): if request.method == "POST": username = request.POST.get("username") password = request.POST.get("password") user_obj = models.Userinfo.objects.filter(username=username,password=password).first() if user_obj: request.mysession["modified"] = True return HttpResponse("ok") return render(request, "login.html") def logout(request): request.mysession.flush() return redirect("login") def index(request): print(request.mysession.data) if request.mysession.data: return JsonResponse(request.mysession.data) return HttpResponse("index")
models.py
from django.db import models # Create your models here. class Userinfo(models.Model): username = models.CharField(max_length=16, verbose_name="用户名") password = models.CharField(max_length=16, verbose_name="密码") age = models.IntegerField(verbose_name="年龄")
register_forms.py
from django import forms from app01 import models class RegisterForms(forms.Form): username = forms.CharField(max_length=16, min_length=4, label="用户名", error_messages={ \'min_length\': \'用户名最少4位\', \'max_length\': \'用户名最大16位\', \'required\': "用户名不能为空" }, widget=forms.widgets.TextInput(attrs={\'class\': \'form-control\'}) ) password = forms.CharField(max_length=16, min_length=4, label="密码", error_messages={ \'min_length\': \'密码最少4位\', \'max_length\': \'密码最大16位\', \'required\': "密码不能为空" }, widget=forms.widgets.PasswordInput(attrs={\'class\': \'form-control\'}) ) re_password = forms.CharField(max_length=16, min_length=4, label="确认密码", error_messages={ \'min_length\': \'确认密码最少4位\', \'max_length\': \'确认密码最大16位\', \'required\': "确认密码不能为空" }, widget=forms.widgets.PasswordInput(attrs={\'class\': \'form-control\'}) ) age = forms.CharField(label="年龄", error_messages={ \'required\': "年龄不能为空" }, widget=forms.widgets.TextInput(attrs={\'class\': \'form-control\'}) ) def clean_username(self): username = self.cleaned_data.get("username") user_obj = models.Userinfo.objects.filter(username=username).first() if user_obj: self.add_error("username", "用户已存在") if username.endswith("sb"): self.add_error("username", "用户名不能以sb结尾") return username def clean_age(self): age = self.cleaned_data.get("age") age = int(age) if not (age < 150 and age >18): self.add_error("age", "年龄必须小于150,大于18") age = str(age) return age def clean(self): password = self.cleaned_data.get("password") re_password = self.cleaned_data.get("re_password") if not password == re_password: self.add_error("re_password", "两次密码不一致") return self.cleaned_data
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- Bootstrap3 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- Bootstrap3 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> <!-- font-awesome.min.css图标库4.7版本 --> <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> {% load static %} </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h1 class="text-center">登录界面</h1> <form action="" method="post"> {% csrf_token %} 用户名:<input type="text" name="username" class="form-control"> 密 码:<input type="password" name="password" class="form-control"> <br> <input type="submit" class="btn btn-info btn-block" id="btn" value="提交"> </form> </div> </div> </div> </body> </html>
register.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- Bootstrap3 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- Bootstrap3 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> <!-- font-awesome.min.css图标库4.7版本 --> <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> {% load static %} </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h1 class="text-center">注册页面</h1> <form action="" method="post" novalidate> {% for form in form_obj %} <p> {{ form.label }}:{{ form }} <span style="color: red" class="input_span"></span> </p> {% endfor %} <input type="button" class="btn btn-info btn-block" id="btn" value="提交"> </form> </div> </div> </div> <script src="{% static \'js/mysteup.js\' %}"></script> <script> $("p span").each(function () { if ($(this).text()) { $(this).prev().css("border", "solid red") } }); $("#btn").click(function () { $.ajax({ url: \'\', type: \'post\', contentType:"application/json", dataType: \'json\', data: JSON.stringify({ "username": $("#id_username").val(), "password": $("#id_password").val(), "re_password": $("#id_re_password").val(), "age": $("#id_age").val(), }), success: function (args) { if (args.code == 200) { window.location.href = args.url } else { $.each(args.msg, function (index, obj) { {#console.log(index,obj) // username ["用户名不能为空"]#} let targetId = \'#id_\' + index; // input标签 $(targetId).next().text(obj[0]).prev().css("border", "solid red") }) } } }) }) $(\'input\').focus(function () { // 将input下面的span标签和input外面的div标签修改内容及属性 $(this).next().text(\'\').prev().removeAttr("style",""); }) </script> </body> </html>
以上是关于通过django中间件和python魔法方法实现自定义session(通过文件存储session)的主要内容,如果未能解决你的问题,请参考以下文章