Custom validation rules and middleware brief

2, the data source can not be updated from time to time, there are two ways

One way: reconstruction constructor (recommended)

Method One: Reconstruction constructor (recommended) 
    class ClassesForm (Form): 
    name = fields.CharField ( 
        required = True # required fields 
        error_messages = { "required": "Name can not be empty!"} # Display Chinese error 
        widget = widgets.TextInput (attrs = { " placeholder": " name", "class": "form -control"}), # automatically generated input box 
    ) 
    # if the direct classteacher_id ,, _ id defined as a form, so that when you add data will not be updated from time to time, so defined below override to 
    # classteacher_id = fields.ChoiceField (choices = models.UserInfo.objects.filter (ut_id = settings.ROLE_CLASSTEACHER) .values_list ( 'id', " username ")) 

        classteacher_id = fields.ChoiceField (choices = []) 
        DEF the __init __ (Self, args *, ** kwargs): # override init method, constantly updated 
            super () .__ init __ (* args,** kwargs) # inherit the parent class
self.fields [ "classteacher_id"] choices = models.UserInfo.objects.filter (ut_id = settings.ROLE_CLASSTEACHER) .values_list ( 'id', "username"). Note: If so: fields.ChoiceField (choices = []) Note choices which pass [(1, 'lecturer'), (2, "class"), (3, "administrator")] database so when taken starting values_list

 

Second way:

Method two: ModelChoiceField (not recommended), QuerySet 
    from django.forms.models # Import for ModelChoiceField first introduced 
    class ClassForm (Form1): 
        Caption = fields.CharField (error_messages, = { 'required': 'class name can not be empty'}) 
        # headmaster = fields.ChoiceField (choices = [( 1, ' Nana',)]) 
        headmaster_id for ModelChoiceField = (QuerySet = models.UserInfo.objects.filter (ut_id = 2))

 

3, Form basic use

    Class 
    field 
    is_valid () 
    cleaned_data 
    errors 
    field parameters: 
        max_length 
        min_length 
        validators = [RegexValidators ( "xxx")] 
        
    hook function 
        clean_ field names 
        Note: 
            There must be a return value 
            can only take their current field values 
            raise ValidationError ( "xxx") 
    drop-down box constantly updated data source 
        1, overwriting init method 
            to perform the parent class constructor 
            self.fields [ "XX"]. XXXXX choices = 
        2, for ModelChoiceField

 

4, the user logs

- form of a regular expression can define fields 
            password = fields.CharField ( 
                required = True, 
                min_length =. 3, 
                MAX_LENGTH = 18 is, 
                error_messages, = { 
                    'required': 'password can not be empty', 
                    'min_length': 'password length not less than . 3 ', 
                    ' MAX_LENGTH ':' password length is not greater than 18 is', 
                    'invalid': 'password malformed', 
                }, 
                validators = [RegexValidator ( '\ D +', 'only a digital')] 
            ) 
            Note: error_messages of higher priority than validators

 You need to import the module

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

 

the LoginForm class (Form1): 
    username = fields.CharField ( 
        required = True, # required field 
        min_length =. 3, 
        MAX_LENGTH 16 =, 
        error_messages, = { 
            "required": "User name can not empty", 
            "min_length": "the length can not be less than. 3 ", 
            " MAX_LENGTH ":" not be greater than 16 " 
        }, 
        the widget = widgets.TextInput ({" placeholder ":" username "," class ":" form-Control "}) 
    ) 
    password = fields.CharField ( 
        required True =, 
        min_length =. 3, 
        MAX_LENGTH 16 =, 
        error_messages, = { 
            "required": "empty entry is not"
            "min_length": "the length of the password can not be less than 3"
            "max_length": "Password not be greater than 16", 
            # "invalid": "Malformed Password"
            # Error_messages high priority, if the writing "invalid": "Password format error" This will take priority over this error 
        }, 
        the widget = widgets.PasswordInput ({ "placeholder": "password", "class": "form- Control "}), 
        validators = [RegexValidator (" \ D + "," password number only ")] may be the regular # match an error 
    ) 

    DEF clean_username (Self): 
        User self.cleaned_data = [" username "] 
        is_exits = models.UserInfo.objects.filter (username = the user) .count () 
        IF not is_exits: 
            The raise ValidationError ( "user name and password error") 
        return the user must 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} # Set the session 
                return the redirect ( "/ teacherindex /") 
            the else: 
                # verification fails, increase give a wrong 
                form .add_error ( "password", "user name or password is incorrect") 
                return the render (Request, "the login.html", { "form":} form) 
        the else: 
            return the render (Request, "the login.html", { " form ": form})

 

- take the initiative to add an error message to the form in
  # form.add_error ( 'password', 'user name or password is incorrect')
  form.add_error ( 'password', ValidationError ( 'user name or password is incorrect'))
  both are, a second recommended

5, Form extension (hook function)

If you do an extension to the username
# do first regular expression to determine
# then custom validation method: that is clean_xx, called hook function

clean_username DEF (Self): 
        # write your own authentication prompt can 
        not just write a regular expression validators. Here are free to write 
        the User = self.clean_data [ "username"] 
        is_esits = models.UserInfo.objects.filter (username = the User) .count () 
        IF not is_esits: 
            The raise validationError ( "Username does not exist") 
        return the User # there must be a return value 
    if def clean_username (self): can only take the value of password field 
    value can only take the username field: If def clean_username (self) 
    Note: at the time to write their own hook function, can only take their own field can not take someone else's 
    each field can use regular regular custom + + custom hook function

6, middleware

1. What is middleware?

Middleware name implies, is interposed between a processing request and response process, relatively lightweight, and changes in the input and output django globally. Because change is global, it is necessary to be cautious and practical, with good will affect the performance.

2, what did?
  User login
  logging
  crsf: for all post requests to do a verification
  session
  Rights Management

3、

Note:
  do batch processing of all requests for time middleware used
  alone do certain processing functions when used decorator

4, using the steps of:

Step: 
1 ,, to build a folder, which is written a py file 2, and then start writing class 1. middleware is a Class A, there are several ways to write class M1 (MiddlewareMixin): must inherit def process_request (self, request): request: request everything inside of print ( "m1.request_request") this method which do not easily return value, return value if there is no longer continue to back up, and perform their own process_response top of the response is generally no return value: continue to perform subsequent middleware and view functions DEF process_response (Self, Request, the Response): return the Response 2. mIDDLEWARE in settings plus the path to the folder name .py file name of the class name. 3. locate inheritance of that class, it took over the class in general do not use the method of introduction, or sometimes there is no update of this class, you put it inherits that class take over,

Graphical analysis process:

process_reques return value:

 

process_reques None Return Value:

 

In the middleware settings:

 

 

Example:

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("...") 

返回结果:

 

 
 

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("...") 

返回结果:

 

Guess you like

Origin www.cnblogs.com/shangping/p/11755779.html