2010-04-06 98 views
14

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

我想创建表单字段,而不用硬编码模型字段的类型。

我知道我可以使用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属性我不舒服。或者,我是否会以完全错误的方式进行讨论?

+0

您的解决方案听起来很合理的,我,本书虽然,我不明白为什么你不想硬编码的2场;也许你动态地获得模型。 – 2010-04-06 11:30:13

+0

我想避免硬编码表单域的类型,以防我改变相应模型域的类型。不确定你想要动态获取模型的意义......? – harto 2010-04-06 13:00:10

回答

14

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

+0

没有注意到该方法,谢谢。这是我正在寻找的答案,但也许凯西斯塔克的建议更合适。 – harto 2010-04-07 00:11:10

11

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

这应该就像使用两个ModelForm s和一个额外的Form一样在一个<form>标签内,在您的模板中使用一个提交按钮。

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的单向

在forms.py

窗体,但是你可以渲染表单域,只要你喜欢。祝你网站好运。

+0

我没有想过在一个'

'元素中使用多个'Form'对象。感谢您的建议 - 我今晚会尝试一下。 – harto 2010-04-07 00:09:59

+0

很酷。我希望这个对你有用。我以前看过它,但没有经过测试。你可能需要玩视图逻辑来获得你想要的。 – 2010-04-07 03:20:49

2

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

4

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

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

虽然这不是正式文件,直到Django的1.8,这应该与早期的Django版本工作了。

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

form_field = my_model_field.formfield()