Как принудительно проверить разрешение на перезаписанный post-метод UpdateModelMixin?

#django #django-rest-framework

#django #django-rest-framework

Вопрос:

Я вынужден написать некоторую грязную работу, мне нужно создать представление partial_update, однако оно должно использовать метод POST, потому что программное обеспечение в конечном итоге не использует методы PUT / PATCH.

Вот несколько предположений:

  • все должно быть перенаправлено через DefaultRouter() in urls.py — вот почему я использую GenericViewSet

  • необходимо использовать метод POST для обновления одного поля — вот почему я перезаписываю post() метод UpdateModelMixin

  • instance.visible является логическим значением, состояние которого устанавливается в True , как только body значение не является пустым.

Обновление работает, за исключением permission_classess которые игнорируются. Он полностью не проверяет запрос на наличие действительных учетных данных. Я думаю, это потому, что я полностью переписал post() , верно? Как мне принудительно проверить аутентификацию в методе post?

urls.py:

 from django.urls import include, path
from rest_framework import routers
from browse.views import *

router = routers.DefaultRouter()
[...]
router.register(r'update-article', UpdateArticleBodyViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'),)
]
  

views.py:

 class UpdateArticleBodyViewSet(mixins.UpdateModelMixin, viewsets.GenericViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = (permissions.IsAuthenticated, )

    def post(self, request, pk):
        instance = get_object_or_404(Article, pk=pk)
        instance.body = request.data.get("body")
        if instance.body:
            instance.visible = True
        instance.save()
        serializer = self.get_serializer(instance=instance, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  

Обновить

Я изменил код после первого вопроса, теперь он выглядит следующим образом:

views.py:

 class UpdateArticleBodyViewSet(mixins.UpdateModelMixin, viewsets.GenericViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = (permissions.IsAuthenticated, )

    def partial_update(self, request, *args, **kwargs):
        instance = self.queryset.get(pk=kwargs.get('pk'))
        instance.body = request.data.get("body")
        if instance.body:
            instance.visible = True
        instance.save()
        serializer = self.get_serializer(instance=instance, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  

urls.py

 articles_viewset = UpdateArticleBodyViewSet.as_view({
    'post': 'update'
})

router = routers.DefaultRouter()
router.register(r'update-article', articles_viewset, basename="article")
  

Что приводит к следующей ошибке:
AttributeError: 'function' object has no attribute 'get_extra_actions'

В StackOverflow уже есть пара вопросов по этому поводу, но ни один из них не дает ответа. Есть ли какой-либо способ, которым я могу использовать маршрутизатор в этом случае, или я вынужден явно писать URL-адреса?

Ответ №1:

Проблема здесь в том, что оба класса, от которых вы наследуете, не имеют post метода, поэтому вы на самом деле не переопределяете его. Таким образом, метод выходит за рамки проверки подлинности.

Существует множество различных способов добиться этого. Самый простой способ, который я могу придумать, — это изменить действие post для вашего маршрута. Что-то вроде:

 articles_viewset = UpdateArticleBodyViewSet.as_view({
    'post': 'update'
})

router.register(r'update-article', articles_viewset)
  

Таким образом, вы смогли бы использовать UpdateMixin без каких-либо проблем. Вы могли бы просто настроить update метод, если это необходимо.

Комментарии:

1. Спасибо, я знал, что упускаю что-то очевидное. Также хороший улов в no post методе, я полностью пропустил это. Я перекодировал часть views, однако я борюсь с urls.py . В вашем ответе отсутствует basename аргумент, который я добавил (проверьте обновление моего вопроса). Тем не менее, я все еще застрял. Заранее спасибо, что изучили это.

2. О, я не думаю, что возможно зарегистрировать маршрутизатор с помощью as_view метода. Я бы просто потерял маршрутизатор, просто создал URL напрямую: urlpatterns = [ url(r'^my_route/$', articles_viewset), ]