from django.forms import * from django.conf import settings as dj_settings from django.utils import formats from dojango.forms import widgets from dojango.util import json_encode __all__ = ( 'Field', 'DEFAULT_DATE_INPUT_FORMATS', 'DEFAULT_TIME_INPUT_FORMATS', # original django classes 'DEFAULT_DATETIME_INPUT_FORMATS', 'MultiValueField', 'ComboField', # original django classes 'DojoFieldMixin', 'CharField', 'ChoiceField', 'TypedChoiceField', 'IntegerField', 'BooleanField', 'FileField', 'ImageField', 'DateField', 'TimeField', 'DateTimeField', 'SplitDateTimeField', 'RegexField', 'DecimalField', 'FloatField', 'FilePathField', 'MultipleChoiceField', 'NullBooleanField', 'EmailField', 'IPAddressField', 'URLField', 'SlugField', ) class DojoFieldMixin(object): """ A general mixin for all custom django/dojo form fields. It passes the field attributes in 'passed_attrs' to the form widget, so they can be used there. The widget itself then evaluates which of these fiels will be used. """ passed_attrs = [ # forwarded field->widget attributes 'required', 'help_text', 'min_value', 'max_value', 'max_length', 'max_digits', 'decimal_places', 'js_regex', # special key for some dojo widgets ] def widget_attrs(self, widget): """Called, when the field is instanitating the widget. Here we collect all field attributes and pass it to the attributes of the widgets using the 'extra_field_attrs' key. These additional attributes will be evaluated by the widget and deleted within the 'DojoWidgetMixin'. """ ret = {'extra_field_attrs': {}} for field_attr in self.passed_attrs: field_val = getattr(self, field_attr, None) #print field_attr, widget, field_val if field_val is not None: ret['extra_field_attrs'][field_attr] = field_val return ret ############################################### # IMPLEMENTATION OF ALL EXISTING DJANGO FIELDS ############################################### class CharField(DojoFieldMixin, fields.CharField): widget = widgets.ValidationTextInput class ChoiceField(DojoFieldMixin, fields.ChoiceField): widget = widgets.Select class TypedChoiceField(DojoFieldMixin, fields.TypedChoiceField): widget = widgets.Select class IntegerField(DojoFieldMixin, fields.IntegerField): widget = widgets.NumberTextInput decimal_places = 0 class BooleanField(DojoFieldMixin, fields.BooleanField): widget = widgets.CheckboxInput class FileField(DojoFieldMixin, fields.FileField): widget = widgets.FileInput class ImageField(DojoFieldMixin, fields.ImageField): widget = widgets.FileInput class DateField(DojoFieldMixin, fields.DateField): widget = widgets.DateInput def __init__(self, input_formats=None, min_value=None, max_value=None, *args, **kwargs): kwargs['input_formats'] = input_formats or \ tuple(list(formats.get_format('DATE_INPUT_FORMATS')) + [ '%Y-%m-%dT%H:%M', '%Y-%m-%dT%H:%M:%S' # also support dojo's default date-strings ]) self.max_value = max_value self.min_value = min_value super(DateField, self).__init__(*args, **kwargs) class TimeField(DojoFieldMixin, fields.TimeField): widget = widgets.TimeInput def __init__(self, input_formats=None, min_value=None, max_value=None, *args, **kwargs): kwargs['input_formats'] = input_formats or \ tuple(list(formats.get_format('TIME_INPUT_FORMATS')) + [ '%Y-%m-%dT%H:%M', '%Y-%m-%dT%H:%M:%S', 'T%H:%M:%S', 'T%H:%M' # also support dojo's default time-strings ]) self.max_value = max_value self.min_value = min_value super(TimeField, self).__init__(*args, **kwargs) class SplitDateTimeField(DojoFieldMixin, fields.SplitDateTimeField): widget = widgets.DateTimeInput def __init__(self, min_value=None, max_value=None, *args, **kwargs): self.max_value = max_value self.min_value = min_value super(SplitDateTimeField, self).__init__(*args, **kwargs) # Overwrite the SplitDateTimeField # copied from original SplitDateTimeField of django errors = self.default_error_messages.copy() if 'error_messages' in kwargs: errors.update(kwargs['error_messages']) fields = ( DateField(error_messages={'invalid': errors['invalid_date']}), TimeField(error_messages={'invalid': errors['invalid_time']}), ) # copied from original MultiValueField of django for f in fields: f.required = False self.fields = fields DateTimeField = SplitDateTimeField # datetime-field is always splitted class RegexField(DojoFieldMixin, fields.RegexField): widget = widgets.ValidationTextInput js_regex = None # we additionally have to define a custom javascript regexp, because the python one is not compatible to javascript def __init__(self, js_regex=None, *args, **kwargs): self.js_regex = js_regex super(RegexField, self).__init__(*args, **kwargs) class DecimalField(DojoFieldMixin, fields.DecimalField): widget = widgets.NumberTextInput class FloatField(DojoFieldMixin, fields.FloatField): widget = widgets.ValidationTextInput class FilePathField(DojoFieldMixin, fields.FilePathField): widget = widgets.Select class MultipleChoiceField(DojoFieldMixin, fields.MultipleChoiceField): widget = widgets.SelectMultiple class NullBooleanField(DojoFieldMixin, fields.NullBooleanField): widget = widgets.NullBooleanSelect class EmailField(DojoFieldMixin, fields.EmailField): widget = widgets.EmailTextInput class IPAddressField(DojoFieldMixin, fields.IPAddressField): widget = widgets.IPAddressTextInput class URLField(DojoFieldMixin, fields.URLField): widget = widgets.URLTextInput class SlugField(DojoFieldMixin, fields.SlugField): widget = widgets.ValidationTextInput js_regex = '^[-\w]+$' # we cannot extract the original regex input from the python regex