adm-ntuh-net/ntuh/dojango/forms/fields.py
2024-12-12 10:19:16 +08:00

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