#django #django-rest-framework
#django #django-rest-framework
Вопрос:
Я вынужден написать некоторую грязную работу, мне нужно создать представление partial_update, однако оно должно использовать метод POST, потому что программное обеспечение в конечном итоге не использует методы PUT / PATCH.
Вот несколько предположений:
-
все должно быть перенаправлено через
DefaultRouter()
inurls.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), ]