原子事务无法正常工作djangorest

问题描述 投票:0回答:4

我正在使用DRF、基于API视图类的视图、post方法。 参数为:文件 逻辑:对文件进行一些验证并逐步保存文件(不同类型的对象) 如果在保存文件的其余部分时发生异常,我正在尝试回滚事务。我设置

'ATOMIC_REQUESTS'
True

class SaveXMlFile(APIView):
   authentication_classes = [TokenAuthentication]
   permission_classes = [IsAuthenticated]
   parser_classes = [FormParser, MultiPartParser]

   def post(self, request):
      """
          Save xml file
          ---
          # inputs
          parameters:
              - name: game_log_file
                description: Game log file
                type: file
                required: true
                paramType: post
                allowMultiple: false
      """
      try:
          # import pdb; pdb.set_trace()
          game_log_file = request.data['game_log_file']
          file_store = FileStore.objects.create(uploaded_file=game_log_file)
          xml_file_processing = ProcessXmlFile(file_store)
          already_saved = xml_file_processing.was_file_saved()
          player_exists = xml_file_processing.player_exists()
          if already_saved:
              file_store.delete()
              return Response({"info": "File was saved previously, no action taken place this time."}, status=200)
          if not player_exists:
              file_store.delete()
              return Response({"info":  "No player exists in the database, ask your administrator to create some."}, status=200)
          xml_file_processing.save()
          file_store.delete()
          return Response({"success": "File has been saved."}, status=status.HTTP_201_CREATED)
      except Exception as err:
          error = "{0}".format(str(err))
          return JsonResponse({'exception': error}, status=500)

当文件的一半已保存时,我故意抛出异常,但即使在过程中引发异常,已提交的事务也不会回滚。

如有任何想法,我们将不胜感激。

django django-rest-framework
4个回答
6
投票

您应该阅读更多有关 Django 事务如何工作的内容。 由于您捕获了异常,Django 将看到一切正常并将提交事务,无论您的响应代码是什么。取自https://docs.djangoproject.com/en/1.10/topics/db/transactions/#tying-transactions-to-http-requests

它的工作原理是这样的。在调用视图函数之前,Django 会启动一个 交易。如果响应生成没有问题,Django 提交交易。如果视图产生异常,Django 回滚事务。

因此,既然您捕获了异常并返回响应,Django 就认为没有理由执行回滚。


3
投票

这里有两个独立的东西。首先,当发生错误时,DRF 会自行引发 500 响应(因此无需捕获异常并显式引发 500)。其次,您也可以考虑像这样应用 method_decorator :

from django.utils.decorators import method_decorator
from django.db.transaction import atomic

@method_decorator(atomic, name='dispatch')
class MyView(APIView):
  ....

这背后的主要原理是,由于性能损失,使用设置为 True 的 ATOMIC_REQUESTS 可能并不总是理想的,但您仍然可能希望将某些特定视图包装在原子块中。当然,在这种情况下你可以使用

with atomic():
  ... your code

因为你可以访问该方法本身,但这有点离题:)

希望这有帮助


3
投票

致未来的访客(假设时间旅行

根据经验...

进行交易时切勿使用 try...catch!因为,通过事务,您正在尝试解决不一致的问题......但是,通过 try...catch,您隐藏了不一致,从而导致事务无法回滚。


0
投票

对我有用的一件事是回滚 except 块中的事务。考虑这个受您的代码片段启发的示例 -

from django.db import transaction #--> import this

class SaveXMlFile(APIView):
  authentication_classes = [TokenAuthentication]
  permission_classes = [IsAuthenticated]
  parser_classes = [FormParser, MultiPartParser]
 
  @transaction.atomic # --> add this
  def post(self, request):
    try:
      # import pdb; pdb.set_trace()
      game_log_file = request.data['game_log_file']
      file_store = FileStore.objects.create(uploaded_file=game_log_file)
      xml_file_processing = ProcessXmlFile(file_store)
      already_saved = xml_file_processing.was_file_saved()
      player_exists = xml_file_processing.player_exists()
      if already_saved:
        file_store.delete()
        return Response({"info": "File was saved previously, no action taken place this time."}, status=200)
      if not player_exists:
        file_store.delete()
        return Response({"info":  "No player exists in the database, ask your administrator to create some."}, status=200)
      xml_file_processing.save()
      file_store.delete()
      return Response({"success": "File has been saved."}, status=status.HTTP_201_CREATED)
    except Exception as err:
     transaction.set_rollback(True) # --> add this
     error = "{0}".format(str(err))
     return JsonResponse({'exception': error}, status=500)

这背后的逻辑是,一旦你尝试并除非你已经将其标记为原子,代码就会认为你可能已经处理了错误并且不会自动回滚。因此,您必须显式地执行此操作,从而将 set_rollback 标记为 true。

© www.soinside.com 2019 - 2024. All rights reserved.