Игнорирование определенных полей при обновлении в зависимости от условия

Описание:

Цель - обновить все Spotlight поля на PUT/PATCH (update/partial update), если его status является YELLOW.

Если status является RED || GREEN, он должен обновлять только свои status и игнорировать любые другие поля. Обходной путь, представленный здесь, является несколько вонючим, и он дает вводящие в заблуждение ответы при использовании PUT.

Есть ли в Django способ добиться этого лучше, чем представленное обходное решение?

Исходный вариант:

if instance.state == instance.STATE_YELLOW:
    custom_data = request.data
else:
    custom_data = {'state': request.data['state']}

Полный код:

from stoplight.filters import StoplightFilter
from stoplight.models import Stoplight
from stoplight.permissions import (
    IsSuperuserOrReadOnly
)
from stoplight.serializers import StoplightSerializer
from rest_framework import status
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet


class StoplightViewSet(GenericViewSet, CreateModelMixin, ListModelMixin, RetrieveModelMixin):
    """
    API endpoint for Stoplights
    """

    queryset = Stoplight.objects.all()
    serializer_class = StoplightSerializer
    filter_class = StoplightFilter
    search_fields = ('name',)
    permission_classes = (IsSuperuserOrReadOnly,)

    def update(self, request, *args, **kwargs):
        """
        Updates Stoplight state
        """
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        
        if instance.state == instance.STATE_YELLOW:
            custom_data = request.data
        else:
            custom_data = {'state': request.data['state']}
        
        serializer = self.get_serializer(instance, data=custom_data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data, status=status.HTTP_200_OK)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

Вернуться на верх