1. form组件创建页面的四种使用方式:
1.1方式一;手动写
<!-- novalidate 告诉浏览器不要去给我校验--> <!-- 方式一 : 手写HTMl-->
<form action="" method="POST" novalidate>
{% csrf_token %}
<!-- novalidate 告诉浏览器不要去给我校验-->
<!-- 方式一 : 手写HTMl-->
<!-- <p>用户名:<input type="text" name="username"></p>-->
<!-- <p>年龄:<input type="text" name="age"></p>-->
<!-- <p>工资: <input type="text" name="salary"></p>-->
<!-- <input type="submit">-->
此时视图函数中的代码:
1.2 利用自定义的form组件类在视图函数创建一个对象填充到前端页面当中去
视图函数中的代码:
def add_emp(request): if request.method == "GET": form = EmpForm() return render(request, "add_emp.html", {"form": form})
前端add_emp.html的代码:
方式二:
<form action="" method="POST" novalidate> {% csrf_token %} <!-- 方式二:form自带的as_p--> <!-- {{ form.as_p }}--> <!--<input type="submit">
方式4:
<div class="container"> <div class="row"> <h3>添加用户</h3> {% csrf_token %} {% for field in form %} <div> <label for="id_{{ field.name }}">{{ field.label }} : </label> {{ field }} <span>{{ field.errors.0 }}</span> </div> {% endfor %} <button class="btn btn-info" id="btn_add">提交</button> </div> </div>
方式三:
<!-- 方式3 --> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h3>新增员工</h3> <form action="" method="POST" novalidate> {% csrf_token %} <div class="form-group {% if form.name.errors.0 %}has-error{% endif %}"> <label for="id_{{ form.name.name }}">{{ form.name.label }}</label> {{ form.name }} <span class="help-block">{{ form.name.errors.0 }}</span> </div> <div class="form-group {% if form.age.errors.0 %}has-error{% endif %} "> <label for="id_{{ form.age.name }}">{{ form.age.label }}</label> {{ form.age }} <span class="help-block">{{ form.age.errors.0 }}</span> </div> <div class="form-group {% if form.salary.errors.0 %}has-error{% endif %}"> <label for="id_salary">工资</label> {{ form.salary }} <span class="help-block">{{ form.salary.errors.0 }}</span> </div> <div class="form-group {% if form.r_salary.errors.0 %}has-error{% endif %}"> <label for="id_r_salary">{{ form.r_salary.label }}</label> {{ form.r_salary }} <span class="help-block">{{ form.r_salary.errors.0 }} {{ clean_errors.0 }}</span> </div> <input type="submit"> </form> </div> </div> </div> </body> </html>
视图函数中的代码:
from django.shortcuts import render, HttpResponse from django.shortcuts import render from app01.My_Forms import EmpForm from app01 import models # Create your views here. def add_emp(request): if request.method == "GET": form = EmpForm() return render(request, "add_emp.html", {"form": form}) else: form = EmpForm(request.POST) if form.is_valid(): # 进行数据校验 # 校验成功 data = form.cleaned_data # 校验成功的值,会放在cleaned_data里。 print(data) data.pop('r_salary') print(data) # {'name': 'alex', 'age': 28, 'salary': Decimal('11')} models.Emp.objects.create(**data) return HttpResponse("ok") else: print(form.errors) # 打印错误的信息 # print(111) # return HttpResponse("aaa") clean_errors = form.errors.get("__all__") return render(request, "add_emp.html", {"form": form, "clean_errors": clean_errors})
小结:在有全局钩子的时候,出错的时候需要将全局钩子出错的clean_errors 传入到后端中填充页面,就行显示。一般的错误传入form对象即可。
2.常用字段定义
# Django Form组件的使用 from django import forms from django.forms import widgets from django.core.validators import RegexValidator from django.core.exceptions import ValidationError class RegForm(forms.Form): name = forms.CharField( # 校验规则相关 max_length=16, label="用户名", error_messages={ "required": "该字段不能为空", }, # widget控制的是生成html代码相关的 widget=widgets.TextInput(attrs={"class": "form-control"}) ) pwd = forms.CharField( label="密码", min_length=6, max_length=10, widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True), error_messages={ "min_length": "密码不能少于6位!", "max_length": "密码最长10位!", "required": "该字段不能为空", } ) re_pwd = forms.CharField( label="确认密码", min_length=6, max_length=10, widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True), error_messages={ "min_length": "密码不能少于6位!", "max_length": "密码最长10位!", "required": "该字段不能为空", } ) email = forms.EmailField( label="邮箱", widget=widgets.EmailInput(attrs={"class": "form-control"}), error_messages={ "required": "该字段不能为空", } ) mobile = forms.CharField( label="手机", # 自己定制校验规则 validators=[ RegexValidator(r'^[0-9]+$', '手机号必须是数字'), RegexValidator(r'^1[3-9][0-9]{9}$', '手机格式有误') ], widget=widgets.TextInput(attrs={"class": "form-control"}), error_messages={ "required": "该字段不能为空", } ) city = forms.ChoiceField( choices=models.City.objects.all().values_list("id", "name"), label="城市", initial=1, widget=forms.widgets.Select ) # 重写父类的init方法 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name") def clean_name(self): value = self.cleaned_data.get("name") if "金 瓶 梅" in value: raise ValidationError("不符合社会主义核心价值观!") return value # 重写父类的clean方法 def clean(self): # 此时 通过检验的字段的数据都保存在 self.cleaned_data pwd = self.cleaned_data.get("pwd") re_pwd = self.cleaned_data.get("re_pwd") if pwd != re_pwd: self.add_error("re_pwd", ValidationError("两次密码不一致")) raise ValidationError("两次密码不一致") return self.cleaned_data # gender = forms.ChoiceField( # choices=((1, "男"), (2, "女"), (3, "保密")), # label="性别", # initial=1, # widget=forms.widgets.RadioSelect # ) # hobby = forms.ChoiceField( # choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), # label="爱好", # initial=3, # widget=forms.widgets.Select # ) # hobby2 = forms.MultipleChoiceField( # choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), # label="爱好", # initial=[1, 3], # widget=forms.widgets.SelectMultiple() # ) # # keep = forms.ChoiceField( # label="是否记住密码", # initial="checked", # widget=forms.widgets.CheckboxInput # ) # hobby3 = forms.MultipleChoiceField( # choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), # label="爱好", # initial=[1, 3], # # widget=forms.widgets.CheckboxSelectMultiple(attrs={"class": "c1"}) # )
其中如果在前端的页面中需要去选择下拉列表的时候:
city = forms.ChoiceField( choices=models.City.objects.all().values_list("id", "name"), label="城市", initial=1, widget=forms.widgets.Select ) # 重写父类的init方法 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")
3.使用ajax请求就行form表单的用户注册校验
add_user.html中的代码:
<div class="container"> <div class="row"> <h3>添加用户</h3> {% csrf_token %} {% for field in form %} <div> <label for="id_{{ field.name }}">{{ field.label }} : </label> {{ field }} <span>{{ field.errors.0 }}</span> </div> {% endfor %} <button class="btn btn-info" id="btn_add">提交</button> </div> </div> <script src="/static/js/jquery.js"></script> <script> $("#btn_add").click(function () { let username = $("#id_username").val(); let password = $("#id_password").val(); $.ajax({ url: "", type: "post", data: { username: username, password: password, csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(), }, success: function (ret) { {#console.log(ret);#} if (ret.status) { location.href = "/login/" } else { {#console.log(ret.msg);#} $('span').html(""); // 清空页面之前的错误信息 $.each(ret.msg, function (i, j) { console.log(i, j); $("#id_" + i).next().text(j[0]) }) } } }) }) </script>
视图函数中函数 add_user代码:
def add_user(request): if request.method == "GET": form = UserForm() # 初始化form对象 return render(request, "add_user.html", {'form': form}) if request.is_ajax(): ret = {'status': 1, "msg": None} print(request.POST) form = UserForm(request.POST) if form.is_valid(): print(form.cleaned_data) # return redirect("/login/") else: print(form.errors) ret['status'] = 0 ret['msg'] = form.errors return JsonResponse(ret)
定义的form 组件类的类代码:My_Form.py中的代码:
from django import forms class UserForm(forms.Form): username = forms.CharField(min_length=4, label="用户名", widget=forms.widgets.TextInput(attrs={"class": "form-control"})) password = forms.CharField(min_length=6, label="密 码", widget=forms.widgets.PasswordInput(attrs={"class": "form-control", }))
即是查询其他的数据库就行一个显示,注意的是需要重写父类的方法,不然需要重启服务器。
参考:李文综老师博客:https://www.cnblogs.com/liwenzhou/p/8747872.html