django中Form组件 1. 用户请求数据验证 2. 自动生成错误信息 3. 打包用户提交正确信息 4. 错误:保留上次输入内容 5. 定制页面上显示的HTML标签 引入: from django.forms import Form from django.forms import fields from django.forms import widgets from django.core.validators import RegexValidator 1. 创建类 -继承Form 2. 字段 要与 数据库中的字段一样 - required=True - min_length=3 - max_length=18 - error_messages={'required':'不能为空','min_length':'长度不能小于3','max_length':'长度不能大于18','invalid':'格式错误'} - widget=widgets.TextInput(attrs={'placeholder':'姓名','class':'c1'} #自动创建标签及属性 CheckboxInput/DateInput/NumberInput/PasswordInput/TimeInput/URLInput/DateTimeInput/EmailInput/FileInput/HiddenInput -validators=[RegexValidator('d+','只能是数字') ] #对于某个字段进行正则匹配,第一个参数是匹配规则,第二个参数是如果匹配错误要显示的信息(没有error_messages内的invalid优先级高) 3. form=Form() #不传参实例化,只是创建标签 4. form=Form(data=request.POST) #把POST里的数据打包放到一起 5. form=Form(initial={'sid':student_obj.sid,'name':student_obj.name}) #Form实例化时初始值设置 6. form.is_valid() #进行数据校验 7. form.cleaned_data #校验成功的数据 字典形式 8. form.errors #校验错误的数据 是个对象 'obj.errors.字典键.0 ' 获取第一个错误信息 9. Form组件 在创建类的时候造成的数据不同步,解决方法:重写构造方法-每次实例化的时候都重新从数据库内取值 方式一:推荐 list=fields.MultipleChoiceField(choices=[]) def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) self.fields['list'].choices=models.Class.objects.values_list('id','name') #choices 有自带的校验功能,如果前端传过来的值不在models.Class.objects.values_list('id','name') 范围内,就会提示错误 方式二: from django.forms.models import ModelChoiceField class ClassForm(Form): caption = fields.CharField(error_messages={'required':'班级名称不能为空'}) headmaster_id = ModelChoiceField(queryset=models.UserInfo.objects.filter(ut_id=2)) 10.遇到的问题:班主任/讲师 的属性: 任课班级字段 修改时的默认值设置 'list':[i.id for i in teacher_obj.class_set.all()] #[1,2,3] 11.在模板中form.as_p 会把自定义Form类内的所有字段按照p标签生成 form.as_table / form.as_ul 不推荐 12.Form扩展: 钩子函数:如果在自定义类中定义 def clean_字段名(上方的定义的字段)方法,那么这个函数就会在校验当前字段名时(自带的正则校验后)自动执行, 可以在此函数中再次进行对数据库的相关判断,因为正则校验不能连接数据库 注意: 必须有返回值 只能拿自己当前字段值 raise ValidationError('xxx') 代码部分 from django.forms import Form from django.forms import fields from django.forms import widgets from django.core.validators import RegexValidator from django.core.exceptions import ValidationError from app01 import models class LoginForm(Form): username = fields.CharField( required=True, min_length=3, max_length=18, error_messages={ 'required': '用户不能为空', 'min_length': '用户长度不能小于3', 'max_length': '用户长度不能大于18', } ) password = fields.CharField( required=True, min_length=3, max_length=18, error_messages={ 'required': '密码不能为空', 'min_length': '密码长度不能小于3', 'max_length': '密码长度不能大于18', 'invalid': '密码格式错误', }, validators=[RegexValidator('d+','只能是数字') ] ) def clean_username(self): #在校验username字段时 自动执行 # ... user = self.cleaned_data['username'] is_exsit = models.UserInfo.objects.filter(username=user).count() if not is_exsit: raise ValidationError('用户名不存在') return user #如果存在 就把前面得到的user值返回给函数就行了,django会把该函数的返回值赋值给 cleaned_data['username'] → cleaned_data['username']=user def clean_password(self): #在校验password字段时 自动执行 user = self.cleaned_data['username'] return user def login(request): if request.method == "GET": form = LoginForm() return render(request,'login.html',{'form':form}) elif request.method =="POST": form = LoginForm(data=request.POST) if form.is_valid(): # 验证成功 user = models.UserInfo.objects.filter(**form.cleaned_data).first() if not user: # 用户名或密码错误 # 主动向form中添加错误信息 #方法1 # form.add_error('password','用户名或密码错误') #向password字段的错误信息中添加 #方法2 - 官方方法 form.add_error('password',ValidationError('用户名或密码错误')) return render(request, 'login.html', {'form': form}) else: request.session[settings.SJF] = {'id':user.id, 'username':user.username} return redirect('/index/') else: # 验证失败 return render(request, 'login.html',{'form':form}) else: return HttpResponse('滚')