加载 Django runserver 提供的静态文件时如何修复 cors 错误
Posted
技术标签:
【中文标题】加载 Django runserver 提供的静态文件时如何修复 cors 错误【英文标题】:How to fix cors error when loading static file served by Django runserver 【发布时间】:2020-10-21 04:55:58 【问题描述】:相关信息:Django 2.2 版
我已安装 django-cors-headers
并将其添加到启用的应用程序中,并将中间件作为第一个中间件添加到中间件设置中。
我也配置了设置:
INSTALLED_APPS = [
...
"corsheaders",
"rest_framework",
"django.contrib.admin",
...
]
MIDDLEWARE = [
...
"corsheaders.middleware.CorsMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
...
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
我的设置有 2 个项目在不同的端口上运行。 Django 服务器运行在 8000 上,我的前端运行在 8080 上。
前端针对后端发送的所有 API 请求都可以正常工作。但是,当我尝试加载后端项目提供的 one.js 文件时,它会失败并出现以下错误:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/static/myscript.js. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
我加载脚本的方式是创建一个新的脚本元素并将 URL http://127.0.0.1:8000/static/myscript.js
添加为脚本标签上 src 属性的值。
当我使用 https://code.jquery.com/jquery-3.5.1.min.js
而不是 http://127.0.0.1:8000/static/myscript.js
之类的值时,不会发生此错误,因此看起来 Django 运行服务器提供的静态文件存在一些问题,但究竟是什么以及为什么超出了我的范围。
我知道有很多与 cors 相关的问题,例如 Django CORS on static asset,但它们与我的问题无关或没有得到答复。另外,我注意到,静态文件的请求无论如何都会绕过 cors 中间件,所以也许我应该在这里做其他事情?
也许有人可以在这里帮助我?
谢谢
【问题讨论】:
【参考方案1】:看来我已经找到了答案:
我所做的是将INSTALLED_APPS.remove('django.contrib.staticfiles')
添加到开发设置中。
我创建了类似的视图
from django.contrib.staticfiles.views import serve
def cors_serve(request, path, insecure=False, **kwargs):
kwargs.pop('document_root')
response = serve(request, path, insecure=insecure, **kwargs)
response['Access-Control-Allow-Origin'] = '*'
return response
用于提供静态内容。我像这样将它添加到 urlconf 中:
from utils.views import cors_serve
...
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT, view=cors_serve)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT, view=cors_serve)
这确实为我解决了这个问题。我知道 Django 文档 (https://docs.djangoproject.com/en/2.2/ref/contrib/staticfiles/#runserver) 建议您可以跳过使用 runserver 提供的静态文件,如下所示:django-admin runserver --nostatic
但如果我的 INSTALLED_APPS
中仍然有 "django.contrib.staticfiles"
,那对我绝对没有影响
【讨论】:
【参考方案2】:基于 Odif Yitsaeb 的想法略有不同的方法,但是您不需要删除 staticfiles
或混淆 urlpatterns
。只需将以下代码放入您的settings.py
:
from django.contrib.staticfiles import handlers
# extend StaticFilesHandler to add "Access-Control-Allow-Origin" to every response
class CORSStaticFilesHandler(handlers.StaticFilesHandler):
def serve(self, request):
response = super().serve(request)
response['Access-Control-Allow-Origin'] = '*'
return response
# monkeypatch handlers to use our class instead of the original StaticFilesHandler
handlers.StaticFilesHandler = CORSStaticFilesHandler
注意事项:
不要在生产中使用它(无论如何你都不应该在生产中使用 devserver) 在处理任何请求之前,必须很早就对处理程序进行猴子补丁。将代码放在settings.py
中即可解决问题
【讨论】:
以上是关于加载 Django runserver 提供的静态文件时如何修复 cors 错误的主要内容,如果未能解决你的问题,请参考以下文章
python manage.py runserver 127.0.0.1:8000 启动后台有两个启动进程