Ticket #3568: htmlnewforms.diff

File htmlnewforms.diff, 15.6 KB (added by Benjamin Hawkes-Lewis <bhawkeslewis@…>, 17 years ago)
  • django/newforms/forms.py

     
    55from django.utils.datastructures import SortedDict, MultiValueDict
    66from django.utils.html import escape
    77from fields import Field
     8from serializations import *
    89from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput
    910from util import flatatt, StrAndUnicode, ErrorDict, ErrorList, ValidationError
    1011import copy
    1112
    12 __all__ = ('BaseForm', 'Form')
     13__all__ = ('BaseForm', 'Form', 'SERIALIZATION_XHTML', 'SERIALIZATION_HTML401', 'SERIALIZATION_DEFAULT', 'SERIALIZATION_HTML_COMPATIBLE_XHTML1')
    1314
    1415NON_FIELD_ERRORS = '__all__'
    1516
     
    107108        """
    108109        return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name
    109110
    110     def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
     111    def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row, serialization=SERIALIZATION_DEFAULT):
    111112        "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
    112113        top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
    113114        output, hidden_fields = [], []
    114115        for name, field in self.fields.items():
    115             bf = BoundField(self, field, name)
     116            bf = BoundField(self, field, name,serialization)
    116117            bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable.
    117118            if bf.is_hidden:
    118119                if bf_errors:
     
    139140                output.append(str_hidden)
    140141        return u'\n'.join(output)
    141142
    142     def as_table(self):
     143    def as_table(self,serialization=SERIALIZATION_DEFAULT):
    143144        "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
    144         return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False)
     145        br = u'<br' + end_empty_element(u'br',serialization)
     146        return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'' + br + '%s', False, serialization)
    145147
    146     def as_ul(self):
     148    def as_ul(self,serialization=SERIALIZATION_DEFAULT):
    147149        "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
    148         return self._html_output(u'<li>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False)
     150        return self._html_output(u'<li>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False, serialization)
    149151
    150     def as_p(self):
     152    def as_p(self,serialization=SERIALIZATION_DEFAULT):
    151153        "Returns this form rendered as HTML <p>s."
    152         return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', u' %s', True)
     154        return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', u' %s', True, serialization)   
     155   
     156    def as_div(self,serialization=SERIALIZATION_DEFAULT):
     157        "Returns this form rendered as HTML <div>s."
     158        return self._html_output(u'<div>%(label)s %(field)s%(help_text)s</div>', u'<div>%s</div>', '</div>', u' %s', True, serialization)   
    153159
    154160    def non_field_errors(self):
    155161        """
     
    209215
    210216class BoundField(StrAndUnicode):
    211217    "A Field plus data"
    212     def __init__(self, form, field, name):
     218    def __init__(self, form, field, name,serialization=SERIALIZATION_DEFAULT):
    213219        self.form = form
    214220        self.field = field
    215221        self.name = name
     
    219225        else:
    220226            self.label = self.field.label
    221227        self.help_text = field.help_text or ''
     228        self.serialization=serialization
    222229
    223230    def __unicode__(self):
    224231        "Renders this field as an HTML widget."
    225232        # Use the 'widget' attribute on the field to determine which type
    226233        # of HTML widget to use.
    227         value = self.as_widget(self.field.widget)
     234        value = self.as_widget(widget=self.field.widget,
     235                               attrs=None,
     236                               serialization=self.serialization)
    228237        if not isinstance(value, basestring):
    229238            # Some Widget render() methods -- notably RadioSelect -- return a
    230239            # "special" object rather than a string. Call the __str__() on that
     
    240249        return self.form.errors.get(self.name, ErrorList())
    241250    errors = property(_errors)
    242251
    243     def as_widget(self, widget, attrs=None):
     252    def as_widget(self, widget, attrs=None, serialization=SERIALIZATION_DEFAULT):
    244253        attrs = attrs or {}
    245254        auto_id = self.auto_id
    246255        if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'):
     
    249258            data = self.form.initial.get(self.name, self.field.initial)
    250259        else:
    251260            data = self.data
    252         return widget.render(self.html_name, data, attrs=attrs)
     261        return widget.render(self.html_name, data, attrs=attrs, serialization=serialization)
    253262
    254     def as_text(self, attrs=None):
     263    def as_text(self, attrs=None, serialization=SERIALIZATION_DEFAULT):
    255264        """
    256265        Returns a string of HTML for representing this as an <input type="text">.
    257266        """
    258         return self.as_widget(TextInput(), attrs)
     267        return self.as_widget(TextInput(), attrs, serialization)
    259268
    260     def as_textarea(self, attrs=None):
     269    def as_textarea(self, attrs=None, serialization=SERIALIZATION_DEFAULT):
    261270        "Returns a string of HTML for representing this as a <textarea>."
    262271        return self.as_widget(Textarea(), attrs)
    263272
    264     def as_hidden(self, attrs=None):
     273    def as_hidden(self, attrs=None, serialization=SERIALIZATION_DEFAULT):
    265274        """
    266275        Returns a string of HTML for representing this as an <input type="hidden">.
    267276        """
    268         return self.as_widget(self.field.hidden_widget(), attrs)
     277        return self.as_widget(self.field.hidden_widget(), attrs, serialization)
    269278
    270279    def _data(self):
    271280        """
  • django/newforms/widgets.py

     
    1414from django.utils.html import escape
    1515from django.utils.translation import gettext
    1616from itertools import chain
     17from serializations import end_empty_element, SERIALIZATION_DEFAULT
    1718
    1819try:
    1920    set # Only available in Python 2.4+
     
    2627    def __init__(self, attrs=None):
    2728        self.attrs = attrs or {}
    2829
    29     def render(self, name, value, attrs=None):
     30    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    3031        """
    3132        Returns this Widget rendered as HTML, as a Unicode string.
    3233
     
    6970    """
    7071    input_type = None # Subclasses must define this.
    7172
    72     def render(self, name, value, attrs=None):
     73    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    7374        if value is None: value = ''
    7475        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
    7576        if value != '': final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty.
    76         return u'<input%s />' % flatatt(final_attrs)
     77        return u'<input%s%s' % (flatatt(final_attrs), end_empty_element(u'input',serialization));
    7778
    7879class TextInput(Input):
    7980    input_type = 'text'
     
    8586        self.attrs = attrs or {}
    8687        self.render_value = render_value
    8788
    88     def render(self, name, value, attrs=None):
     89    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    8990        if not self.render_value: value=None
    90         return super(PasswordInput, self).render(name, value, attrs)
     91        return super(PasswordInput, self).render(name, value, attrs, serialization)
    9192
    9293class HiddenInput(Input):
    9394    input_type = 'hidden'
     
    103104        self.attrs = attrs or {}
    104105        self.choices = choices
    105106
    106     def render(self, name, value, attrs=None, choices=()):
     107    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    107108        if value is None: value = []
    108109        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
    109         return u'\n'.join([(u'<input%s />' % flatatt(dict(value=smart_unicode(v), **final_attrs))) for v in value])
     110        return u'\n'.join([(u'<input%s%s' % (flatatt(dict(value=smart_unicode(v), **final_attrs)), end_empty_element(u'input',serialization))) for v in value])
    110111
    111112    def value_from_datadict(self, data, name):
    112113        if isinstance(data, MultiValueDict):
     
    117118    input_type = 'file'
    118119
    119120class Textarea(Widget):
    120     def render(self, name, value, attrs=None):
     121    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    121122        if value is None: value = ''
    122123        value = smart_unicode(value)
    123124        final_attrs = self.build_attrs(attrs, name=name)
     
    130131        self.attrs = attrs or {}
    131132        self.check_test = check_test
    132133
    133     def render(self, name, value, attrs=None):
     134    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    134135        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
    135136        try:
    136137            result = self.check_test(value)
     
    140141            final_attrs['checked'] = 'checked'
    141142        if value not in ('', True, False, None):
    142143            final_attrs['value'] = smart_unicode(value) # Only add the 'value' attribute if a value is non-empty.
    143         return u'<input%s />' % flatatt(final_attrs)
     144        return u'<input%s%s' % (flatatt(final_attrs),end_empty_element(u'input',serialization))
    144145
    145146class Select(Widget):
    146147    def __init__(self, attrs=None, choices=()):
     
    150151        # more than once.
    151152        self.choices = list(choices)
    152153
    153     def render(self, name, value, attrs=None, choices=()):
     154    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    154155        if value is None: value = ''
    155156        final_attrs = self.build_attrs(attrs, name=name)
    156157        output = [u'<select%s>' % flatatt(final_attrs)]
     
    170171        choices = ((u'1', gettext('Unknown')), (u'2', gettext('Yes')), (u'3', gettext('No')))
    171172        super(NullBooleanSelect, self).__init__(attrs, choices)
    172173
    173     def render(self, name, value, attrs=None, choices=()):
     174    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    174175        try:
    175176            value = {True: u'2', False: u'3', u'2': u'2', u'3': u'3'}[value]
    176177        except KeyError:
    177178            value = u'1'
    178         return super(NullBooleanSelect, self).render(name, value, attrs, choices)
     179        return super(NullBooleanSelect, self).render(name, value, attrs, choices, serialization)
    179180
    180181    def value_from_datadict(self, data, name):
    181182        value = data.get(name, None)
     
    187188        self.attrs = attrs or {}
    188189        self.choices = choices
    189190
    190     def render(self, name, value, attrs=None, choices=()):
     191    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    191192        if value is None: value = []
    192193        final_attrs = self.build_attrs(attrs, name=name)
    193194        output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)]
     
    213214        self.choice_label = smart_unicode(choice[1])
    214215        self.index = index
    215216
    216     def __unicode__(self):
    217         return u'<label>%s %s</label>' % (self.tag(), self.choice_label)
     217    def __unicode__(self, serialization=SERIALIZATION_DEFAULT):
     218        return u'<label>%s %s</label>' % (self.tag(serialization), self.choice_label)
    218219
    219220    def is_checked(self):
    220221        return self.value == self.choice_value
    221222
    222     def tag(self):
     223    def tag(self,serialization=SERIALIZATION_DEFAULT):
    223224        if self.attrs.has_key('id'):
    224225            self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index)
    225226        final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
    226227        if self.is_checked():
    227228            final_attrs['checked'] = 'checked'
    228         return u'<input%s />' % flatatt(final_attrs)
     229        return u'<input%s%s' % (flatatt(final_attrs),end_empty_element(u'input',serialization))
    229230
    230231class RadioFieldRenderer(StrAndUnicode):
    231232    "An object used by RadioSelect to enable customization of radio widgets."
    232     def __init__(self, name, value, attrs, choices):
     233    def __init__(self, name, value, attrs, choices, serialization=SERIALIZATION_DEFAULT):
    233234        self.name, self.value, self.attrs = name, value, attrs
    234235        self.choices = choices
     236        self.serialization = serialization;
    235237
    236238    def __iter__(self):
    237239        for i, choice in enumerate(self.choices):
     
    241243        choice = self.choices[idx] # Let the IndexError propogate
    242244        return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
    243245
    244     def __unicode__(self):
     246    def __unicode__(self, serialization):
    245247        "Outputs a <ul> for this set of radio fields."
    246248        return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % w for w in self])
    247249
    248250class RadioSelect(Select):
    249     def render(self, name, value, attrs=None, choices=()):
     251    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    250252        "Returns a RadioFieldRenderer instance rather than a Unicode string."
    251253        if value is None: value = ''
    252254        str_value = smart_unicode(value) # Normalize to string.
    253255        attrs = attrs or {}
    254         return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)))
     256        return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)), serialization)
    255257
    256258    def id_for_label(self, id_):
    257259        # RadioSelect is represented by multiple <input type="radio"> fields,
     
    264266    id_for_label = classmethod(id_for_label)
    265267
    266268class CheckboxSelectMultiple(SelectMultiple):
    267     def render(self, name, value, attrs=None, choices=()):
     269    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    268270        if value is None: value = []
    269271        has_id = attrs and attrs.has_key('id')
    270272        final_attrs = self.build_attrs(attrs, name=name)
     
    277279                final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
    278280            cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
    279281            option_value = smart_unicode(option_value)
    280             rendered_cb = cb.render(name, option_value)
     282            rendered_cb = cb.render(name, option_value, serialization=serialization)
    281283            output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(smart_unicode(option_label))))
    282284        output.append(u'</ul>')
    283285        return u'\n'.join(output)
     
    311313        self.widgets = [isinstance(w, type) and w() or w for w in widgets]
    312314        super(MultiWidget, self).__init__(attrs)
    313315
    314     def render(self, name, value, attrs=None):
     316    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    315317        # value is a list of values, each corresponding to a widget
    316318        # in self.widgets.
    317319        if not isinstance(value, list):
     
    322324                widget_value = value[i]
    323325            except KeyError:
    324326                widget_value = None
    325             output.append(widget.render(name + '_%s' % i, widget_value, attrs))
     327            output.append(widget.render(name + '_%s' % i, widget_value, attrs, serialization))
    326328        return self.format_output(output)
    327329
    328330    def value_from_datadict(self, data, name):
Back to Top