forms组件(注册用户讲解)(自定义校验字段,渲染模板功能,渲染错误信息功能,局部钩子渲染错误信息,全局钩子渲染错误信息),基于forms组件写的注册系统(前台前台加载文件)

forms组件

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
class Myforms(forms.Form): # 继承Form类 name = forms.CharField(max_length=8,min_length=3 ,label='用户名', error_messages={'max_length':"最长是8","min_length":'最短是3','required':'这个必须填'}, # 错误信息变成中文 widget=widgets.TextInput(attrs={"class":"form-control","id":"name"}) # 渲染模板输入框 ) pwd = forms.CharField(max_length=8,min_length=3,label='密码' ,required=True, error_messages={'max_length':"最长是8","min_length":'最短是3','required':'这个必须填'}, widget=widgets.PasswordInput(attrs={"class":"form-control","id":"pwd"}) ) re_pwd = forms.CharField(max_length=8, min_length=3, label='确认密码', required=True, error_messages={'max_length': "最长是8", "min_length": '最短是3', 'required': '这个必须填'}, widget=widgets.PasswordInput(attrs={"class":"form-control","id":"re_pwd"}) ) email = forms.EmailField(label='邮箱',error_messages={'required':'这个必须填','invalid':'不符合邮箱格式'}, widget=widgets.EmailInput(attrs={"class":"form-control","id":"email"})
  
# 局部钩子(写在自定义的form类里,校验单独字段,自定义2次校验)
  # 单个字段的二次校验
def clean_name(self): # 函数名为clean + 校验的字段名 import re data = self.cleaned_data.get("name") if not re.match('^[0-9]', data): return data raise ValidationError("不能以数字开头") # 抛django内置的异常

# 全局钩子(写在自定义的form类里,校验多个字段,自定义2次校验)
   # 所有字段的二次校验
   def clean(self): # 函数名只能为clean if self.cleaned_data: pwd = self.cleaned_data.get("pwd") re_pwd = self.cleaned_data.get("re_pwd") if pwd != re_pwd: raise ValidationError("两次密码不一致") # 抛django内置的异常 return self.cleaned_data

校验字段功能

# 渲染模板(数据)
forms_obj = Check_forms()         # 生成forms渲染表单对象
forms_obj.username.errors.0       # 单个字段的错误信息
forms_obj.username.label          # 字段名
forms_obj.username.html_name      # 字段名
forms_obj.username.auto_id        # 字段名

