158 lines
6.1 KiB
Python
Executable file
158 lines
6.1 KiB
Python
Executable file
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
|