Django-rest-framework permissions for create in viewset

前端 未结 3 1403
我寻月下人不归
我寻月下人不归 2020-12-28 08:18

I am trying to create a REST API and am stuck at user registration: basically I need to have the access token before I register.

This is the view:

cl         


        
相关标签:
3条回答
  • 2020-12-28 09:00

    Customize the get_queryset method:

    def get_queryset(self):
        if self.request.user.is_superuser:
            return User.objects.all()
        else:
            return User.objects.filter(id=self.request.user.id)
    

    This way, an authenticated user can only retrieve, modify or delete its own object.

    Specify the permission_classes = (AllowAny,) so an authenticated user can create a new one.

    EDIT: further explanation from comments

    Customizing the get_queryset method this way means the following:

    1. Yes, non-authenticated users can send the GET request to retrieve the user list but it will be empty because the return User.objects.filter(id=self.request.user.id) ensures that only information about the authenticated user is returned.

    2. The same applies for other methods, if an authenticated user tries to DELETE another user object, a detail: Not found will be returned (because the user it is trying to access is not in the queryset).

    3. Authenticated users can do whatever they want to their user objects.

    0 讨论(0)
  • 2020-12-28 09:14

    This is based on @argaen answer and it worked for me:

    class UserViewSet(viewsets.ModelViewSet):
        serializer_class = UserSerializer
        permission_classes = (AllowAny,)
        authentication_classes = (NoAuthentication,)
        filter_backends = (filters.DjangoFilterBackend,)
        filter_fields = ('id', 'email', 'name')
    
        def get_queryset(self):
            user = TokenAuthentication().authenticate(self.request)
            if user is not None:
                user = user[0]
                if user.is_superuser:
                    return get_user_model().objects.all()
                else:
                    return get_user_model().objects.filter(id=user.id)
    
            return get_user_model().objects.none() 
    
    0 讨论(0)
  • 2020-12-28 09:20

    You could utilizing Django REST Framework's ability to define custom permissions. You can specify both a has_permission and has_object_permission within a custom class. This will give you the expected behavior of throwing 403s to anon users for everything except posting to the creation endpoint. It might look something like:

    class IsAnonCreate(permissions.BasePermission):
        def has_permission(self, request, view):
            if request.method == "POST" and not request.user.is_authenticated():
                return True
            elif not request.user.is_authenticated() and request.method != "POST":
                return False
            elif request.method in permissions.SAFE_METHODS:
                return True
    
            return False
    
        def has_object_permission(self, request, view, obj):
            if not request.user.is_authenticated():
                return False
            if request.method in permissions.SAFE_METHODS:
                return True
    
            return obj.username == request.user.username
    

    You could then add some custom handling for authenticated users if you wanted.

    Then all you need to do is add the permission class to your ModelViewSet:

    class UserViewSet(viewsets.ModelViewSet):
    
        """
        API endpoint that allows users to be viewed or edited.
        """
        queryset = User.objects.all()
        serializer_class = UserSerializer
        permission_classes = (IsAnonCreate, )
    
    0 讨论(0)
提交回复
热议问题