PyQt5应用登录Django后上传文件遇403 CSRF错误求助
嘿,我之前也碰到过一模一样的情况!你能成功登录说明session和CSRF Token的基础逻辑是对的,但上传文件时的403(提示“CSRF cookie not set”),大概率是请求里的CSRF信息没跟上Django的验证规则,或者session没正确保持住。下面给你一步步排查和解决的方案:
1. 必须用同一个Session实例处理所有请求
requests的Session对象是核心——你登录用的client(应该是requests.Session()实例吧?)要和上传文件的请求共用同一个,不然登录后的session会直接丢失,Django根本认不出你是已登录用户,CSRF验证自然失败。
给你修正后的代码示例:
import requests login_url = "http://127.0.0.1:8000/accounts/login/" upload_url = "http://127.0.0.1:8000/ranking" # 关键:用同一个Session实例处理登录+上传 client = requests.Session() # 第一步:先访问登录页,让Django把CSRF Token写到cookie里 client.get(login_url) csrf_token = client.cookies.get('csrftoken') # 执行登录 login_data = { 'username': '你的用户名', 'password': '你的密码', 'csrfmiddlewaretoken': csrf_token } login_response = client.post(login_url, data=login_data) # 确认登录成功(比如检查是否跳转到了首页,或者状态码) if login_response.url != login_url: print("登录成功!") # 上传文件:必须用同一个client,同时请求头带上X-CSRFToken files = {'file': open('要上传的文件路径', 'rb')} upload_headers = {'X-CSRFToken': csrf_token} upload_response = client.post(upload_url, files=files, headers=upload_headers) print("上传响应状态码:", upload_response.status_code) print("响应内容:", upload_response.text)
2. 对齐Django的CSRF验证规则
Django默认的CSRF验证会同时检查两个点:
- 请求的cookie里必须有
csrftoken(这个由Session自动保持,只要你用同一个client就没问题) - 请求的头里要有
X-CSRFToken,而且值必须和cookie里的csrftoken完全一致
你之前可能只传了表单里的csrfmiddlewaretoken,但上传文件用的是files参数,表单数据和文件数据分开时,Django可能没识别到表单里的token——所以直接在请求头里带X-CSRFToken是最稳妥的方式。
3. 别手动从HTML里抠CSRF Token
很多人会从登录页的HTML里提取csrfmiddlewaretoken的值,但其实更可靠的是直接从Session的cookie里拿csrftoken——因为Django在你第一次访问登录页时,就已经把这个token写到cookie里了,后续所有请求用这个值就行,不会出错。
4. 检查Django端的视图配置
确保你的上传视图没有禁用CSRF保护(除非你故意这么做,但是不安全),而且是处理POST请求的:
- 如果是函数视图,要确保加了
@csrf_protect装饰器(默认已经加了,除非你用了@csrf_exempt) - 如果是类视图,要确保继承了
View,并且没有用csrf_exempt装饰器
5. 调试小技巧
如果还是不行,打印出请求的cookie和头,看看是不是哪里漏了:
print("当前Session的Cookie:", client.cookies) print("上传请求的Headers:", upload_headers)
这样能快速定位是cookie没带上,还是token值不对。
内容的提问来源于stack exchange,提问作者Setti

