Django:如何使用 formset extra 更改标签?
Posted
技术标签:
【中文标题】Django:如何使用 formset extra 更改标签?【英文标题】:Django: how to change label using formset extra? 【发布时间】:2013-01-04 09:49:15 【问题描述】:我使用formset生成额外字段,但我不知道如何更改formset生成的额外字段的标签。
我的代码:
class GetMachine(forms.Form):
Number_of_Lines = forms.IntegerField(max_value=4)
class GetLine(forms.Form):
beamline_name = forms.CharField(max_length=15, label='Name of Beamline-%i')
def install(request):
MachineFormSet = formset_factory(GetMachine, extra=1)
formset = MachineFormSet()
if request.method == 'POST':
# formset = MachineFormSet(request.POST)
# if formset.is_valid(): # All validation rules pass
line_no = request.POST['form-0-Number_of_Lines']
GetLineFormSet = formset_factory(GetLine, extra=int(line_no))
formset = GetLineFormSet()
return render_to_response('install.html', 'formset': formset, 'action': 'step1')
return render_to_response('install.html', 'formset': formset, )
install.html 模板:
% for form in formset.forms %
% for field in form %
<tr>
<td> field.label_tag </td> <td> field </td><td> field.errors </td>
</tr>
% endfor %
% endfor %
例如,如果 "Number_of_Lines" = 2,那么我期望下一个带有标签的表单,
Name of Beamline-1:
Name of Beamline-2:
【问题讨论】:
【参考方案1】:我假设您希望第一个表单的结果确定第二个表单的字段数及其标签,您可能需要查看Django form wizards。但这是一种简单的非表单向导(可能不太理想/可维护)的方法,利用表单集的__init__
方法来修改表单标签*:
forms.py:
# File: forms.py
from django import forms
from django.forms.formsets import BaseFormSet
# What you've called 'GetMachine'
class MachineForm(forms.Form):
no_of_lines = forms.IntegerField(max_value=4)
# What you've called 'GetLine'
class LineForm(forms.Form):
beamline_name = forms.CharField(max_length=15, label='Name of Beamline')
# Create a custom formset and override __init__
class BaseLineFormSet(BaseFormSet):
def __init__(self, *args, **kwargs):
super(BaseLineFormSet, self).__init__(*args, **kwargs)
no_of_forms = len(self)
for i in range(0, no_of_forms):
self[i].fields['beamline_name'].label += "-%d" % (i + 1)
views.py:
# File: views.py
from django.forms.formsets import formset_factory
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from forms import MachineForm, LineForm, BaseLineFormSet
def get_no_of_lines(request):
if request.method == 'POST':
machine_form = MachineForm(request.POST)
if machine_form.is_valid():
# At this point, form fields have already been
# converted to Python data types :)
# so no need to convert `line_no` to an integer
no_of_lines = machine_form.cleaned_data['no_of_lines']
return HttpResponseRedirect(reverse('line_form', kwargs='no_of_lines': no_of_lines))
else:
# It looks to me like you probably don't mean to
# use formsets here (but a form instead)
machine_form = MachineForm()
c = RequestContext(request,
'machine_form': machine_form,
)
return render_to_response('get_no_of_lines.html', c)
def line_form(request, no_of_lines):
# You probably should validate this number (again).
# In fact, you probably need to validate first form (MachineForm).
# ...But I'm assuming it'll be valid in this example.
no_of_lines = int(no_of_lines)
LineFormSet = formset_factory(LineForm, extra=no_of_lines, formset=BaseLineFormSet)
if request.method == "POST":
formset = LineFormSet(request.POST, request.FILES)
if formset.is_valid():
pass
# Do stuff with form submission
# Redirect
else:
formset = LineFormSet()
c = RequestContext(request,
'formset': formset,
)
return render_to_response('line_form.html', c)
urls.py:
from django.conf.urls import url, patterns
from views import get_no_of_lines, line_form
urlpatterns = patterns('',
url(r'^$', get_no_of_lines, name='get_no_of_lines'),
url(r'^line_form/(?P<no_of_lines>\d1)$', line_form, name='line_form'),
)
get_no_of_lines.html:
<form method="POST">
% csrf_token %
machine_form
</form>
line_form.html:
<form method="POST">
% csrf_token %
formset.as_p
我之所以说这种方法可能不是最好的方法是因为你必须验证 no_of_lines
被传递给 line_form
视图(可能 > 4,所以你必须执行验证在这里并介绍验证逻辑,而不是把它放在一个地方——表单)。如果您需要在第一个表单中添加一个新字段,您可能最终不得不修改代码。因此,为什么我建议您查看form wizards。
如需更多或动态表单,请查看Jacob Kaplan-Moss's post on dynamic form generation。
【讨论】:
【参考方案2】:我能想到的唯一方法是在将 FormSet 传递给您的模板之前在您的视图中调整它。
您可以遍历不同的表单和标签并相应地更改它们的值。
另一种可能的解决方案是将默认标签设置为“光束线名称-”。 在您的模板中执行类似
% for field in form %
<td> field.label_tag forloop.counter1 </td>
% endfor %
【讨论】:
我使用了 counter 它对两个标签都显示 1,1,如果我使用 counter1 没有任何反应,如果我使用 counter0 它对两个标签都显示 0,0。我不明白为什么会这样!以上是关于Django:如何使用 formset extra 更改标签?的主要内容,如果未能解决你的问题,请参考以下文章
Django Formset.is_valid() 额外表单失败
Django-Dynamic Form在formset中添加的每个新输入元素的增量ID
与 django-dynamic-formset 一起使用的 Django Formset 不显示删除链接
Django 和 jQuery.formset,如何操作删除按钮位置