如何在给出实例时如何设置ModelForm的初始值

时间:2013-08-15 14:04:13

标签: django django-forms django-1.4

似乎给ModelForm一个实例,它会忽略你为initial提供的任何值,而是将它设置为实例的值 - 即使该实例是一个空的模型记录。

有没有办法用实例创建表单并且让它设置初始数据?

我需要它,因为我正在保存相关记录,除非在创建时为ModelForm提供实例,否则它们似乎无法正确保存。

我确信答案是直截了当的,我只是遗漏了一些明显的东西。

以下是相关代码:

视图中的

form = form_class(person=person, conference=conference, initial=initial, instance=registration)

其中form_class为RegistrationForm,然后在注册表中:

class RegisterForm(forms.ModelForm):
    ... fields here ...

    def __init__(self, *args, **kwargs):
        ... other code ...
        self.person = kwargs.pop('person')
        super(RegisterForm, self).__init__(*args, **kwargs)
        for key, in self.fields.keys():
            if hasattr(self.person, key):
                self.fields[k].initial = getattr(self.person, key)

然后当我调用该字段时,相关字段为空。

3 个答案:

答案 0 :(得分:6)

在谷歌谷歌搜索后想出来。

您必须在致电super 之前设置初始值。

因此,我不得不循环浏览self.fields.keys(),而是输入我想要的字段列表,然后通过它来循环:

class RegisterForm(forms.ModelForm):
    ... fields here ...
    initial_fields = ['first_name', 'last_name', ... ]

    def __init__(self, *args, **kwargs):
        ... other code ...
        self.person = kwargs.pop('person')
        for key in self.initial_fields:
            if hasattr(self.person, key):
                self.fields[k].initial = getattr(self.person, key)
        super(RegisterForm, self).__init__(*args, **kwargs)

@Daria在调用super之前正确指出你没有self.fields。我很确定这会奏效:

class RegisterForm(forms.ModelForm):
    ... fields here ...
    initial_fields = ['first_name', 'last_name', ... ]

    def __init__(self, *args, **kwargs):
        ... other code ...
        initial = kwargs.pop('initial', {})
        self.person = kwargs.pop('person')
        for key in self.initial_fields:
            if hasattr(self.person, key):
                initial[key] = initial.get(key) or getattr(self.person, key)
        kwargs['initial'] = initial
        super(RegisterForm, self).__init__(*args, **kwargs)

在这个版本中,我们使用initial参数来传递值。它也是这样编写的,如果我们已经为该字段初始化了一个值,我们就不会覆盖它。

答案 1 :(得分:1)

听起来你可能正在寻找一个约束形式。不完全确定,我正试图解开类似的问题:

Django表单可以用两个参数来实例化,这两个参数控制着这种事情。据我了解:

form = MyForm(initial={...}, data={...}, ...)

initial将为字段设置可能的值设置一个queryset- 数据将设置表单的实际(或选定)值并创建一个绑定表单。也许这就是你想要的。您可能觉得有趣的另一个切线点是考虑工厂方法而不是构造函数,我认为语法更自然:

class MyForm(forms.ModelForm):

    ...

    @staticmethod
    def makeBoundForm(user):
        myObjSet = MyObject.objects.filter(some_attr__user=user)
        if len(myObjSet) is not 0:
            data = {'myObject': myObjSet[0]}
        else:
            raise ValueError()
        initial = {'myObject': myObjSet}
        return MyForm(initial=initial, data=data)

答案 2 :(得分:0)

初始化时,您还可以将额外的变量传递给类。您传递的值可以覆盖初始数据或POST数据。

class RegisterForm(forms.ModelForm):
    ... fields here ...

    def __init__(self, person, conference, *args, **kwargs):
        ... other code ...
        super(RegisterForm, self).__init__(*args, **kwargs)
        self.fields['person'] = person
        self.fields['conference'] = conference

form = RegisterForm(person, conference, initial=initial, instance=registration)