views:

3837

answers:

4

I know you can specify fieldsets in django for Admin helpers. However, I cannot find anything useful for ModelForms. Just some patches which I cannot use. Am I missing something? Is there a way I could achieve something like fieldsets without manually writing out each field on my template in the appropriate tag.

I would ideally like to iterate through a set of BoundFields. However, doing something like this at the end of my 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

fails as the items contained in my data structure are the raw fields, not the BoundFields. t looks like BoundFields are generated on the fly... this makes me sad. Could I create my own subclass of forms.Form which contains a concept of fieldsets (even a rough one that is not backward compatible... this is just for my own project) and if so, can you give any pointer? I do not want to mess with the django code.

+11  A: 

Fieldsets in modelforms are still in "design" stage. There's a ticket in Django trac with low activity.

It's something I've been interested in researching myself in the near future, but since I haven't done it yet the best I can offer are these snippets:

Edit: I just noticed this question again and I realize it needs an edit to point out Carl's project django-form-utils which contains a BetterForm class which can contain fieldsets. If you like this project give him a +1 for his answer below :)

Van Gale
The second link gave me the clue that I needed to implement my rudimentary fieldset support. Thank you.
+1  A: 

One thing you can do is break your logical fieldsets into separate model form classes.

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

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

Pass them to your template in different variables and break up the formsets:

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

In that sense each of your form classes is just a fragment of the actual HTML form.

It introduces a touch of complexity when you call save on the form. You'll probably want to pass commit=False and then merge the resultant objects. Or just avoid using ModelForm.save altogether and populate your model object by hand with 'cleaned_data'

Joe Holloway
+7  A: 

I think this snippet does exactly what you want. It gives you a Form subclass that allows you to declaratively subdivide your form into fieldsets and iterate through them in your template.

Carl Meyer
Excellent, it's going in my current project!
Van Gale
Cool. It's not GPLed, but if you make any improvements I'd certainly love to see them.
Carl Meyer
+1  A: 

Daniel Greenfelds django-uni-form solves this with a the Layout helper class. I'm trying it out right now and it looks pretty clean to me.

Uniform helpers can use layout objects. A layout can consist of fieldsets, rows, columns, HTML and fields.

I originally picked Django-uni-form because it complies with section 508.

oivvio