目录
一、myforms.py - forms组件设计
注意知识点:
- 局部钩子命名方式必须为:clean_类内属性名
- 全局钩子命名方式必须为:clean ---- 即重写clean方法
from django import forms from django.forms import widgets from bbs import models from django.core.exceptions import ValidationError class MyForm(forms.Form): username = forms.CharField( max_length=18, min_length=2, label='用户名', widget=widgets.TextInput(attrs={'class': 'form-control', 'placeholder': "请输入用户名"}), error_messages={'max_length': '长度不大于18', 'min_length': '长度不小于2', 'required': '必填选项', } ) password = forms.CharField( max_length=18, min_length=2, label='密码', widget=widgets.PasswordInput(attrs={'class': 'form-control', 'placeholder': "请输入密码"}), error_messages={'max_length': '长度不大于18', 'min_length': '长度不小于2', 'required': '必填选项', } ) re_password = forms.CharField( max_length=18, min_length=2, label='确认密码', widget=widgets.PasswordInput(attrs={'class': 'form-control', 'placeholder': "请确认密码"}), error_messages={'max_length': '长度不大于18', 'min_length': '长度不小于2', 'required': '必填选项', } ) email = forms.CharField( label='邮箱', widget=widgets.EmailInput(attrs={'class': 'form-control', 'placeholder': "请输入邮箱"}), error_messages={ 'invalid':'格式不合法', 'required': '必填选项', } ) # 用户名存在校验 def clean_username(self): name = self.cleaned_data.get('username') valid = models.UserInfo.objects.filter(username=name).first() if valid: raise ValidationError('用户名已存在') return name # 密码确认校验 def clean(self): pwd = self.cleaned_data.get('password') re_pwd = self.cleaned_data.get('re_password') if pwd == re_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致')
二、 views.py - 视图函数处理传输数据
注意知识点:
- 使用forms组件必须导入自定义的form文件
- 必须在视图函数内建立对应form对象
myform = myforms.MyForm()
- 习惯设置返回字典
response = {'status': 200, 'msg': None}
- 进行数据库ORM操作时,若选择使用**快捷填入,必须将forms自定属性和数据库内字段名完全一致
user = models.UserInfo.objects.create_user(**dic)
- forms组件进行判断之后,所有数据放在cleaned_data属性内
- forms组件进行判断之后,报错信息放在errors属性内
from django.shortcuts import render, HttpResponse from django.http import JsonResponse from bbs import myforms from bbs import models def register(request): ''' 注册功能 - 使用forms组件进行验证 :param request: :return: ''' if request.method == 'GET': myform = myforms.MyForm() return render(request, 'register.html', locals()) elif request.is_ajax(): # 设置返回对象,200默认成功 response = {'status': 200, 'msg': None} myform = myforms.MyForm(request.POST) print(myform.errors) if myform.is_valid(): dic = myform.cleaned_data dic.pop('re_password') my_file = request.FILES.get('my_file') if my_file: dic['avatar'] = my_file # 使用**dic进行传值,必须保证dic内的key值和数据库内的字段名完全相同 # 即自定义forms内类属性和数据库内字段名完全相同 # 注意数据库内头像字段的属性为FileField 时,只要传入对象就可以进行自动处理数据保存 user = models.UserInfo.objects.create_user(**dic) else: response['status'] =None response['msg'] = myform.errors return JsonResponse(response)
三、register.html - 前端
注意知识点:
- 注意必须带上{% csrf_token %}进行传输
- 可使用循环对视图函数传输的myform对象进行循环渲染
- for="{{ foo.auto_id }}” -- 用于对应相应label
- {{ foo.label }} -- 属性label名,在forms类内自定
- {{foo}} -- 属性的值,根据forms内属性widget进行渲染
- {{foo.errors.0}} -- 属性的值,根据forms内的错误信息进行渲染
- 将头像文件的选择项隐藏在图片显示框后,可实现点击图片选择文件
<div> <label for="my_file">头像 <img src="/static/img/default.png" id="img_file"> </label> <input type="file" id="my_file" style="display: none"> </div>
- 使用jq实现当文件选择项发生变化,触发图像放置框内图像文件的改变
{#当头像文件发生变化,触发页面img显示为放入的图像文件#} $('#my_file').change(function () { var file_obj = $('#my_file')[0].files[0]; var filereader = new FileReader();//文件阅读器对象生成,将图片放到img标签上 {# 获取图片对象的地址,放入filereader.result #} filereader.readAsDataURL(file_obj); {# 必须等路径加载完成后才能进行渲染操作 #} filereader.onload = function () { $('#img_file').attr('src', filereader.result) } })
- ajax使用formdata对象放入数据时候,可使用serializeArray()方法+循环放入
var formdata = new FormData(); {# 将form表单内内容打包,转成对象(列表套字典) #} var arr = $('#form').serializeArray(); {#console.log(arr);#} {# 循环将arr内对象放入formdata内 #} $.each(arr, function (k, obj) { {#console.log(k);#} {#console.log(obj);#} formdata.append(obj.name, obj.value); }); {# formdata添加文件对象 #} formdata.append('my_file', $('#my_file')[0].files[0]);
- 使用jq的each能实现循环操作
- 清除页面上原有的错误信息
$(".error_right").html(""); $(".error_right").parent().removeClass("has-error");
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <script src="/static/jquery-3.3.1.js"></script> <title>注册</title> </head> <style> .has-error { color: red; } #img_file { width: 80px; height: 80px; margin-left: 10px; } </style> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1>注册</h1> <form id="form"> {% csrf_token %} {% for foo in myform %} <div class="form-group"> <label for="{{ foo.auto_id }}">{{ foo.label }}</label> {{ foo }} </div> {% endfor %} <div> <label for="my_file">头像 <img src="/static/img/default.png" id="img_file"> </label> {# accept='image/*'只允许显示所有图片格式文件 #} <input accept='image/*'type="file" id="my_file" style="display: none"> </div> <input type="button" id='btn' value="注册" class="btn btn-primary pull-right"> </form> </div> </div> </div> </body> <script> {#当头像文件发生变化,触发页面img显示为放入的图像文件#} $('#my_file').change(function () { var file_obj = $('#my_file')[0].files[0]; var filereader = new FileReader();//文件阅读器对象生成,将图片放到img标签上 {# 获取图片对象的地址,放入filereader.result #} filereader.readAsDataURL(file_obj); {# 必须等路径加载完成后才能进行渲染操作 #} filereader.onload = function () { $('#img_file').attr('src', filereader.result) } }) {# 实现ajax传输数据给后台#} $('#btn').click(function () { var formdata = new FormData(); {# 将form表单内内容打包,转成对象(列表套字典) #} var arr = $('#form').serializeArray(); {#console.log(arr);#} {# 循环将arr内对象放入formdata内 #} $.each(arr, function (k, obj) { {#console.log(k);#} {#console.log(obj);#} formdata.append(obj.name, obj.value); }); {# formdata添加文件对象 #} formdata.append('my_file', $('#my_file')[0].files[0]); $(".error_right").html(""); $(".error_right").parent().removeClass("has-error"); $.ajax({ url: '/register/', type: 'post', data: formdata, processData: false, contentType: false, success: function (data) { if (data['status']) { location.href = '/index/' } else { console.log(data['msg']); var msg = data['msg']; $.each(msg, function (k, v) { console.log(msg) $span = $('<span>'); $span.addClass('error_right').css("color", 'red'); $span.html(v[0]); $('#id_' + k).after($span).parent().addClass('has-error'); if (k == '__all__') { $("#btn").after($span); } }); } } }) }); </script> </html>