Source code for shuup.admin.forms.fields

from decimal import Decimal
from numbers import Number

from django.core.exceptions import ValidationError
from django.forms import DecimalField, Field, MultipleChoiceField, Select, SelectMultiple
from django.utils.translation import gettext_lazy as _

from shuup.utils.django_compat import force_text


[docs] class PercentageField(DecimalField): MULTIPLIER = Decimal(100)
[docs] def prepare_value(self, value): # Percentage values are 0..1 in database, so multiply by 100 if value is not None and isinstance(value, Number): value *= self.MULTIPLIER return super().prepare_value(value)
[docs] def to_python(self, value): value = super().to_python(value) if value is not None: # We got a value, so divide it by 100 to get the 0..1 range value value /= self.MULTIPLIER return value
[docs] def widget_attrs(self, widget): attrs = super().widget_attrs(widget) if self.min_value is not None: attrs["min"] = self.min_value * self.MULTIPLIER if self.max_value is not None: attrs["max"] = self.max_value * self.MULTIPLIER return attrs
[docs] class Select2ModelField(Field): """ This form field class is deprecated and it will be removed on version 3. Use ObjectSelect2ModelField class instead. """ widget = Select
[docs] def __init__(self, model, *args, **kwargs): self.model = model super().__init__(*args, **kwargs)
[docs] def prepare_value(self, value): return getattr(value, "pk", value)
[docs] def to_python(self, value): if value: return self.model.objects.filter(pk=value).first()
[docs] def widget_attrs(self, widget): attrs = super().widget_attrs(widget) model_name = f"{self.model._meta.app_label}.{self.model._meta.model_name}" attrs.update({"data-model": model_name}) if not self.required: attrs["data-allow-clear"] = "true" attrs["data-placeholder"] = _("Select an option") return attrs
[docs] class Select2MultipleField(Field): """ This form field class is deprecated and it will be removed on version 3. Use ObjectSelect2MultipleField class instead. """ widget = SelectMultiple
[docs] def __init__(self, model, search_mode=None, *args, **kwargs): self.model = model if search_mode: self.search_mode = search_mode super().__init__(*args, **kwargs)
[docs] def prepare_value(self, value): values = [getattr(v, "pk", v) for v in value or []] # make sure to add the initial values as choices to the field if values and not self.widget.choices: from django.utils.encoding import force_text self.widget.choices = [ (instance.pk, force_text(instance)) for instance in self.model.objects.filter(pk__in=values) ] return values
[docs] def to_python(self, value): value = super().to_python(value) # Here we have sometimes None which will cause errors when # saving related fields so let's fallback to empty list return value or []
[docs] def widget_attrs(self, widget): attrs = super().widget_attrs(widget) model_name = f"{self.model._meta.app_label}.{self.model._meta.model_name}" attrs.update({"data-model": model_name}) if getattr(self, "search_mode", None): attrs.update({"data-search-mode": self.search_mode}) if not self.required: attrs["data-allow-clear"] = "true" return attrs
[docs] class Select2ModelMultipleField(Select2MultipleField): """ Just like Select2MultipleField, but return instances instead of ids. This form field class is deprecated and it will be removed on version 3. Use ObjectSelect2ModelMultipleField class instead. """
[docs] def prepare_value(self, value): return [getattr(v, "pk", v) for v in value or []]
[docs] def to_python(self, value): if value and isinstance(value, (list, tuple)): value = [v for v in value if v] if value: return self.model.objects.filter(pk__in=value) return []
[docs] class Select2MultipleMainProductField(Select2MultipleField): """ Search only from parent and normal products. This form field class is deprecated and it will be removed on version 3. Use ObjectSelect2MultipleMainProductField class instead. """
[docs] def widget_attrs(self, widget): attrs = super().widget_attrs(widget) attrs.update({"data-search-mode": "main"}) return attrs
[docs] class WeekdaysSelectMultiple(SelectMultiple):
[docs] def format_value(self, value): # TODO: Used with WeekdayField test, but not sure if this is correct. if value is None and self.allow_multiple_selected: return [] if isinstance(value, str): value = value.split(",") if not isinstance(value, (tuple, list)): value = [value] return [force_text(v) if v is not None else "" for v in value]
[docs] class WeekdayField(MultipleChoiceField): widget = WeekdaysSelectMultiple DAYS_OF_THE_WEEK = [ (0, _("Monday")), (1, _("Tuesday")), (2, _("Wednesday")), (3, _("Thursday")), (4, _("Friday")), (5, _("Saturday")), (6, _("Sunday")), ]
[docs] def __init__( self, choices=(), required=True, widget=None, label=None, initial=None, help_text="", *args, **kwargs, ): if not choices: choices = self.DAYS_OF_THE_WEEK super().__init__( choices=choices, required=required, widget=widget, label=label, initial=initial, help_text=help_text, **kwargs, )
[docs] def clean(self, value): return ",".join(super().clean(value))
[docs] class ObjectSelect2ModelField(Select2ModelField): """ Class for select2 form fields. Replacement for the class Select2ModelField. """
[docs] def __init__(self, model, selector=None, search_mode=None, *args, **kwargs): super().__init__(model, *args, **kwargs) self.selector = selector
[docs] def prepare_value(self, value): if self.model: return super().prepare_value(value) return value
[docs] def to_python(self, value): if self.model: return super().to_python(value) return value
[docs] def widget_attrs(self, widget): if self.model: attrs = super().widget_attrs(widget) else: attrs = super(Select2ModelField, self).widget_attrs(widget) attrs["data-model"] = self.selector if not self.required: attrs["data-allow-clear"] = "true" attrs["data-placeholder"] = _("Select an option") attrs["class"] = "object-selector" return attrs
[docs] class ObjectSelect2MultipleField(Select2MultipleField): """ Class for select2 form fields. Replacement for the class Select2MultipleField. """
[docs] def __init__(self, model, selector=None, search_mode=None, *args, **kwargs): super().__init__(model, *args, **kwargs) self.selector = selector
[docs] def prepare_value(self, value): if self.model: return super().prepare_value(value) return value
[docs] def to_python(self, value): if self.model: return super().to_python(value) if not value: return [] elif not isinstance(value, (list, tuple)): raise ValidationError(self.error_messages["invalid_list"], code="invalid_list") return [str(val) for val in value]
[docs] def widget_attrs(self, widget): if self.model: attrs = super().widget_attrs(widget) else: attrs = super(Select2MultipleField, self).widget_attrs(widget) attrs["data-model"] = self.selector if getattr(self, "search_mode", None): attrs.update({"data-search-mode": self.search_mode}) if not self.required: attrs["data-allow-clear"] = "true" attrs["class"] = "object-selector" return attrs
[docs] class ObjectSelect2ModelMultipleField(Select2ModelMultipleField): """ Class for select2 form fields. Replacement for the class Select2ModelMultipleField. """
[docs] def __init__(self, model, selector=None, search_mode=None, *args, **kwargs): super().__init__(model, *args, **kwargs) self.selector = selector
[docs] def prepare_value(self, value): if self.model: return super().prepare_value(value) return list(value or [])
[docs] def to_python(self, value): if self.model: return super().to_python(value) if value and isinstance(value, (list, tuple)): return value return []
[docs] def widget_attrs(self, widget): if self.model: attrs = super().widget_attrs(widget) else: attrs = super(Select2MultipleField, self).widget_attrs(widget) attrs["data-model"] = self.selector if getattr(self, "search_mode", None): attrs.update({"data-search-mode": self.search_mode}) if not self.required: attrs["data-allow-clear"] = "true" attrs["class"] = "object-selector" return attrs
[docs] class ObjectSelect2MultipleMainProductField(Select2MultipleMainProductField): """ Class for select2 form fields. Replacement for the class Select2MultipleMainProductField. """
[docs] def __init__(self, model, selector=None, search_mode=None, *args, **kwargs): super().__init__(model, *args, **kwargs) self.selector = selector
[docs] def prepare_value(self, value): if self.model: return super().prepare_value(value) return list(value or [])
[docs] def to_python(self, value): if self.model: return super().to_python(value) if value and isinstance(value, (list, tuple)): return value return []
[docs] def widget_attrs(self, widget): if self.model: attrs = super().widget_attrs(widget) else: attrs = super(Select2MultipleField, self).widget_attrs(widget) attrs["data-model"] = self.selector if getattr(self, "search_mode", None): attrs.update({"data-search-mode": self.search_mode}) if not self.required: attrs["data-allow-clear"] = "true" return attrs attrs["class"] = "object-selector" return attrs