Django类视图下如何传递表单到模板并实现数据存储?
问题解答
现有实现的问题
你当前的实现不符合Django最佳实践,核心问题如下:
- 完全没有用到你定义的
itemCreationForm,也没有做任何数据校验,直接从POST请求取参数写入数据库,会存在非法数据写入的风险,比如空值、超出字段长度限制的内容都可能直接入库引发异常 - 你在
ListView中声明了form_class但没有实际调用,属于无效配置 - POST请求完成后直接返回HttpResponse,不符合表单提交后的最佳实践,容易出现用户刷新页面重复提交表单的问题
正确实现步骤
第一步:修正视图逻辑
你需要重写get_context_data方法把表单注入模板上下文,同时改写POST逻辑用上表单的校验能力,修正后的代码如下:
from django.shortcuts import redirect from django.views.generic import ListView from .models import Item from .forms import itemCreationForm # 建议类名改为大驼峰的ItemCreationForm,符合Python命名规范 class Home(ListView): model = Item template_name = 'home/todo.html' form_class = itemCreationForm # 把表单注入模板上下文,前端就能拿到表单对象 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['form'] = self.form_class() return context def post(self, request, *args, **kwargs): # 用POST请求数据初始化表单 form = self.form_class(request.POST) # 表单校验通过后再存储数据 if form.is_valid(): # ModelForm自带save方法,无需手动调用Item.objects.create form.save() # 重定向到当前页,避免刷新重复提交,此处home替换为你对应路由的name值 return redirect('home') # 校验失败时,把带错误信息的表单传回模板展示 self.object_list = self.get_queryset() context = self.get_context_data(form=form) return self.render_to_response(context)
第二步:模板中渲染表单
在home/todo.html中加入表单渲染逻辑即可,示例如下:
<form method="post"> {% csrf_token %} <!-- 快速渲染表单,也可以逐个字段自定义样式 --> {{ form.as_p }} <button type="submit">提交</button> <!-- 展示校验错误信息 --> {% if form.errors %} <div class="error-tips"> {% for field in form %} {% for error in field.errors %} <p>{{ field.label }}: {{ error }}</p> {% endfor %} {% endfor %} </div> {% endif %} </form> <!-- 原有列表展示逻辑无需修改 --> {% for item in object_list %} <p>{{ item.name }}</p> {% endfor %}
内容的提问来源于stack exchange,提问作者Kay
相关产品推荐
相关产品推荐

