加载 Django 运行服务器提供的静态文件时如何修复 cors 错误

How to fix cors error when loading static file served by Django runserver

相关信息: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 runserver 提供的静态文件存在一些问题,但到底是什么以及为什么超出我的范围。

我知道有很多与 cors 相关的问题,例如 Django CORS on static asset,但它们与我的问题无关或没有得到解答。另外,我注意到,对静态文件的请求无论如何都会绕过 cors 中间件,所以也许我应该在这里做些其他事情?

也许有人可以帮助我?

谢谢

看来我找到了答案:

我所做的是将 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 但如果我仍然有 "django.contrib.staticfiles" ,那对我来说绝对没有影响我的 INSTALLED_APPS

一种基于 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)
  • 处理程序必须尽早进行 monkeypatched,在处理任何请求之前。将代码放在 settings.py 中就可以了