diff --git a/django/newforms/extras/widgets.py b/django/newforms/extras/widgets.py
index e3ef1d7..bd6220d 100644
--- a/django/newforms/extras/widgets.py
+++ b/django/newforms/extras/widgets.py
@@ -9,10 +9,11 @@ from django.newforms.widgets import Widget, Select
from django.utils.dates import MONTHS
from django.utils.safestring import mark_safe
-__all__ = ('SelectDateWidget',)
+__all__ = ('SelectDateWidget', )
RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
+
class SelectDateWidget(Widget):
"""
A Widget that splits date input into three boxes.
@@ -25,7 +26,8 @@ class SelectDateWidget(Widget):
year_field = '%s_year'
def __init__(self, attrs=None, years=None):
- # years is an optional list/tuple of years to use in the "year" select box.
+ # years is an optional list/tuple of years to use in the
+ # "year" select box.
self.attrs = attrs or {}
if years:
self.years = years
@@ -41,7 +43,8 @@ class SelectDateWidget(Widget):
if isinstance(value, basestring):
match = RE_DATE.match(value)
if match:
- year_val, month_val, day_val = [int(v) for v in match.groups()]
+ year_val, month_val, day_val = [
+ int(v) for v in match.groups()]
output = []
@@ -53,17 +56,20 @@ class SelectDateWidget(Widget):
month_choices = MONTHS.items()
month_choices.sort()
local_attrs = self.build_attrs(id=self.month_field % id_)
- select_html = Select(choices=month_choices).render(self.month_field % name, month_val, local_attrs)
+ select_html = Select(choices=month_choices).render(
+ self.month_field % name, month_val, local_attrs)
output.append(select_html)
day_choices = [(i, i) for i in range(1, 32)]
local_attrs['id'] = self.day_field % id_
- select_html = Select(choices=day_choices).render(self.day_field % name, day_val, local_attrs)
+ select_html = Select(choices=day_choices).render(
+ self.day_field % name, day_val, local_attrs)
output.append(select_html)
year_choices = [(i, i) for i in self.years]
local_attrs['id'] = self.year_field % id_
- select_html = Select(choices=year_choices).render(self.year_field % name, year_val, local_attrs)
+ select_html = Select(choices=year_choices).render(
+ self.year_field % name, year_val, local_attrs)
output.append(select_html)
return mark_safe(u'\n'.join(output))
@@ -73,7 +79,9 @@ class SelectDateWidget(Widget):
id_for_label = classmethod(id_for_label)
def value_from_datadict(self, data, files, name):
- y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name)
+ y = data.get(self.year_field % name)
+ m = data.get(self.month_field % name)
+ d = data.get(self.day_field % name)
if y and m and d:
return '%s-%s-%s' % (y, m, d)
return data.get(name, None)
diff --git a/django/newforms/fields.py b/django/newforms/fields.py
index dfe46a2..6d74c74 100644
--- a/django/newforms/fields.py
+++ b/django/newforms/fields.py
@@ -21,7 +21,9 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import StrAndUnicode, smart_unicode, smart_str
from util import ErrorList, ValidationError
-from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput
+from widgets import TextInput, PasswordInput, HiddenInput
+from widgets import MultipleHiddenInput, FileInput, CheckboxInput, Select
+from widgets import NullBooleanSelect, SelectMultiple, DateTimeInput
__all__ = (
@@ -40,8 +42,10 @@ EMPTY_VALUES = (None, '')
class Field(object):
- widget = TextInput # Default widget to use when rendering this type of Field.
- hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
+ # Default widget to use when rendering this type of Field.
+ widget = TextInput
+ # Default widget to use when rendering this as "hidden".
+ hidden_widget = HiddenInput
default_error_messages = {
'required': _(u'This field is required.'),
'invalid': _(u'Enter a valid value.'),
@@ -119,6 +123,7 @@ class Field(object):
result.widget = copy.deepcopy(self.widget, memo)
return result
+
class CharField(Field):
default_error_messages = {
'max_length': _(u'Ensure this value has at most %(max)d characters (it has %(length)d).'),
diff --git a/django/newforms/forms.py b/django/newforms/forms.py
index 2c481e4..163a2c2 100644
--- a/django/newforms/forms.py
+++ b/django/newforms/forms.py
@@ -17,11 +17,13 @@ __all__ = ('BaseForm', 'Form')
NON_FIELD_ERRORS = '__all__'
+
def pretty_name(name):
"Converts 'first_name' to 'First name'"
name = name[0].upper() + name[1:]
return name.replace('_', ' ')
+
def get_declared_fields(bases, attrs, with_base_fields=True):
"""
Create a list of form field instances from the passed in 'attrs', plus any
@@ -32,7 +34,8 @@ def get_declared_fields(bases, attrs, with_base_fields=True):
Otherwise, only fields in the 'declared_fields' attribute on the bases are
used. The distinction is useful in ModelForm subclassing.
"""
- fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
+ fields = [(field_name, attrs.pop(field_name)) \
+ for field_name, obj in attrs.items() if isinstance(obj, Field)]
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
# If this class is subclassing another Form, add that Form's fields.
@@ -49,20 +52,26 @@ def get_declared_fields(bases, attrs, with_base_fields=True):
return SortedDict(fields)
+
class DeclarativeFieldsMetaclass(type):
"""
Metaclass that converts Field attributes to a dictionary called
'base_fields', taking into account parent class 'base_fields' as well.
"""
+
def __new__(cls, name, bases, attrs):
attrs['base_fields'] = get_declared_fields(bases, attrs)
return type.__new__(cls, name, bases, attrs)
+
class BaseForm(StrAndUnicode):
- # This is the main implementation of all the Form logic. Note that this
- # class is different than Form. See the comments by the Form class for more
- # information. Any improvements to the form API should be made to *this*
- # class, not to the Form class.
+ """
+ This is the main implementation of all the Form logic. Note that this
+ class is different than Form. See the comments by the Form class for more
+ information. Any improvements to the form API should be made to *this*
+ class, not to the Form class.
+ """
+
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':'):
self.is_bound = data is not None or files is not None
@@ -118,18 +127,27 @@ class BaseForm(StrAndUnicode):
Subclasses may wish to override.
"""
- return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name
+ return self.prefix and ('%s-%s' % (self.prefix, field_name)) or \
+ field_name
- def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
- "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
- top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
+ def _html_output(self, normal_row, error_row, row_ender,
+ help_text_html, errors_on_separate_row):
+ """
+ Helper function for outputting HTML. Used by as_table(),
+ as_ul(), as_p().
+ """
+ # Errors that should be displayed above all fields.
+ top_errors = self.non_field_errors()
output, hidden_fields = [], []
for name, field in self.fields.items():
bf = BoundField(self, field, name)
- bf_errors = self.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable.
+ # Escape and cache in local variable.
+ bf_errors = self.error_class([escape(error) \
+ for error in bf.errors])
if bf.is_hidden:
if bf_errors:
- top_errors.extend([u'(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
+ top_errors.extend([u'(Hidden field %s) %s' % (
+ name, force_unicode(e)) for e in bf_errors])
hidden_fields.append(unicode(bf))
else:
if errors_on_separate_row and bf_errors:
@@ -148,7 +166,11 @@ class BaseForm(StrAndUnicode):
help_text = help_text_html % force_unicode(field.help_text)
else:
help_text = u''
- output.append(normal_row % {'errors': force_unicode(bf_errors), 'label': force_unicode(label), 'field': unicode(bf), 'help_text': help_text})
+ output.append(normal_row % {
+ 'errors': force_unicode(bf_errors),
+ 'label': force_unicode(label),
+ 'field': unicode(bf),
+ 'help_text': help_text})
if top_errors:
output.insert(0, error_row % force_unicode(top_errors))
if hidden_fields: # Insert any hidden fields in the last row.
@@ -157,7 +179,8 @@ class BaseForm(StrAndUnicode):
last_row = output[-1]
# Chop off the trailing row_ender (e.g. '') and
# insert the hidden fields.
- output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender
+ output[-1] = last_row[:-len(row_ender)] + str_hidden + \
+ row_ender
else:
# If there aren't any rows in the output, just append the
# hidden fields.
@@ -165,16 +188,35 @@ class BaseForm(StrAndUnicode):
return mark_safe(u'\n'.join(output))
def as_table(self):
- "Returns this form rendered as HTML s -- excluding the ."
- return self._html_output(u' %(label)s %(errors)s%(field)s%(help_text)s ', u'%s ', '', u' %s', False)
+ """
+ Returns this form rendered as HTML s -- excluding the
+ .
+ """
+ return self._html_output(
+ u' %(label)s %(errors)s%(field)s%(help_text)s\
+ ',
+ u'%s ',
+ '',
+ u' %s',
+ False)
def as_ul(self):
"Returns this form rendered as HTML s -- excluding the ."
- return self._html_output(u' %(errors)s%(label)s %(field)s%(help_text)s ', u'%s ', '', u' %s', False)
+ return self._html_output(
+ u'%(errors)s%(label)s %(field)s%(help_text)s ',
+ u'%s ',
+ '',
+ u' %s',
+ False)
def as_p(self):
"Returns this form rendered as HTML s."
- return self._html_output(u'
%(label)s %(field)s%(help_text)s
', u'%s', '
', u' %s', True)
+ return self._html_output(
+ u'%(label)s %(field)s%(help_text)s
',
+ u'%s',
+ '',
+ u' %s',
+ True)
def non_field_errors(self):
"""
@@ -197,7 +239,8 @@ class BaseForm(StrAndUnicode):
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
- value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
+ value = field.widget.value_from_datadict(self.data,
+ self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
@@ -238,6 +281,7 @@ class BaseForm(StrAndUnicode):
return True
return False
+
class Form(BaseForm):
"A collection of Fields, plus their associated data."
# This is a separate class from BaseForm in order to abstract the way
@@ -247,8 +291,10 @@ class Form(BaseForm):
# BaseForm itself has no way of designating self.fields.
__metaclass__ = DeclarativeFieldsMetaclass
+
class BoundField(StrAndUnicode):
"A Field plus data"
+
def __init__(self, form, field, name):
self.form = form
self.field = field
@@ -294,7 +340,8 @@ class BoundField(StrAndUnicode):
def as_text(self, attrs=None):
"""
- Returns a string of HTML for representing this as an .
+ Returns a string of HTML for representing this as
+ an .
"""
return self.as_widget(TextInput(), attrs)
@@ -304,7 +351,8 @@ class BoundField(StrAndUnicode):
def as_hidden(self, attrs=None):
"""
- Returns a string of HTML for representing this as an .
+ Returns a string of HTML for representing this as an
+ .
"""
return self.as_widget(self.field.hidden_widget(), attrs)
@@ -312,23 +360,26 @@ class BoundField(StrAndUnicode):
"""
Returns the data for this BoundField, or None if it wasn't given.
"""
- return self.field.widget.value_from_datadict(self.form.data, self.form.files, self.html_name)
+ return self.field.widget.value_from_datadict(
+ self.form.data, self.form.files, self.html_name)
data = property(_data)
def label_tag(self, contents=None, attrs=None):
"""
- Wraps the given contents in a , if the field has an ID attribute.
- Does not HTML-escape the contents. If contents aren't given, uses the
- field's HTML-escaped label.
+ Wraps the given contents in a , if the field has an ID
+ attribute. Does not HTML-escape the contents. If contents aren't
+ given, uses the field's HTML-escaped label.
- If attrs are given, they're used as HTML attributes on the tag.
+ If attrs are given, they're used as HTML attributes on the
+ tag.
"""
contents = contents or escape(self.label)
widget = self.field.widget
id_ = widget.attrs.get('id') or self.auto_id
if id_:
attrs = attrs and flatatt(attrs) or ''
- contents = '%s ' % (widget.id_for_label(id_), attrs, contents)
+ contents = '%s ' % (
+ widget.id_for_label(id_), attrs, contents)
return mark_safe(contents)
def _is_hidden(self):
@@ -339,7 +390,8 @@ class BoundField(StrAndUnicode):
def _auto_id(self):
"""
Calculates and returns the ID attribute for this BoundField, if the
- associated Form has specified auto_id. Returns an empty string otherwise.
+ associated Form has specified auto_id. Returns an empty string
+ otherwise.
"""
auto_id = self.form.auto_id
if auto_id and '%s' in smart_unicode(auto_id):
diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py
index ebbf2ab..6e7e6d0 100644
--- a/django/newforms/widgets.py
+++ b/django/newforms/widgets.py
@@ -25,9 +25,12 @@ __all__ = (
'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget',
)
+
class Widget(object):
- is_hidden = False # Determines whether this corresponds to an .
- needs_multipart_form = False # Determines does this widget need multipart-encrypted form
+ is_hidden = False # Determines whether this corresponds to
+ #an .
+ needs_multipart_form = False # Determines does this widget
+ # need multipart-encrypted form
def __init__(self, attrs=None):
if attrs is not None:
@@ -77,6 +80,7 @@ class Widget(object):
return id_
id_for_label = classmethod(id_for_label)
+
class Input(Widget):
"""
Base class for all widgets (except type='checkbox' and
@@ -85,16 +89,19 @@ class Input(Widget):
input_type = None # Subclasses must define this.
def render(self, name, value, attrs=None):
- if value is None: value = ''
+ if value is None:
+ value = ''
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if value != '':
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_unicode(value)
return mark_safe(u' ' % flatatt(final_attrs))
+
class TextInput(Input):
input_type = 'text'
+
class PasswordInput(Input):
input_type = 'password'
@@ -103,25 +110,30 @@ class PasswordInput(Input):
self.render_value = render_value
def render(self, name, value, attrs=None):
- if not self.render_value: value=None
+ if not self.render_value:
+ value=None
return super(PasswordInput, self).render(name, value, attrs)
+
class HiddenInput(Input):
input_type = 'hidden'
is_hidden = True
+
class MultipleHiddenInput(HiddenInput):
"""
A widget that handles for fields that have a list
of values.
"""
+
def __init__(self, attrs=None, choices=()):
super(MultipleHiddenInput, self).__init__(attrs)
# choices can be any iterable
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
- if value is None: value = []
+ if value is None:
+ value = []
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
return mark_safe(u'\n'.join([(u' ' %
flatatt(dict(value=force_unicode(v), **final_attrs)))
@@ -132,6 +144,7 @@ class MultipleHiddenInput(HiddenInput):
return data.getlist(name)
return data.get(name, None)
+
class FileInput(Input):
input_type = 'file'
needs_multipart_form = True
@@ -143,7 +156,9 @@ class FileInput(Input):
"File widgets take data from FILES, not POST"
return files.get(name, None)
+
class Textarea(Widget):
+
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
self.attrs = {'cols': '40', 'rows': '10'}
@@ -151,12 +166,14 @@ class Textarea(Widget):
self.attrs.update(attrs)
def render(self, name, value, attrs=None):
- if value is None: value = ''
+ if value is None:
+ value = ''
value = force_unicode(value)
final_attrs = self.build_attrs(attrs, name=name)
return mark_safe(u'' % (flatatt(final_attrs),
conditional_escape(force_unicode(value))))
+
class DateTimeInput(Input):
input_type = 'text'
format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59'
@@ -173,7 +190,9 @@ class DateTimeInput(Input):
value = value.strftime(self.format)
return super(DateTimeInput, self).render(name, value, attrs)
+
class CheckboxInput(Widget):
+
def __init__(self, attrs=None, check_test=bool):
super(CheckboxInput, self).__init__(attrs)
# check_test is a callable that takes a value and returns True
@@ -198,9 +217,12 @@ class CheckboxInput(Widget):
# A missing value means False because HTML form submission does not
# send results for unselected checkboxes.
return False
- return super(CheckboxInput, self).value_from_datadict(data, files, name)
+ return super(CheckboxInput, self).value_from_datadict(
+ data, files, name)
+
class Select(Widget):
+
def __init__(self, attrs=None, choices=()):
super(Select, self).__init__(attrs)
# choices can be any iterable, but we may need to render this widget
@@ -209,26 +231,31 @@ class Select(Widget):
self.choices = list(choices)
def render(self, name, value, attrs=None, choices=()):
- if value is None: value = ''
+ if value is None:
+ value = ''
final_attrs = self.build_attrs(attrs, name=name)
output = [u'' % flatatt(final_attrs)]
# Normalize to string.
str_value = force_unicode(value)
for option_value, option_label in chain(self.choices, choices):
option_value = force_unicode(option_value)
- selected_html = (option_value == str_value) and u' selected="selected"' or ''
+ selected_html = (option_value == str_value) and \
+ u' selected="selected"' or ''
output.append(u'%s ' % (
escape(option_value), selected_html,
conditional_escape(force_unicode(option_label))))
output.append(u' ')
return mark_safe(u'\n'.join(output))
+
class NullBooleanSelect(Select):
"""
A Select Widget intended to be used with NullBooleanField.
"""
+
def __init__(self, attrs=None):
- choices = ((u'1', ugettext('Unknown')), (u'2', ugettext('Yes')), (u'3', ugettext('No')))
+ choices = ((u'1', ugettext('Unknown')), (u'2', ugettext('Yes')),
+ (u'3', ugettext('No')))
super(NullBooleanSelect, self).__init__(attrs, choices)
def render(self, name, value, attrs=None, choices=()):
@@ -236,26 +263,33 @@ class NullBooleanSelect(Select):
value = {True: u'2', False: u'3', u'2': u'2', u'3': u'3'}[value]
except KeyError:
value = u'1'
- return super(NullBooleanSelect, self).render(name, value, attrs, choices)
+ return super(NullBooleanSelect, self).render(
+ name, value, attrs, choices)
def value_from_datadict(self, data, files, name):
value = data.get(name, None)
- return {u'2': True, u'3': False, True: True, False: False}.get(value, None)
+ return {u'2': True, u'3': False, True: True, False: False}.get(
+ value, None)
+
class SelectMultiple(Widget):
+
def __init__(self, attrs=None, choices=()):
super(SelectMultiple, self).__init__(attrs)
# choices can be any iterable
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
- if value is None: value = []
+ if value is None:
+ value = []
final_attrs = self.build_attrs(attrs, name=name)
output = [u'' % flatatt(final_attrs)]
- str_values = set([force_unicode(v) for v in value]) # Normalize to strings.
+ # Normalize to strings.
+ str_values = set([force_unicode(v) for v in value])
for option_value, option_label in chain(self.choices, choices):
option_value = force_unicode(option_value)
- selected_html = (option_value in str_values) and ' selected="selected"' or ''
+ selected_html = (option_value in str_values) and \
+ ' selected="selected"' or ''
output.append(u'%s ' % (
escape(option_value), selected_html,
conditional_escape(force_unicode(option_label))))
@@ -267,6 +301,7 @@ class SelectMultiple(Widget):
return data.getlist(name)
return data.get(name, None)
+
class RadioInput(StrAndUnicode):
"""
An object used by RadioFieldRenderer that represents a single
@@ -286,7 +321,8 @@ class RadioInput(StrAndUnicode):
else:
label_for = ''
choice_label = conditional_escape(force_unicode(self.choice_label))
- return mark_safe(u'%s %s ' % (label_for, self.tag(), choice_label))
+ return mark_safe(u'%s %s ' % (
+ label_for, self.tag(), choice_label))
def is_checked(self):
return self.value == self.choice_value
@@ -294,11 +330,13 @@ class RadioInput(StrAndUnicode):
def tag(self):
if 'id' in self.attrs:
self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index)
- final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
+ final_attrs = dict(self.attrs, type='radio',
+ name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return mark_safe(u' ' % flatatt(final_attrs))
+
class RadioFieldRenderer(StrAndUnicode):
"""
An object used by RadioSelect to enable customization of radio widgets.
@@ -310,11 +348,13 @@ class RadioFieldRenderer(StrAndUnicode):
def __iter__(self):
for i, choice in enumerate(self.choices):
- yield RadioInput(self.name, self.value, self.attrs.copy(), choice, i)
+ yield RadioInput(self.name, self.value, self.attrs.copy(),
+ choice, i)
def __getitem__(self, idx):
choice = self.choices[idx] # Let the IndexError propogate
- return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
+ return RadioInput(self.name, self.value, self.attrs.copy(),
+ choice, idx)
def __unicode__(self):
return self.render()
@@ -324,6 +364,7 @@ class RadioFieldRenderer(StrAndUnicode):
return mark_safe(u'' % u'\n'.join([u'%s '
% force_unicode(w) for w in self]))
+
class RadioSelect(Select):
renderer = RadioFieldRenderer
@@ -336,7 +377,8 @@ class RadioSelect(Select):
def get_renderer(self, name, value, attrs=None, choices=()):
"""Returns an instance of the renderer."""
- if value is None: value = ''
+ if value is None:
+ value = ''
str_value = force_unicode(value) # Normalize to string.
final_attrs = self.build_attrs(attrs)
choices = list(chain(self.choices, choices))
@@ -355,15 +397,19 @@ class RadioSelect(Select):
return id_
id_for_label = classmethod(id_for_label)
+
class CheckboxSelectMultiple(SelectMultiple):
+
def render(self, name, value, attrs=None, choices=()):
- if value is None: value = []
+ if value is None:
+ value = []
has_id = attrs and 'id' in attrs
final_attrs = self.build_attrs(attrs, name=name)
output = [u'']
# Normalize to strings
str_values = set([force_unicode(v) for v in value])
- for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
+ for i, (option_value, option_label) in enumerate(chain(
+ self.choices, choices)):
# If an ID attribute was given, add a numeric index as a suffix,
# so that the checkboxes don't all have the same ID attribute.
if has_id:
@@ -371,12 +417,14 @@ class CheckboxSelectMultiple(SelectMultiple):
label_for = u' for="%s"' % final_attrs['id']
else:
label_for = ''
-
- cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
+
+ cb = CheckboxInput(final_attrs,
+ check_test=lambda value: value in str_values)
option_value = force_unicode(option_value)
rendered_cb = cb.render(name, option_value)
option_label = conditional_escape(force_unicode(option_label))
- output.append(u'%s %s ' % (label_for, rendered_cb, option_label))
+ output.append(u'%s %s ' % (
+ label_for, rendered_cb, option_label))
output.append(u' ')
return mark_safe(u'\n'.join(output))
@@ -387,6 +435,7 @@ class CheckboxSelectMultiple(SelectMultiple):
return id_
id_for_label = classmethod(id_for_label)
+
class MultiWidget(Widget):
"""
A widget that is composed of multiple widgets.
@@ -414,6 +463,7 @@ class MultiWidget(Widget):
You'll probably want to use this class with MultiValueField.
"""
+
def __init__(self, widgets, attrs=None):
self.widgets = [isinstance(w, type) and w() or w for w in widgets]
super(MultiWidget, self).__init__(attrs)
@@ -433,7 +483,8 @@ class MultiWidget(Widget):
widget_value = None
if id_:
final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
- output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
+ output.append(widget.render(name + '_%s' % i, widget_value,
+ final_attrs))
return mark_safe(self.format_output(output))
def id_for_label(self, id_):
@@ -444,7 +495,8 @@ class MultiWidget(Widget):
id_for_label = classmethod(id_for_label)
def value_from_datadict(self, data, files, name):
- return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
+ return [widget.value_from_datadict(data, files, name + '_%s' % i) \
+ for i, widget in enumerate(self.widgets)]
def format_output(self, rendered_widgets):
"""
@@ -464,10 +516,12 @@ class MultiWidget(Widget):
"""
raise NotImplementedError('Subclasses must implement this method.')
+
class SplitDateTimeWidget(MultiWidget):
"""
A Widget that splits datetime input into two boxes.
"""
+
def __init__(self, attrs=None):
widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs))
super(SplitDateTimeWidget, self).__init__(widgets, attrs)
@@ -476,4 +530,3 @@ class SplitDateTimeWidget(MultiWidget):
if value:
return [value.date(), value.time().replace(microsecond=0)]
return [None, None]
-
--
1.5.5.1