98 lines
3.7 KiB
Python
98 lines
3.7 KiB
Python
# 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) |