♻️(backend) custom pydantic errors to be compatible with our handler

We are using the drf_standardized_errors handler to have "nice" errors
for the frontend application. We decided to override the SchemaField
from the django_pydantic_field library in order to make it compatible
with this error handler.
This commit is contained in:
Manuel Raynaud
2026-03-31 11:13:24 +02:00
committed by Nathan Panchout
parent b3b113ae74
commit e6b2dab5c0
4 changed files with 75 additions and 7 deletions
+29 -1
View File
@@ -1,8 +1,13 @@
"""A JSONField for DRF to handle serialization/deserialization."""
import json
import typing as ty
from rest_framework import serializers
import pydantic
from django_pydantic_field.v2.rest_framework.fields import (
SchemaField as PydanticSchemaField,
)
from rest_framework import exceptions, serializers
class JSONField(serializers.Field):
@@ -23,3 +28,26 @@ class JSONField(serializers.Field):
if data is None:
return None
return json.dumps(data)
class SchemaField(PydanticSchemaField):
"""
Custom SchemaField in order to create error messages compatible with
drf_standardized_errors handler.
"""
def to_internal_value(self, data: ty.Any):
try:
if isinstance(data, (str, bytes)):
return self.adapter.validate_json(data)
return self.adapter.validate_python(data)
except pydantic.ValidationError as exc:
pydantic_errors = exc.errors(
include_url=False, include_context=False, include_input=False
)
errors = []
for pydantic_error in pydantic_errors:
for location in pydantic_error.get("loc"):
errors.append({location: pydantic_error.get("msg")})
raise exceptions.ValidationError(errors, code="invalid") from exc
+1 -1
View File
@@ -12,12 +12,12 @@ from django.conf import settings
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django_pydantic_field.rest_framework import SchemaField
from lasuite.drf.models.choices import LinkReachChoices, get_equivalent_link_definition
from rest_framework import serializers
from core import models
from core.api import utils
from core.api.fields import SchemaField
from core.storage import get_storage_compute_backend
from wopi import utils as wopi_utils
+1 -3
View File
@@ -213,9 +213,7 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
short_name = models.CharField(_("short name"), max_length=100, null=True, blank=True)
email = models.EmailField(_("identity email address"), blank=True, null=True)
column_preferences = SchemaField(
ColumnPreferences, blank=True, null=True, default=None
)
column_preferences = SchemaField(ColumnPreferences, blank=True, null=True, default=None)
# Unlike the "email" field which stores the email coming from the OIDC token, this field
# stores the email used by staff users to login to the admin site
+44 -2
View File
@@ -684,8 +684,10 @@ def test_api_users_patch_column_preferences_valid(column2, column1):
assert user.column_preferences == models.ColumnPreferences(**column_preferences)
@pytest.mark.parametrize("column_name", ["column1", "column2"])
def test_api_users_patch_column_preferences_missing_column_should_fail(column_name):
@pytest.mark.parametrize(
"column_name,missing_column", [("column1", "column2"), ("column2", "column1")]
)
def test_api_users_patch_column_preferences_missing_column_should_fail(column_name, missing_column):
"""Patching column_preferences with a missing required column parameter should fails."""
user = factories.UserFactory()
@@ -705,6 +707,17 @@ def test_api_users_patch_column_preferences_missing_column_should_fail(column_na
format="json",
)
assert response.json() == {
"type": "validation_error",
"errors": [
{
"code": "invalid",
"detail": "Field required",
"attr": f"column_preferences.0.{missing_column}",
}
],
}
assert response.status_code == 400
@@ -732,6 +745,17 @@ def test_api_users_patch_column_preferences_extra_value_should_fail():
format="json",
)
assert response.json() == {
"type": "validation_error",
"errors": [
{
"code": "invalid",
"detail": "Extra inputs are not permitted",
"attr": "column_preferences.0.not_allowed",
},
],
}
assert response.status_code == 400
@@ -758,6 +782,24 @@ def test_api_users_patch_column_preferences_invalid_value():
format="json",
)
assert response.json() == {
"type": "validation_error",
"errors": [
{
"code": "invalid",
"detail": "Input should be 'last_modified', 'created', 'created_by', "
"'file_type' or 'file_size'",
"attr": "column_preferences.0.column1",
},
{
"code": "invalid",
"detail": "Input should be 'last_modified', 'created', 'created_by', "
"'file_type' or 'file_size'",
"attr": "column_preferences.1.column2",
},
],
}
assert response.status_code == 400