Django项目中SavedClass视图POST请求权限控制及模型字段权限配置求助
Hey there! Let's break down how to fix your two issues step by step—since you're new to Django REST Framework, I'll keep explanations straightforward so you can follow along easily.
Issue 1: Restrict POST requests to create SavedClass records only for the current user
Right now, your SavedClassView's POST method just returns a 403, which isn't what you want. Instead, we need to ensure that when a user creates a SavedClass, the user field is automatically set to the currently logged-in user (and prevent the frontend from passing a different user ID).
Step 1: Update the Serializer
First, mark the user field as read-only in your SavedClass_serializer so the frontend can't override it:
# serializers.py class SavedClass_serializer(serializers.ModelSerializer): class Meta: model = models.SavedClass fields = '__all__' read_only_fields = ['user'] # Make user field read-only to block frontend input
Step 2: Fix the SavedClassView
Update your SavedClassView to:
- Properly handle POST requests (remove the hardcoded 403)
- Automatically assign the current user to the SavedClass record on creation
- Fix the
get_querysetto use the User object directly (cleaner than usingid)
# views.py class SavedClassView(LoginRequiredMixin, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): serializer_class = serializers.SavedClass_serializer lookup_field = 'id' # Needed for delete operations to find the correct record def get_queryset(self): # Filter SavedClasses to only the current logged-in user (use User object directly) return models.SavedClass.objects.filter(user=self.request.user) def get(self, request): return self.list(request) def post(self, request, *args, **kwargs): # Let the CreateModelMixin handle creation, we'll set the user in perform_create return self.create(request, *args, **kwargs) def delete(self, request, id=None, *args, **kwargs): return self.destroy(request, *args, **kwargs) def perform_create(self, serializer): # Automatically set the user to the currently logged-in user serializer.save(user=self.request.user)
Now, when a user sends a POST request to create a SavedClass, the user field will always be set to their own account—no way to spoof another user's ID.
Issue 2: Restrict is_registered field modifications to admins only
We need to ensure that only superusers can change the is_registered value. There are two clean ways to handle this; let's cover both so you can choose what fits your workflow.
Option 1: Control via the Serializer
Modify the update method in your SavedClass_serializer to strip out the is_registered field if the user isn't an admin:
# serializers.py class SavedClass_serializer(serializers.ModelSerializer): class Meta: model = models.SavedClass fields = '__all__' read_only_fields = ['user'] def update(self, instance, validated_data): # Get the current user from the request context current_user = self.context['request'].user # If the user isn't a superuser, remove is_registered from the data to update if not current_user.is_superuser: validated_data.pop('is_registered', None) # Proceed with the normal update return super().update(instance, validated_data)
Option 2: Control via the View
First, add mixins.UpdateModelMixin to your SavedClassView inheritance (to handle PUT requests), then check for admin permissions before allowing is_registered changes:
# views.py class SavedClassView(LoginRequiredMixin, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): serializer_class = serializers.SavedClass_serializer lookup_field = 'id' def get_queryset(self): return models.SavedClass.objects.filter(user=self.request.user) def get(self, request): return self.list(request) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) def put(self, request, id=None, *args, **kwargs): # Check if user is trying to modify is_registered without admin rights if 'is_registered' in request.data and not request.user.is_superuser: return Response( {"detail": "Only administrators can modify the is_registered field."}, status=status.HTTP_403_FORBIDDEN ) return self.update(request, *args, **kwargs) def delete(self, request, id=None, *args, **kwargs): return self.destroy(request, *args, **kwargs) def perform_create(self, serializer): serializer.save(user=self.request.user)
This option gives you more explicit control and returns a clear error message when a non-admin tries to modify the field.
Final Notes
- Don't forget to add the
UpdateModelMixinto your view if you choose Option 2 (or if you want to allow users to update other fields likeis_attended). - Test both scenarios: log in as a regular user and try to create a SavedClass with another user's ID (it should ignore the user input and use your own), then try to modify
is_registered(it should block you). Log in as an admin to confirm you can modify the field.
内容的提问来源于stack exchange,提问作者dhruv singhal

