Add LocalizedFloatField

This commit is contained in:
Alexandru Arnautu 2020-03-09 12:12:45 +02:00
parent 0d9ec6385c
commit 5ed1a1219d
2 changed files with 93 additions and 0 deletions

View File

@ -5,6 +5,7 @@ from .file_field import LocalizedFileField
from .integer_field import LocalizedIntegerField
from .text_field import LocalizedTextField
from .uniqueslug_field import LocalizedUniqueSlugField
from .float_field import LocalizedFloatField
__all__ = [
"LocalizedField",
@ -14,6 +15,7 @@ __all__ = [
"LocalizedTextField",
"LocalizedFileField",
"LocalizedIntegerField",
"LocalizedFloatField"
]
try:

View File

@ -0,0 +1,91 @@
from typing import Optional, Union, Dict
from django.conf import settings
from django.db.utils import IntegrityError
from .field import LocalizedField
from ..value import LocalizedValue, LocalizedFloatValue
from ..forms import LocalizedIntegerFieldForm
class LocalizedFloatField(LocalizedField):
"""Stores float as a localized value."""
attr_class = LocalizedFloatValue
@classmethod
def from_db_value(cls, value, *_) -> Optional[LocalizedFloatValue]:
db_value = super().from_db_value(value)
if db_value is None:
return db_value
# if we were used in an expression somehow then it might be
# that we're returning an individual value or an array, so
# we should not convert that into an :see:LocalizedFloatValue
if not isinstance(db_value, LocalizedValue):
return db_value
return cls._convert_localized_value(db_value)
def to_python(self, value: Union[Dict[str, int], int, None]) -> LocalizedFloatValue:
"""Converts the value from a database value into a Python value."""
db_value = super().to_python(value)
return self._convert_localized_value(db_value)
def get_prep_value(self, value: LocalizedFloatValue) -> dict:
"""Gets the value in a format to store into the database."""
# apply default values
default_values = LocalizedFloatValue(self.default)
if isinstance(value, LocalizedFloatValue):
for lang_code, _ in settings.LANGUAGES:
local_value = value.get(lang_code)
if local_value is None:
value.set(lang_code, default_values.get(lang_code, None))
prepped_value = super().get_prep_value(value)
if prepped_value is None:
return None
# make sure all values are proper floats
for lang_code, _ in settings.LANGUAGES:
local_value = prepped_value[lang_code]
try:
if local_value is not None:
float(local_value)
except (TypeError, ValueError):
raise IntegrityError('non-float value in column "%s.%s" violates '
'float constraint' % (self.name, lang_code))
# convert to a string before saving because the underlying
# type is hstore, which only accept strings
prepped_value[lang_code] = str(local_value) if local_value is not None else None
return prepped_value
def formfield(self, **kwargs):
"""Gets the form field associated with this field."""
defaults = {
'form_class': LocalizedIntegerFieldForm
}
defaults.update(kwargs)
return super().formfield(**defaults)
@staticmethod
def _convert_localized_value(value: LocalizedValue) -> LocalizedFloatValue:
"""Converts from :see:LocalizedValue to :see:LocalizedFloatValue."""
float_values = {}
for lang_code, _ in settings.LANGUAGES:
local_value = value.get(lang_code, None)
if local_value is None or local_value.strip() == '':
local_value = None
try:
float_values[lang_code] = float(local_value)
except (ValueError, TypeError):
float_values[lang_code] = None
return LocalizedFloatValue(float_values)