Django未为Locust压测客户端生成sessionid问题排查求助
问题原因分析与解决方案
核心问题定位
你代码中提交登录请求时使用json.dumps(udata)序列化参数,请求的Content-Type会默认变为application/json,但Django内置的auth.login视图默认只解析application/x-www-form-urlencoded格式的表单数据,不会解析JSON请求体,所以会判定登录参数缺失,校验失败自然不会下发sessionid。你用admin用户测试无异常的情况,大概率是之前测试admin登录时代码用的是表单格式提交,和当前非admin用户的测试代码逻辑不一致导致的。
排查思路
- 首先确认登录接口返回的
response.text内容:如果是登录页重新渲染、或者提示用户名密码错误,就说明参数没有被Django正确解析 - 可以在Django登录视图处加临时日志,打印
request.POST的内容,你会发现JSON提交的场景下request.POST是空的 - 对比浏览器登录时的请求头:浏览器提交登录表单时Content-Type是
application/x-www-form-urlencoded,和你当前Locust的请求头不一致
解决方案
方案1:修改Locust提交格式为表单格式(推荐,适配Django默认登录逻辑)
把POST请求的参数直接传字典,不要做JSON序列化,修改后的login方法代码如下:
def login(self): udata = {'username': self.username, 'password': self.password} log.info("Current cookies in Login:" + str(self.client.cookies)) # 直接传udata字典,不要json.dumps,locust会自动设置为表单格式的Content-Type response = self.client.post("/accounts/login/", data=udata, headers=self.headers) log.info("Response from client.post="+str(response)) log.info("Response status code:" + str(response.status_code)) log.info("Response text=" + response.text) log.info("Headers from post/accts/login = " + str(response.headers))
方案2:如果你的登录接口确实是支持JSON提交的
需要给请求头补充Content-Type配置,同时Django侧要从request.body中解析JSON参数:
# locust侧修改headers self.headers = {'X-CSRFToken': self.csrftoken, 'Content-Type': 'application/json'}
同时Django的登录视图要修改参数解析逻辑:
# Django视图侧示例 import json def login_view(request): if request.method == "POST": data = json.loads(request.body) username = data.get("username") password = data.get("password") # 后续校验逻辑
额外注意项
- 确认你请求的登录路径末尾斜杠和Django路由配置一致,你GET用的是
/accounts/login,POST用的是/accounts/login/,Django如果开启APPEND_SLASH配置会自动重定向,重定向过程可能会丢失POST参数,建议统一路径格式 - 确认测试用的普通用户状态是激活状态,没有被Django禁用
内容的提问来源于stack exchange,提问作者Hank B
相关产品推荐
相关产品推荐

