Django表单
一、今日学习内容概述
学习模块 | 重要程度 | 预计学时 |
---|---|---|
表单基础与创建 | ⭐⭐⭐⭐⭐ | 1.5小时 |
表单验证机制 | ⭐⭐⭐⭐⭐ | 2小时 |
CSRF保护机制 | ⭐⭐⭐⭐⭐ | 1.5小时 |
表单渲染与处理 | ⭐⭐⭐⭐ | 1小时 |
二、Django表单基础知识
Django的表单处理是Web应用程序中最重要的部分之一,它提供了一种方便的方式来处理用户输入数据。表单不仅包括HTML表单,还包括验证逻辑和数据处理逻辑。
2.1 创建表单类
让我们通过一个实际的例子来学习Django表单。假设我们要创建一个用户注册表单:
python"># forms.py
from django import formsclass 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 UserRegistrationFormdef 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 模板展示表单
<!-- 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的表单验证分为多个层次:
- 字段级验证
- 表单级验证
- 自定义验证器
3.1 字段级验证
python"># forms.py
from django import forms
import redef 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令牌:
<form method="post">{% csrf_token %}<!-- 表单字段 -->
</form>
对于AJAX请求,需要在请求头中包含CSRF令牌:
// 获取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 modelsclass 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 Articleclass ArticleForm(ModelForm):class Meta:model = Articlefields = ['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_factoryclass 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:# 处理每个表单的数据passelse:formset = ItemFormSet()return render(request, 'manage_items.html', {'formset': formset})
八、常见问题与解决方案
-
表单验证失败但没有显示错误信息
- 确保在模板中正确显示错误信息
- 检查表单的clean方法是否正确抛出ValidationError
-
CSRF验证失败
- 检查是否包含csrf_token
- 确认CSRF中间件已启用
- 检查会话cookie是否正常工作
-
文件上传失败
- 确保表单包含enctype=“multipart/form-data”
- 检查文件大小是否超过限制
- 验证文件类型是否允许
九、今日总结
- 学习了Django表单的基本概念和创建方法
- 掌握了表单验证机制和自定义验证方法
- 理解了CSRF保护的重要性和实现方式
- 学习了ModelForm的使用和表单集的高级特性
十、练习任务
- 创建一个包含文件上传的表单,实现图片预览功能
- 实现一个动态生成字段的表单,并添加相应的验证规则
- 使用表单集实现一个订单系统的表单,包含多个商品项
- 为表单添加自定义的JavaScript验证和实时反馈
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!