diff --git a/django_translatable_fields/fields.py b/django_translatable_fields/fields.py index 3eab78c..d8342b7 100644 --- a/django_translatable_fields/fields.py +++ b/django_translatable_fields/fields.py @@ -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 diff --git a/django_translatable_fields/serializers.py b/django_translatable_fields/serializers.py index c8dcd35..745dd9b 100644 --- a/django_translatable_fields/serializers.py +++ b/django_translatable_fields/serializers.py @@ -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: