0

I have an API endpoint to trigger a payment request to a third party. The endpoint is called with some data in a POST request and goes something like the code below. Somehow when the payment request failed (payment.is_successful = False), no data was ever saved to the database, although the debug log showed SQL INSERTs being made, and no error was thrown. The data was just dropped silently.

I've not set the database to use ATOMIC_REQUESTS (I'm using postgreSQL). And I'm using django 1.11.5 and DRF 3.6.3.

I figured that if I changed HTTP_400_BAD_REQUEST to HTTP_200_OK then my data is saved.

  • Why is this happening (and where is the code responsible for it)?
  • Is there a way to prevent it from happening (I want my data in the db for this view, no matter what) with some setting in Django/DRF?
  • I've temporarily set the return code to 200, but it feels wrong as the request actually failed. What code would make more sense, that doesn't cause the data to disappear?

view code

ser = MySerializer(data=request.data)
if ser.is_valid():
    payment = ser.save()
else:
    # do some non database stuff
    return Response(result, status=status.HTTP_400_BAD_REQUEST)

if payment.is_successful:
    # some more processing
    return Response({'success': True}, status=status.HTTP_201_CREATED)
else:
    return Response({'success': False}, status=status.HTTP_400_BAD_REQUEST)  ## THIS LINE ##

serializer code

class MySerializer(serializers.ModelSerializer):
    def create(...):
        # call payment provider and process response
        payment = MyPayment()
        payment.save()   # contains response from the provider that I always want to keep
        return payment
Laurent S
  • 4,106
  • 3
  • 26
  • 50
  • Have you set your transactions to be atomic for requests in your DATABASES config parameter? – JRajan Oct 12 '17 at 08:53
  • No, I haven't. I'm using the default postgresql settings (besides the connection name). I updated the question to mention that. – Laurent S Oct 12 '17 at 09:15

1 Answers1

0

DRF doesn't rollbacks transactions unless it's an exceptions and it meets some criteria.

This looks like the issue is somewhere outside Django REST framework.

Double check your middlewares for some may apply a rollback in case of a non 200 error.

Linovia
  • 19,812
  • 4
  • 47
  • 48