Django笔记
表单功能
一、Django 表单的功能
Django 表单不仅简化了 HTML 表单的生成过程,还提供了数据验证、清理和与数据库模型集成的能力,帮助开发者快速构建安全、高效的表单处理逻辑,同时提供灵活的方式来自定义表单的外观和行为。
功能 | 描述 |
---|---|
自动生成 HTML 表单 | 根据表单字段定义自动生成对应的 HTML 输入元素。 |
数据验证 | 提供内置及自定义的数据验证规则,确保用户输入符合预期格式和要求。 |
数据清理 | 对用户输入的数据进行转换和标准化,以便后续处理。 |
与数据库模型集成 | ModelForm 可以基于现有的数据库模型快速创建表单,并支持数据保存操作。 |
错误信息处理 | 当验证失败时,提供详细的错误信息反馈给用户,帮助其修正输入错误。 |
二、具体介绍
功能一:自动生成 HTML 表单
简介:Django 表单可以根据定义的字段自动创建对应的 HTML 输入元素。这包括文本框、密码框、文本区域等。
示例:
表单定义:forms.py
from django import forms
class MessageBoardForm(forms.Form):
title = forms.CharField(min_length=2, max_length=20, label='标题',
error_messages={
"min_length": '标题最小长度不能小于2',
"max_length": '标题最大长度不能超过20'
})
content = forms.CharField(widget=forms.Textarea, label='内容')
email = forms.EmailField(label='邮箱')
模板渲染:html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>留言板</title>
</head>
<body>
<h1>留言板</h1>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="提交">
</form>
</body>
</html>
效果:
视图函数:views.py
from django.shortcuts import render, HttpResponse
from .forms import MessageBoardForm
# 请求验证装饰器
from django.views.decorators.http import require_http_methods
# Create your views here.
# 请求的method
# 1、GET: 主要用来从服务器获取数据
# 2、POST: 主要用来向服务器提供数据
# 3、PUT/DELETE/HEAD
# 装饰器,用于限制视图函数只接受指定的 HTTP 请求方法,此处是GET和POST
@require_http_methods(['GET', 'POST'])
def index(request):
# 如果用GET请求,直接返回一个页面
if request.method == 'GET':
form = MessageBoardForm()
return render(request, 'index.html', context={'form': form})
# 如果用POST请求提交上来数据,用表单验证是否满足要求
# elif request.method == 'POST': 因为装饰器限制了,所以直接用else就行
else:
form = MessageBoardForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
content = form.cleaned_data['content']
email = form.cleaned_data['email']
return HttpResponse(f"{title}, {content}, {email}")
else:
print(form.errors)
return HttpResponse('表单验证失败!')
功能二:数据验证
简介:Django 表单提供了丰富的验证机制,既包括内置的如必填项、长度限制等,也支持通过自定义函数添加额外的验证逻辑。
示例:
表单定义:forms.py
from django import forms
from django.core import validators
class RegisterForm(forms.Form):
telephone = forms.CharField(validators=[validators.RegexValidator(r'1[3-9]\d{9}',message='输入正确格式的手机号')])
password1 = forms.CharField(min_length=6, max_length=20)
password2 = forms.CharField(min_length=6, max_length=20)
# clean_[field]:对特定字段执行额外的验证或数据处理
def clean_telephone(self):
telephone = self.cleaned_data.get('telephone')
# 从数据库中查找telephone是否存在,如果存在,抛出验证错误
if telephone == '17777777777':
raise forms.ValidationError('手机号码已注册')
else:
return telephone
# clean:跨字段验证
# 验证password1和password2是否一致
def clean(self):
cleaned_data = super().clean()
password1 = cleaned_data.get('password1')
password2 = cleaned_data.get('password2')
if password1 != password2:
raise forms.ValidationError('两次密码不一致')
else:
return cleaned_data
- telephone 字段:使用正则表达式验证器确保用户输入的是符合中国大陆手机号格式的数字。
- password1 和 password2 字段:用于让用户重复输入密码,以确保没有输入错误。
- clean_telephone 方法:在基础验证之后对 telephone 字段进行额外检查,例如检查该电话号码是否已被注册。
- clean 方法:跨字段验证的一个例子,确保两个密码字段输入的内容相同。
前端页面:html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<form action="" method="POST">
{% csrf_token %}
<div>
<input type="text" name="telephone" placeholder="请输入手机号"> <!--此处的name要跟表单中的name保持一致-->
</div>
<div>
<input type="password" name="password1" placeholder="请输入密码">
</div>
<div>
<input type="password" name="password2" placeholder="请验证密码">
</div>
<input type="submit" value="提交">
</form>
</body>
</html>
**注意:**手动创建 HTML 表单元素时,每个 <input>
元素的 name 属性必须与 Django 表单类中的字段名称相匹配。
视图函数:views.py
from django.shortcuts import render, HttpResponse
from .forms import RegisterForm
# 请求验证装饰器
from django.views.decorators.http import require_http_methods
@require_http_methods(['GET', 'POST'])
def register_view(request):
if request.method == 'GET':
return render(request, 'register.html')
else:
form = RegisterForm(request.POST)
if form.is_valid():
telephone = form.cleaned_data.get('telephone')
return HttpResponse(telephone)
else:
# print(form.errors)
# <ul class="errorlist"><li>__all__<ul class="errorlist nonfield"><li>两次密码不一致</li></ul></li></ul>
# print(form.errors.get_json_data())
# {'__all__': [{'message': '两次密码不一致', 'code': ''}]}
print(form.errors.as_json())
# {"__all__": [{"message": "\u4e24\u6b21\u5bc6\u7801\u4e0d\u4e00\u81f4", "code": ""}]}
return HttpResponse('表单验证失败')
@require_http_methods([‘GET’, ‘POST’]):装饰器限制了视图仅响应 GET 和 POST 请求。
if request.method == ‘GET’:当请求方法为 GET 时,渲染并返回注册页面。
else (即 POST 请求):创建一个 RegisterForm 实例,并传入 request.POST 数据。如果表单有效,则提取并处理数据;否则打印错误信息并返回“表单验证失败”的消息给客户端。
三种不同的输出 Django 表单验证错误信息的方法及其特点和适用场景:
方法 输出类型 特点描述 适用场景 print(form.errors)
HTML字符串 返回一个包含所有错误信息的 ErrorDict
对象,并以HTML列表的形式展示。适合直接嵌入到模板中用于向用户显示错误信息。直接在网页上呈现错误信息,方便用户查看。 form.errors.get_json_data()
Python字典 返回一个字典对象,其中包含了所有的错误信息,每个错误信息都是一个字典,包括了错误的 message
和可选的code
。需要将错误信息序列化成 JSON 格式的情况,例如通过 AJAX 请求返回错误信息给前端 JavaScript 处理。 form.errors.as_json()
JSON字符串 直接提供了一个 JSON 格式的字符串,而不是 Python 字典。特别适用于需要直接作为 HTTP 响应返回给客户端的应用场景。注意这里的非ASCII字符会被转义成 Unicode 编码。 适用于构建 API 的响应,或者任何需要直接在网络传输中使用的场合。
功能三:数据清理
简介:除了验证外,Django 表单还负责将用户输入的数据转换为适当的 Python 数据类型,例如日期时间字符串到 datetime
对象的转换。
示例:
表单定义:forms.py
from django import forms
class DateInputForm(forms.Form):
birth_date = forms.DateField(input_formats=['%Y-%m-%d'], label="出生日期")
def clean_birth_date(self):
data = self.cleaned_data['birth_date']
# 假设我们希望用户年龄至少为18岁
from datetime import date
today = date.today()
age = today.year - data.year - ((today.month, today.day) < (data.month, data.day))
if age < 18:
raise forms.ValidationError("您必须年满18岁才能注册。")
return data
功能四:与数据库模型集成 (ModelForm
)
简介:ModelForm
是一种特殊类型的表单,可以直接基于数据库模型生成表单,并简化了从表单到数据库的操作流程。
示例:
模型定义:models.py
from django.db import models
from django.core import validators
class Article(models.Model):
title = models.CharField(max_length=200, validators=[validators.MinLengthValidator(limit_value=2)])
content = models.TextField(validators=[validators.MinLengthValidator(limit_value=3)])
# 指定了auto_now_add=True,那么在表单中可以不用传入这个字段
creat_time = models.DateTimeField(auto_now_add=True)
# blank=True 代表表单验证时允许为空,不代表数据库可以为空
category = models.CharField(max_length=200, blank=False)
- title 和 content 字段都带有长度验证器。
- creat_time 使用 auto_now_add=True 自动设置创建时间,无需在表单中显示或提供输入。
- category 字段设置为不允许在表单中为空(通过 blank=False),但没有指定是否可以在数据库中为空。
表单定义:forms.py
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
# fields 属性的作用是明确指定哪些模型字段应包含在表单中进行展示、验证和数据处理
fields = '__all__'
# fields = ['title', 'content']
# exclude : 如果不想验证某些字段可以用exclude
# exclude = ['category']
# 自定义错误信息
error_messages = {
'category': {
'required': 'category不能为空'
}
}
# <ul class="errorlist"><li>category<ul class="errorlist" id="id_category_error"><li>category不能为空</li></ul></li></ul>
- 使用
fields = '__all__'
包含所有模型字段,或者你可以明确列出你想要包含的字段。 - error_messages 允许你为特定字段定制错误信息,这里为 category 字段指定了一个自定义的“必填”错误信息。
前端页面:html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>article</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<div>
<input type="text" name="title" placeholder="请输入标题">
</div>
<div>
<textarea name="content" placeholder="请输入内容" cols="30" rows="10"></textarea>
</div>
<div>
<input type="submit" value="提交">
</div>
</form>
</body>
</html>
视图函数:views.py
from django.shortcuts import render, HttpResponse
from .forms import ArticleForm
# 请求验证装饰器
from django.views.decorators.http import require_http_methods
@require_http_methods(['GET', 'POST'])
def article_view(request):
if request.method == 'GET':
return render(request, 'article.html')
else:
form = ArticleForm(request.POST)
if form.is_valid():
# 获取title和content以及create_time,然后创建article模型对象,在存储到数据库中
title = form.cleaned_data.get('title')
content = form.cleaned_data.get('content')
return HttpResponse(f"{title}, {content}")
else:
print(form.errors)
return HttpResponse('表单验证失败')
- 当请求方法为 GET 时,渲染并返回注册页面
- 在 POST 请求中,创建了一个 ArticleForm 实例并传入 request.POST 数据。
- 如果表单有效,则调用 form.save() 方法将数据保存到数据库,并返回确认信息。
- 如果表单无效,则打印错误信息并返回错误响应给用户。