|
|
@@ -1,11 +1,9 @@
|
|
|
import re
|
|
|
-from collections import OrderedDict
|
|
|
from datetime import datetime, date
|
|
|
|
|
|
from django import forms
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
from django.contrib.postgres.fields import ArrayField
|
|
|
-from django.core.serializers.json import DjangoJSONEncoder
|
|
|
from django.core.validators import RegexValidator, ValidationError
|
|
|
from django.db import models
|
|
|
from django.utils.safestring import mark_safe
|
|
|
@@ -18,55 +16,6 @@ from utilities.querysets import RestrictedQuerySet
|
|
|
from utilities.validators import validate_regex
|
|
|
|
|
|
|
|
|
-class CustomFieldModel(BigIDModel):
|
|
|
- """
|
|
|
- Abstract class for any model which may have custom fields associated with it.
|
|
|
- """
|
|
|
- custom_field_data = models.JSONField(
|
|
|
- encoder=DjangoJSONEncoder,
|
|
|
- blank=True,
|
|
|
- default=dict
|
|
|
- )
|
|
|
-
|
|
|
- class Meta:
|
|
|
- abstract = True
|
|
|
-
|
|
|
- @property
|
|
|
- def cf(self):
|
|
|
- """
|
|
|
- Convenience wrapper for custom field data.
|
|
|
- """
|
|
|
- return self.custom_field_data
|
|
|
-
|
|
|
- def get_custom_fields(self):
|
|
|
- """
|
|
|
- Return a dictionary of custom fields for a single object in the form {<field>: value}.
|
|
|
- """
|
|
|
- fields = CustomField.objects.get_for_model(self)
|
|
|
- return OrderedDict([
|
|
|
- (field, self.custom_field_data.get(field.name)) for field in fields
|
|
|
- ])
|
|
|
-
|
|
|
- def clean(self):
|
|
|
- super().clean()
|
|
|
-
|
|
|
- custom_fields = {cf.name: cf for cf in CustomField.objects.get_for_model(self)}
|
|
|
-
|
|
|
- # Validate all field values
|
|
|
- for field_name, value in self.custom_field_data.items():
|
|
|
- if field_name not in custom_fields:
|
|
|
- raise ValidationError(f"Unknown field name '{field_name}' in custom field data.")
|
|
|
- try:
|
|
|
- custom_fields[field_name].validate(value)
|
|
|
- except ValidationError as e:
|
|
|
- raise ValidationError(f"Invalid value for custom field '{field_name}': {e.message}")
|
|
|
-
|
|
|
- # Check for missing required values
|
|
|
- for cf in custom_fields.values():
|
|
|
- if cf.required and cf.name not in self.custom_field_data:
|
|
|
- raise ValidationError(f"Missing required custom field '{cf.name}'.")
|
|
|
-
|
|
|
-
|
|
|
class CustomFieldManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
|
use_in_migrations = True
|
|
|
|