如何从模型字段获取Django表单字段?

22 投票
5 回答
13366 浏览
提问于 2025-04-15 21:17

我想创建一个表单,这个表单需要包含两个不同模型的字段,还有一些其他普通的字段(不是模型的字段)。这个表单会为每个模型创建一个实例。我觉得我不能使用内联表单集,因为我不想包含两个模型的所有字段。

我希望能创建表单字段,而不需要硬编码模型字段的类型。

我知道可以通过 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 个回答

12

现在有一个官方文档的接口,可以用来从模型类中获取模型字段:

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

虽然在Django 1.8之前没有正式的文档说明,但在早期版本的Django中也应该可以使用。

一旦你有了这个,你可以这样获取表单字段:

form_field = my_model_field.formfield()
13

你不需要自己去构建表单字段,除非你想要一些特别的功能。

其实这很简单,只需要用两个 ModelForm 和一个额外的 Form,把它们放在一个 <form> 标签里,然后加一个提交按钮就行了。

在 forms.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,但你可以根据自己的喜好来渲染表单字段。祝你的网站顺利!

19

你还可以看看 django.forms.models.fields_for_model 这个功能。它会给你一个字段的字典,然后你就可以把这些字段添加到表单里。

撰写回答