1.Form
form组件的主要作用:
-
帮助我们生成HTML标签 + 携带数据
-
数据校验,对用户提交的数据进行格式校验
1.1 简单使用
cleaned_data():校验合格的数据
errors:校验错误的数据,以字段为键,错误为值
is_valid():校验字段是否全部正确
定义模型类如下
class Student(models.Model): SEX_CHOICES = ( (0, "女"), (1, "男"), (2, "保密"), ) # 定义CharField类型字段 name = models.CharField(max_length=20, db_index=True, verbose_name="姓名") # 定义SmallIntegerField类型字段 age = models.SmallIntegerField(verbose_name="年龄") sex = models.SmallIntegerField(choices=SEX_CHOICES, default=2) class Meta: db_table = 'tb_student' # 指明数据库表名,如果没有指定表明,则默认为子应用目录名_模型名称 def __str__(self): return self.name
自定义Form类
class StudentForm(forms.Form): SEX_CHOICES = ( (0, "女"), (1, "男"), (2, "保密"), ) name = forms.CharField( max_length=6, min_length=2, required=True, label='姓名', widget=forms.TextInput(), ) age = forms.IntegerField(required=True, label='年龄', widget=forms.NumberInput(), ) sex = forms.ChoiceField(choices=SEX_CHOICES, label='性别', widget=forms.Select()) def clean_name(self): """ 钩子函数,针对name字段进行校验,不通过可以抛出异常,正常则返回该字段 :return: """ return self.cleaned_data['name'] def clean(self): """ 钩子函数,在校验完所有字段时,同一再进行字段的校验,返回clean_data :return: """ return self.cleaned_data
模板文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post" novalidate> {% csrf_token %} {% for foo in form %} <div> <label id="id_{{ foo.name }}">{{ foo.label }}</label> {{ foo }} <span style="color: red">{{ foo.errors.0 }}</span> </div> {% endfor %} <input type="submit" value="提交"> </form> </body> </html>
视图函数
def index(request): if request.method == "GET": # 让前端自动帮助我们生成页面 form = StudentForm() return render(request, 'app02/index.html', {'form': form}) form = StudentForm(data=request.POST) # 校验数据 if form.is_valid(): print(form.cleaned_data) else: # 校验失败 将错误信息返回页面 return render(request, 'app02/index.html', {'form': form}) return HttpResponse('OK')
get请求页面
提交数据不符合规范
1.2 源码分析
从上图中可以发现
校验顺序为:字段校验->字段的钩子函数->字段的整体校验->字段的整体处理
2.ModelForm
在写
modelform是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来。
模型类
class Student(models.Model): name = models.CharField(max_length=12) age = models.SmallIntegerField() email = models.EmailField() birthday = models.DateField()
表单类
class StudentModelForm(ModelForm): class Meta: model = Student # 对应的Model中的类 fields = "__all__" # 字段,如果是__all__,就是表示列出所有的字段 # exclude = None #排除的字段 # error_messages用法: error_messages = { 'name': {'required': "用户名不能为空"}, } # widgets用法 # 首先得导入模块 from django.forms import widgets as wid # 因为重名,所以起个别名 widgets = { "birthday": wid.Input(attrs={"type": "date", 'class': 'form-control'}), # 还可以自定义属性 } # labels,自定义在前端显示的名字 labels = { "name": "用户名" }, # 局部校验 def clean_name(self): pass
视图函数
def addstus(request): if request.method == "GET": studentModelFormObj = StudentModelForm() return render(request, "addstu.html", {"studentModelFormObj": studentModelFormObj}) else: # create a form instance and populate it with data from the request studentModelFormObj = StudentModelForm(data=request.POST) # check whether it's valid: if studentModelFormObj.is_valid(): # 将form中的cleaned_data插入一条记录 studentModelFormObj.save() return HttpResponse("添加成功!") else: return JsonResponse(studentModelFormObj.errors)
模板文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> </head> <body> <hr> <div class="row"> <div class="col-md-8 col-md-offset-2"> <form action="/addstus/" method="post"> {% csrf_token %} {% for studentModelFormField in studentModelFormObj %} <div class="form-group"> <label for="">{{ studentModelFormField.label }}</label> <div> {{ studentModelFormField }}</div> </div> {% endfor %} <input type="submit" class="btn btn-success"> </form> </div> </div> </body> </html>