Skip to content
Snippets Groups Projects
Verified Commit 80c6c0d9 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Move most of field type specifics to template field model

parent 5b119ed7
Branches
Tags
No related merge requests found
......@@ -13,29 +13,16 @@ from django.utils.translation import gettext as _
class FieldType:
name: str = ""
verbose_name: str = ""
models: Sequence = []
data_type: type = str
converter: Optional[Callable] = None
alternative: Optional[str] = None
match: bool = False
@classproperty
def column_name(cls) -> str:
return cls.name
class MatchFieldType(FieldType):
"""Field type for getting an instance."""
db_field: str = ""
priority: int = 1
class DirectMappingFieldType(FieldType):
"""Set value directly in DB."""
db_field: str = ""
class ProcessFieldType(FieldType):
"""Field type with custom logic for importing."""
......@@ -57,11 +44,9 @@ class MultipleValuesFieldType(ProcessFieldType):
class FieldTypeRegistry:
def __init__(self):
self.field_types = {}
self.allowed_field_types_for_models = {}
self.allowed_models = set()
# FIXME Fill dynamically
self.allowed_models = set(Person, Group)
self.converters = {}
self.alternatives = {}
self.match_field_types = []
def register(self, field_type: Type[FieldType]):
"""Add new :class:`FieldType` to registry.
......@@ -72,18 +57,9 @@ class FieldTypeRegistry:
raise ValueError(f"The field type {field_type.name} is already registered.")
self.field_types[field_type.name] = field_type
for model in field_type.models:
self.allowed_field_types_for_models.setdefault(model, []).append(field_type)
self.allowed_models.add(model)
if field_type.converter:
self.converters[field_type.name] = field_type.converter
if field_type.alternative:
self.alternatives[field_type] = field_type.alternative
if issubclass(field_type, MatchFieldType):
self.match_field_types.append((field_type.priority, field_type))
return field_type
def get_from_name(self, name: str) -> FieldType:
......@@ -103,142 +79,48 @@ class FieldTypeRegistry:
field_type_registry = FieldTypeRegistry()
class UniqueReferenceFieldType(MatchFieldType):
class UniqueReferenceFieldType(FieldType):
name = "unique_reference"
verbose_name = _("Unique reference")
models = [Person, Group]
db_field = "import_ref_csv"
priority = 10
match = True
field_type_registry.register(UniqueReferenceFieldType)
@field_type_registry.register
class IsActiveFieldType(DirectMappingFieldType):
name = "is_active"
verbose_name = _("Is active? (0/1)")
models = [Person]
db_field = "is_active"
class BoolFieldType(FieldType):
name = "bool"
verbose_name = _("Boolean type (True/False)")
data_type = bool
@field_type_registry.register
class NameFieldType(DirectMappingFieldType):
name = "name"
verbose_name = _("Name")
models = [Group]
db_field = "name"
alternative = "short_name"
@field_type_registry.register
class FirstNameFieldType(DirectMappingFieldType):
name = "first_name"
verbose_name = _("First name")
models = [Person]
db_field = "first_name"
@field_type_registry.register
class LastNameFieldType(DirectMappingFieldType):
name = "last_name"
verbose_name = _("Last name")
models = [Person]
db_field = "last_name"
@field_type_registry.register
class AdditionalNameFieldType(DirectMappingFieldType):
name = "additional_name"
verbose_name = _("Additional name")
models = [Person]
db_field = "additional_name"
@field_type_registry.register
class ShortNameFieldType(MatchFieldType):
name = "short_name"
verbose_name = _("Short name")
models = [Person, Group]
priority = 8
db_field = "short_name"
alternative = "name"
class CharFieldType(FieldType):
name = "char"
verbose_name = _("Free text")
@field_type_registry.register
class EmailFieldType(DirectMappingFieldType):
name = "email"
verbose_name = _("Email")
models = [Person]
db_field = "email"
@field_type_registry.register
class DateOfBirthFieldType(DirectMappingFieldType):
name = "date_of_birth"
verbose_name = _("Date of birth")
models = [Person]
db_field = "date_of_birth"
class DatehFieldType(FieldType):
name = "date"
verbose_name = _("Date")
converter = parse_date
@field_type_registry.register
class SexFieldType(DirectMappingFieldType):
class SexFieldType(FieldType):
name = "sex"
verbose_name = _("Sex")
models = [Person]
db_field = "sex"
converter = parse_sex
@field_type_registry.register
class StreetFieldType(DirectMappingFieldType):
name = "street"
verbose_name = _("Street")
models = [Person]
db_field = "street"
@field_type_registry.register
class HouseNumberFieldType(DirectMappingFieldType):
name = "housenumber"
verbose_name = _("Housenumber")
models = [Person]
db_field = "housenumber"
@field_type_registry.register
class PostalCodeFieldType(DirectMappingFieldType):
name = "postal_code"
verbose_name = _("Postal code")
models = [Person]
db_field = "postal_code"
@field_type_registry.register
class PlaceFieldType(DirectMappingFieldType):
name = "place"
verbose_name = _("Place")
models = [Person]
db_field = "place"
@field_type_registry.register
class PhoneNumberFieldType(DirectMappingFieldType):
class PhoneNumberFieldType(FieldType):
name = "phone_number"
verbose_name = _("Phone number")
models = [Person]
db_field = "phone_number"
converter = parse_phone_number
@field_type_registry.register
class MobileNumberFieldType(DirectMappingFieldType):
name = "mobile_number"
verbose_name = _("Mobile number")
models = [Person]
db_field = "mobile_number"
converter = parse_phone_number
......@@ -246,7 +128,6 @@ class MobileNumberFieldType(DirectMappingFieldType):
class IgnoreFieldType(FieldType):
name = "ignore"
verbose_name = _("Ignore data in this field")
models = [Person, Group]
@classproperty
def column_name(cls) -> str:
......
......@@ -226,19 +226,23 @@ class ImportTemplateField(ExtensibleModel):
field_type = models.CharField(
max_length=255, verbose_name=_("Field type"), choices=field_type_registry.choices
)
db_field = models.CharField(
max_length=255, verbose_name=_("Target model field"), blank=True
)
altervative = models.CharField(
max_length=255, verbose_name=_("Alternative field"), blank=True
)
priority = models.PositiveSmallIntegerField(
verbose_name=_("Priority"), null=True
)
match = models.BooleanField(
verbose_name=_("Match field"), null=True
)
@property
def field_type_class(self):
return field_type_registry.get_from_name(self.field_type)
def clean(self):
"""Validate correct usage of field types."""
model = self.template.content_type.model_class()
if self.field_type not in field_type_registry.allowed_field_types_for_models[model]:
raise ValidationError(
_("You are not allowed to use this field type in this model.")
)
class Meta:
ordering = ["template", "index"]
unique_together = ["template", "index"]
......
......@@ -5,10 +5,8 @@ from django.db.models import Model
from django.utils.translation import gettext as _
from .field_types import (
ShortNameFieldType,
LastNameFieldType,
FirstNameFieldType,
DateOfBirthFieldType,
CharFieldType,
DateFieldType,
SexFieldType,
IgnoreFieldType,
UniqueReferenceFieldType, FieldType,
......@@ -31,9 +29,20 @@ def update_or_create_template(
defaults={"verbose_name": verbose_name, "content_type": ct, **extra_args},
)
for i, field in enumerate(fields):
for i, field_def in enumerate(fields):
keys = ("field", "db_field", "alternative", "priority", "match")
field_def = dict(zip(keys, field_def))
field = field_def["field"]
ImportTemplateField.objects.update_or_create(
template=template, index=i, defaults={"field_type": field.name},
template=template, index=i, defaults={
"field_type": field.name,
"db_field": field_def.get("db_field", ""),
"alternative": field_def.get("alternative", ""),
"priority": field_def.get("priority", None),
"match": field_def.get("match", None)
},
)
ImportTemplateField.objects.filter(template=template, index__gt=i).delete()
......@@ -47,13 +56,13 @@ def update_or_create_default_templates():
verbose_name=_("Pedasos: Teachers"),
extra_args={"has_header_row": True, "separator": "\t"},
fields=[
ShortNameFieldType,
LastNameFieldType,
FirstNameFieldType,
DateOfBirthFieldType,
SexFieldType,
IgnoreFieldType, # DEPARTMENTS
IgnoreFieldType, # IGNORE
(CharFieldType, "short_name", "name", 8, True),
(CharFieldType, "last_name"),
(CharFieldType, "first_name"),
(DateFieldType, "date_of_birth"),
(SexFieldType, "sex"),
(IgnoreFieldType,), # DEPARTMENTS
(IgnoreFieldType,), # IGNORE
],
)
update_or_create_template(
......@@ -62,9 +71,9 @@ def update_or_create_default_templates():
verbose_name=_("Pedasos: Classes"),
extra_args={"has_header_row": True, "separator": "\t"},
fields=[
ShortNameFieldType,
IgnoreFieldType, # GROUP_OWNER_BY_SHORT_NAME
IgnoreFieldType, # GROUP_OWNER_BY_SHORT_NAME
(CharFieldType, "short_name", "name", 8, True),
(IgnoreFieldType,), # GROUP_OWNER_BY_SHORT_NAME
(IgnoreFieldType,), # GROUP_OWNER_BY_SHORT_NAME
],
)
update_or_create_template(
......@@ -73,7 +82,7 @@ def update_or_create_default_templates():
verbose_name=_("Pedasos: Courses"),
extra_args={"has_header_row": True, "separator": "\t"},
fields=[
ShortNameFieldType,
(CharFieldType, "short_name", "name", 8, True),
IgnoreFieldType, # PEDASOS_CLASS_RANGE
IgnoreFieldType, # SUBJECT_BY_SHORT_NAME
IgnoreFieldType, # GROUP_OWNER_BY_SHORT_NAME
......@@ -85,11 +94,11 @@ def update_or_create_default_templates():
verbose_name=_("Pedasos: Students"),
extra_args={"has_header_row": True, "separator": "\t"},
fields=[
UniqueReferenceFieldType,
LastNameFieldType,
FirstNameFieldType,
DateOfBirthFieldType,
SexFieldType,
(UniqueReferenceFieldType,),
(CharFieldType, "last_name"),
(CharFieldType, "first_name"),
(DateFieldType, "date_of_birth"),
(SexFieldType, "sex"),
IgnoreFieldType, # PRIMARY_GROUP_BY_SHORT_NAME
IgnoreFieldType, # MOTHER GUARDIAN_LAST_NAME GUARDIAN_FIRST_NAME GUARDIAN_EMAIL
IgnoreFieldType,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment