将initial传递给Django的ModelFormSet

Vin*_*nce 22 django

我有一个模型formset,我需要传递关键字initial in(在formset中有一些初始值,例如设置为今天的日期).据我所知,queryset参数(默认为YourModel.objects.all())会覆盖此功能,以便创建初始空表单.我将查询集指定为:YourModel.objects.none(),它阻止它使用数据库中的条目填充formset,但我仍然无法弄清楚如何有效地传递initial.我是否需要从ModelForm子类化方法?

sim*_*rsh 11

您正在将空的查询集传递给ModelFormset.

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2)
formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(),
                          initial=[{'name': 'Some Name'},
                                   {'name': 'Another Name'}])
Run Code Online (Sandbox Code Playgroud)

这确实是达到你想要的方式.传递空的查询集是有意义的,否则初始值将覆盖模型的数据库值.

如果我想,你传递一个非空的查询集,但是希望你的额外表单填充初始值,你可以覆盖Formset.

from django.forms.models import modelformset_factory  
ExampleFormset = modelformset_factory(OpenIDProfile, extra=3)

class myFormset(ExampleFormset):

    def _construct_form(self, i, **kwargs):
        """
        Instantiates and returns the i-th form instance in a formset.
        """
        if self.is_bound and i < self.initial_form_count():
            pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
            pk = self.data[pk_key]
            pk_field = self.model._meta.pk
            pk = pk_field.get_db_prep_lookup('exact', pk)
            if isinstance(pk, list):
                pk = pk[0]
            kwargs['instance'] = self._existing_object(pk)
        if i < self.initial_form_count() and not kwargs.get('instance'):
            kwargs['instance'] = self.get_queryset()[i]

        defaults = {'auto_id': self.auto_id, 'prefix': self.add_prefix(i)}
        if self.data or self.files:
            defaults['data'] = self.data
            defaults['files'] = self.files
        # Check to confirm we are not overwriting the database value.
        if not i in range(self.initial_form_count()) and self.initial:
            try:
                defaults['initial'] = self.initial[i - self.initial_form_count()]
            except IndexError:
                pass
        # Allow extra forms to be empty.
        if i >= self.initial_form_count():
            defaults['empty_permitted'] = True
        defaults.update(kwargs)
        form = self.form(**defaults)
        self.add_fields(form, i)        
        return form
Run Code Online (Sandbox Code Playgroud)

注意:initial是dicts列表.它希望列表中的项目与额外的数量完全相等.

  • 让我来到这里的一个技巧是,您必须设置额外大于或等于初始数据中的元素数。我知道它在您的答案中,但我认为值得强调。 (2认同)

Ane*_*pic 9

Django 1.4中的新功能...如果你在一个modelformset上设置了初始值,它现在只适用于'extra'表单,而不是那些绑定到queryset实例的表单:

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values

所以上面的各种黑客不再是必要的,使用initial就是答案.


Cha*_*had 5

我发现最好的方法是在初始化后手动调整表单对象的“额外”属性。这已经过测试,可以在Django 1.9中使用。

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1)
formset = ExampleModelFormSet(initial=[{'name': 'Some Name'},
                                       {'name': 'Another Name'}])
formset.extra = 3
Run Code Online (Sandbox Code Playgroud)

这将吐出3种形式(2种预填充和1种空白)。

如果您想要更动态的内容(例如initial,在其他位置计算出的var),则可以执行以下操作:

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1)
formset = ExampleModelFormSet(initial=initial)
formset.extra += len(initial)
Run Code Online (Sandbox Code Playgroud)

希望能有所帮助。


Lak*_*sad 0

一个简单的解决方案可能是传递一个将 modelform() 扩展为表单集(而不是 modelformset)的表单。

这样您就可以在表单中设置初始值。