Login

Form splitting/Fieldset templatetag

Author:
peritus
Posted:
September 4, 2008
Language:
Python
Version:
1.0
Score:
6 (after 6 ratings)

Syntax: {% get_fieldset list,of,fields as new_form_object from original_form %}

Example:

{% load fieldsets %}
...
<fieldset id="contact_details">
    <legend>Contact details</legend>
    <ul>
{% get_fieldset first_name,last_name,email,cell_phone as personal_fields from form %}
{{ personal_fields.as_ul }}
    </ul>
</fieldset>

<fieldset>
    <legend>Address details</legend>
    <ul>
{% get_fieldset street_address,post_code,city as address_fields from form %}
{{ address_fields.as_ul }}
    </ul>
</fieldset>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import copy

from django import template
from django import forms
from django.utils.datastructures import SortedDict

register = template.Library()

def get_fieldset(parser, token):
    try:
        name, fields, as_, variable_name, from_, form = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError('bad arguments for %r'  % token.split_contents()[0])

    return FieldSetNode(fields.split(','), variable_name, form)

get_fieldset = register.tag(get_fieldset)


class FieldSetNode(template.Node):
    def __init__(self, fields, variable_name, form_variable):
        self.fields = fields
        self.variable_name = variable_name
        self.form_variable = form_variable

    def render(self, context):
        
        form = template.Variable(self.form_variable).resolve(context)
        new_form = copy.copy(form)        
        new_form.fields = SortedDict([(key, value) for key, value in form.fields.items() if key in self.fields])

        context[self.variable_name] = new_form

        return u''

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

gregb (on August 9, 2009):

Thanks for this snippet - very handy. I created a similar "excluding" tag which works in the same way but excludes the listed fields - using the two together saves a bit of typing especially if you just want to split out a few fields from a long form into their own fieldset.

#

czartur (on August 8, 2011):

I would personally recommend to change this:

    #new_form.fields = SortedDict(
        #[(key, value) for key, value in form.fields.items() 
         #if key in self.fields])

to that:

    new_form.fields = SortedDict(
        [(key, form.fields[key]) for key in self.fields]
    )

So you can preserve ordering in your forms.

Apart from that – Brilliant snippet, saved me ton of work.

#

benjaoming (on January 17, 2012):

This is obviously a classic! Thanks a million :)

#

tkrapp (on September 9, 2019):

Please note that custom form validation via clean-method may throw errors when accessing fields which are not part of the copied sub form. I solved this by creating a simple proxy class and custom as_ul, as_table and as_p methods which accept fields to filter the displayed fields.

This means copying entire methods from the django source but saves a lot of template code :-)

The form proxy looks like this:

class FormProxy(): def init(self, form, displayed_fields): self._form = form self._displayed_fields = displayed_fields def getattr(self, attr): return getattr(self._form, attr) def as_ul(self): return self._form.as_ul(fields=self.displayed_fields) # ... same for as_p and as_table

#

Please login first before commenting.