Ticket #3568: htmlnewforms.2.diff

File htmlnewforms.2.diff, 16.4 KB (added by Benjamin Hawkes-Lewis <bhawkeslewis@…>, 17 years ago)

A couple fixes to my patch

  • 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         "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)
     143    def as_table(self,serialization=SERIALIZATION_DEFAULT):
     144        """
     145        Returns this form rendered as HTML <tr>s -- excluding the <table></table>.
     146        Takes a serialization as an optional argument.
     147        """
     148        br = u'<br' + end_empty_element(u'br',serialization)
     149        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)
    145150
    146     def as_ul(self):
    147         "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)
     151    def as_ul(self,serialization=SERIALIZATION_DEFAULT):
     152        """
     153        Returns this form rendered as HTML <li>s -- excluding the <ul></ul>.
     154        Takes a serialization as an optional argument.
     155        """
     156        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)
    149157
    150     def as_p(self):
    151         "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)
     158    def as_p(self,serialization=SERIALIZATION_DEFAULT):
     159        """
     160        Returns this form rendered as HTML <p>s.
     161        Takes a serialization as an optional argument.
     162        """
     163        return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', u' %s', True, serialization)   
     164   
     165    def as_div(self,serialization=SERIALIZATION_DEFAULT):
     166        """
     167        Returns this form rendered as HTML <div>s.
     168        Takes a serialization as an optional argument.
     169        """
     170        return self._html_output(u'<div>%(label)s %(field)s%(help_text)s</div>', u'<div>%s</div>', '</div>', u' %s', True, serialization)   
    153171
    154172    def non_field_errors(self):
    155173        """
     
    209227
    210228class BoundField(StrAndUnicode):
    211229    "A Field plus data"
    212     def __init__(self, form, field, name):
     230    def __init__(self, form, field, name,serialization=SERIALIZATION_DEFAULT):
    213231        self.form = form
    214232        self.field = field
    215233        self.name = name
     
    219237        else:
    220238            self.label = self.field.label
    221239        self.help_text = field.help_text or ''
     240        self.serialization=serialization
    222241
    223242    def __unicode__(self):
    224243        "Renders this field as an HTML widget."
    225244        # Use the 'widget' attribute on the field to determine which type
    226245        # of HTML widget to use.
    227         value = self.as_widget(self.field.widget)
     246        value = self.as_widget(widget=self.field.widget,
     247                               attrs=None,
     248                               serialization=self.serialization)
    228249        if not isinstance(value, basestring):
    229250            # Some Widget render() methods -- notably RadioSelect -- return a
    230251            # "special" object rather than a string. Call the __str__() on that
     
    240261        return self.form.errors.get(self.name, ErrorList())
    241262    errors = property(_errors)
    242263
    243     def as_widget(self, widget, attrs=None):
     264    def as_widget(self, widget, attrs=None, serialization=SERIALIZATION_DEFAULT):
    244265        attrs = attrs or {}
    245266        auto_id = self.auto_id
    246267        if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'):
     
    249270            data = self.form.initial.get(self.name, self.field.initial)
    250271        else:
    251272            data = self.data
    252         return widget.render(self.html_name, data, attrs=attrs)
     273        return widget.render(self.html_name, data, attrs=attrs, serialization=serialization)
    253274
    254     def as_text(self, attrs=None):
     275    def as_text(self, attrs=None, serialization=SERIALIZATION_DEFAULT):
    255276        """
    256277        Returns a string of HTML for representing this as an <input type="text">.
    257278        """
    258         return self.as_widget(TextInput(), attrs)
     279        return self.as_widget(TextInput(), attrs, serialization)
    259280
    260     def as_textarea(self, attrs=None):
     281    def as_textarea(self, attrs=None, serialization=SERIALIZATION_DEFAULT):
    261282        "Returns a string of HTML for representing this as a <textarea>."
    262283        return self.as_widget(Textarea(), attrs)
    263284
    264     def as_hidden(self, attrs=None):
     285    def as_hidden(self, attrs=None, serialization=SERIALIZATION_DEFAULT):
    265286        """
    266287        Returns a string of HTML for representing this as an <input type="hidden">.
    267288        """
    268         return self.as_widget(self.field.hidden_widget(), attrs)
     289        return self.as_widget(self.field.hidden_widget(), attrs, serialization)
    269290
    270291    def _data(self):
    271292        """
  • 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)]
     
    206207
    207208class RadioInput(StrAndUnicode):
    208209    "An object used by RadioFieldRenderer that represents a single <input type='radio'>."
    209     def __init__(self, name, value, attrs, choice, index):
     210    def __init__(self, name, value, attrs, choice, index, serialization=SERIALIZATION_DEFAULT):
    210211        self.name, self.value = name, value
    211212        self.attrs = attrs
    212213        self.choice_value = smart_unicode(choice[0])
    213214        self.choice_label = smart_unicode(choice[1])
    214215        self.index = index
     216        self.serialization = serialization
    215217
    216218    def __unicode__(self):
    217         return u'<label>%s %s</label>' % (self.tag(), self.choice_label)
     219        return u'<label>%s %s</label>' % (self.tag, self.choice_label)
    218220
    219221    def is_checked(self):
    220222        return self.value == self.choice_value
     
    225227        final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
    226228        if self.is_checked():
    227229            final_attrs['checked'] = 'checked'
    228         return u'<input%s />' % flatatt(final_attrs)
     230        return u'<input%s%s' % (flatatt(final_attrs),end_empty_element(u'input',self.serialization))
    229231
    230232class RadioFieldRenderer(StrAndUnicode):
    231233    "An object used by RadioSelect to enable customization of radio widgets."
    232     def __init__(self, name, value, attrs, choices):
     234    def __init__(self, name, value, attrs, choices, serialization=SERIALIZATION_DEFAULT):
    233235        self.name, self.value, self.attrs = name, value, attrs
    234236        self.choices = choices
     237        self.serialization = serialization;
    235238
    236239    def __iter__(self):
    237240        for i, choice in enumerate(self.choices):
     
    239242
    240243    def __getitem__(self, idx):
    241244        choice = self.choices[idx] # Let the IndexError propogate
    242         return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
     245        return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx, self.serialization)
    243246
    244247    def __unicode__(self):
    245248        "Outputs a <ul> for this set of radio fields."
    246249        return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % w for w in self])
    247250
    248251class RadioSelect(Select):
    249     def render(self, name, value, attrs=None, choices=()):
     252    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    250253        "Returns a RadioFieldRenderer instance rather than a Unicode string."
    251254        if value is None: value = ''
    252255        str_value = smart_unicode(value) # Normalize to string.
    253256        attrs = attrs or {}
    254         return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)))
     257        return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)), serialization)
    255258
    256259    def id_for_label(self, id_):
    257260        # RadioSelect is represented by multiple <input type="radio"> fields,
     
    264267    id_for_label = classmethod(id_for_label)
    265268
    266269class CheckboxSelectMultiple(SelectMultiple):
    267     def render(self, name, value, attrs=None, choices=()):
     270    def render(self, name, value, attrs=None, choices=(), serialization=SERIALIZATION_DEFAULT):
    268271        if value is None: value = []
    269272        has_id = attrs and attrs.has_key('id')
    270273        final_attrs = self.build_attrs(attrs, name=name)
     
    277280                final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
    278281            cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
    279282            option_value = smart_unicode(option_value)
    280             rendered_cb = cb.render(name, option_value)
     283            rendered_cb = cb.render(name, option_value, serialization=serialization)
    281284            output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(smart_unicode(option_label))))
    282285        output.append(u'</ul>')
    283286        return u'\n'.join(output)
     
    311314        self.widgets = [isinstance(w, type) and w() or w for w in widgets]
    312315        super(MultiWidget, self).__init__(attrs)
    313316
    314     def render(self, name, value, attrs=None):
     317    def render(self, name, value, attrs=None, serialization=SERIALIZATION_DEFAULT):
    315318        # value is a list of values, each corresponding to a widget
    316319        # in self.widgets.
    317320        if not isinstance(value, list):
     
    322325                widget_value = value[i]
    323326            except KeyError:
    324327                widget_value = None
    325             output.append(widget.render(name + '_%s' % i, widget_value, attrs))
     328            output.append(widget.render(name + '_%s' % i, widget_value, attrs, serialization))
    326329        return self.format_output(output)
    327330
    328331    def value_from_datadict(self, data, name):
Back to Top