ModelForm
在上面我们使用form来验证了字段,假如我们注册的时候,数据表里的每个字段都要显示在页面上,难道我们需要一个一个写吗?答案肯定不是的,上面我们的类继承了Form,现在我们继承ModelForm就能达成我们的需求。
from django import forms from crm import models from django.core.exceptions import ValidationError # 注册form class RegForm(forms.ModelForm): # 继承ModelForm,比Form功能强大 ''' 这里重写之后会把Meta里的覆盖,这里如果没写,Meta里写了,Meta里的也不会生效 ''' password = forms.CharField( label='密码', min_length=6, widget=forms.widgets.PasswordInput, error_messages={ 'min_length': '最小长度为6位', 'required': '密码不能为空', } ) re_password = forms.CharField( label='确认密码', widget=forms.widgets.PasswordInput, ) class Meta: # 展示内容的配置 model = models.UserProfile # 用户表 # fields = '__all__' # 页面上显示数据表里的所有字段 # exclude = ['',''] # 页面上不显示某些字段 fields = ['username', 'password', 're_password', 'name', 'department'] # 页面上指定显示某些字段 widgets = { # 使用插件改写密码输入框的type类型 'username': forms.widgets.EmailInput(attrs={'class':'form-control'}), # 把username输入框的type改为email,添加一个class属性form-control 'password': forms.widgets.PasswordInput, # 改写密码输入框的type类型为password } ''' 定义页面显示的内容 ''' labels = { 'username':'用户名', 'password':"密码", 're_password': '确认密码', 'name':'姓名', 'department':'部门' } def __init__(self, *args, **kwargs): # 获取每一个字段,往里面加class属性 super().__init__(*args, **kwargs) for filed in self.fields.values(): filed.widget.attrs.update({'class':'form-control'}) ''' 这里判断密码和确认密码是不是相同,如果不同,给出错误信息 ''' 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 self.add_error('re_password','两次密码不一致') # 给re_password添加一个错误信息 raise ValidationError('两次密码不一致') # 抛出错误信息
ModelForm的强大之处不止于此,比如你要编辑一条数据,你是不是需要把这条数据查询出来,在输入框里显示,然后在进行编辑,之前我们查询出来之后,然后一个一个的循环显示在输入框里。ModelForm提供了简单的方法。
# 编辑客户 def edit_customer(request, edit_id): # 根据id查询出要编辑的客户对象 obj = models.Customer.objects.filter(id=edit_id).first() # 将查询到的对象和对应的html渲染 form_obj = CustomerForm(instance=obj) 重要 if request.method == 'POST': # 将提交的数据和要修改的实例交给form对象 form_obj = CustomerForm(request.POST, instance=obj) 重要 if form_obj.is_valid(): # 修改后保存 form_obj.save() return redirect(reverse('customer')) return render(request,'crm/edit_customer.html',{'form_obj': form_obj})
说明: form_obj = CustomerForm(request.POST, instance=obj) 里如果没有instance=obj,则是新增
自定义校验规则
虽然Django里的Form给我们提供了一些常用的规则,但往往满足不了产品经理的sb需求,这时候就要我们自己定义校验规则了,Django给我们提供了两种校验规则,一种是可以通过正则的方式,另一种是自定义函数。
通过正则的方式
先来写个form验证的
from django import forms from django.core.validators import RegexValidator class Phone(forms.Form): phone = forms.CharField( label='手机号', validators=[ RegexValidator(r'^1[3-9]\d{9}$', '手机号格式不正确') ] )
这里要导入RegexValidator,然后在里面写正则,第一个参数是正则表达式,第二个是错误信息
在来写对应的视图函数
from appTest01 import forms def register2(request): form_obj = forms.Phone() if request.method == 'POST': form_obj = forms.Phone(request.POST) if form_obj.is_valid(): return HttpResponse('注册成功') return render(request, 'register1.html', {"form_obj": form_obj})
最后来写html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} {{ form_obj.phone.label }} {{ form_obj.phone }} <button>提交</button> {{ form_obj.errors.phone.0 }} </form> </body> </html>
这样我们就通过了正则来验证了我们输入的手机号是不是符合格式
通过自定义函数来验证
from django.core.validators import RegexValidator from django.core.exceptions import ValidationError def check(value): if 'ma' in value: raise ValidationError('输入的有非法字符') class Phone(forms.Form): phone = forms.CharField( label='手机号', validators=[ check ] )
其他的地方都不需要改,如果输入框里包含“ma”则认为非法