核心功能:校验字段和钩子
注意:我会省略部分相同代码
校验的简单例子:
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 forms
2: 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>