Django中如何用前一个HTML表单提交的数据预填充表单?
解决Django 2.2中跨表单预填充字段的问题
嘿,我完全懂你的需求——提交NewCashierForm后,自动把cashier_name和cashier_boxid的值带到NewPersonForm里,避免重复输入对吧?下面给你两种适配Django 2.2的可行方案,都是当前可用的:
方案一:通过URL查询参数传递数据
这种方法简单直接,适合不需要隐藏数据的场景:
1. 修改views.py中的addcashier视图
提交NewCashierForm成功后,重定向到addperson页面时,把需要传递的字段作为查询参数附在URL后面:
from django.urls import reverse from django.http import QueryDict def addcashier(request): if request.method == 'GET': form = NewCashierForm() else: form = NewCashierForm(request.POST) if form.is_valid(): fs = form.save(commit=False) fs.user = request.user fs.save() # 构造要传递的参数并编码 params = QueryDict(mutable=True) params['name'] = fs.cashier_name params['boxid'] = fs.cashier_boxid # 重定向到addperson并带上参数 return redirect(f"{reverse('addperson')}?{params.urlencode()}") return render(request, 'main/addcashier.html', {'form':form})
2. 修改views.py中的addperson视图
在GET请求初始化表单时,读取URL中的查询参数,用initial参数预填充表单:
def addperson(request): if request.method == 'GET': # 从URL参数中获取值,没有的话为空字符串 prefilled_name = request.GET.get('name', '') prefilled_boxid = request.GET.get('boxid', '') # 用initial初始化表单字段 form = NewPersonForm(initial={ 'person_name': prefilled_name, 'person_boxid': prefilled_boxid }) else: form = NewPersonForm(request.POST) if form.is_valid(): fs = form.save(commit=False) fs.user = request.user fs.save() return redirect('/addcashier') return render(request, 'main/addperson.html', {'form':form})
3. 给URL命名(可选但推荐)
在urls.py中给addperson路径加上name属性,方便后续用reverse调用:
from django.urls import path from . import views urlpatterns = [ # 其他路径... path('addcashier/', views.addcashier, name='addcashier'), path('addperson/', views.addperson, name='addperson'), ]
方案二:通过Session存储数据
如果不想把字段值暴露在URL里,可以用Django的Session来临时存储数据:
1. 修改addcashier视图
保存Cashier对象后,把需要传递的数据存入Session:
def addcashier(request): if request.method == 'GET': form = NewCashierForm() else: form = NewCashierForm(request.POST) if form.is_valid(): fs = form.save(commit=False) fs.user = request.user fs.save() # 存入Session临时存储 request.session['cashier_prefill_data'] = { 'name': fs.cashier_name, 'boxid': fs.cashier_boxid } return redirect(reverse('addperson')) return render(request, 'main/addcashier.html', {'form':form})
2. 修改addperson视图
从Session中读取数据预填充表单,用完后记得删除Session中的数据(避免下次访问还带着旧数据):
def addperson(request): prefilled_data = {} # 检查Session中是否有预填充数据 if 'cashier_prefill_data' in request.session: prefilled_data = request.session.pop('cashier_prefill_data') # 取出并删除数据 if request.method == 'GET': form = NewPersonForm(initial={ 'person_name': prefilled_data.get('name', ''), 'person_boxid': prefilled_data.get('boxid', '') }) else: form = NewPersonForm(request.POST) if form.is_valid(): fs = form.save(commit=False) fs.user = request.user fs.save() return redirect('/addcashier') return render(request, 'main/addperson.html', {'form':form})
注意事项
- 两种方案都完全兼容Django 2.2版本,不用担心过时问题;
- 方案一中的
QueryDict.urlencode()会自动处理特殊字符(比如空格、中文)的编码,避免URL乱码; - 方案二中的Session数据会在用户关闭浏览器后自动过期,也可以通过
request.session.set_expiry()手动设置过期时间。
内容的提问来源于stack exchange,提问作者Aleksa Terzic
相关产品推荐
相关产品推荐

