DRF行动中的原子交易?

时间:2018-10-09 06:56:48

标签: python django django-rest-framework

我正试图第一次进入Django atomic transactions。我想知道是否有可能使用这样的东西:

class TaskViewSet(MultiSerializerViewSet):
    @transaction.atomic
    @action(methods=['PATCH'], detail=True)
    def move_task(self, request, pk):
        # making queries, trying to update them, roll back if last one fails.    
        return Response("message: SUCCESS", status=_status.HTTP_200_OK)

我进行了一些搜索-有关如何使用事务的一些信息,但是如果可以在DRF中使用它们,我没有找到任何信息。

2 个答案:

答案 0 :(得分:1)

class PayViewSet(ModelViewSet):

    @action(methods=['PATCH'], detail=True)
    @transaction.atomic
    def approval(self, request, *args, **kwargs):
        sid = transaction.savepoint()
        success = something 
        if success:
            transaction.savepoint_commit(sid)
            return success_response('yes')
        else:
            transaction.savepoint_rollback(sid)
            return error_response('no')

保存点视情况而定

答案 1 :(得分:0)

如果您需要将所有API调用和DRF动作包装到事务中,则可以使用[ATOMIC_REQUEST)Django数据库设置(来自Django 1.8)< / p>

DATABASES = {
    "default": {
        ....
        "ATOMIC_REQUESTS": True,

如果您使用自定义异常处理程序DRF Issue),则可能需要进行如下调整

REST_FRAMEWORK = {
    ....
    "EXCEPTION_HANDLER": "api.exceptions.your_exception_handler",
}


import logging
from django.db import IntegrityError
from rest_framework.response import Response
from rest_framework.views import exception_handler, set_rollback


def your_exception_handler(exc, context):
    """
    DRF custom exception handler.  This will allow us to add useful information
    to any exceptions to help out our frontend devs
    """

    # Call REST framework's default exception handler first, to get the standard error response.
    response = exception_handler(exc, context)

    if not response and isinstance(exc, IntegrityError):
        # https://github.com/encode/django-rest-framework/issues/5760
        if 'duplicate key value violates unique constraint' in str(exc):
            set_rollback()
            msg = "Unique constraint violated: {exc}".format(exc=exc)
            response = Response({"error": True, "content": msg}, status=400)

    if response is None:
        set_rollback()
        logger.exception(exc)
        response = Response({"error": True, "content": str(exc)}, status=500)

    return response