Get the context for outputing raw json in api and admin, no looping over the fields anymore
This commit is contained in:
@@ -74,11 +74,12 @@ class TranslatableMixin:
|
|||||||
if not self.translatable:
|
if not self.translatable:
|
||||||
return value
|
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())
|
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_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:
|
try:
|
||||||
translations = json.loads(value) if isinstance(value, str) else value
|
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}")
|
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
|
# For admin/forms/API, return the full dict so serializers/widgets can access all translations
|
||||||
if is_admin_context:
|
if is_admin_context or is_api_context:
|
||||||
logging.debug(
|
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
|
return translations
|
||||||
|
|
||||||
# For regular use, return the appropriate language
|
# For regular use, return the appropriate language
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class TranslatableSerializerMixin:
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._setup_translatable_fields()
|
self._setup_translatable_fields()
|
||||||
|
|
||||||
def _setup_translatable_fields(self):
|
def _setup_translatable_fields(self):
|
||||||
"""Identify and setup translatable fields in the serializer"""
|
"""Identify and setup translatable fields in the serializer"""
|
||||||
self._translatable_fields = []
|
self._translatable_fields = []
|
||||||
@@ -184,19 +184,8 @@ class TranslatableSerializerMixin:
|
|||||||
if field_name in validated_data:
|
if field_name in validated_data:
|
||||||
new_value = validated_data[field_name]
|
new_value = validated_data[field_name]
|
||||||
|
|
||||||
# Get RAW value from database using raw SQL (bypass ALL descriptors)
|
# Get existing value (model field returns dict in API context)
|
||||||
from django.db import connection
|
existing_value = getattr(instance, field_name, None)
|
||||||
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
|
|
||||||
|
|
||||||
# Parse existing value
|
# Parse existing value
|
||||||
existing_translations = {}
|
existing_translations = {}
|
||||||
@@ -271,10 +260,17 @@ class TranslatableField(serializers.Field):
|
|||||||
|
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
"""Convert database value to API representation"""
|
"""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:
|
if not value:
|
||||||
return '' if self.language else {}
|
return '' if request_language else {}
|
||||||
|
|
||||||
# Handle JSON string from database
|
# Value is already a dict in API context (from model field's from_db_value)
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
try:
|
try:
|
||||||
translations = json.loads(value)
|
translations = json.loads(value)
|
||||||
@@ -284,11 +280,11 @@ class TranslatableField(serializers.Field):
|
|||||||
translations = value
|
translations = value
|
||||||
else:
|
else:
|
||||||
translations = {'en': str(value)}
|
translations = {'en': str(value)}
|
||||||
|
|
||||||
# Return specific language or full dict
|
# Return specific language or full dict
|
||||||
if self.language:
|
if request_language:
|
||||||
if self.language in translations:
|
if request_language in translations:
|
||||||
return translations[self.language]
|
return translations[request_language]
|
||||||
elif 'en' in translations:
|
elif 'en' in translations:
|
||||||
return translations['en']
|
return translations['en']
|
||||||
elif translations:
|
elif translations:
|
||||||
|
|||||||
Reference in New Issue
Block a user