【问题标题】:How to get Django form field from model field?如何从模型字段中获取 Django 表单字段?
【发布时间】:2011-02-04 18:18:47
【问题描述】:

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

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

我知道我可以使用 model_field.formfield() 从模型字段中获取表单字段。但是如何获取具体的model字段呢?

我的第一个解决方案:

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 属性感到不舒服。还是我的做法完全错误?

【问题讨论】:

  • 您的解决方案对我来说听起来很合理,尽管如此,我不明白您为什么不想对这两个字段进行硬编码;也许您可以动态获取模型。
  • 我想避免对表单字段的类型进行硬编码,以防我更改相应模型字段的类型。不确定动态获取模型是什么意思...?

标签: python django django-models django-forms


【解决方案1】:

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

【讨论】:

  • 没注意到这个方法,谢谢。这就是我一直在寻找的答案,但也许 Casey Stark 的建议更合适。
【解决方案2】:

除非您想要一些特殊的行为,否则您永远不必自己构建字段。

这应该像在模板中的一个 <form> 标记中使用两个 ModelForms 和一个额外的 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,但您可以随意渲染表单字段。祝你的网站好运。

【讨论】:

  • 我没想到会在一个 &lt;form&gt; 元素中使用多个 Form 对象。感谢您的建议 - 我今晚会尝试一下。
  • 酷。我希望这个对你有用。我以前看过它,但没有经过测试。您可能需要使用视图逻辑来获得所需的内容。
【解决方案3】:

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

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

虽然它直到 Django 1.8 才正式记录,但这也应该适用于早期的 Django 版本。

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

form_field = my_model_field.formfield()

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      据我所知,它仍然没有记录,但 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

      【讨论】:

        猜你喜欢
        • 2020-07-07
        • 2016-08-11
        • 1970-01-01
        • 2011-03-07
        • 2017-05-20
        • 2020-11-30
        • 2022-11-27
        • 2015-05-31
        • 1970-01-01
        相关资源
        最近更新 更多