表单支持

Django的forms模块提供了用于处理表单数据的功能,它对表单创建、验证和数据处理进行了封装,使得开发者可以方便地处理表单类型请求,这篇笔记我们对forms模块进行简单介绍。

注意:forms模块通常是和模板引擎结合使用的,和模板引擎技术类似,forms也是个相对过时的技术,它主要用于传统的服务端MVC工程。在前后端分离项目中,数据封装和验证功能通常由DRF的序列化器实现。

表单模块基本使用

我们这里使用一个例子工程,工程目录结构如下,表单类我们这里将其全部放置到forms.py中。

|_ demo01 # APP子模块
    |_ views.py # 视图函数
    |_ models.py # 数据模型
    |_ forms.py # 表单模块
    |_ templates # 模板文件夹
        |_ index.html # 模板文件

demo01/models.py

from django.db import models


class ClassRoom(models.Model):
    class Meta:
        verbose_name = '教室'
        verbose_name_plural = '教室'

    room_code = models.CharField(max_length=10, verbose_name='教室号')

    def __str__(self):
        return self.room_code


class Student(models.Model):
    class Meta:
        verbose_name = '学生'
        verbose_name_plural = '学生'

    stu_code = models.CharField(max_length=10, unique=True, verbose_name='学号')
    name = models.CharField(max_length=20, verbose_name='学生姓名')
    age = models.IntegerField(default=-1, verbose_name='年龄')
    class_room = models.ForeignKey(ClassRoom, null=True, on_delete=models.DO_NOTHING, related_name='students',
                                   verbose_name='所在教室')

数据模型中,我们有ClassRoom教室模型和Student学生模型,它们通过外键字段class_room关联,具有一对多关系。

demo01/forms.py

from django import forms
from demo01.models import *


class StudentForm(forms.Form):
    stu_code = forms.CharField(max_length=10, label='学号')
    name = forms.CharField(max_length=20, label='学生姓名')
    age = forms.IntegerField(label='年龄')
    class_room = forms.ModelChoiceField(queryset=ClassRoom.objects.all(), label='所在教室')

表单类中,我们定义了4个字段,分别是stu_code学号、name姓名、age年龄和class_room所在教室,其中class_room字段对应数据模型的外键字段。对于普通字段我们使用了CharFieldIntegerField表示需要用户输入字符串和数字,外键字段我们使用ModelChoiceField字段类型,它表示一个模型选择字段,queryset参数指定了查询集,这里我们查询了所有教室。表单字段中,我们还用到了max_length命名参数,它用于表单校验,此外在渲染表单时,对应HTML的<input>标签也会添加相关最大长度限制。

demo01/views.py

from django.shortcuts import render

from demo01.forms import StudentForm


def index(request):
    if request.method == 'POST':
        form = StudentForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data.get('stu_code'))
            print(form.cleaned_data.get('name'))
            print(form.cleaned_data.get('age'))
            print(form.cleaned_data.get('class_room').room_code)
            return render(request, 'success.html')
        else:
            return render(request, 'index.html', {
                'form': form
            })
    else:
        form = StudentForm()
        return render(request, 'index.html', {
            'form': form
        })

视图函数index()中,当浏览器发起GET请求时,我们返回index.html模板页面,其中渲染了空表单;当浏览器发起POST请求时,我们使用forms模块自动解析表单请求,如果表单验证通过则重定向到成功页面,如果表单验证不通过则继续将表单传入index.html模板页面,模板会自动回显相关错误信息。由于模板页面上总是会用到form对象,因此其实我们可以看到,代码中任何时候我们都会将forms对象传入模板,GET请求时也会传一个空的form对象,大多数Web开发框架其实都是类似的使用方式。

demo01/templates/index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Student</title>
</head>
<body>
<form method="post">
    {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    <button type="submit">提交</button>
</form>
</body>
</html>

模板中,我们创建了<form>标签,它使用POST提交表单,此外我们没有指定action因此它将默认提交表单到当前路径(如果我们要提交到其他路径则需要指定action)。模板中我们还调用了form.as_table方法,它会将表单渲染成一个表格,最终效果如下图所示。

它实际上渲染的HTML结果如下。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap