Django【第12篇】:Django之中间件
自定义验证规则以及中间件简单介绍
1、python2和python3中的区别
对于python2内置的字符串类型有str和unicode
比如:"abc"是字符串,u"你好"是unicode
字符串(utf-8/gbk编码之后值) unicode
对于python3内置的字符串类型有bytes和unicode
bytes(utf-8/gbk编码之后值) 字符串(unicode) python3 中的bytes,就是python2中的字符串
python2 中的字符串,就是python3中的unicode
2、数据源无法时时更新,有两种方法
方式一:重构构造方法(推荐)
方法一:重构构造方法(推荐)
class ClassesForm(Form):
name = fields.CharField(
required=True, # 必填字段
error_messages={"required": "姓名不能为空!!"}, # 显示中文错误提示
widget=widgets.TextInput(attrs={"placeholder": "姓名", "class": "form-control"}), # 自动生成input框
)
# 如果直接定义成classteacher_id,,_id 的形式,这样你添加数据的时候不会时时更新,所以在下面定义一个重写的方法
# classteacher_id = fields.ChoiceField(choices= models.UserInfo.objects.filter(ut_id = settings.ROLE_CLASSTEACHER).values_list('id', "username")) classteacher_id = fields.ChoiceField(choices=[])
def __init__(self,*args,**kwargs): #重写init方法,时时更新
super().__init__(*args,**kwargs) #继承父类
self.fields["classteacher_id"].choices = models.UserInfo.objects.filter(ut_id = settings.ROLE_CLASSTEACHER).values_list('id', "username")
注意:
要是这样:fields.ChoiceField(choices=[])
注意choices里面传[(1,"讲师"),(2,"班主任"),(3,"管理员")]所以数据库里取的时候得用values_list
方式二:
方法二:ModelChoiceField(不推荐),queryset
from django.forms.models import ModelChoiceField #先导入
class ClassForm(Form):
caption = fields.CharField(error_messages={'required':'班级名称不能为空'})
# headmaster = fields.ChoiceField(choices=[(1,'娜娜',)])
headmaster_id = ModelChoiceField(queryset=models.UserInfo.objects.filter(ut_id=2))
3、Form基本使用
类
字段
is_valid()
cleaned_data
errors
字段参数:
max_length
min_length
validators = [RegexValidators("xxx")] 钩子函数
clean_字段名
注意:
必须有返回值
只能拿自己当前字段值
raise ValidationError("xxx")
下拉框数据源时时更新
1、重写init方法
先执行父类构造方法
self.fields["xx"].choices = xxxxx
2、ModelChoiceField
4、用户登录
- form的字段可以定义正则表达式
password = fields.CharField(
required=True,
min_length=3,
max_length=18,
error_messages={
'required': '密码不能为空',
'min_length': '密码长度不能小于3',
'max_length': '密码长度不能大于18',
'invalid': '密码格式错误',
},
validators=[RegexValidator('\d+','只能是数字') ]
)
注意:error_messages的优先级比validators高
需要导入的模块
from django.forms import Form
from django.forms import fields
from django.forms import widgets
from django.conf import settings
from django.core.validators import ValidationError
from django.core.validators import RegexValidator
class LoginForm(Form):
username = fields.CharField(
required=True, #必填字段
min_length=3,
max_length=16,
error_messages={
"required":"用户名不能为空",
"min_length":"长度不能小于3",
"max_length":"长度不能大于16"
},
widget=widgets.TextInput({"placeholder":"username","class":"form-control"})
)
password = fields.CharField(
required=True,
min_length=3,
max_length=16,
error_messages={
"required": "密码不能为空",
"min_length": "密码长度不能小于3",
"max_length": "密码长度不能大于16",
# "invalid":"密码格式错误"
# error_messages的优先级高,如果写上"invalid":"密码格式错误"这个就会优先显示这个错误
},
widget=widgets.PasswordInput({"placeholder":"password","class":"form-control"}),
validators=[RegexValidator("\d+","密码只能是数字")] #可以进行正则匹配提示错误
) def clean_username(self):
user = self.cleaned_data["username"]
is_exits = models.UserInfo.objects.filter(username=user).count()
if not is_exits:
raise ValidationError("用户名和密码错误")
return user #必须有return
views.py ---------login
def login(request):
if request.method == "GET":
form = LoginForm()
return render(request, "login.html", {"form": form})
else:
form = LoginForm(data=request.POST)
if form.is_valid():
print(form.cleaned_data)
# username = form.cleaned_data["username"]
# password = form.cleaned_data["password"]
# user = models.UserInfo.objects.filter(username=username, password=password).first()
user = models.UserInfo.objects.filter(**form.cleaned_data).first()
if user: #这次是和数据库里的数据进行比较
#验证成功
print(user.username)
request.session[settings.GDP] = {"id":user.id,"username":user.username} #设置session
return redirect("/teacherindex/")
else:
#验证失败,就给增加一个错
form.add_error("password","用户名或密码不正确")
return render(request, "login.html", {"form": form})
else:
return render(request, "login.html", {"form": form})
- 主动向form中添加错误信息
# form.add_error('password','用户名或密码错误')
form.add_error('password',ValidationError('用户名或密码错误'))
这两个都可以,建议用第二个
5、Form扩展(钩子函数)
如果对username做扩展
#先做正则表达式判断
#然后自定义方法验证:也就是clean_xx,称为钩子函数
def clean_username(self):
#可以写自己的验证提示
不像validators只写正则表达式。在这里可以随意写
user=self.clean_data["username"]
is_esits = models.UserInfo.objects.filter(username=user).count()
if not is_esits:
raise validationError("用户名不存在")
return user #必须有返回值
如果 def clean_username(self): 只能取password字段的值
如果 def clean_username(self): 只能取username字段的值
注意:在自己写钩子函数的时候,只能拿自己的字段不能拿别人的
每一种字段就可以用 正则+自定义正则+自定义钩子函数
6、中间件
1、中间件是什么?
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
2、做过什么?
用户登录
日志记录
crsf:对所有的post请求做了一个验证
session
权限管理
3、
注意:
对于所有请求的批量做处理的时候用中间件
单独对某几个函数做处理的时候用装饰器
4、使用步骤:
步骤:
1、、先建一个文件夹,里面写一个py文件
2、、然后开始写类
1.中间件就是一个类,类里面写几个方法
class M1(MiddlewareMixin): 必须继承
def process_request(self,request): request:请求里面的所有的东西
print("m1.request_request")
这个方法里面别轻易返回值,要是有返回值就不再继续执行后面的了,执行自己的process_response和上边的response
一般是无返回值的:继续执行后续的中间件和视图函数
def process_response(self,request,response):
return response 2.在settings中的MIDDLEWARE加上路径
文件夹名称.py文件名称.类名
3.找到继承的那个类,吧那个类拿过来
一般不要用导入的方法,不然有时候更新了就没有这个类了,你就把它继承的那个类拿过来,
图示分析过程:
process_reques有返回值:
process_reques无返回值:
在中间件中设置:
示例:
class MiddlewareMixin(object):
def __init__(self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self).__init__() def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response # 至少要有两个类
class Md1(MiddlewareMixin): #必须继承
def process_request(self,request):
print("md1===process_request")
l = ["/login/"]
#request.path_info:当前的路径
if request.path_info in l: #因为login不做验证,就直接返回none就行了
return None
if not request.session.get(settings.GDP):
return redirect("/login/")
#
# 如果无返回值,就继续执行后续中间件和视图函数
# 如果有返回值,就执行自己的process_response和上面的response
def process_response(self,request,response):
print("md1====process_response1")
return response #必须有返回值 class Md2(MiddlewareMixin):
def process_request(self,request):
print("md2====process_request2")
def process_response(self,request,response):
print("md2====process_response2")
return response
测试:
def testMD(request):
print("view.test")
return HttpResponse("...")
返回结果:
Django【第12篇】:Django之中间件的更多相关文章
- Django框架第九篇--Django和Ajax、序列化组件(serializers)、自定义分页器、模型表choice参数
Django和Ajax 一.什么是Ajax AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”.即使用Javascript语 ...
- Django基础-04篇 Django开发前后端联动
1. 写views views.py代码块 1.在前端以/article/{{ article.id }}这种方式请求后台, 参数配置在urls.py中path('category/<int:i ...
- 【12】Django 中间件
前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装 ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
- Python之路【第十七篇】:Django【进阶篇】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Django【进阶篇 】
Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...
- Django【基础篇】
Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...
- Python之Django【进阶篇 】
Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...
- Python之Django【基础篇】
Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...
随机推荐
- centOS7 flask项目布署
先用1张图表示centOS布署flask的关键点,以及可能遇到的问题,及解决办法. 图片看不清,可以[下载]下来看,清晰度能够看清字 [目标] 局域网内,通过url可以访问flask编写的api 更新 ...
- 阶段3 1.Mybatis_10.JNDI扩展知识_2 补充-JNDI搭建maven的war工程
使用骨架 src下创建test目录 再新建java和resources两个Directory test下面创建java java的目录,让他作为源码的跟目录 test下的java文件夹 选择 完成之后 ...
- 小姐姐带你一起学:如何用Python实现7种机器学习算法(附代码)
小姐姐带你一起学:如何用Python实现7种机器学习算法(附代码) Python 被称为是最接近 AI 的语言.最近一位名叫Anna-Lena Popkes的小姐姐在GitHub上分享了自己如何使用P ...
- Linux 命令 - man 查看命令的文档
man 命令是 Linux 中最常用的命令,碰到任何让你疑惑的命令,都可以 man 一下来查看详情.不只是 shell 命令,C 语言库函数和系统调用等内容也可以通过 man 命令查看. man 命令 ...
- spring-mvc 3.* 多视图解析配置实例 ContentNegotiatingViewResolver
一.起因 从spring 3.1.0升级到spring 3.2.0时,配置文件servlet.xml中出错. 错误信息: java.lang.String cannot be cast to ...
- Vue 渲染函数
Vue 推荐在绝大多数情况下使用模板来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力.这时你可以用渲染函数,它比模板更接近编译器. 一 项目结构 二 App组 ...
- cocos2dx基础篇(8) 开关按钮CCControlSwitch
[3.x] (1)去掉 “CC” (2)对象类 CCObject 改为 Ref (3)标签类 LabelTTF 改为 Label (4)CCControlEvent 改为强枚举 Control::Ev ...
- ERROR 1045 (28000): Access denied for user 'xxx'@'localhost' (using password: YES)
# Bug描述 今天周末,在家里学点新技术,虽然公司分配的任务没有完成(滑稽滑稽) 我先创建了一个mysql数据库,用root用户创建一个新用户,毕竟项目中使用root是非常危险的,尤其是我这样的实 ...
- Java基础/时间日期格式
Java时间日期格式转换 一.Date转String和String转Date 参考博客:https://www.cnblogs.com/sharpest/p/7879377.html public s ...
- 关于Logcat
1 android logcat api Log.i(String tag, String msg) info,普通信息 Log.d(String tag, String msg) debug,调试信 ...