PageRenderTime 36ms CodeModel.GetById 22ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 1ms

/renderform/templatetags/forms.py

https://bitbucket.org/baratrion/django-renderform
Python | 114 lines | 96 code | 11 blank | 7 comment | 20 complexity | 0039bfd8da2aae181461755d8e409211 MD5 | raw file
  1from django.template import Library, Node
  2from django import forms
  3import re
  4
  5register = Library()
  6
  7SPLIT_RE = re.compile(r'[\s,]+')
  8
  9def show_form(form, wrap_with_tag='div'):
 10    "Render all fields in `form`, passing `wrap_with_tag` to `show_field`."
 11    return {'form': form, 'tag': wrap_with_tag}
 12register.inclusion_tag("forms/form.html")(show_form)
 13
 14def show_field(field, wrap_with_tag='div', classes=()):
 15    "Render `field` (label, input, and help text) encosed in `wrap_with_tag`."
 16    if isinstance(classes, basestring):
 17        classes = classes.split(',')
 18    is_checkbox = (
 19        isinstance(field.field.widget, forms.widgets.CheckboxInput) or
 20        getattr(field.field.widget, 'input_type', None) == 'checkbox'
 21    )
 22    is_radio = (
 23        isinstance(field.field.widget, forms.widgets.RadioInput) or
 24        getattr(field.field.widget, 'input_type', None) == 'radio'
 25    )
 26    return {
 27        'field': field,
 28        'errors': field.errors,
 29        'is_hidden': field.is_hidden,
 30        'is_checkbox': is_checkbox,
 31        'is_radio': is_radio,
 32        'tag': wrap_with_tag,
 33        'classes': classes,
 34        'required': field.field.required
 35    }
 36register.inclusion_tag("forms/field.html")(show_field)
 37
 38def show_errors(field_or_errors, errors=None):
 39    if errors is None:
 40        if isinstance(field_or_errors, forms.forms.BoundField):
 41            field = field_or_errors
 42            errors = field.errors.pop()
 43        else:
 44            field = None
 45            errors = field_or_errors
 46    else:
 47        field = field_or_errors
 48    return {'field': field, 'errors': errors}
 49register.inclusion_tag("forms/errors.html")(show_errors)
 50
 51def show_label(field, label=None, classes=()):
 52    "Render the label tag for `field`, overriding its label text with `label`."
 53    if label is None:
 54        label = field.label
 55    if isinstance(classes, basestring):
 56        classes = SPLIT_RE.split(classes)
 57    return {
 58        'field': field,
 59        'label': label,
 60        'classes': classes,
 61        'required': field.field.required
 62    }
 63register.inclusion_tag("forms/label.html")(show_label)
 64
 65def show_help_text(field_or_text, classes=()):
 66    "Render the text or the field's help text given by `field_or_text`."
 67    if isinstance(field_or_text, basestring):
 68        field = None
 69        help_text = field_or_text
 70    else:
 71        field = field_or_text
 72        help_text = field.help_text
 73    if isinstance(classes, basestring):
 74        classes = SPLIT_RE.split(classes)
 75    return {'field': field, 'help_text': help_text, 'classes': classes}
 76register.inclusion_tag("forms/help_text.html")(show_help_text)
 77
 78def do_class_list(parser, token):
 79    "Resolve arguments, flatten lists, and split strings to get class names."
 80    bits = token.split_contents()[1:]
 81    class_vars = [parser.compile_filter(bit) for bit in bits]
 82    return ClassListNode(class_vars)
 83register.tag('class_list', do_class_list)
 84
 85def do_class_attr(parser, token):
 86    """
 87    Render a HTML class attribute if the given classes are non-empty,
 88    otherwise returns an empty string to avoid including an empty attribute.
 89    Takes the same arguments as `class_list`. The attribute name is prefixed
 90    with a space to help avoid extraneous spaces.
 91    
 92    """
 93    bits = token.split_contents()[1:]
 94    class_vars = [parser.compile_filter(bit) for bit in bits]
 95    return ClassListNode(class_vars, ' class="%s"')
 96register.tag('class_attr', do_class_attr)
 97
 98class ClassListNode(Node):
 99    def __init__(self, class_vars, output_format="%s"):
100        self.class_vars = class_vars
101        self.output_format = output_format
102    
103    def render(self, context):
104        classes = [var.resolve(context) for var in self.class_vars]
105        class_names = []
106        for class_ in classes:
107            if isinstance(class_, basestring):
108                class_ = [class_]
109            for names in class_:
110                for name in SPLIT_RE.split(names):
111                    if name and name not in class_names:
112                        class_names.append(name)
113        value = " ".join(class_names)
114        return value and self.output_format % value