Django组件之forms组件

核心功能:校验字段和钩子

注意:我会省略部分相同代码

校验的简单例子:

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>

最后,为了程序的解耦性,可以将钩子放到一个单独的py文件里,记得文件名不要冲突!

原文地址:https://www.cnblogs.com/haoqirui/p/10230500.html