# forms校验(数据)
forms_user = Check_forms({"name":"lxx","pwd":"123")    # 开始校验字段
forms_user.is_valid()   # 是否校验通过
forms_user.cleared_data   # 校验通过的数据
forms_user.errors # 错误信息
forms_user.errors[0] # 取其中一条
forms_user.errors['__all__'][0] # 全局钩子错误信息

渲染模板的三种方式 [ 推荐第二种 ]

# 第一种:通过校验对象
<p>用户名:{{ myform.name }}</p>
<p>密码: {{ myform.pwd }}</p>
<p>密码<input type="text" name="re_pwd"></p>
<p>邮箱:{{ myform.email }}</p>
<input type="submit" value="提交">


# 第二种:for循环校验对象 (推荐)
{% for foo in myform %}
    <p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
<input type="submit" value="提交">


# 第三种:
 <p>{{ myform.as_p }}</p>
 <p>{{ myform.as_ul }}</p>
 <input type="submit" value="提交">

基于forms组件写的注册系统

要校验的字段

from django import forms

from django.forms import widgets
from django.core.exceptions import ValidationError
from blog import models


class RegForm(forms.Form):
    username = forms.CharField(max_length=18, min_length=2, label='用户名',
                               widget=widgets.TextInput(attrs={'class': 'form-control'})
                               )
    password = forms.CharField(max_length=18, min_length=2, label='密码',
                               widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
    re_password = forms.CharField(max_length=18, min_length=2, label='确认密码',
                                  widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
    email = forms.EmailField(label='邮箱',
                             widget=widgets.TextInput(attrs={'class': 'form-control'}))

    # 局部校验钩子函数
    def clean_username(self):
        name = self.cleaned_data.get('username')
        # 去数据库校验
        ret = models.UserInfo.objects.filter(username=name).first()
        if ret:
            raise ValidationError('用户名已存在')
        return name

    # 全局校验钩子函数
    def clean(self):
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('re_password')
        if pwd and re_pwd:
            if pwd == re_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
要校验的字段 以及局部钩子,全局钩子

views文件 后台校验逻辑

def register(request):
    if request.method == 'GET':
        myform = myforms.MyForm()  # Forms组件渲染登陆模板(可以不用)
        return render(request,'register.html',{'myform':myform})
    elif request.method == 'POST':
        response = { 'user':None,'msg':None }   # 设置好返回前台的形式 mas 对应错误信息  user 对应是否登录成功
        myform = myforms.MyForm(request.POST)  # 传入需要校验的数据,必须是字典
        if myform.is_valid():  # 校验通过
            dic = myform.cleaned_data    # 校验是否通过 

            dic.pop('re_pwd')  # 删除 确认密码字段
            user = models.UserInfo.objects.create_user(username=dic.get('username'),
                                                       password=dic.get('pwd'),
                                                       email= dic.get('email'),)                                                      

            response['user'] = user.username
            response['img'] = '注册成功'
        else:
            response['msg'] = myform.errors
        return JsonResponse(response)

注册系统前台代码  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>注册页面</title>

    <style>
        #my_file {
            display: none;
        }
        #all_error {
            color: red;
            position: relative;
            margin: 0;
        }
        .span_errpr {
            color: red;
            float: right;
        }
    </style>


</head>
<body>

<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h1>博客注册系统</h1>
            <form action="" id="form">
                {% csrf_token %}
                {% for foo in myform %}
                    <div class="form-group">

                        <label for="{{ foo.auto_id }}"> {{ foo.label }}

                        </label>
                         {{ foo }}

                    </div>

                {% endfor %}
                <label for="my_file">上传
                    <img src="/static/img/default.png" alt="" width="60" height="60" id="img_file">
                </label>
                <input type="file" id='my_file'>
            </form>


            <div>
                {# 全局错误信息 #}
                <span id="all_error" class="pull-left" ></span>
                <div class="pull-right">
                    <button id="btn">注册</button>
                </div>
            </div>

        </div>
    </div>
</div>

</body>

<script>
    $('#my_file').change(function () {
        {# 把文件取出来 #}
        var file_obj =  $('#my_file')[0].files[0];
        {# 生成文件阅读器 #}
        var filereader = new FileReader();
        {# 把文件读到阅读器中 #}
        filereader.readAsDataURL(file_obj);
        {# 文件全部加载完毕以后的结果,赋值给其他标签的属性 js修改属性 #}
        filereader.onload = function () {
            $('#img_file').attr('src',filereader.result)
        }
    });

    $("#btn").click(function () {
        var formdata = new FormData();
        {#formdata.append( 'file', $('#my_file')[0].files[0]);#}
        {#formdata.append( 'pwd', $('#id_pwd').val());#}
        {#formdata.append( 'name', $('#id_name').val());#}
        {#formdata.append( 'email', $('#id_email').val());#}
        {#formdata.append( 're_pwd', $('#id_re_pwd').val());#}
        {# 相当于把 form 表单里所有的值放入一个数组里 #}
        var arr = $('#form').serializeArray();
        {# jq循环  #}
        $.each(arr,function (k ,v) {
            {#console.log(k);#}
            console.log(v);
            formdata.append(v.name,v.value)
        });


        $.ajax({
            url: '/register/',
            type: 'post',
            processData:false,
            contentType:false,

            data: formdata,
            success: function (data) {
                if (data.user) {
                    location.href = '/index/'
                } else {
                    $('.span_errpr').remove();
                    {#console.log(data);#}
                    {#console.log(data.msg);#}
                    for ( k in data.msg ) {
                        {# 判断是否是全局信息 #}
                        if (k === '__all__'){
                         {#  js修改标签内容  #}
                         $('#all_error').text(data.msg[k])
                        } else {
                            {# js生成标签 #}
                            $('#'+'id_'+k).before('<span class="span_errpr">' + data.msg[k] + '</span>' )
                        }
                    }
                }
            }
        })
    })

</script>
前台代码,前台加载文件移动至另一标签
posted @ 2018-11-22 09:46  星牧  阅读(239)  评论(0编辑  收藏  举报