如何在 Django REST Framework 中覆盖viewsets.ModelViewSet?

trs*_*anx 5 python django django-rest-framework

所以我的模型很简单

class Face(models.Model):
    uid = models.CharField(max_length=510, primary_key=True)
    photo = models.ImageField(upload_to='face_photos')
Run Code Online (Sandbox Code Playgroud)

串行器

class FaceSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Face
        fields = ['uid', 'photo']
        extra_kwargs = {'uid': {'required': True}, 'photo': {'required': True}}
Run Code Online (Sandbox Code Playgroud)

视图应该是这样的

class FaceViewSet(viewsets.ModelViewSet):
    queryset = Face.objects.all()
    serializer_class = FaceSerializer
    permission_classes = [permissions.AllowAny]
Run Code Online (Sandbox Code Playgroud)

它有效。然而:

  1. 我不需要列出、更新、删除选项。仅 POST 和 GET。
  2. 我想在帖子中添加我的逻辑,因此如果uid存在则更新,否则创建......以及其他处理。
  3. 我想要在 POST 之后自定义响应。

我如何实现这一切而不失去提供的所有好处viewsets.ModelViewSet,例如验证、Rest API Web 视图中自动生成的 HTML 字段等?

trs*_*anx 5

这对我有用:

class FaceViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    """
    API endpoint for adding and processing new client (by uid) face
    """
    queryset = Face.objects.all()
    serializer_class = FaceSerializer
    permission_classes = [permissions.AllowAny]

    def create(self, request):
        if "uid" in request.POST:
            try:
                instance = Face.objects.get(pk=request.POST['uid'])
                serializer = FaceSerializer(
                    instance=instance,
                    data=request.data
                )
            except Face.DoesNotExist:
                serializer = FaceSerializer(data=request.data)
        else:
            serializer = FaceSerializer(data=request.data)

        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = FaceSerializer(instance=instance)
        return Response(serializer.data)
Run Code Online (Sandbox Code Playgroud)