django rest framework - using detail_route and detail_list

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.


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