Retrofit调用Django REST Framework POST接口返回400错误求助
你遇到的400 Bad Request错误,大概率是Android端的请求格式、参数或路径和后端预期不匹配导致的——毕竟Postman能正常调用,说明后端接口本身没问题,咱们从几个关键细节逐一排查:
1. 先确认请求路径拼接是否正确
你的BASE_URL是http://10.0.2.2:8000/(末尾带斜杠),接口注解用了@POST("/api-auth/")(开头也带斜杠),拼接后会变成http://10.0.2.2:8000//api-auth/,这种重复斜杠的路径可能会被DRF拒绝。
解决方法:
把接口的POST路径改成不带开头斜杠的形式,避免重复拼接:
@FormUrlEncoded @POST("api-auth/") Call<Tokken> get_tokken(@Field("username") String username, @Field("password") String password);
同时对比Postman里的请求路径,确保完全一致(比如Postman里是不是用的/api-auth不带末尾斜杠?如果是,就把注解改成@POST("api-auth"))。
2. 检查请求参数与后端的匹配度
DRF的默认登录接口接收的参数是username和password,你代码里的@Field参数名看起来没问题,但要注意大小写完全一致——比如别把后端期望的username写成了Username。另外,也确认下Postman里的表单参数键名和你代码里的完全一样。
3. 打印错误响应体,获取具体报错信息
400错误通常会返回DRF的详细错误描述,这是定位问题最快的方式,你可以在Retrofit的回调里打印错误响应的内容:
call.enqueue(new Callback<Tokken>() { @Override public void onResponse(Call<Tokken> call, Response<Tokken> response) { if (!response.isSuccessful()) { try { // 打印DRF返回的错误详情 String errorContent = response.errorBody().string(); Log.e("RetrofitError", "错误详情: " + errorContent); } catch (IOException e) { e.printStackTrace(); } return; } // 处理成功响应逻辑 } @Override public void onFailure(Call<Tokken> call, Throwable t) { t.printStackTrace(); } });
比如如果返回{"username": ["This field is required."]},就说明参数没正确传递;如果返回{"non_field_errors": ["Unable to log in with provided credentials."]},那就是用户名密码的问题(但Postman能成功的话这个可能性低)。
4. 确认Tokken实体类与返回JSON结构匹配
如果DRF返回的是{"token": "xxxxxx"},那你的Tokken类字段必须和这个键名完全对应(注意大小写):
public class Tokken { private String token; // 别写成Token或者其他名称 // 对应的getter和setter public String getToken() { return token; } public void setToken(String token) { this.token = token; } }
如果字段不匹配,GsonConverter解析失败也可能间接导致请求被判定为无效。
5. 排除CSRF防护的影响
Django默认开启CSRF防护,但/api-auth/接口通常是豁免CSRF的,不过如果你的后端自定义了配置,也可以简单排查下:如果Postman里没有手动添加CSRF Token就能成功,那Android端也不需要处理,这个可以暂时排除。
先按照上面的步骤排查,尤其是打印错误响应体这一步,基本上能快速找到问题根源。
内容的提问来源于stack exchange,提问作者user7128116

