Django self.client.post 不发送数据给装饰器查看

Django self.client.post does not send data to view with decorator

我有一个简单的测试用例,它检查 POST 请求是否包含有效数据 returns 一个 HTML 响应是否包含 200 状态代码:

class PostRequestTestCase(TestCase):
    def test_valid_post_request(self):
        response = self.client.post('/foo/', data={'text': 'bar'})
        self.assertEqual(response.status_code, 200)

这是为该请求触发的视图 foo

logger = logging.getLogger(__name__)

# decorator to trace enter and exit events
enter_exit_tracer = enter_exit_Tracer(logger)

@enter_exit_tracer
def foo(request):  
    if request.method == 'POST':
        #
        print('request.POST:', request.POST)
        # 
        # some stuff

其中 @enter_exit_tracer 是跟踪 entering/exiting 函数的装饰器:

def enter_exit_Tracer(logger):
    def middle(f): 
        def inner(*args, **kwargs):
            session_string = args[-1] if 'session_key' in args[-1] else '[]'
            logger.debug('%s Enter %s.', session_string, f.__name__)
            result = f(*args, **kwargs)
            logger.debug('%s Exit %s.',  session_string, f.__name__)
            return result
        return inner
    return middle

事实证明,当我将这个装饰器添加到foo函数时,通过self.client.post发送的POST数据实际上并没有传递给foo。它们在测试请求中丢失了 - 所以我的测试失败了:

DEBUG: [] Enter foo.
request.POST: <QueryDict: {}>
ERROR: Invalid form
F
======================================================================
FAIL: test_valid_post_request (textstat.tests.PostRequestTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/user/Pro/myapp/tests.py", line 111, in test_valid_post_request
    self.assertEqual(response.status_code, 200)
AssertionError: 400 != 200

----------------------------------------------------------------------
Ran 1 test in 0.018s

FAILED (failures=1)

我们看到 request.POST: <QueryDict: {}> 并最终导致 ERROR: Invalid form

与此同时,当我执行类似的 POST 请求时,但通过网络浏览器一切正常 - 表单填充了数据,网页呈现正常,@enter_exit_tracer 执行其按预期记录。

如果我注释掉 @enter_exit_tracer 装饰器,那么一切正常,测试通过:

request.POST: <QueryDict: {'text': ['bar']}>
.
----------------------------------------------------------------------
Ran 1 test in 0.007s

OK

问题:

原来装饰器在这一行出现了TypeError错误:

session_string = args[-1] if 'session_key' in args[-1] else '[]'

所以当 args[-1] 不是 str 时,这应该不起作用。用 str(args[-1]) 修复它解决了缺少 POST 数据的整个问题。

奇怪的是 self.client.post 没有引发任何 TypeError 并且 session_string 是以某种方式计算出来的。而不是这个 POST 数据没有发送到视图,没有任何错误或提示警告。 POST 数据刚刚消失。同时,当从 Web 浏览器发送 POST 请求时,相同的代码工作正常,因此错误没有被注意到。