Django Rest Framework POST Update if existing or create

前端 未结 8 1833
余生分开走
余生分开走 2020-12-13 09:24

I am new to DRF. I read the API docs, maybe it is obvious but I couldn\'t find a handy way to do it.

I have an Answer object which has one-to-one relationship with a

8条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-13 10:01

    I tried the serializer solution but it seems exception raised before hitting the serializer function create(self, validated_data). That's because I'm using ModelViewSet (which in turn using class CreatedModelMixin). Further study reveals that exception raised here:

    rest_framework/mixins.py
    
    class CreateModelMixin(object):
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True) <== Here
    

    Since I want to keep all features provided by framework, so I prefer capturing the exceptions and route over to update:

    from rest_framework.exceptions import ValidationError
    
    class MyViewSet(viewsets.ModelViewSet)
    
        def create(self, request, *args, **kwargs):
            pk_field = 'uuid'
            try:
                response = super().create(request, args, kwargs)
            except ValidationError as e:
                codes = e.get_codes()
                # Check if error due to item exists
                if pk_field in codes and codes[pk_field][0] == 'unique':
                    # Feed the lookup field otherwise update() will failed
                    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
                    self.kwargs[lookup_url_kwarg] = request.data[pk_field]
                    return super().update(request, *args, **kwargs)
                else:
                    raise e
            return response
    

    My app can always call POST /api/my_model/ with parameters (here, uuid = primary key).

    However, would it be better if we handle this in update function?

        def update(self, request, *args, **kwargs):
            try:
                response = super().update(request, *args, **kwargs)
            except Http404:
                mutable = request.data._mutable
                request.data._mutable = True
                request.data["uuid"] = kwargs["pk"]
                request.data._mutable = mutable
                return super().create(request, *args, **kwargs)
            return response
    

提交回复
热议问题