Skip to content

第8章:Django表单(Forms)

8.1 表单基础

Form类定义

Django表单系统提供了一种强大且灵活的方式来处理HTML表单。表单类继承自django.forms.Form,用于定义表单字段和验证逻辑。

基本的表单类定义:

python
from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    subject = forms.CharField(max_length=200)
    message = forms.CharField(widget=forms.Textarea)

表单字段类型

Django提供了多种内置表单字段类型,每种类型都有特定的验证规则:

python
from django import forms
from django.core.validators import RegexValidator

class ExampleForm(forms.Form):
    # 字符串字段
    name = forms.CharField(
        max_length=100,
        min_length=2,
        label='姓名',
        help_text='请输入您的真实姓名'
    )
    
    # 邮箱字段
    email = forms.EmailField(
        label='邮箱地址',
        help_text='请输入有效的邮箱地址'
    )
    
    # 整数字段
    age = forms.IntegerField(
        min_value=0,
        max_value=150,
        label='年龄'
    )
    
    # 浮点数字段
    salary = forms.FloatField(
        min_value=0,
        label='薪资'
    )
    
    # URL字段
    website = forms.URLField(
        required=False,
        label='个人网站'
    )
    
    # 日期字段
    birth_date = forms.DateField(
        label='出生日期',
        widget=forms.DateInput(attrs={'type': 'date'})
    )
    
    # 日期时间字段
    appointment = forms.DateTimeField(
        label='预约时间'
    )
    
    # 布尔字段
    subscribe = forms.BooleanField(
        required=False,
        label='订阅邮件'
    )
    
    # 选择字段
    GENDER_CHOICES = [
        ('male', '男'),
        ('female', '女'),
        ('other', '其他')
    ]
    gender = forms.ChoiceField(
        choices=GENDER_CHOICES,
        label='性别'
    )
    
    # 多选字段
    INTERESTS_CHOICES = [
        ('tech', '科技'),
        ('sports', '体育'),
        ('music', '音乐'),
        ('travel', '旅行')
    ]
    interests = forms.MultipleChoiceField(
        choices=INTERESTS_CHOICES,
        widget=forms.CheckboxSelectMultiple,
        label='兴趣爱好'
    )
    
    # 文件字段
    avatar = forms.ImageField(
        required=False,
        label='头像'
    )
    
    # 自定义验证字段
    phone = forms.CharField(
        validators=[RegexValidator(
            regex=r'^\+?1?\d{9,15}$',
            message="请输入有效的手机号码"
        )],
        label='手机号码'
    )

表单验证

Django表单提供了多种验证机制:

  1. 字段级别的验证
  2. 表单级别的验证
  3. 自定义验证方法
python
from django import forms
from django.core.exceptions import ValidationError

class RegistrationForm(forms.Form):
    username = forms.CharField(max_length=150)
    email = forms.EmailField()
    password = forms.CharField(widget=forms.PasswordInput)
    password_confirm = forms.CharField(widget=forms.PasswordInput)
    
    def clean_username(self):
        """验证用户名是否已存在"""
        username = self.cleaned_data['username']
        if User.objects.filter(username=username).exists():
            raise ValidationError("用户名已存在")
        return username
    
    def clean_email(self):
        """验证邮箱是否已存在"""
        email = self.cleaned_data['email']
        if User.objects.filter(email=email).exists():
            raise ValidationError("邮箱已被注册")
        return email
    
    def clean(self):
        """表单整体验证"""
        cleaned_data = super().clean()
        password = cleaned_data.get('password')
        password_confirm = cleaned_data.get('password_confirm')
        
        if password and password_confirm and password != password_confirm:
            raise ValidationError("两次输入的密码不一致")
        
        return cleaned_data

表单渲染

Django提供了多种方式来渲染表单:

html
<!-- forms.py -->
from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    subject = forms.CharField(max_length=200)
    message = forms.CharField(widget=forms.Textarea)

<!-- views.py -->
from django.shortcuts import render
from .forms import ContactForm

def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            # 处理表单数据
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            # 发送邮件等操作
            return render(request, 'contact_success.html')
    else:
        form = ContactForm()
    
    return render(request, 'contact.html', {'form': form})

<!-- contact.html -->
<form method="post">
    {% csrf_token %}
    
    <!-- 方式1:手动渲染每个字段 -->
    <div>
        <label for="{{ form.name.id_for_label }}">姓名:</label>
        {{ form.name }}
        {% if form.name.errors %}
            <div class="error">{{ form.name.errors }}</div>
        {% endif %}
    </div>
    
    <!-- 方式2:使用表单的as_p方法 -->
    {{ form.as_p }}
    
    <!-- 方式3:使用表单的as_table方法 -->
    <table>
        {{ form.as_table }}
    </table>
    
    <!-- 方式4:使用表单的as_ul方法 -->
    <ul>
        {{ form.as_ul }}
    </ul>
    
    <button type="submit">提交</button>
</form>

<!-- 方式5:循环渲染字段 -->
<form method="post">
    {% csrf_token %}
    {% for field in form %}
        <div class="form-group">
            {{ field.label_tag }}
            {{ field }}
            {% if field.errors %}
                <div class="error">
                    {% for error in field.errors %}
                        <p>{{ error }}</p>
                    {% endfor %}
                </div>
            {% endif %}
            {% if field.help_text %}
                <small class="help-text">{{ field.help_text }}</small>
            {% endif %}
        </div>
    {% endfor %}
    <button type="submit">提交</button>
</form>

在模板中使用CSS类和属性:

python
# forms.py
class StyledForm(forms.Form):
    name = forms.CharField(
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '请输入姓名'
        })
    )
    email = forms.EmailField(
        widget=forms.EmailInput(attrs={
            'class': 'form-control',
            'placeholder': '请输入邮箱'
        })
    )

通过这种方式,你可以创建功能完整、验证完善的表单系统。

小结

Django表单基础是Web应用交互的核心:

  1. ✅ Form类定义表单结构和验证规则
  2. ✅ 多种字段类型满足不同数据需求
  3. ✅ 多层次验证机制确保数据有效性
  4. ✅ 灵活的表单渲染方式
  5. ✅ 与Bootstrap等CSS框架的良好集成

掌握表单基础是构建用户交互功能的前提。

下一篇

我们将学习ModelForm的使用。

8.2 模型表单 →

目录

返回课程目录

Released under the Apache 2.0 License.