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/
Надеюсь, это поможет.