Change to I18nField for validation

This commit is contained in:
Richard Schreiber
2026-09-22 11:38:51 +02:00
parent 0e38518e9f
commit ab248d0d97
2 changed files with 29 additions and 26 deletions
+21 -20
View File
@@ -28,6 +28,7 @@ from django.db import transaction
from django.db.models import Q
from django.utils.crypto import get_random_string
from django.utils.translation import gettext, gettext_lazy as _
from i18nfield.rest_framework import I18nField
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
@@ -661,9 +662,20 @@ class MetaPropertyListField(serializers.ListField):
class MetaPropertyDictField(serializers.DictField):
child_per_key = {
"label": I18nField()
}
def to_representation(self, value):
# django added unneccessary keys DELETE, ORDER through formsets, filter them here for backwards compat
return super().to_representation({k: value[k] for k in ("key", "label") if k in value})
d = {
"key": value["key"]
}
if "label" in value:
f = I18nField()
d["label"] = f.to_representation(value["label"])
return super().to_representation(d)
def to_internal_value(self, data):
if not isinstance(data, dict):
@@ -675,30 +687,19 @@ class MetaPropertyDictField(serializers.DictField):
if any(k not in {"key", "label"} for k in data.keys()):
raise ValidationError("Meta properties may only have a key and optionally a label.")
if "label" in data:
f = I18nField()
try:
data["label"] = f.to_internal_value(data["label"])
except ValidationError as e:
raise ValidationError({"label": e.detail})
return super().to_internal_value(data)
class I18nField(serializers.Field):
def to_representation(self, value):
return value
def to_internal_value(self, data):
if isinstance(data, str):
return data
if not isinstance(data, dict):
raise ValidationError("Must either be a string or a dict.")
if not all(isinstance(k, str) for k in data.keys()):
raise ValidationError("All keys must be strings.")
if not all(isinstance(v, str) for v in data.values()):
raise ValidationError("All values must be strings.")
class EventMetaPropertiesSerializer(I18nAwareModelSerializer):
choices = MetaPropertyListField(
child=MetaPropertyDictField(
# careful: this only works because I18nField allows plain strings (e.g. keys need to be plain strings)
child=I18nField()
),
child=MetaPropertyDictField(),
allow_null=True,
)
+8 -6
View File
@@ -21,6 +21,7 @@
#
import pytest
from django_scopes import scopes_disabled
from i18nfield.strings import LazyI18nString
@pytest.fixture
@@ -32,7 +33,7 @@ def event_meta_property(organizer):
choices=[
{
"key": "Red",
"label": "Rot",
"label": LazyI18nString("Rot"),
"DELETE": False,
"ORDER": 1,
}
@@ -44,7 +45,7 @@ TEST_TYPE_RES = {
"name": "Color",
"default": "Red",
"required": False,
"choices": [{"key": "Red", "label": "Rot"}],
"choices": [{"key": "Red", "label": {"en": "Rot"}}],
'filter_allowed': True,
'filter_public': False,
'protected': False,
@@ -120,8 +121,8 @@ def test_meta_property_create(token_client, organizer):
"default": "r",
"required": False,
"choices": [
{"key": "r", "label": "Red"},
{"key": "r", "label": "Razzmatazz"},
{"key": "r", "label": {"en": "Red"}},
{"key": "r", "label": {"en": "Razzmatazz"}},
],
}
)
@@ -192,8 +193,9 @@ def test_meta_property_patch(token_client, organizer, event_meta_property):
}
)
assert resp.status_code == 400
assert str(resp.data["choices"][0]["label"][0]) == "Must either be a string or a dict."
assert str(resp.data["choices"][1]["label"][0]) == "All values must be strings."
#assert resp.data == 123
assert str(resp.data["choices"][0]["label"][0]) == "Invalid data type."
assert str(resp.data["choices"][1]["label"][0]) == "All entries must be strings."
resp = token_client.patch(