from functools import lru_cache
from flask_babel import lazy_gettext as _
from mongoengine import fields
from werkzeug.utils import import_string
from .base import AbstractBaseField
from .string import StringField
class DynamicField(AbstractBaseField, fields.DynamicField):
"""A dynamic field."""
field_name = _('Dynamisch')
_allow_multilingual = True
_allow_multivalue = True
class FieldClassField(StringField):
"""A field that references another field class."""
field_name = _('Feld Typ')
FIELDS_MODULE = 'xmm.models.fields'
@classmethod
@lru_cache()
def get_field_class(cls, import_path):
"""
Get the Field class for a given import path.
:param str import_path:
"""
if isinstance(import_path, type) and issubclass(import_path, fields.BaseField):
return import_path
if import_path.islower():
# old style datatype references
import_path = '{}.{}Field'.format(cls.FIELDS_MODULE, import_path.capitalize())
if '.' not in import_path:
import_path = '{}.{}'.format(cls.FIELDS_MODULE, import_path)
try:
return import_string(import_path)
except ImportError:
raise
def __set__(self, instance, value):
if isinstance(value, str):
value = FieldClassField.get_field_class(value)
return super().__set__(instance, value)
def __get__(self, instance, owner):
value = super().__get__(instance, owner)
if isinstance(value, str):
return FieldClassField.get_field_class(value)
return value
def to_mongo(self, value):
return value.get_name()
def to_python(self, value):
return FieldClassField.get_field_class(value)
def to_str(self, value, format_spec=None):
value = self.to_python(value)
return value.type_name
def validate(self, value):
if not issubclass(value, AbstractBaseField):
self.error('Only Fields may be used.')
return super().validate(self.to_mongo(value))