Get the context for outputing raw json in api and admin, no looping over the fields anymore

This commit is contained in:
Holger Sielaff
2026-01-12 13:32:57 +01:00
parent 6e58334190
commit c2dc9215c2
2 changed files with 23 additions and 26 deletions

View File

@@ -74,11 +74,12 @@ class TranslatableMixin:
if not self.translatable:
return value
# Check if we're in admin context by looking at the call stack
# Check if we're in admin or API context by looking at the call stack
frames = inspect.getouterframes(inspect.currentframe())
is_admin_context = os.environ.get('DJANGO_ADMIN_OVERRIDE', False) == '1' or any('admin' in frame.filename or 'forms' in frame.filename for frame in frames[:5])
is_api_context = any('serializers' in frame.filename or 'rest_framework' in frame.filename or '/api/' in frame.filename for frame in frames[:10])
logging.debug(f"{self.__class__.__name__} from_db_value - admin context: {is_admin_context}")
logging.debug(f"{self.__class__.__name__} from_db_value - admin context: {is_admin_context}, api context: {is_api_context}")
try:
translations = json.loads(value) if isinstance(value, str) else value
@@ -87,10 +88,10 @@ class TranslatableMixin:
logging.debug(f"{self.__class__.__name__} from_db_value - parsed translations: {translations}")
# For admin/forms, return the full dict so widgets can access all translations
if is_admin_context:
# For admin/forms/API, return the full dict so serializers/widgets can access all translations
if is_admin_context or is_api_context:
logging.debug(
f"{self.__class__.__name__} from_db_value - returning full dict for admin: {translations}")
f"{self.__class__.__name__} from_db_value - returning full dict for admin/api: {translations}")
return translations
# For regular use, return the appropriate language

View File

@@ -75,7 +75,7 @@ class TranslatableSerializerMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._setup_translatable_fields()
def _setup_translatable_fields(self):
"""Identify and setup translatable fields in the serializer"""
self._translatable_fields = []
@@ -184,19 +184,8 @@ class TranslatableSerializerMixin:
if field_name in validated_data:
new_value = validated_data[field_name]
# Get RAW value from database using raw SQL (bypass ALL descriptors)
from django.db import connection
model_class = instance.__class__
table_name = model_class._meta.db_table
pk_field = model_class._meta.pk.name
with connection.cursor() as cursor:
cursor.execute(
f"SELECT {field_name} FROM {table_name} WHERE {pk_field} = %s",
[instance.pk]
)
row = cursor.fetchone()
existing_value = row[0] if row else None
# Get existing value (model field returns dict in API context)
existing_value = getattr(instance, field_name, None)
# Parse existing value
existing_translations = {}
@@ -271,10 +260,17 @@ class TranslatableField(serializers.Field):
def to_representation(self, value):
"""Convert database value to API representation"""
# Get lang parameter from request if not set explicitly on field
request_language = self.language
if not request_language and hasattr(self, 'parent') and self.parent:
if hasattr(self.parent, 'context') and 'request' in self.parent.context:
request = self.parent.context['request']
request_language = request.query_params.get('lang') or request.query_params.get('language')
if not value:
return '' if self.language else {}
# Handle JSON string from database
return '' if request_language else {}
# Value is already a dict in API context (from model field's from_db_value)
if isinstance(value, str):
try:
translations = json.loads(value)
@@ -284,11 +280,11 @@ class TranslatableField(serializers.Field):
translations = value
else:
translations = {'en': str(value)}
# Return specific language or full dict
if self.language:
if self.language in translations:
return translations[self.language]
if request_language:
if request_language in translations:
return translations[request_language]
elif 'en' in translations:
return translations['en']
elif translations: