Django之Form表单
1:什么是表单
2:HTML表单与Django表单
3:Django中表单的使用流程
4:常用的字段与验证器
5:自定义验证器
6: 提取错误信息
7:ModelForm:
(1)自定义错误消息
(2)save()方法
1什么是表单:表单是用来收集用户信息的表的集合,比如用户在网站上登入(输入自己的用户名,密码提交到网站)这个过程用到的表就是表单
2HTML表单与django表单
html表单:form标签,提交地址,请求方式,提交按钮
<form action="" method="post" enctype="multipart/form-data"> <input type="text" name="username"> <input type="password" name="password"> <input type="file"> <input type="checkbox"> <input type="submit"> </form>
django表单:是由Form类实现的,主要分为forms.Form和forms.ModelForm两种,前者为基本的表单或者为结合模型生成的表单
django表单的作用:(1)类似于html页面一样生成表单模板(2)对表单提交上来的数据进行验证(重点)
3:django表单使用的基本流程:
(1)生成一个表单模板:
在APP中创建一个py文件,名字为forms;这里面写表单的内容:目录如下
forms.py代码:
from django import forms class IndexForm(forms.Form): title = forms.CharField(max_length=12,label="标题") //max_length表示最大长度,label表示标题名字 content = forms.CharField(widget= forms.Textarea,label="内容") //widget表示表单的属性 replay = forms.BooleanField(required=False,label="记住我")
view.py代码:
from django.shortcuts import render from django.views.generic import View from .forms import IndexForm class IndexView(View): def get(self,request): //get请求的时候,返回一个IndexForm form = IndexForm() return render(request,"index.html",context={"form":form})
html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <table> {{ form.as_table }} //在HTML中渲染一个表单三种方式(form.as_table,form.as_ul,form.as_p),之后还要添加提交按钮 <tr> <td></td> <td><input type="submit"></td> </tr> </table> </form> </body> </html>
(2)对表单提交上来的数据进行验证
forms.py
from django import forms class IndexFrom(forms.Form): title = forms.CharField(max_length=12,label="标题",min_length=4) //最少不能小于4个 content = forms.CharField(widget= forms.Textarea,label="内容") email = forms.EmailField() //添加一个邮箱的验证 replay = forms.BooleanField(required=False,label="记住我") //required=False 表示值可以不填,默认为True
view.py
from django.shortcuts import render,HttpResponse from django.views.generic import View from .forms import IndexFrom class IndexView(View): def get(self,request): form = IndexFrom() return render(request,"index.html",context={"form":form}) def post(self,request): form = IndexFrom(request.POST) //将request.POST接收到的值传给IndexForm表单进行验证, if form.is_valid(): //如果验证成功则为True return HttpResponse("ok") else: print(form.errors.get_json_data()) return HttpResponse("fail")
4:常用的验证器
(1)常用的字段(Field):
CharField: 用来接收文本
max_length:表示最大长度
min_length:表示最小长度
required:表示是否必须填写,默认为True(必须)
error_messages:验证失败给出的错误信息
EmailField:用来验证邮箱
错误信息的key:required,invalid
FloatField:用来接收浮点类型,通过验证后会将值转换为浮点型
max_value:最大值
min_value:最小值
错误信息的key:required,invalid,max_value,min_value
IntegerField:用来接收整型,通过验证后会将值转换为整型
max_value:最大值
min_value:最小值
错误信息的key:required,invalid,max_value,min_value
URLField:用来接收url格式的字符串
错误信息的key:required,invalid
(2)常用的验证器(validator):在验证某个字段的时候可以传递一个验证器对数据进一步验证
MaxValueValidator:验证最大值
MinValueValidator:验证最小值
MaxLengthValidator:验证最大长度
MinLengthValidator:验证最小长度
EmailValidator:验证是否是邮箱格式
URLValidator:验证是否是URL格式
RegexValidator:正则验证
from django import forms from django.core import validators //导入验证器 class IndexFrom(forms.Form): telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message="请输入正确的手机号")]) //验证手机号
5自定义验证器
(1)如果要对一个字段进行验证不是一个长度,也不是一个最大值,正则或者也表达不清楚,还需要一些更复杂的逻辑,那么我们可以对这个字段进行自定义验证;比如注册的时候我们要判断数据库中有没有这个手机号,有的话就不能再注册了,这是我们就要在数据库中判断才知道,那么就要定义一个方法;这个方法有一个规则就是clean_fieldname(比如:clean_telephone,clean_username等,是个是固定的),比如我们要对手机号进行验证:
from django import forms from django.core import validators from .models import User class IndexFrom(forms.Form): title = forms.CharField(max_length=12,label="标题",min_length=4) content = forms.CharField(widget= forms.Textarea,label="内容") email = forms.EmailField() replay = forms.BooleanField(required=False,label="记住我") telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message="请输入正确的手机号")]) def clean_telephone(self): //对手机号进行验证方式(clean_telephone) telephone = self.cleaned_data.get("telephone") //拿到这个手机号 exists = User.objects.filter(telephone=telephone).exists() //在数据库中判断是否存在 if exists: raise forms.ValidationError("手机号已经存在") else: return telephone
(2)以上是对单个字段进行验证,如果是对多个字段进行验证的话就可以重写clean方法; 比如注册的时候要判断两次输入的密码是否一致:
from django import forms from django.core import validators from .models import User class IndexFrom(forms.Form): title = forms.CharField(max_length=12,label="标题",min_length=4) content = forms.CharField(widget= forms.Textarea,label="内容") email = forms.EmailField() password = forms.CharField(max_length=18,min_length=6) re_password = forms.CharField(max_length=18,min_length=6) replay = forms.BooleanField(required=False,label="记住我") telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message="请输入正确的手机号")]) def clean(self): //重写clean方法 cleaned_data = super().clean() //调用父的clean() password = cleaned_data.get("password") re_password = cleaned_data.get("re_password") if password != re_password: raise forms.ValidationError("两次密码不一致") return cleaned_data
6提取错误信息
如果验证失败了,会有一些错误提示信息,如:
form.errors:这个属性的错误信息是包含了一些html标签的错误信息
form.errors.get_json_data():这个方法获取到的是一个字典类型的错误信息,将某个字段的名字作为key,错误信息为值得字典
form.as_json():这个方法是将form.get_json_data()返回的字典dump成json格式的字符串。
以上方法获取的都是比较复杂的数据比如:
{'email': [{'message': 'Enter a valid email address.', 'code': 'invalid'}], '__all__': [{'message': '两次密码不一致', 'code': ''}]}
如果我们想把错误信息放到一个列表而不是字典中,我们可以自己定义一个方法,对错误信息重新整理:
def get_errors(self): errors = self.errors.get_json_data() new_errors = {} for key,message_dicts in errors.items(): //对字典进行遍历 messages = [] for message in message_dicts: // messages.append(message["message"]) new_errors[key] = messages return new_errors
7ModelForm:
(1)我们在写表单的时候发现表单中的Field和模型中的Field基本上一样,而且表单中需要验证的数据就是我们要保存到数据库中的数据,那么我们就可以将两者绑定。比如我们有个模型(User):
from django.db import models class User(models.Model): username = models.CharField(max_length=12) telephone = models.CharField(max_length=11) password = models.CharField(max_length=18) email = models.EmailField() class Meta: db_table = "user"
那么我们再写表单的时候可以这样写:
class UserForm(forms.ModelForm): //继承自ModelForm class Meta: //定义Meta类 model = User //规定继承自那个模型 fields = "__all__" //规定继承那些字段(继承所有字段) # fields = ["username","telephone"] //继承username,telephone两个字段 # exclude = ["username"] //除了username字段其他都继承 error_messages={ //定义一个错误提示信息 "username":{"max_length":"最多不能超过10个字符","min_length":"最少不能少于3个字符"}, "telephone":{"required":"必须传入手机号"} }
(2)save()方法:这个方法是把数据直接保存到数据库中(必须保证clean方法没有问题之后才能使用,不然会报错),我们还可以传入一个参数commit=False;表示只会生成一个对象不会真正的保存到数据库中。
def post(self,request): form = IndexFrom(request.POST) if form.is_valid(): # form.save() //直接保存到数据库中 user = form.save(commit=False) //生成一个user对象 user.password = "123123" //给对象添加一个密码 user.save() //保存到数据库中 return HttpResponse("ok")