mirror of
https://github.com/SectorLabs/django-localized-fields.git
synced 2025-12-14 07:42:24 +03:00
added new LocalizedCharField, LocalizedTextField and LocalizedFileField fields
This commit is contained in:
@@ -2,10 +2,13 @@ from typing import List
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms.widgets import FILE_INPUT_CONTRADICTION
|
||||
|
||||
from .localized_value import LocalizedValue
|
||||
from .widgets import LocalizedFieldWidget
|
||||
|
||||
from .localized_value import LocalizedValue, LocalizedStingValue, \
|
||||
LocalizedFileValue
|
||||
from .widgets import LocalizedFieldWidget, LocalizedCharFieldWidget, \
|
||||
LocalizedFileWidget
|
||||
|
||||
|
||||
class LocalizedFieldForm(forms.MultiValueField):
|
||||
@@ -13,6 +16,7 @@ class LocalizedFieldForm(forms.MultiValueField):
|
||||
the field in multiple languages."""
|
||||
|
||||
widget = LocalizedFieldWidget
|
||||
field_class = forms.fields.CharField
|
||||
value_class = LocalizedValue
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -27,7 +31,7 @@ class LocalizedFieldForm(forms.MultiValueField):
|
||||
field_options['required'] = kwargs.get('required', True)
|
||||
|
||||
field_options['label'] = lang_code
|
||||
fields.append(forms.fields.CharField(**field_options))
|
||||
fields.append(self.field_class(**field_options))
|
||||
|
||||
super(LocalizedFieldForm, self).__init__(
|
||||
fields,
|
||||
@@ -57,3 +61,106 @@ class LocalizedFieldForm(forms.MultiValueField):
|
||||
localized_value.set(lang_code, value)
|
||||
|
||||
return localized_value
|
||||
|
||||
|
||||
class LocalizedCharFieldForm(LocalizedFieldForm):
|
||||
"""Form for a localized char field, allows editing
|
||||
the field in multiple languages."""
|
||||
|
||||
widget = LocalizedCharFieldWidget
|
||||
value_class = LocalizedStingValue
|
||||
|
||||
|
||||
class LocalizedTextFieldForm(LocalizedFieldForm):
|
||||
"""Form for a localized text field, allows editing
|
||||
the field in multiple languages."""
|
||||
|
||||
value_class = LocalizedStingValue
|
||||
|
||||
|
||||
class LocalizedFileFieldForm(LocalizedFieldForm, forms.FileField):
|
||||
"""Form for a localized file field, allows editing
|
||||
the field in multiple languages."""
|
||||
|
||||
widget = LocalizedFileWidget
|
||||
field_class = forms.fields.FileField
|
||||
value_class = LocalizedFileValue
|
||||
|
||||
def clean(self, value, initial=None):
|
||||
"""
|
||||
Most part of this method is a copy of
|
||||
django.forms.MultiValueField.clean, with the exception of initial
|
||||
value handling (this need for correct processing FileField's).
|
||||
All original comments saved.
|
||||
"""
|
||||
if initial is None:
|
||||
initial = [None for x in range(0, len(value))]
|
||||
else:
|
||||
if not isinstance(initial, list):
|
||||
initial = self.widget.decompress(initial)
|
||||
|
||||
clean_data = []
|
||||
errors = []
|
||||
if not value or isinstance(value, (list, tuple)):
|
||||
if (not value or not [v for v in value if
|
||||
v not in self.empty_values]) \
|
||||
and (not initial or not [v for v in initial if
|
||||
v not in self.empty_values]):
|
||||
if self.required:
|
||||
raise ValidationError(self.error_messages['required'],
|
||||
code='required')
|
||||
else:
|
||||
raise ValidationError(self.error_messages['invalid'],
|
||||
code='invalid')
|
||||
for i, field in enumerate(self.fields):
|
||||
try:
|
||||
field_value = value[i]
|
||||
except IndexError:
|
||||
field_value = None
|
||||
try:
|
||||
field_initial = initial[i]
|
||||
except IndexError:
|
||||
field_initial = None
|
||||
if field_value in self.empty_values and \
|
||||
field_initial in self.empty_values:
|
||||
if self.require_all_fields:
|
||||
# Raise a 'required' error if the MultiValueField is
|
||||
# required and any field is empty.
|
||||
if self.required:
|
||||
raise ValidationError(self.error_messages['required'],
|
||||
code='required')
|
||||
elif field.required:
|
||||
# Otherwise, add an 'incomplete' error to the list of
|
||||
# collected errors and skip field cleaning, if a required
|
||||
# field is empty.
|
||||
if field.error_messages['incomplete'] not in errors:
|
||||
errors.append(field.error_messages['incomplete'])
|
||||
continue
|
||||
try:
|
||||
clean_data.append(field.clean(field_value, field_initial))
|
||||
except ValidationError as e:
|
||||
# Collect all validation errors in a single list, which we'll
|
||||
# raise at the end of clean(), rather than raising a single
|
||||
# exception for the first error we encounter. Skip duplicates.
|
||||
errors.extend(m for m in e.error_list if m not in errors)
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
out = self.compress(clean_data)
|
||||
self.validate(out)
|
||||
self.run_validators(out)
|
||||
return out
|
||||
|
||||
def bound_data(self, data, initial):
|
||||
bound_data = []
|
||||
if initial is None:
|
||||
initial = [None for x in range(0, len(data))]
|
||||
else:
|
||||
if not isinstance(initial, list):
|
||||
initial = self.widget.decompress(initial)
|
||||
for d, i in zip(data, initial):
|
||||
if d in (None, FILE_INPUT_CONTRADICTION):
|
||||
bound_data.append(i)
|
||||
else:
|
||||
bound_data.append(d)
|
||||
return bound_data
|
||||
|
||||
Reference in New Issue
Block a user