29👍
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:
-
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.
-
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).
-
Authenticated users can do whatever they want to their user objects.
6👍
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, )
- How do I memoize expensive calculations on Django model objects?
- Coverage in parallel for django tests
- How do you divide your project into applications in Django?
- Learning the Django framework
- Django Foreign Key: get related model?
2👍
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()
- In a schemamigration, what should be the default value for a null=False field which I'm sure that won't have null values?
- Appropriate choice of authentication class for python REST API used by web app