# operations/mixins.py from django.db import transaction from rest_framework import serializers from rest_framework import status class DynamicFieldsModelSerializerMixin: """ Slojeviti Mixin za SERIALIZERE. Čisti prazne stringove iz FormData i dinamički uvozi ugniježđene relacije (Lazy Load). """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) request = self.context.get('request') # Ako smo na GET zahtjevu, automatski aktiviramo ugniježđeni prikaz (Read-only) if request and request.method == 'GET': self._setup_nested_serializers() def _setup_nested_serializers(self): nested_config = getattr(self.Meta, 'nested_fields_config', {}) for field_name, serializer_path in nested_config.items(): if field_name in self.fields: try: module_path, class_name = serializer_path.rsplit('.', 1) module = __import__(module_path, fromlist=[class_name]) serializer_class = getattr(module, class_name) self.fields[field_name] = serializer_class(read_only=True, context=self.context) except (ImportError, AttributeError) as e: print(f"[Mixin Error] Neuspješan dinamički uvoz za {serializer_path}: {e}") def to_internal_value(self, data): if hasattr(data, 'dict'): # Pretvara prazne HTML stringove "" u prave Python None vrijednosti data = data.copy() for key, value in data.items(): if value == '': data[key] = None return super().to_internal_value(data) class AstroBridgeViewSetMixin: """ Slojeviti Mixin za VIEWSETOVE. Presreće perform_create/update za automatsko spremanje request.FILES u galerije i omata izlazni JSON u standardni omotač (Envelope) za Astro proxy. """ auto_handle_files = False file_field_name = 'slike' related_file_model = None related_file_fk = None def finalize_response(self, request, response, *args, **kwargs): """Omata DRF odgovor u stabilnu strukturu za Astro klijent.""" if isinstance(response.data, (dict, list)): if status.is_success(response.status_code): response.data = { "success": True, "data": response.data, "errors": None } else: response.data = { "success": False, "data": None, "errors": response.data } return super().finalize_response(request, response, *args, **kwargs) def perform_create(self, serializer): instance = serializer.save() if self.auto_handle_files: self._process_attached_files(instance) return instance def perform_update(self, serializer): instance = serializer.save() if self.auto_handle_files: self._process_attached_files(instance) return instance def _process_attached_files(self, instance): """Automatski izvlači višestruki upload iz FormData boundary-ja.""" request = self.request if not self.related_file_model or not self.related_file_fk: return files = request.FILES.getlist(self.file_field_name) opis = request.data.get('slika_opis', f"Prilog uz {str(instance)}") for f in files: build_kwargs = { self.related_file_fk: instance, 'slika': f, } if hasattr(self.related_file_model, 'opis'): build_kwargs['opis'] = opis self.related_file_model.objects.create(**build_kwargs)