每天40分玩转Django:Django表单

Django表单

一、今日学习内容概述

学习模块 重要程度 预计学时
表单基础与创建 ⭐⭐⭐⭐⭐ 1.5小时
表单验证机制 ⭐⭐⭐⭐⭐ 2小时
CSRF保护机制 ⭐⭐⭐⭐⭐ 1.5小时
表单渲染与处理 ⭐⭐⭐⭐ 1小时

二、Django表单基础知识

Django的表单处理是Web应用程序中最重要的部分之一,它提供了一种方便的方式来处理用户输入数据。表单不仅包括HTML表单,还包括验证逻辑和数据处理逻辑。

2.1 创建表单类

让我们通过一个实际的例子来学习Django表单。假设我们要创建一个用户注册表单:

python 复制代码
# forms.py
from django import forms

class UserRegistrationForm(forms.Form):
    username = forms.CharField(
        label='用户名',
        max_length=100,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '请输入用户名'
        })
    )
    email = forms.EmailField(
        label='电子邮件',
        widget=forms.EmailInput(attrs={
            'class': 'form-control',
            'placeholder': '请输入邮箱'
        })
    )
    password = forms.CharField(
        label='密码',
        min_length=6,
        widget=forms.PasswordInput(attrs={
            'class': 'form-control',
            'placeholder': '请输入密码'
        })
    )
    confirm_password = forms.CharField(
        label='确认密码',
        min_length=6,
        widget=forms.PasswordInput(attrs={
            'class': 'form-control',
            'placeholder': '请再次输入密码'
        })
    )
    
    def clean(self):
        cleaned_data = super().clean()
        password = cleaned_data.get('password')
        confirm_password = cleaned_data.get('confirm_password')
        
        if password and confirm_password and password != confirm_password:
            raise forms.ValidationError('两次输入的密码不匹配')
        
        return cleaned_data

2.2 视图处理表单

python 复制代码
# views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegistrationForm

def register(request):
    if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            # 获取清理后的数据
            cleaned_data = form.cleaned_data
            # 这里可以添加用户注册逻辑
            messages.success(request, '注册成功!')
            return redirect('login')
    else:
        form = UserRegistrationForm()
    
    return render(request, 'registration/register.html', {'form': form})

2.3 模板展示表单

html 复制代码
<!-- templates/registration/register.html -->
{% extends 'base.html' %}

{% block content %}
<div class="container mt-5">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card">
                <div class="card-header">
                    <h3 class="text-center">用户注册</h3>
                </div>
                <div class="card-body">
                    <form method="post" novalidate>
                        {% csrf_token %}
                        
                        {% if form.non_field_errors %}
                        <div class="alert alert-danger">
                            {% for error in form.non_field_errors %}
                                {{ error }}
                            {% endfor %}
                        </div>
                        {% endif %}
                        
                        {% for field in form %}
                        <div class="form-group mb-3">
                            {{ field.label_tag }}
                            {{ field }}
                            {% if field.errors %}
                            <div class="alert alert-danger mt-1">
                                {{ field.errors }}
                            </div>
                            {% endif %}
                        </div>
                        {% endfor %}
                        
                        <button type="submit" class="btn btn-primary w-100">注册</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

三、表单验证机制

Django的表单验证分为多个层次:

  1. 字段级验证
  2. 表单级验证
  3. 自定义验证器

3.1 字段级验证

python 复制代码
# forms.py
from django import forms
import re

def validate_chinese_phone(value):
    pattern = r'^1[3-9]\d{9}$'
    if not re.match(pattern, value):
        raise forms.ValidationError('请输入有效的中国手机号码')

class ContactForm(forms.Form):
    name = forms.CharField(
        min_length=2,
        max_length=50,
        error_messages={
            'required': '姓名不能为空',
            'min_length': '姓名长度不能小于2个字符',
            'max_length': '姓名长度不能超过50个字符'
        }
    )
    phone = forms.CharField(
        validators=[validate_chinese_phone],
        error_messages={
            'required': '手机号码不能为空'
        }
    )
    
    def clean_name(self):
        name = self.cleaned_data['name']
        if name.isdigit():
            raise forms.ValidationError('姓名不能为纯数字')
        return name

3.2 表单级验证

python 复制代码
def clean(self):
    cleaned_data = super().clean()
    name = cleaned_data.get('name')
    phone = cleaned_data.get('phone')
    
    # 示例:检查特定组合条件
    if name and phone:
        if name.lower() in phone:
            raise forms.ValidationError('手机号码不能包含姓名')
    
    return cleaned_data

四、CSRF保护机制

CSRF(Cross-Site Request Forgery)跨站请求伪造是一种常见的Web安全漏洞。Django内置了CSRF保护机制。

4.1 CSRF中间件配置

python 复制代码
# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',  # CSRF中间件
    ...
]

4.2 CSRF令牌使用

在模板中使用CSRF令牌:

html 复制代码
<form method="post">
    {% csrf_token %}
    <!-- 表单字段 -->
</form>

对于AJAX请求,需要在请求头中包含CSRF令牌:

javascript 复制代码
// 获取CSRF令牌
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;

// 发送AJAX请求
fetch('/api/endpoint/', {
    method: 'POST',
    headers: {
        'X-CSRFToken': csrftoken,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
})

五、ModelForm使用

ModelForm是Django提供的一种特殊表单类,它可以直接从模型创建表单。

python 复制代码
# models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200, verbose_name='标题')
    content = models.TextField(verbose_name='内容')
    published_date = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
    
    class Meta:
        verbose_name = '文章'
        verbose_name_plural = verbose_name

# forms.py
from django.forms import ModelForm
from .models import Article

class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content']
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'content': forms.Textarea(attrs={'class': 'form-control'})
        }
        error_messages = {
            'title': {
                'required': '标题不能为空',
                'max_length': '标题长度不能超过200个字符'
            },
            'content': {
                'required': '内容不能为空'
            }
        }

六、表单处理流程图

七、表单高级特性

7.1 动态表单字段

python 复制代码
class DynamicForm(forms.Form):
    def __init__(self, *args, **kwargs):
        extra_fields = kwargs.pop('extra_fields', {})
        super().__init__(*args, **kwargs)
        
        for field_name, field_type in extra_fields.items():
            self.fields[field_name] = field_type

7.2 表单集(Formset)使用

python 复制代码
from django.forms import formset_factory

class ItemForm(forms.Form):
    name = forms.CharField(max_length=100)
    quantity = forms.IntegerField(min_value=0)

# 创建表单集
ItemFormSet = formset_factory(ItemForm, extra=2, max_num=10)

# 视图中使用
def manage_items(request):
    if request.method == 'POST':
        formset = ItemFormSet(request.POST)
        if formset.is_valid():
            for form in formset:
                if form.cleaned_data:
                    # 处理每个表单的数据
                    pass
    else:
        formset = ItemFormSet()
    return render(request, 'manage_items.html', {'formset': formset})

八、常见问题与解决方案

  1. 表单验证失败但没有显示错误信息

    • 确保在模板中正确显示错误信息
    • 检查表单的clean方法是否正确抛出ValidationError
  2. CSRF验证失败

    • 检查是否包含csrf_token
    • 确认CSRF中间件已启用
    • 检查会话cookie是否正常工作
  3. 文件上传失败

    • 确保表单包含enctype="multipart/form-data"
    • 检查文件大小是否超过限制
    • 验证文件类型是否允许

九、今日总结

  1. 学习了Django表单的基本概念和创建方法
  2. 掌握了表单验证机制和自定义验证方法
  3. 理解了CSRF保护的重要性和实现方式
  4. 学习了ModelForm的使用和表单集的高级特性

十、练习任务

  1. 创建一个包含文件上传的表单,实现图片预览功能
  2. 实现一个动态生成字段的表单,并添加相应的验证规则
  3. 使用表单集实现一个订单系统的表单,包含多个商品项
  4. 为表单添加自定义的JavaScript验证和实时反馈

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

相关推荐
SomeB1oody32 分钟前
【Rust自学】3.5. 控制流:if else
开发语言·后端·rust
TenniCC1 小时前
python 中使用pip操作flask离线下载(包含依赖包下载)和安装
python·flask·pip
宸码1 小时前
【机器学习】【集成学习——决策树、随机森林】从零起步:掌握决策树、随机森林与GBDT的机器学习之旅
人工智能·python·算法·决策树·随机森林·机器学习·集成学习
Mobius80862 小时前
探索 Seaborn Palette 的奥秘:为数据可视化增色添彩
图像处理·python·信息可视化·数据分析·pandas·matplotlib·数据可视化
Java Fans2 小时前
构建树莓派温湿度监测系统:从硬件到软件的完整指南
java·后端·struts
星霜旅人2 小时前
【Python】pandas库---数据分析
python
小陈phd3 小时前
深度学习之目标检测——RCNN
python·深度学习·算法·计算机视觉
好奇的菜鸟4 小时前
Rust操作符和符号全解析
开发语言·后端·rust
从以前4 小时前
Python 爱心代码实现动态爱心图案展示
python