Django formset中每个表单的不同初始数据

时间:2009-12-13 21:09:46

标签: django django-forms

是否可以为每行预填充包含不同数据的formset?我想在上一个视图的隐藏字段中添加一些信息。

根据文档,您只能全面设置。

5 个答案:

答案 0 :(得分:51)

如果你和我犯了同样的错误,你就会误解文件。

当我第一次看到这个例子时......

formset = ArticleFormSet(initial=[
 {'title': 'Django is now open source',
  'pub_date': datetime.date.today(),}
])

我假设每个表单都基于字典给出了相同的初始数据集。

但是,如果你仔细观察,你会发现formset实际上是传递了一个词典列表。

为了在表单集中为每个表单设置不同的初始值,您只需要传递包含不同数据的字典列表。

Formset = formset_factory(SomeForm, extra=len(some_objects)
some_formset = FormSet(initial=[{'id': x.id} for x in some_objects])

答案 1 :(得分:10)

您需要使用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方法的每个评估。我们可以迭代我们喜欢的东西,所以我使用这个事实迭代一组对象并将每个对象的值作为不同的初始参数传递。

答案 2 :(得分:2)

我遇到了这个问题,我制作了一个新的小部件:

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))

也许这对你也有用。

答案 3 :(得分:2)

在Antony Vennard的回答基础上,我不确定他使用的是什么版本的python / django,但我也无法让发电机在咖喱方法中工作。我目前在python2.7.3和django1.5.1上。我没有使用自定义生成器,而是使用内置的iter()来创建迭代器,并在curry方法中传递迭代器本身,并在next()上调用它。 {1}} Form。这是我的解决方案:

__init__()

以表格形式:

# 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上的formset_factory kwarg来指定与您传递的列表对应的列表到迭代器(在上面的例子中,我将my_list_of_things列表的initial传递给'extra'kwarg到formset_factory)。这对于在formset中实际创建许多表单是必要的。

答案 4 :(得分:0)

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 文件中定义的表单或表单集名称