核心功能:校验字段和钩子
注意:我会省略部分相同代码
校验的简单例子:
views.py
1: from from django import forms
2: class UserForm(forms.Form):
3:4: name = forms.CharField(min_length=4)
5: email = forms.EmailField()6:7: def func(request):
8: if request.method == "POST":9:10: # 对于不包含的类中的字段,forms并不关心11: form = UserForm({"name":"yuan", "email":"123@qq.com","xxx":"xxx"})12: # form = UserForm({"name":"yu", "email":"123@qq.com","xxx":"xxx"})13:14: # 检测是否通过15: if form.is_valid():
16: # {"name":"yuan", "email":"123@qq.com"}17: print(form.cleaned_data)
18: else:
19: # {"email":"123@qq.com"}20: print(form.cleaned_data)
21: # {"name":["........"]}22: print(form.errors)
完整的例子:
models.py
1: class UserInfo(models.Model):
2: name = models.CharField(max_length=32)
3: pwd = models.CharField(max_length=32)4: email = models.EmailField()5: tel = models.CharField(max_length=32)
views.py
1: from django.shortcuts import render, HttpResponse
2: # Create your views here.3: from django import forms
4: class UserForm(forms.Form):
5:6: name = forms.CharField(min_length=4)
7: pwd = forms.CharField(min_length=4)8: r_pwd = forms.CharField(min_length=4)9: email = forms.EmailField()10: tel = forms.CharField()11:12: def reg(request):
13:14: if request.method=="POST":15:16: form表单的属性值与forms组件字段相同,否则不会校验17: form = UserForm(request.POST)18:19: if form.is_valid():
20: print(form.cleaned_data)
21: else:
22: print(form.cleaned_data)
23: print(form.errors)
24:25: return HttpResponse("OK!")26:27: return render(request, "reg.html")
reg.html
1: <form action="" method="post">
2: {% csrf_token %}3: <p>用户<input type="text" name="name"></p>4: <p>密码<input type="text" name="pwd"></p>5: <p>确认密码<input type="text" name="r_pwd"></p>6: <p>邮箱<input type="text" name="email"></p>7: <p>电话<input type="text" name="tel"></p>8: <input type="submit">
9: </form>
渲染标签功能
方法1
views.py
1: def...
2: form = UserForm()3:4: return render(request, "reg.html", {"form": form, })
reg.html
1: <h3>forms组件渲染方式1</h3>2: <form action="" method="post">3:4: {% csrf_token %}5: <p>用户名{{ form.name }}</p>6: <p>密码{{ form.pwd }}</p>7: <p>确认密码{{ form.r_pwd }}</p>8: <p>邮箱{{ form.email }}</p>9: <p>电话{{ form.tel }}</p>10: <input type="submit">11: </form>
其他方法
views.py
1: from django import forms2: class UserForm(forms.Form):3: name = forms.CharField(min_length=4, label="用户名")4: pwd = forms.CharField(min_length=4, label="密码")5: r_pwd = forms.CharField(min_length=4, label="确认密码")6: email = forms.EmailField(label="邮箱")7: tel = forms.CharField(label="号码")
1: <h3>forms组件渲染方式2</h3>2: <form action="" method="post">3:4: {% csrf_token %}5: {% for field in form %}6: <div>7: <label for="">{{ field.label }}</label>8: {{ field }}9: </div>10: {% endfor %}11: <input type="submit">12: </form>
1: {# 不建议实际中使用,自由度简易型较低 #}2: <h3>forms组件渲染方式3</h3>3: <form action="" method="post">4: {% csrf_token %}5: {{ form.as_p }}6: {{ form.as_ul }}7: <input type="submit">8: </form>
渲染错误信息
views.py
1: def reg(request):
2:3: if request.method == "POST":4: form = UserForm(request.POST)5:6: if form.is_valid():
7: print(form.cleaned_data)
8: else:
9: print(form.cleaned_data)
10: print(form.errors)
11:12: return render(request, "reg.html", locals())13:14: form = UserForm()15:16: return render(request, "reg.html", {"form": form, })
html
1: <h3>forms组件错误渲染</h3>2: <form action="" method="post" novalidate>3:4: {% csrf_token %}5: <p>{{ form.name.label }}6: {{ form.name }} <span>{{ form.name.errors.0 }}</span>7: </p>8: <p>{{ form.pwd.label }}9: {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span>10: </p>11: <p>{{ form.r_pwd.label }}12: {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span>13: </p>14: <p>{{ form.email.label }}15: {{ form.email }} <span>{{ form.email.errors.0 }}</span>16: </p>17: <p>{{ form.tel.label }}18: {{ form.tel }} <span>{{ form.tel.errors.0 }}</span>19: </p>20: <input type="submit">21: </form>
参数配置功能
如果说需要将错误提示信息改成中文提示(django默认是英文)等类似的需求,就需要用到参数配置功能
views.py
1: from django.forms import widgets
2: class UserForm(forms.Form):
3:4: error_messages = {"required": "该字段不能为空", "invalid": "格式错误!"}5: name = forms.CharField(min_length=4, label="用户名", error_messages=error_messages,6: widget=widgets.TextInput(attrs={"class": "form-control"}))7: pwd = forms.CharField(min_length=4, label="密码", widget=widgets.PasswordInput(attrs={"class": "form-control"}),8: error_messages=error_messages)9: r_pwd = forms.CharField(min_length=4, label="确认密码", widget=widgets.PasswordInput(attrs={"class": "form-control"}),10: error_messages=error_messages)11: email = forms.EmailField(label="邮箱", error_messages=error_messages,
12: widget=widgets.EmailInput(attrs={"class": "form-control"}))13: tel = forms.CharField(label="号码", error_messages=error_messages,
14: widget=widgets.TextInput(attrs={"class": "form-control"}))
reg.html(需要bootstrap)
1: <div class="container">2: <div class="row">3: <div class="col-md-6 col-lg-offset-3" >4: <h3>forms组件错误渲染</h3>5: <form action="" method="post" novalidate>6: {% csrf_token %}7: <p>{{ form.name.label }}8: {{ form.name }} <span>{{ form.name.errors.0 }}</span>9: </p>10: <p>{{ form.pwd.label }}11: {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span>12: </p>13: <p>{{ form.r_pwd.label }}14: {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span>15: </p>16: <p>{{ form.email.label }}17: {{ form.email }} <span>{{ form.email.errors.0 }}</span>18: </p>19: <p>{{ form.tel.label }}20: {{ form.tel }} <span>{{ form.tel.errors.0 }}</span>21: </p>22: <input type="submit">23: </form>24: <div>25: <div>26: <div>
钩子功能
比较复杂的字段检测功能,看源码是双重校验,全局钩子校验和局部钩子校验
局部钩子
views.py
1: from app01.models import UserInfo
2: from django.core.exceptions import ValidationError
3:4: def...(同上)
5: # clean_%s固定写法6: def clean_name(self):
7:8: val = self.cleaned_data.get("name")
9: res = UserInfo.objects.filter(name=val)
10: if not res:
11: return val
12: else:
13: raise ValidationError("该用户已注册")
14:15: def clean_tel(self):
16:17: val = self.cleaned_data.get("tel")
18: if len(val) == 11:
19: return val
20: else:
21: raise ValidationError("手机号格式错误")
22:
全局钩子
1: class...
2: def clean(self):
3:4: pwd = self.cleaned_data.get("pwd")
5: r_pwd = self.cleaned_data.get("r_pwd")
6: # 为了避免同时出现两个错误(比如pwd字段检验不通过并且pwd!=r_pwd)7: if pwd and r_pwd:
8: if pwd == r_pwd:
9: return self.cleaned_data
10: else:
11: raise ValidationError("两次密码不一致")
12: else:
13: return self.cleaned_data
14:15:16: def...
17:18: errors = form.errors.get("__all__")
19:
html
1: <p>{{ form.r_pwd.label }}2: {{ form.r_pwd }} <span class="error">{{ form.r_pwd.errors.0 }}</span><span class="error">{{ errors.0 }}</span>3: </p>