如何在Django REST Framework中重写generics类的delete方法
问题排查与正确实现方案
现有代码存在的问题
- delete方法位置完全错误:你将
delete方法定义在了ArtistSerializer的内部Meta类中,Meta类仅用于存放序列化器的配置项,定义在内部的方法永远不会被调用。 - 逻辑绑定位置错误:
generics.RetrieveUpdateDestroyAPIView的删除逻辑默认执行流程是调用视图自带的destroy方法,直接触发模型实例的delete()操作,不会主动调用序列化器中自定义的delete方法,哪怕你把delete挪到序列化器的外层也不会生效。 - 路由配置不规范:
all-artist/<int:pk>路径末尾缺少斜杠,不符合Django路由的默认规范,可能会触发不必要的301重定向,甚至接口404。
正确的实现方式
推荐两种常见方案,按需选择:
方案1:重写视图的destroy方法(最推荐,符合DRF分层逻辑)
直接在ArtistView中重写删除逻辑,不需要改动序列化器,把序列化器里错误定义的delete方法删除即可:
# views.py 代码 from rest_framework import status from rest_framework.response import Response class ArtistView(generics.RetrieveUpdateDestroyAPIView): serializer_class = ArtistSerializer queryset = Users.objects.filter(user_type='artist') def destroy(self, request, *args, **kwargs): instance = self.get_object() # 先删除关联的profile profile = instance.profiles profile.delete() # 再删除用户本身 instance.delete() return Response(status=status.HTTP_204_NO_CONTENT)
方案2:修复序列化器方法并主动调用(适合删除逻辑和序列化强绑定的场景)
先修正序列化器的代码,把delete方法移到Meta类外,成为序列化器的成员方法:
# serializers.py 代码 class ArtistProfileSerializer(serializers.ModelSerializer): class Meta: model = Profile fields = ('profile_pic_url','cover_pic_url','full_name','genre','location') class ArtistSerializer(serializers.ModelSerializer): profiles = ArtistProfileSerializer(many=False) class Meta: model = Users fields = ['id','user_type', 'email', 'profiles','username'] # 注意缩进,移到Meta类外面 def delete(self, instance, *arg, **kwargs): profile = instance.profiles profile.delete() instance.delete()
再在视图的destroy方法里主动调用序列化器的delete方法:
# views.py 代码 class ArtistView(generics.RetrieveUpdateDestroyAPIView): serializer_class = ArtistSerializer queryset = Users.objects.filter(user_type='artist') def destroy(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) serializer.delete(instance) return Response(status=status.HTTP_204_NO_CONTENT)
路由修正
将urls.py的对应路径补全末尾斜杠,符合Django规范:
urlpatterns = [ path('all-artist/', views.ArtistListView.as_view()), path('all-artist/<int:pk>/', views.ArtistView.as_view()) ]
内容的提问来源于stack exchange,提问作者ete112
相关产品推荐
相关产品推荐

