Source code for shuup.admin.forms.fields

# This file is part of Shuup.
#
# Copyright (c) 2012-2021, Shuup Commerce Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
from decimal import Decimal
from django.forms import DecimalField, Field, MultipleChoiceField, Select, SelectMultiple
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from numbers import Number


[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(PercentageField, self).prepare_value(value)
[docs] def to_python(self, value): value = super(PercentageField, self).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(PercentageField, self).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): widget = Select def __init__(self, model, *args, **kwargs): self.model = model super(Select2ModelField, self).__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(Select2ModelField, self).widget_attrs(widget) model_name = "%s.%s" % (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): widget = SelectMultiple def __init__(self, model, search_mode=None, *args, **kwargs): self.model = model if search_mode: self.search_mode = search_mode super(Select2MultipleField, self).__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(Select2MultipleField, self).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(Select2MultipleField, self).widget_attrs(widget) model_name = "%s.%s" % (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. """
[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."""
[docs] def widget_attrs(self, widget): attrs = super(Select2MultipleMainProductField, self).widget_attrs(widget) attrs.update({"data-search-mode": "main"}) return attrs
[docs]class WeekdaysSelectMultiple(SelectMultiple):
[docs] def format_value(self, value): 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")), ] 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(WeekdayField, self).clean(value))