【发布时间】:2010-12-26 05:56:03
【问题描述】:
是否可以为每行预填充不同数据的表单集?我想将一些信息放在以前视图的隐藏字段中。
根据文档,您只能全面设置初始值。
【问题讨论】:
标签: django django-forms
是否可以为每行预填充不同数据的表单集?我想将一些信息放在以前视图的隐藏字段中。
根据文档,您只能全面设置初始值。
【问题讨论】:
标签: django django-forms
formset = BookFormset(request.GET or None,initial=[{'formfield1': x.modelfield_name1,'formfield2':x.modelfield_name2} for x in model])
formfield1,formfield2 是表单域的名称。
modelfield_name1,modelfield_name2 是模态字段名称。
model 是 models.py 文件中模态类的名称。
BookFormset 是您的 forms.py 文件中定义的表单或表单集名称
【讨论】:
如果你和我一样犯了同样的错误,那你只是稍微弄错了文档。
当我第一次看到这个例子时......
formset = ArticleFormSet(initial=[
{'title': 'Django is now open source',
'pub_date': datetime.date.today(),}
])
我假设每个表单都根据字典获得相同的初始数据集。
但是,如果您仔细观察,您会发现表单集实际上是通过字典列表传递的。
为了在表单集中为每个表单设置不同的初始值,您只需要传递包含不同数据的字典列表。
Formset = formset_factory(SomeForm, extra=len(some_objects)
some_formset = FormSet(initial=[{'id': x.id} for x in some_objects])
【讨论】:
ArticleFormSet 成为unbound form,因为初始值将覆盖从文章查询集返回的值。
{'id': x.id}而不是{'id': 'x.id'}
基于 Antony Vennard 的回答,我不确定他使用的是什么版本的 python/django,但我也无法让生成器在 curry 方法中工作。我目前在 python2.7.3 和 django1.5.1 上。我最终没有使用自定义生成器,而是在事物列表中使用内置 iter() 创建迭代器,并在 curry 方法中传递迭代器本身,并在 Form @987654324 中调用 next() @。这是我的解决方案:
# Build the Formset:
my_iterator = iter(my_list_of_things) # Each list item will correspond to a form.
Formset = formset_factory(MyForm, extra=len(my_list_of_things))
Formset.form = staticmethod(curry(MyForm, item_iterator=my_iterator))
形式如下:
# forms.py
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
# Calling next() on the iterator/generator here:
list_item = kwargs.pop('item_iterator').next()
# Now you can assign whatever you passed in to an attribute
# on one of the form elements.
self.fields['my_field'].initial = list_item
我发现的一些关键事情是您需要在 formset_factory 中指定一个“额外”值,或者在表单集上使用 initial kwarg 来指定一个与您传递给迭代器的列表相对应的列表(在上面的示例中,我将 my_list_of_things 列表的 len() 传递给“额外”kwarg 到 formset_factory)。这是在表单集中实际创建多个表单所必需的。
【讨论】:
我遇到了这个问题,我制作了一个新的小部件:
from django.forms.widgets import Select
from django.utils.safestring import mark_safe
class PrepolutatedSelect(Select):
def render(self, name, value, attrs=None, choices=()):
if value is None: value = ''
if value == '':
value = int(name.split('-')[1])+1
final_attrs = self.build_attrs(attrs, name=name)
output = [u'<select%s>' % flatatt(final_attrs)]
options = self.render_options(choices, [value])
if options:
output.append(options)
output.append('</select>')
return mark_safe(u'\n'.join(output))
也许这对你也有用。
【讨论】:
您需要使用this post 中描述的技术才能将参数传入。感谢该作者的出色帖子。您可以通过几个部分来实现这一点:
知道它会获取额外参数的表单
来自链接问题的示例:
def __init__(self, *args, **kwargs):
someeobject = kwargs.pop('someobject')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["somefield"].queryset = ServiceOption.objects.filter(
somem2mrel=someobject)
或者您可以将后面的代码替换为
self.fields["somefield"].initial = someobject
直接,它的工作原理。
柯里化表单初始化设置:
formset = formset_factory(Someform, extra=3)
formset.form = staticmethod(curry(someform, somem2mrel=someobject))
这使您可以传递自定义表单参数。现在你需要的是:
获取不同初始参数的生成器
我正在使用这个:
def ItemGenerator(Item):
i = 0
while i < len(Item):
yield Item[i]
i += 1
现在,我可以这样做了:
iterdefs = ItemGenerator(ListofItems) # pass the different parameters
# as an object here
formset.form = staticmethod(curry(someform, somem2mrel=iterdefs.next()))
嘿,转眼间。 form 方法的每次评估都在传递迭代参数的部分中进行评估。我们可以迭代我们喜欢的东西,所以我使用这个事实来迭代一组对象并将每个对象的值作为不同的初始参数传递。
【讨论】:
DecorationFileFormSet.form = staticmethod(curry(DecorationFileForm, filetype=counter.next())) 每次创建文件类型属性为 1 的表单。计数器是itertools.count(1) 的一个实例