zoukankan      html  css  js  c++  java
  • form表单使用(博客系统的登陆验证,注册)

    先从小的实例来看form的用法

    登陆验证实例,来看form的常规用法

    1. forms.py

     1 # 用于登陆验证验证
     2 from django.core.validators import RegexValidator 支持正则
     3 # 登陆验证手动触发错误对象
     4 from django.core.exceptions import ValidationError    
     5 
     6 # 登陆规则
     7 class loginform(Form):
     8     name = fields.CharField(
     9         required=True,
    10         min_length=3,
    11         max_length=18,
    12         error_messages={
    13             'required':'用户不能为空',
    14             'min_length':'用户长度不能小于3',
    15             'max_length':'用户长度不能大于18',
    16         }
    17     )
    18     pwd = fields.CharField(
    19         required=True,
    20         min_length=3,
    21         max_length=18,
    22         error_messages={
    23             'required': '用户不能为空',
    24             'min_length': '用户长度不能小于3',
    25             'max_length': '用户长度不能大于18',
    26             'invalid':'密码格式错误',    #自定义错误,优先级高
    27         },validators=[RegexValidator('d+','只能是数字',code)] #只能是数字也是报错信息,不过优先级低,也就是说如果用户输入非数字,那么提示invalid错误,如果invalid没有,那么报‘只能是数字’错误,code就是给invalid重新命名而已,没有什么用处,可以不写)
    28 29 
    30     # from扩展,可以直接在里面进行数据库操作,场景注册,局部钩子,博客系统注册,详细介绍了用法,见下文#######
    31     def clean_name(self):
    32         # 验证可以直接写在这里,进行验证,返回可以是任意类型,重新赋值给clean_date里面的user
    33         user = self.cleaned_data['name']
    34         is_exsit = models.UserInfo.objects.filter(name=user).count()
    35         if not is_exsit:
    36             raise ValidationError('用户名不存在')
    37         return user
    38 
    39     def clean_pwd(self):
    40         # 这里可以匹配数据库其他校验,返回可以是任意类型,重新赋值给clean_date里面的pwd
    41         return True

    2. views.py

     1 def login(request):
     2     if request.method=='GET':
     3         form = loginform()
     4         return render(request,'login.html',{'form':form})
     5     elif request.method=='POST':
     6         form = loginform(request.POST)  # 前端提交数据给form
     7         # 规则验证
     8         if form.is_valid():
     9             # 数据库验证
    10             print('name',form.cleaned_data['name'])
    11             user_obj = models.UserInfo.objects.filter(**form.cleaned_data).first()
    12             if not user_obj:
    13                 form.add_error('pwd',ValidationError('用户名或者密码错误')) #当你符合格式,但是数据库没有的时候就会报错,跟局部钩子触发错误是一样的
    14                 return render(request,'login.html',{'form':form})
    15             else:
    16                 print(form.cleaned_data['name'])
    17                 work_boj = models.Workers.objects.filter(utow__name=form.cleaned_data['name'], utow__pwd=form.cleaned_data['pwd']).first()
    18                 work = work_boj.workname
    19                 request.session[settings.USEROBJ] = {'username': user_obj.name, 'work': work}
    20                 return redirect('/index/')
    21         else:
    22             return render(request,'login.html',{'form':form})
    23     else:
    24         return HttpResponse('访问请求非get,post')

    3. login.html

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     6     <meta name="viewport" content="width=device-width, initial-scale=1">
     7     <title>Title</title>
     8 </head>
     9 <body>
    10     <form method="POST">
    11         {% csrf_token %}
    12             <p>{{ form.username }} {{ form.errors.username.0 }} </p>
    13             <p>{{ form.password }} {{ form.errors.password.0 }} </p>
    14         <input type="submit" value="提交" />
    15     </form>
    16 </body>
    17 </html>

    通过问卷的创建修改来看form的高级用法forms.fields.ChoiceField

    主要了解下 forms.fields.ChoiceField(choices=[(1,'a'),(2,'b')]),和初始化数据

    models.py

     1 class UserInfo(models.Model):
     2     """
     3     员工表
     4     """
     5     name = models.CharField(max_length=32)
     6 
     7     def __str__(self):
     8         return self.name
     9 
    10 class ClassInfo(models.Model):
    11     """
    12     班级表
    13     """
    14     name = models.CharField(max_length=32)
    15     def __str__(self):
    16         return self.name
    17 
    18 class Questionnaire(models.Model):  # 问卷: 班级 :创建者
    19     """
    20     问卷表
    21 
    22     """
    23     title = models.CharField(max_length=64)
    24     cls = models.ForeignKey(to=ClassInfo)
    25     creator = models.ForeignKey(to=UserInfo)
    26 
    27     def __str__(self):
    28         return self.title

    1. forms.py

     1 from django import forms
     2 from django.forms import widgets  # 插件,可以插入些样式
     3 from django.core.exceptions import ValidationError # 手动触发错误
     4 from django.core.validators import RegexValidator # 支持正则
     5 
     6 from app01 import models
     7 
     8 from django.forms.models import ModelChoiceField # 下拉框实时刷新第二种方法
     9 
    10 class questionnaire_form(forms.Form): # 问卷规则
    11     title = forms.fields.CharField(required=True,
    12                                    error_messages={'required':'名称不能为空','invalid':'格式错误'},
    13                                    widget=widgets.TextInput(attrs={'placeholder':'问卷名称',
    14                                                                     'class':'form-control questionnaire_title'},))
    15 
    16     # 其他框使用
    17     # password = forms.fields.CharField(required=True, error_messages={'required': '密码不能为空'},
    18                                 #widget=widgets.TextInput(attrs={'placeholder': '密码', 'class': 'form-control'}))  # 不能为空
    19     # email = forms.fields.EmailField(required=True, error_messages={'required': '邮箱不能为空', 'invalid': '邮箱格式错误'},
    20     #                           widget=widgets.PasswordInput(attrs={'placeholder': '邮箱', 'class': 'form-control'}))  # 不能为空,且邮箱格式
    21     # text = forms.fields.CharField(required=True,error_messages={'required':'密码不能为空'},
    22     #                               widget=widgets.Textarea(attrs={'class':'textatea'}))
    23     # cls_list = fields.MultipleChoiceField(choices=[])  # 多选框,传过来的值,是列表
    24     # def __init__(self, *args, **kwargs):
    25     #     super().__init__(*args, **kwargs)
    26     #     self.fields['cls_list'].choices = models.ClassList.objects.values_list('id', 'caption')
    27 
    28     # 第一种实时刷新,通过重构init方法,不需要models的str方法
    29     # cls_id = forms.fields.ChoiceField(choices=[])
    30     # creator_id = forms.fields.ChoiceField(choices=[])
    31     # def __init__(self,*args,**kwargs):
    32     #     super().__init__(*args,**kwargs)
    33         # 不需要重启,修改后提交后,再点进来可以保证修改完成
    34         # self.fields['cls_id'].choices= models.ClassInfo.objects.all().values_list('id','name')
    35         # self.fields['creator_id'].choices = models.UserInfo.objects.all().values_list('id','name')
    36     
    37     # 第二种实时刷新,需要models里面的str方法,不然下拉框都是对象,访问数据库因为返回的是对象
    38     cls_id = ModelChoiceField(queryset=models.ClassInfo.objects.all())
    39     creator_id = ModelChoiceField(queryset=models.UserInfo.objects.all())
    40 
    41 
    42     # 局部钩子
    43     def clean_title(self): # 针对添加的时候,如果有questionnaire_title,就存在,没有可以正常进行
    44         questionnaire_title = models.Questionnaire.objects.filter(title=self.cleaned_data.get('title')) # 前端传来的数据保存在clean_data里
    45         if not questionnaire_title:
    46             return self.cleaned_data.get('title')
    47         else:
    48             raise ValidationError('用户名已经存在')   # 触发错误

    2. views.py

     1 from django.shortcuts import render,HttpResponse,redirect
     2 
     3 # Create your views here.
     4 
     5 from .forms import *
     6 from app01 import models
     7 
     8 def questionnaire_list(request):
     9     '''
    10     问卷首页,格式:8000/questionnaire首页,
    11     :param request: 
    12     :param questionnaire_id: 
    13     :return: 
    14     '''
    15     questionnaire_list = models.Questionnaire.objects.all() # 所有问卷
    16     return render(request, "questionnaire_list.html", {'questionnaire_list':questionnaire_list})
    17 
    18 
    19 def add_questionnaire_obj(request,**kwargs):
    20     '''
    21     添加问卷
    22     :param request: 
    23     :param kwargs: 
    24     :return: 
    25     '''
    26     if request.method == 'GET':
    27         form = questionnaire_form()
    28         return render(request, 'add_questionnaire_obj.html',{'form':form})
    29     elif request.method == 'POST':
    30         form = questionnaire_form(request.POST)
    31         print(request.POST)
    32         # 校验
    33         if form.is_valid():
    34             print(form.cleaned_data)
    35             # 下拉框第二种实时更新方法,因为前端是queryset对象,所以需要把cleand_data数据重新更改一下
    36             # form.cleaned_data['creator_id'] = form.cleaned_data['creator_id'].id
    37             # form.cleaned_data['cls_id'] = form.cleaned_data['cls_id'].id
    38             models.Questionnaire.objects.create(**form.cleaned_data)
    39             return redirect('/questionnaire/')
    40         else:
    41             return render(request, 'add_questionnaire_obj.html', {'form': form})
    42 
    43 
    44 
    45 def edit_questionnaire_obj(request,**kwargs):
    46     '''
    47     问卷对象,格式:8000/questionnaire/questionnaire_id,选中问卷编辑
    48     :param request: 
    49     :param kwargs: 
    50     :return: 
    51     '''
    52     questionnaire_id = kwargs.get('questionnaire_id')  # 得到需要编辑的问卷的ID
    53     if request.method == 'GET':
    54         questionnaire_obj = models.Questionnaire.objects.filter(id=questionnaire_id).first()  # 通过ID找到问卷对象
    55         # form的实例化,initial初始化,适用于初始默认的值,
    56         # form = questionnaire_form(),没有数据,只是可以在前端渲染标签,需要在FORM里面执行,例如TEXTIINPUT
    57         # form = questionnaire_form(data=request.POST),有数据,并且到FORM里面进行验证
    58         # 初始化的值,initial={'对象字段名称':,'对象字段,如果是关联字段加上ID,也就是数据库字段是什么,就是什么':}
    59         # 初始化的字段名称最好跟MODELS的一样,FORM验证最好也是一样,前端也是一样,这样确保可以正常  ###########  注意
    60         form = questionnaire_form(initial={"title":questionnaire_obj.title, "cls_id":questionnaire_obj.cls_id,"creator_id":questionnaire_obj.creator_id}) # 默认值
    61         return render(request, "edit_questionnaire_obj.html", {'form': form})
    62     if request.method == 'POST':
    63         form =questionnaire_form(data=request.POST)
    64         if form.is_valid():
    65             print(form.cleaned_data)
    66             print(form.errors)
    67             models.Questionnaire.objects.filter(id=questionnaire_id).update(**form.cleaned_data)
    68             return redirect('/questionnaire/')
    69         else:
    70             return render(request, 'edit_questionnaire_obj.html', {'form': form})

    3. questionnaire_obj.html 

    1     <form action="" method="post">
    2         {% csrf_token %}
    3         <p>问卷调查名称:{{ form.title }}</p>
    4         <p>选择班级:{{ form.cls_id }}</p>
    5         <p>选择创建者:{{ form.creator_id }}</p>
    6         <input type="submit" value="提交">
    7     </form>

    博客系统注册,读完肯定清晰明了,注意这里面有全局钩子的用法,

    针对from.error下的__all__

    models结构如下

     1 class UserInfo(AbstractUser):
     2     """
     3     用户信息
     4     """
     5     nid = models.AutoField(primary_key=True)
     6     nickname = models.CharField(verbose_name='昵称', max_length=32)
     7     telephone = models.CharField(max_length=11, null=True, unique=True)
     8     avatar = models.FileField(upload_to='avatar/',default="/avatar/default.png")
     9     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    10     blog = models.OneToOneField(to='Blog', to_field='nid',null=True)
    11 
    12     def __str__(self):
    13         return self.username

    forms

     1 from django import forms
     2 from django.forms import widgets
     3 
     4 from . models import UserInfo
     5 from django.core.exceptions import NON_FIELD_ERRORS,ValidationError  #  手动触发错误
     6 
     7 
     8 
     9 class RegForm(forms.Form): # 子类
    10     # widget 默认情况下,CharField 具有一个TextInput 在HTML 中生成一个<input type="text">
    11     # attrs 可以对input标签添加属性
    12     def __init__(self,request,*args,**kwargs): # 派生方法
    13         super().__init__(*args,**kwargs)
    14         self.request = request # 派生属性
    15     user = forms.CharField(min_length=5,max_length=12,required=True,  # 规则
    16                            error_messages={'min_length':'最小长度5','max_length':'最大长度12','required':'不能为空'}, # 错误信息
    17                            widget = widgets.TextInput(attrs={'class':'form-control','placeholder':'username'})) # 生成标签,标签属性
    18 
    19     pwd = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.PasswordInput(attrs={'class':'form-control','placeholder':'password'}))
    20 
    21     repeat_pwd = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.PasswordInput(attrs={'class':'form-control','placeholder':'repeat_password'}))
    22 
    23     email = forms.EmailField(required=True,error_messages={'invalid':'格式错误','required':'不能为空'},
    24                              # 生成一个EmailInput <input type="input">
    25                              widget = widgets.EmailInput(attrs={'class':'form-control','placeholder':'email','required':'不能为空'}))
    26 
    27     valid_code = forms.CharField(required=True,error_messages={'required':'不能为空'},widget = widgets.TextInput(attrs={'class':'form-control','placeholder':'valid_code'}))
    28 
    29     # 局部钩子,针对user的验证
    30     def clean_user(self):
    31         user = UserInfo.objects.filter(username=self.cleaned_data.get('user'))
    32         if not user:
    33             return self.cleaned_data.get('user')
    34         else:
    35             raise ValidationError('用户名已经存在')
    36 
    37     # 局部钩子,针对pwd的验证
    38     def clean_pwd(self):
    39         pwd = self.cleaned_data.get('pwd')
    40         if pwd.isdigit() or pwd.isalpha():
    41             raise ValidationError('不能是纯数字或者纯字母')
    42         else:
    43             return pwd
    44 
    45     # 局部钩子,针对验证码的验证
    46     def clean_valid_code(self):
    47         val = self.cleaned_data.get('valid_code')
    48         if val.upper() == self.request.session.get('valid_code_str').upper():
    49             return val
    50         else:
    51             raise ValidationError('验证码错误')
    52 
    53     # 全局钩子,针对全局上的验证,注意,先走局部后走全局
    54     def clean(self):
    55         if self.cleaned_data.get('pwd'):
    56             if self.cleaned_data.get('pwd') == self.cleaned_data.get('repeat_pwd'):
    57                 return self.cleaned_data
    58             else:
    59                 raise ValidationError('俩次密码不一致')
    60 
    61     # 正确信息保存在,clean.data
    62     # 错误信息保存在,clean.error

    1. urls

    1 urlpatterns = [
    2     url(r'^admin/', admin.site.urls),
    3     url(r'^login/', views.login_in),
    4     url(r'^register/', views.register),
    5 ]

    2. views

     1 from .forms import *
     2 def register(request):
     3     if request.is_ajax():
     4         # 通过from表单验证
     5         print(request.POST)
     6         regForm = RegForm(request,request.POST)
     7         regResponse = {'user':None,'errors':None}
     8         if regForm.is_valid():
     9             # 通过验证,可以注册
    10             data = regForm.cleaned_data  # 合法的表单数据,是以字典形式保存
    11             user = data.get('user')
    12             pwd = data.get('pwd')
    13             email = data.get('email')
    14             avatar_img = request.FILES.get('valid_img') #获取的文件对象
    15             print(avatar_img)
    16             print(type(avatar_img))
    17             # user_obj = UserInfo.objects.filter(nid=2).update(avatar=avatar_img)
    18             user_obj = UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_img)
    19             regResponse['user'] = user_obj.username
    20         else:
    21             regResponse['errors'] = regForm.errors   # regForm.errors 保存所有错误信息,包括__all__全局钩子错误
    22         return JsonResponse(regResponse)
    23 
    24     regForm = RegForm(request) # 前端渲染,虽然没有数据,但是会渲染出标签来
    25     return render(request,'register.html',{'regForm':regForm})

    3. reg.html

     1 <div class="container">
     2     <div class="row">
     3         <div class="col-md-6 col-md-offset-3">
     4             <form>
     5                 {% csrf_token %}
     6                 <div class="form-group">
     7                     <label for="user">用户名:</label>
     8 {#                    <input type="text" class="form-control" id="user" placeholder="User">#}
     9                     {{ regForm.user }} <span></span>
    10                 </div>
    11 
    12                 <div class="form-group">
    13                     <label for="pwd">密码:</label>
    14 {#                    <input type="password" class="form-control" id="pwd" placeholder="Password">#}
    15                     {{ regForm.pwd }} <span></span>
    16                 </div>
    17 
    18                 <div class="form-group">
    19                     <label for="repeat_pwd">确认密码:</label>
    20 {#                    <input type="password" class="form-control" id="repeat_pwd" placeholder="Repeat Password">#}
    21                     {{ regForm.repeat_pwd }} <span></span>
    22                 </div>
    23 
    24                 <div class="form-group">
    25                     <label for="email">邮箱:</label>
    26 {#                    <input type="email" class="form-control" id="email" placeholder="Email">#}
    27                     {{ regForm.email }} <span></span>
    28                 </div>
    29                 <div class="row">
    30                     <div class="col-md-6">
    31                         <input type="button" value="confirm register" class="btn btn-primary regBtn">
    32                     </div>
    33                 </div>
    34 
    35             </form>
    36 
    37         </div>
    38     </div>
    39 </div>
    40 
    41 <script>
    42  {#    AJAX提交注册表单,注册用户 #}
    43     $(".regBtn").click(function () {
    44 
    45         var $formData = new FormData();
    46 
    47         $formData.append('user',$('#id_user').val());
    48         $formData.append('pwd',$('#id_pwd').val());
    49         $formData.append('repeat_pwd',$('#id_repeat_pwd').val());
    50         $formData.append('email',$('#id_email').val());
    51         $formData.append('valid_code',$('#id_valid_code').val());
    52         var file = $('#avatar_file')[0].files[0];
    53         $formData.append('valid_img',file);
    54         $formData.append('csrfmiddlewaretoken',$("[name='csrfmiddlewaretoken']").val());
    55 
    56         $.ajax({
    57             url: "/register/",
    58             type: "POST",
    59             data: $formData,
    60             processData:false,   // 不做转码或预处理
    61             contentType:false,   // 文件类型不做处理
    62             success: function (data) {
    63                 if (data.user) {
    64                     location.href = '/login/'
    65                 }
    66                 else {
    67                     $('span').html('');
    68                     $(".form-group").removeClass("has-error");
    69                     console.log(data.errors);
    70 
    71                     $.each(data.errors,function (i,j) {
    72                         $("#id_" + i).next().addClass('pull-right').css('color', 'red').html(j[0]).parent().addClass('has-error');
    73                         if(i == "__all__") {
    74                             $("#id_repeat_pwd").next().addClass("pull-right").css("color", "red").html(j[0]).parent().addClass("has-error");
    75                             $("#id_pwd").parent().addClass("has-error");
    76                         }
    77                     })
    78                 }
    79             }
    80         })
    81     })
    82 </script>
  • 相关阅读:
    计蒜客 奇怪的国家
    计蒜客 泥塑课
    计蒜客 判断质数
    hiho #1143 : 骨牌覆盖问题·一 (运用快速幂矩阵)
    二叉树建立,先序、中序、后序遍历(c实现)
    hiho #1272 买零食 [Offer收割]编程练习赛2
    hiho #1283 hiho密码 [Offer收割]编程练习赛3
    hiho #1288 微软2016.4校招笔试题 Font Size
    hiho一下 第九十八周 搜索一·24点
    hiho一下 第九十七周 数论六·模线性方程组
  • 原文地址:https://www.cnblogs.com/jokerbj/p/8157741.html
Copyright © 2011-2022 走看看