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

时间:2021-11-26 06:45:02

I'd like to create a form that includes fields from two separate models, along with some other regular (non-model) fields. The form will create an instance of each model. I don't think I can use inline formsets for this, since I don't want to include all the fields from both models.

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

I'd like to create the form field without hard-coding the type of the model fields.

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

I know I can get a form field from a model field using model_field.formfield(). But how can I get the specific model field?

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

My first solution:

我的第一个解答:

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 = ...

Is there an equivalent of get_fields already? Is this a bad idea? I'm uncomfortable relying on the model _meta attribute. Or am I going about this the completely wrong way?

是否已经有相当于get_fields?这是一个坏主意吗?依赖于模型_meta属性,我感到很不舒服。或者我是以完全错误的方式来做这件事的?

4 个解决方案

#1


14  

You also can take a look at django.forms.models.fields_for_model. That should give you a dictionary of fields, and then you can add the fields of the form

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

#2


11  

You should never have to build the fields yourself unless you want some special behavior.

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

This should be as simple as using two ModelForms and an extra Form inside one <form> tag in your template with one submit button.

这应该就像在模板中使用一个提交按钮在一个

标记内使用两个ModelForms和一个额外的Form一样简单。

in forms.py:

在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

in views.py:

在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...

and in the template:

并在模板中:

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

I'm used to using django-uni-form, but you can render the form fields however you like. Good luck with your site.

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

#3


5  

There is now a documented API for getting the model field from a model class:

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

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

Although it's not officially documented until Django 1.8, this should work with earlier Django versions too.

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

Once you have this, you can get the form field like so:

一旦你有了这个,你可以像这样得到表单字段:

form_field = my_model_field.formfield()

#4


2  

Another solution can be to create one 'uber'-form that aggregates the concrete modelforms. The form supports the methods that a form normally provides and it forward them to all the child forms. Some will be simple, other complicated. The big advantage of that approach is that no code beyond the form is affected (client validation code and alike). The concept isn't really revolutionary but i guess complicated to add afterwards. Paul

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

#1


14  

You also can take a look at django.forms.models.fields_for_model. That should give you a dictionary of fields, and then you can add the fields of the form

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

#2


11  

You should never have to build the fields yourself unless you want some special behavior.

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

This should be as simple as using two ModelForms and an extra Form inside one <form> tag in your template with one submit button.

这应该就像在模板中使用一个提交按钮在一个

标记内使用两个ModelForms和一个额外的Form一样简单。

in forms.py:

在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

in views.py:

在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...

and in the template:

并在模板中:

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

I'm used to using django-uni-form, but you can render the form fields however you like. Good luck with your site.

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

#3


5  

There is now a documented API for getting the model field from a model class:

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

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

Although it's not officially documented until Django 1.8, this should work with earlier Django versions too.

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

Once you have this, you can get the form field like so:

一旦你有了这个,你可以像这样得到表单字段:

form_field = my_model_field.formfield()

#4


2  

Another solution can be to create one 'uber'-form that aggregates the concrete modelforms. The form supports the methods that a form normally provides and it forward them to all the child forms. Some will be simple, other complicated. The big advantage of that approach is that no code beyond the form is affected (client validation code and alike). The concept isn't really revolutionary but i guess complicated to add afterwards. Paul

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