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的表单验证分为多个层次:
- 字段级验证
- 表单级验证
- 自定义验证器
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})
八、常见问题与解决方案
-
表单验证失败但没有显示错误信息
- 确保在模板中正确显示错误信息
- 检查表单的clean方法是否正确抛出ValidationError
-
CSRF验证失败
- 检查是否包含csrf_token
- 确认CSRF中间件已启用
- 检查会话cookie是否正常工作
-
文件上传失败
- 确保表单包含enctype="multipart/form-data"
- 检查文件大小是否超过限制
- 验证文件类型是否允许
九、今日总结
- 学习了Django表单的基本概念和创建方法
- 掌握了表单验证机制和自定义验证方法
- 理解了CSRF保护的重要性和实现方式
- 学习了ModelForm的使用和表单集的高级特性
十、练习任务
- 创建一个包含文件上传的表单,实现图片预览功能
- 实现一个动态生成字段的表单,并添加相应的验证规则
- 使用表单集实现一个订单系统的表单,包含多个商品项
- 为表单添加自定义的JavaScript验证和实时反馈
怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!