2009-02-06 170 views
34

我知道你可以在django中爲Admin助手指定字段集。但是,我無法找到對ModelForms有用的任何內容。只是一些我不能使用的補丁。我錯過了什麼嗎?有沒有一種方法可以實現類似字段集的操作,而無需在適當的標籤中手動寫出我模板中的每個字段。ModelForm上的Django和fieldsets

我想理想地遍歷一組BoundFields。但是,做這樣的事情在我的ModelForm的末尾:

fieldsets = [] 
    fieldsets.append(('Personal Information', 
         [username,password,password2,first_name,last_name,email]),) # add a 2 element tuple of string and list of fields 
    fieldsets.append(('Terms & Conditions', 
         [acceptterms,acceptprivacy]),) # add a 2 element tuple of string and list of fields 

載於我的數據結構中的項目是原始字段,而不是綁定列失敗。 t看起來像BoundFields在飛行中生成...這讓我很難過。我可以創建自己的forms.Form的子類,它包含fieldset的概念(即使是粗糙的,不向後兼容......這僅僅適用於我自己的項目),如果是這樣,你可以給任何指針嗎?我不想惹django代碼。

回答

34

模型中的字段集仍處於「設計」階段。 Django trac中有一個ticket,活動較少。

這件事情我一直有興趣在不久的將來,研究自己,但因爲我沒有這麼做過,我可以提供最好的是這些片段:

編輯:我只是再次注意到這個問題,我重新alize它需要一個編輯指出卡爾的項目django-form-utils其中包含一個BetterForm類可以包含字段集。如果你喜歡這個項目,請給他+1以下的答案:)

+1

第二個鏈接給我,我需要實現我的基本的字段集支持的線索。謝謝。 – 2009-02-07 21:24:45

+1

2010年11月,在1.2.3中成功使用了django-form-utils。感謝提示。 – Boldewyn 2010-11-24 14:18:33

16

你可以做的一件事是將你的邏輯字段集分解成單獨的模型表單類。

class PersonalInfoForm (forms.ModelForm): 
    class Meta: 
     model=MyModel 
     fields=('field1', 'field2', ...) 

class TermsForm (forms.ModelForm): 
    class Meta: 
     model=MyModel 
     fields=('fieldX', 'fieldY', ...) 

它們傳遞到不同的變量,你的模板,並打破了表單集:

<form ...> 
    <fieldset><legend>Personal Information</legend> 
     {{ personal_info_form }} 
    </fieldset> 
    <fieldset><legend>Terms and Conditions</legend> 
     {{ terms_form }} 
    </fieldset> 
</form> 

在這個意義上每個表單類的只是實際的HTML格式的片段。

當您調用窗體上的保存時,它會帶來一些複雜性。您可能需要傳遞commit = False,然後合併結果對象。或者只是完全避免使用ModelForm.save,並用'cleared_data'手工填充模型對象。

+1

這太費力了,尤其是在視圖層。 – Greg 2011-04-29 00:34:08

50

我認爲this snippet完全符合您的要求。它爲您提供了一個Form子類,允許您聲明性地將表單細分爲字段集,並在您的模板中遍歷它們。

更新:該段已從此成爲django-form-utils

0

這是我爲了瞭解自定義標籤(帶有鏈接)而開發的代碼。我用它來創建一個fieldset。

聲明:我鼓勵使用上述任何答案,這只是爲了學習。

templatetags/myextras.py

from django import template 
from django.template import Context 

register = template.Library() 


class FieldsetNode(template.Node): 
    """ Fieldset renderer for 'fieldset' tag """ 
    def __init__(self, nodelist, fieldset_name): 
     """ Initialize renderer class 
     https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-renderer 
     :param nodelist: a list of the template nodes inside a block of 'fieldset' 
     :param fieldset_name: the name of the fieldset 
     :return: None 
     """ 
     self.nodelist = nodelist 
     self.fieldset_name = fieldset_name 

    def render(self, context): 
     """ Render the inside of a fieldset block based on template file 
     https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#auto-escaping-considerations 
     :param context: the previous template context 
     :return: HTML string 
     """ 
     t = context.template.engine.get_template('myapp/fieldset.html') 
     return t.render(Context({ 
      'var': self.nodelist.render(context), 
      'name': self.fieldset_name, 
     }, autoescape=context.autoescape)) 


@register.tag 
def fieldset(parser, token): 
    """ Compilation function for fieldset block tag 
    Render a form fieldset 
    https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-compilation-function 
    https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#parsing-until-another-block-tag 
    :param parser: template parser 
    :param token: tag name and variables 
    :return: HTML string 
    """ 
    try: 
     tag_name, fieldset_name = token.split_contents() 
    except ValueError: 
     raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0]) 
    if not (fieldset_name[0] == fieldset_name[-1] and fieldset_name[0] in ('"', "'")): 
     raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name) 
    nodelist = parser.parse(('endfieldset',)) 
    parser.delete_first_token() 
    return FieldsetNode(nodelist, fieldset_name[1:-1]) 

templates/myapp/fieldset.html

<div class="fieldset panel panel-default"> 
    <div class="panel-heading">{{ name }}</div> 
    <div class="panel-body">{{ var }}</div> 
</div> 

templates/myapp/myform.html

<form action="{% url 'myapp:myurl' %}" method="post"> 
    {% csrf_token %} 
    {% fieldset 'General' %} 
     {{form.myfield1 }} 
    {% endfieldset %} 
    {# my submit button #} 
</form>