django rest framework - using detail_route and detail_list

谁都会走 提交于 2019-12-10 12:39:15

问题


In my code I have a viewset for the User. I want is to allow only Read operations (/users/42 and /users/) which the ReadOnlyModelViewSet does just fine.

In addition, I want to have a /users/register URL that I can POST to in order to register a new User.

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @list_route(methods=['post'])
    def register(request):
        serializer = UserSerializer(data=request.DATA)
        if serializer.is_valid():
            user = User.objects.create_user(
                username = serializer.init_data['username'],
                password = serializer.init_data['password'],
            )

            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Couple of questions:

  • Would this be this the right way of doing that?

  • Is there a specific signature for a method if I put it in a list_route or the detail_route decorator? because in the detail_route examples its always the same signature for the method: method_name(self, request, pk=None):

thanks!


回答1:


Your code is almost correct, you're just missing the right signature on the register method:

def register(self, request):

This is the correct signature according to the documentation. Additionally the tests suggest that it's not possible to pass an additional parameter for routing, and that pk will always be passed for a @detail_route, so you would have to have:

@detail_route
def register(self, request, pk=None):

for detail routes and

@list_route
def register(self, request):

for list routes.

However I would suggest you take advantage of the built in ViewSetMixins as ModelViewSet does internally:

from rest_framework import exceptions, mixins
class UserViewSet(mixins.CreateModelMixin,
               mixins.RetrieveModelMixin,
               mixins.ListModelMixin,
               GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    def create(self, request):
        serializer = UserSerializer(data=request.DATA)
            if serializer.is_valid():
                user = User.objects.create_user(
                    username = serializer.init_data['username'],
                    password = serializer.init_data['password'],
                )

                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

For user sign ups in general you can also take a look at django-registration-restframework which I'm currently making work for my project.

Personally I rely on the ModelViewSet in my projects and make sure only properly authorized users can perform certain actions. To do this you can use model wide permissions or in combination with django guardian object specific permissions.

Especially with a REST API you will eventually come to the point that you'd like certain users to perform actions only on certain objects, without having to micromanage every request. Object level permissions can be of great use here.




回答2:


detail_route and detail_list will get deprecated on DRF 3.0 instead use @action:

from rest_framework.decorators import action
    @action(methods=['POST'], detail=True)
    def sale(self):
       ...

Use detail=True when this method will account for a single instance of the Model represented by that endpoint and False when it needs to represent a Queryset of that model



来源:https://stackoverflow.com/questions/30410432/django-rest-framework-using-detail-route-and-detail-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!