基于Ajax提交formdata数据、错误信息展示和局部钩子、全局钩子的校验。

formdata重点:

  1. 实例化FormData这个类
  2. 循环serializeArray可以节省代码量
  3. 图片要用$('#id')[0].files[0]来获得
  4. 加上contentType:false和processData:false

错误信息展示重点:

  1. input框的id是id_field,可以通过循环错误信息获取错误信息的字段field,然后通过id_filed展示错误信息
  2. 展示错误信息前先把错误信息清空了

 全局钩子重点:

可在前端通过__all__获取全局错误信息并展示出来

html

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form id="fm">
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        {{ field }}
                        <span class="error-info pull-right"></span>
                    </div>
                {% endfor %}

                <div class="form-group">
                    <label for="id_avatar">头像
                        <img width="60" height="60" id="avatar_img" src="/static/blog/img/default_avatar.jpg">
                    </label>

                    <input type="file" name="avatar" id="id_avatar" class="hidden">
                </div>

                <input type="button" id="reg_btn" class="btn btn-info" value="提交">
            </form>
        </div>
    </div>
</div>

js

    // 头像预览功能
    $('#id_avatar').change(function () {   // 图片发生了变化,所以要用change事件
        // 获取用户选中的文件对象
        let file_obj = $(this)[0].files[0];

        // 获取文件对象的路径
        let reader = new FileReader();  // 等同于在python里拿到了实例对象
        reader.readAsDataURL(file_obj);

        reader.onload = function () {
            // 修改img的src属性,src = 文件对象的路径
            $("#avatar_img").attr('src', reader.result);  // 这个是异步,速度比reader读取路径要快,
                                                          // 所以要等reader加载完后在执行。
        };
    });

    // 基于Ajax提交数据
    $('#reg_btn').click(function () {
        let formdata = new FormData();  // 相当于python里实例化一个对象
        let request_data = $('#fm').serializeArray();
        $.each(request_data, function (index, data) {
            formdata.append(data.name, data.value)
        });
        formdata.append('avatar', $('#id_avatar')[0].files[0]);

        $.ajax({
            url: '',
            type: 'post',
            contentType: false,
            processData: false,
            data: formdata,
            success: function (data) {
                if (data.user) {
                    // 注册成功
                    location.href = '{% url "blog:login" %}'
                } else {
                    // 注册失败

                    // 清空错误信息,每次展示错误信息前,先把之前的清空了。
                    $('span.error-info').html("");
                    $('.form-group').removeClass('has-error');
                    // 展示此次提交的错误信息
                    $.each(data.msg, function (field, error_list) {
                        if (field === '__all__') {  // 全局错误信息,在全局钩子里自己定义的
                            $('#id_re_pwd').next().html(error_list[0]);
                        }
                        $('#id_' + field).next().html(error_list[0]);
                        $('#id_' + field).parent().addClass('has-error');  // has-error是bootstrap提供的
                    });
                }
            }
        })
    })

regForm.py

"""
用户注册验证
"""
from django import forms
from django.forms import widgets, ValidationError

from blog.models import UserInfo


class RegForm(forms.Form):
    user = forms.CharField(
        max_length=32,
        min_length=6,
        error_messages={
            'required': '用户名不能为空',
            'max_length': '用户名长度不能超过32个',
            'min_length': '用户名长度不能少于6个',
        },
        label='用户名',
        widget=widgets.TextInput(
            attrs={'class': 'form-control'}
        )
    )
    pwd = forms.CharField(
        max_length=32,
        min_length=6,
        error_messages={
            'required': '密码不能为空',
            'max_length': '密码长度不能超过32个',
            'min_length': '密码长度不能少于6个',
        },
        label='密码',
        widget=widgets.PasswordInput(
            attrs={'class': 'form-control'}
        )
    )
    re_pwd = forms.CharField(
        max_length=32,
        min_length=6,
        error_messages={
            'required': '确认密码不能为空',
            'max_length': '密码长度不能超过32个',
            'min_length': '密码长度不能少于6个',
        },
        label='确认密码',
        widget=widgets.PasswordInput(
            attrs={'class': 'form-control'}
        )
    )
    email = forms.EmailField(
        max_length=32,
        error_messages={
            'required': '用户名不能为空',
            'invalid': '请输入正确的邮箱格式',
        },
        label='邮箱',
        widget=widgets.EmailInput(
            attrs={'class': 'form-control'}
        )
    )

    def clean_user(self):
        username = self.cleaned_data.get('user')

        user = UserInfo.objects.filter(username=username).first()

        if not user:
            return username
        else:
            raise ValidationError('该用户已注册')

    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')

        if pwd and re_pwd:
            if pwd == re_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')

views.py

from django.contrib import auth
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse

from blog.utils.slide_auth_code import pcgetcaptcha
from blog.forms.regForm import RegForm


def register(request):
    if request.is_ajax():
        print(request.POST)
        form = RegForm(request.POST)
        response = {'user': None, 'msg': None}
        if form.is_valid():
            response['user'] = form.cleaned_data.get('user')
        else:
            print(form.cleaned_data)
            print(form.errors)
            response['msg'] = form.errors

        return JsonResponse(response)

    form = RegForm()

    context = {
        'form': form
    }
    return render(request, 'register.html', context=context)

原文地址:https://www.cnblogs.com/lshedward/p/10384218.html