Django 1.11测试中Test Client POST无法传递数据问题排查
嘿,我之前在Django 1.11+Python 3.6的环境下做单元测试时,也碰到过一模一样的问题——调用self.client.post后视图里的request.POST始终是空字典,表单根本没法填充。结合当时的排查经验,给你几个实用的解决方向:
确认POST数据的传递方式
别犯低级错误:一定要用字典格式把数据传给data参数,而不是传JSON字符串或者用错参数。正确的写法应该是这样的:response = self.client.post( '/your-form-view-url/', {'username': 'test_user', 'password': 'test_pass123'} )如果你非要传JSON格式的请求体,那得指定
content_type='application/json',但这时候数据会被放到request.body里,而不是request.POST——表单处理视图默认处理的是application/x-www-form-urlencoded类型的请求,所以优先用字典传data才对。检查视图的请求方法逻辑
先确认你的视图代码里,是不是只有在request.method == 'POST'时才处理表单?有没有不小心写成request.method == 'GET'了?另外,如果视图用了@require_POST装饰器,要是请求没通过验证,也可能出现request.POST为空的假象——这时候可以看看响应的状态码是不是405(方法不允许)。排查CSRF验证的影响
单元测试里的Client默认是绕过CSRF验证的,但如果你手动开启了enforce_csrf_checks=True,那不带CSRF Token的POST请求会被Django拒绝,导致request.POST为空。可以试试手动带上Token:from django.middleware.csrf import get_token # 获取CSRF Token csrf_token = get_token(self.client) # 带着Token发请求 response = self.client.post( '/your-form-view-url/', {'username': 'test_user', 'csrfmiddlewaretoken': csrf_token} )不过一般单元测试不需要这么做,除非你特意开启了CSRF检查。
核对表单字段名是否匹配
有没有可能你POST的字段名和表单定义的字段名不匹配?比如表单里是email,你传的是user_email,那表单自然没法填充,看起来就像request.POST没数据一样。可以在视图里临时加两行打印:print("Request POST:", request.POST) print("Request Body:", request.body)看看实际传过来的内容到底是什么,很快就能定位问题。
检查测试用例的Setup逻辑
有没有在测试用例的setUp()方法里不小心重置了client?或者之前的测试用例修改了client的请求头,导致后续POST请求的Content-Type不对?可以试试在POST请求前显式指定content_type='application/x-www-form-urlencoded',确保请求格式正确:response = self.client.post( '/your-form-view-url/', {'username': 'test_user'}, content_type='application/x-www-form-urlencoded' )
内容的提问来源于stack exchange,提问作者ÁlvaroSL

