Django REST Framework update record mixin

Я использую Django 3.2 и последнюю версию djangorestframework.

Мне нужно иметь возможность обновлять значения записи JobStatus, уже созданной ранее.

Например, у меня есть

 {
    "id": 1,
    "status_timestamp": "2022-04-07T10:51:42Z",
    "status_activity": "Sync DDT",
    "status_status": "running",
    "launcher": 1
  }

и мне нужно получить это (в БД) через API

 {
    "id": 1,
    "status_timestamp": "2022-04-07T11:51:42Z",
    "status_activity": "Sync DDT",
    "status_status": "completed",
    "launcher": 1
  }

Может кто-нибудь мне помочь?

PS Мне нужно поддерживать метод аутентификации Token


МОДЕЛИ

class JobStatus(models.Model):
    status_timestamp = models.DateTimeField()
    status_activity = models.CharField(max_length=200)
    status_status = models.CharField(max_length=200)
    launcher = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.RESTRICT)
    class Meta:
        verbose_name = "Status"
        verbose_name_plural = "Status list"

    def __str__(self):
        return str(self.status_timestamp) + " " + self.status_activity

УРЛЫ

from django.urls import path, include
from apps.api_c import views
from rest_framework.routers import DefaultRouter
from rest_framework.urlpatterns import format_suffix_patterns


router = DefaultRouter()
router.register('alert', views.AlertViewSet)
router.register('jstatus', views.UpdateStatus)

urlpatterns = [
    ...
    path("", include(router.urls)),
]

ПРОСМОТРОВ

class UpdateStatus(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin):
    """update status"""
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    serializer_class = StatusSerializer
    #queryset = JobStatus.objects.all()
#TEST1
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
#TEST2
    def perform_update(self, serializer):
        serializer_class.update()

Вы можете сделать следующее:

urls.py

from apps.api_c import views
from rest_framework.routers import DefaultRouter
from rest_framework.urlpatterns import format_suffix_patterns


router = DefaultRouter()
router.register('alert', views.AlertViewSet,basename="alert")
router.register('jstatus', views.UpdateStatus, basename="updatestatus")

urlpatterns = [
    ...
    path("", include(router.urls)),
]

views.py


    class UpdateStatus(viewsets.GenericViewSet, 
                       mixins.ListModelMixin, 
                       mixins.RetrieveModelMixin, 
                       mixins.UpdateModelMixin):
        """update status"""
        authentication_classes = (TokenAuthentication,)
        permission_classes = (IsAuthenticated,)
        queryset = JobStatus.objects.all()
        serializer_class = StatusSerializer

        def get_serializer_class(self):

           if self.action == 'update' or self.action == 'put' or self.action == 'patch':
              return StatusUpdateSerializer

       

           return StatusSerializer



Тогда ваш StatusUpdateSerializer будет выглядеть следующим образом:

class StatusUpdateSerializer(serializers.ModelSerializer):
    

    class Meta:

        model = models.JobStatus
        fields =("id","status_timestamp","status_activity","status_status",
        "launcher")
        read_only_fields = ("id","status_timestamp","status_activity",
        "launcher")

Это должно работать.

По сути, вам нужно переключить сериализаторы в зависимости от метода запроса, который делает пользователь, таким образом: def get_serializer_class(self) method.

В StatusUpdateSerializer перечислены все поля, но в поле readonly перечислены только те поля, которые вы не хотите, чтобы пользователь мог обновлять или редактировать.

Я думаю, что вы сделали большинство вещей правильно. Вам нужно немного изменить файл views.py.

views.py

from rest_framework import get_object_or_404
from rest_framework.response import Response

class UpdateStatus(viewsets.GenericViewSet, 
                   mixins.ListModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    serializer_class = StatusSerializer
    queryset = JobStatus.objects.all()
    
    def list(self, request, *args, **kwargs):
        if 'id' in self.request.query_params:
            data = get_object_or_404(self.queryset, id=request.query_params.get('id'))
            serializer = self.serializer_class(data)
            return Response(serializer.data)
        else:
            return super().list(request, *args, **kwargs)

Теперь используйте следующее, чтобы сделать все, что вы хотите:

Получить все записи: (GET) 127.0.0.1:8000/jstatus/

Получение одной записи : (GET) 127.0.0.1:8000/jstatus/?id=1

Создать запись : (POST) 127.0.0.1:8000/jstatus/1/

Обновление записи : (PATCH) 127.0.0.1:8000/jstatus/1/

Удаление записи : (DELETE) 127.0.0.1:8000/jstatus/1/

Надеюсь, это поможет.

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