可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to run a validation before an object is deleted, to prevent deletion in certain cases and return as a validation error. How do I do that? What I have currently doesn't seem right:
class CallDetail(generics.RetrieveUpdateDestroyAPIView): queryset = XCall.objects.all() serializer_class = CallSerializer ... def pre_delete(self, obj): if obj.survey: raise serializers.ValidationError("Too late to delete")
回答1:
You can solve it with permissions:
from rest_framework import permissions class IsSurvey(permissions.BasePermission): def has_object_permission(self, request, view, obj): if request.method == 'DELETE' and obj.survey: return False return True
Then add to your view's permission_classes
from permissions import IsSurvey class MyViewSet(viewsets.ModelViewSet): permission_classes = (IsSurvey, )
回答2:
The solution I found was to override the destroy method on the api.
class CallDetail(generics.RetrieveUpdateDestroyAPIView): queryset = XCall.objects.all() serializer_class = CallSerializer ... def destroy(self, request, *args, **kwargs): obj = self.get_object() if obj.survey: return Response(data={'message': "Too late to delete"}, status=status.HTTP_400_BAD_REQUEST) self.perform_destroy(obj) return Response(status=status.HTTP_204_NO_CONTENT)
For me makes much more sense to validate on the destroy method instead of validating on the object permission check as avances123 mentioned, since permission should only check for permission stuffs, and doesn't return any messages related to validation.
Hope that helps ;)
回答3:
Rather than raising a ValidationError
, I will just raise a ParseError or another custom error that fits the error description:
from rest_framework import exceptions def pre_delete(self, obj): if obj.survey: raise exceptions.ParseError("Too late to delete")
回答4:
Update
validate doesn't get called on delete.
Hmmm. Right yes. In that case I'd raise the exception in pre_delete
just as you are and override delete
to wrap the destroy
call in a try
block.
If you except ValidationError as e
you can use that to construct the response you want by hand...
return Response({"error" : e.message})
... or such.
You could probably populate self._errors
and leverage the existing error response behaviour but I can't think how to do that off-hand.
I hope that helps.
First Answer (didn't work):
Check the doc on Object Level Validation.
Implement validate
to check if the survey is set:
def validate(self, attrs): if attrs['survey'] raise serializers.ValidationError("Too late to delete") return attrs
If attrs
I hope that helps.