[Django] django.db.transaction.TransactionManagementError


ケース
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

django単位で
  • をテストしています.db.transaction.TransactionManagementErrorが表示されます.
  • エラーが発生した部分は、ユニークフィールド(電話)をチェックする部分(Integraty Error異常処理)です.
  • 印刷文で確認し、user.testsself.assertEqual()はすべて通過しました.
  • コードは以下の通りです.
  • # user.tests
    class UserSignUpTest(TestCase):
        def setUp(self):
            self.client = Client()
            User.objects.create(
                nickname='user1',
                phone='010111110000',
                password=bcrypt.hashpw('user1111'.encode('utf-8'), bcrypt.gensalt()).decode('utf-8'),
                is_staff=False
            )
            User.objects.create(
                nickname='admin1',
                phone='01099999999',
                password=bcrypt.hashpw('admin1234'.encode('utf-8'), bcrypt.gensalt()).decode('utf-8'),
                is_staff=True
            )
    
        def tearDown(self):
            User.objects.all().delete()
        
        def test_fail_duplicate_phone(self):
            data = {
                "nickname": "user3",
                "phone": "010111110000",
                "password": "user3333",
                "is_staff": False
            }
            response = self.client.post("/user/signup/", data=data, content_type="application/json")
            self.assertEqual(response.status_code, 400)
            self.assertEqual(response.json(), {"message": "DUPLICATE_PHONE"})
    # user.views
    class SignUpView(APIView):
        @swagger_auto_schema(tags=["Sign Up"], request_body=UserSerializer, responses={201: 'Success'})
        def post(self, request):
            try:
                data = json.loads(request.body)
    
                if check_length(data["nickname"], 2):
                    return JsonResponse({"message": "NICKNAME_SHORT"}, status=400)
    
                if check_length(data["phone"], 10):
                    return JsonResponse({"message": "PHONE_SHORT"}, status=400)
    
                if check_password(data["password"]):
                    return JsonResponse({"message": "INVALID_PASSWORD"}, status=400)
    
                User(
                    phone=data["phone"],
                    nickname=data["nickname"],
                    password=hash_password(data["password"]).decode("utf-8"),
                    is_staff=data["is_staff"]
                ).save()
    
                return HttpResponse(status=201)
    
            except IntegrityError:
                return JsonResponse({"message": "DUPLICATE_PHONE"}, status=400)
            except KeyError:
                return JsonResponse({"message": "INVALID_KEYS"}, status=400)
    の原因となる
    参考記事を見て
    1.TestCaseはトランザクションで実行されます.
    2.IntegratyErrorが発生すると、現在のトランザクションが破損します.
    解決する
    TestCaseの代わりにTransactionTestCaseを使用
    コメントサイト
    1. https://stackoverflow.com/questions/24588520/testing-several-integrityerrors-in-the-same-django-unittest-test-case/24589930
    2. https://ondemand.tistory.com/328