从模型字段中获取Django表单字段

时间:2010-04-06 10:36:29

标签: python django django-models django-forms

我想创建一个包含两个独立模型的字段的表单,以及一些其他常规(非模型)字段。表单将创建每个模型的实例。我不认为我可以使用内联表单集,因为我不想包含两个模型的所有字段。

我想创建表单字段而不对模型字段的类型进行硬编码。

我知道我可以使用model_field.formfield()从模型字段中获取表单字段。但是我怎样才能获得特定的模型字段?

我的第一个解决方案:

def get_fields(model_class):
    fields = {}
    for f in model_class._meta.fields:
        fields[f.name] = f

class MyForm(forms.Form):
    foo_name = get_fields(Foo)['name'].formfield()
    bar_name = get_fields(Bar)['name'].formfield()
    other_field = ...

是否已经等效get_fields了?这是一个坏主意吗?依赖于模型_meta属性,我感到很不舒服。或者我是以完全错误的方式解决这个问题?

5 个答案:

答案 0 :(得分:14)

您还可以查看django.forms.models.fields_for_model。 那应该给你一个字段字典,然后你可以添加表格的字段

答案 1 :(得分:10)

除非你想要一些特殊的行为,否则你不应该自己构建字段。

这应该就像在模板中的一个ModelForm标记中使用两个Form和一个额外的<form>一样简单,只需一个提交按钮。

form.py中的

class Model1Form(forms.ModelForm):
    class Meta:
        model = Model1
        fields = ('fields', 'you', 'want')

class Model2Form(forms.ModelForm):
    class Meta:
        model = Model2
        fields = ('fields', 'you', 'want')

class ExtraFieldsForm(forms.Form):
    extra_field = form.TextField() # or whatever field you're looking for
在views.py中

form1 = Model1Form(request.POST or None)
form2 = Model2Form(request.POST or None)
form3 = ExtraFieldsForm(request.POST or None)

if form1.is_valid() and form2.is_valid() and form3.is_valid():
    form1.save()
    form2.save()
    form3.save()

    ...do other stuff like a redirect...

并在模板中:

<form method="POST" action="">{% csrf_token %}
    <fieldset>
        {{ form1|as_uni_form }}
        {{ form2|as_uni_form }}
        {{ form3|as_uni_form }}
        <div class="form_block">
            <input type="submit" value="Save both models"/>
        </div>
    </fieldset>
</form>

我习惯使用django-uni-form,但你可以随意渲染表单字段。祝你的网站好运。

答案 2 :(得分:6)

现在有一个documented API用于从模型类中获取模型字段:

my_model_field = MyModel._meta.get_field('my_model_field_name')

虽然在Django 1.8之前没有正式记录,但这也适用于早期的Django版本。

一旦你有了这个,你就可以得到这样的表格字段:

form_field = my_model_field.formfield()

答案 3 :(得分:2)

另一个解决方案可以是创建一个聚合具体模型的'超级'形式。表单支持表单通常提供的方法,并将它们转发给所有子表单。有些会很简单,其他很复杂。这种方法的最大优点是不会影响表单之外的代码(客户端验证代码等)。这个概念并不是真正具有革命性,但我觉得后来加入很复杂。 保罗

答案 4 :(得分:0)

据我所知,它仍然没有记录,但是since Django 3.0可以使用以下命令从名为field_name的单个模型字段中创建一个表单字段:

MyModel.field_name.field.formfield()

如果您的模型是parler.models.TranslatableModel,并且field_nametranslations内部,则可以使用:

MyModel.translations.field.model.field_name.field.formfield()

或者,如果您希望更详细一些,但记录得更好,可以使用:

MyModel._meta.get_field("field_name").formfield()

MyModel._parler_meta.get_model_by_related_name("translations")._meta.get_field("field_name").formfield()

请参阅:
Django get_field
django-parler get_model_by_related_name