Как создать конечную точку настраиваемого действия, которая соответствует функции put и выполнения в классе модели? - PullRequest
0 голосов
/ 13 декабря 2018

Я использую Django Rest Framework: v3.7 и Django v1.11 и Dynamic Rest v1.9.2

В моем классе MyModel есть следующее:

class MyModel():
    # .. fields declared here..

    def change_status(self):
        #... other code not crucial
        allowed = self.status in possible_new_states
        if allowed:
            return self.save()
        return True

У меня естьследующий ViewSet

from dynamic_rest.viewsets import DynamicModelViewSet
# from rest_framework.decorators import action # for DRF 3.8
from rest_framework.decorators import detail_route # for DRF 3.7
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

class MyModelViewSet(DynamicModelViewSet):
    """
    VendorQuotations API.
    """
    permission_classes = (IsAuthenticated,)
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    @detail_route(methods=['put']) # use this for DRF 3.7
    # @action(detail=True, methods=['put']) # use this for DRF 3.8 and above
    def status(self, request, pk=None):
        """Update the status."""

и следующий сериализатор:

class VendorQuotationSerializer(DynamicModelSerializer):

DynamicModelSerializer наследуется от serializers.ModelSerializer, а DyanmicModelViewSet наследуется от viewsets.ModelViewSet

Я хотел, чтобы конечная точка, подобная / my_models /: id / change_status, указывала на метод status в наборе, который, в свою очередь, каким-то образом выполняет метод change_status на уровне модели.

Я посмотрел остальные документы django и скопировал пример для change_password , но я не уверен, как соединить точки между набором и моделью.

Пожалуйста, посоветуйте

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

@ ruddra ответ велик, но вместо пользовательского поиска вы должны использовать существующий метод get_object(), который уже заботится о 404 и проверяет разрешения (очень важно!)

from rest_framework import status

# from rest_framework.decorators import action # for DRF 3.8
from rest_framework.decorators import detail_route # for DRF 3.7

@detail_route(methods=['put']) # use this for DRF 3.7
# @action(detail=True, methods=['put']) # use this for DRF 3.8 and above
def status(self, request, pk):
   obj = self.get_object()
   changed_status = obj.change_status()
   return Response({'success':True, "status_changed": changed_status},status=status.HTTP_200_OK) 
0 голосов
/ 13 декабря 2018

Вы можете попробовать вот так:

from rest_framework.response import Response
from rest_framework import status, viewsets
...

@action(detail=True, methods=['put'], name='Change Status',  url_path='change-status', url_name='change_status')
def status(self, request, pk):
    try:
       obj = MyModel.objects.get(pk=pk)
       changed_status = obj.change_status()
       return Response({'success':True, "status_changed": changed_status}, status=status.HTTP_200_OK)
    except MyModel.DoesNotExists:
       return Response({'success':False}, status=status.HTTP_400_BAD_REQUEST)
...