如何让 Django 使用 Gunicorn 提供静态文件?

Posted

技术标签:

【中文标题】如何让 Django 使用 Gunicorn 提供静态文件?【英文标题】:How to make Django serve static files with Gunicorn? 【发布时间】:2012-09-29 20:00:04 【问题描述】:

我想在本地主机上的 gunicorn 下运行我的 django 项目。我安装并集成了 gunicorn。当我跑步时:

python manage.py run_gunicorn

它可以工作,但没有任何静态文件(css 和 js)

我在 settings.py 中禁用了 debug 和 template_debug(使它们为假),但它仍然是一样的。我错过了什么吗?

我称静态为:

 STATIC_URL css/etc....

【问题讨论】:

【参考方案1】:

当处于 开发 模式并且当您使用其他服务器进行本地开发时将此添加到您的 url.py

from django.contrib.staticfiles.urls import staticfiles_urlpatterns

# ... the rest of your URLconf goes here ...

urlpatterns += staticfiles_urlpatterns()

更多信息here

生产中,你永远不会把 gunicorn 放在前面。相反,您使用 像 nginx 这样的服务器,它将请求分派到 gunicorn 工作人员池并提供静态文件。

见here

【讨论】:

当我重新启用调试和模板调试时,它开始正常工作。将这些行放入 urls.py 并不重要。但现在我看不到我的自定义 404 和 500 错误页面。在生产中;我应该做 False Debug 和 template_debug 吗? @drTerminal 我更新了我的答案,并包含了我引用的 django 链接的具体措辞。自定义 404/500 页面仅在 DEBUG=False 时显示。请阅读具体链接,我认为它会回答您的大部分问题。 这对我有用,虽然我使用的是 Django 1.6。在文档docs.djangoproject.com/en/1.4/howto/static-files/… 中,1.6. 的 urlpattern 有不同的用法,但对我来说没有结果。所以我成功使用了 1.4 解决方案。 @binki 啊!你让我搜索:P 所以......因为我有模糊的记忆,你实际上可以这样做,所以我搜索了一下。如果您下载此 pdf media.readthedocs.org/pdf/django/1.4.X/django.pdf,这是我的答案所指的过时版本,您会发现您的应用服务器是否可以,因为 Django 为您完成了它。当然,这是非常低效的,但仍然可行。不知道有没有可能,如果有,怎么做。 啊,看起来可能是django.views.static.serve,它仍然存在于现代文档中。但基本上与 1.4 文档中没有改变的相同警告“此视图未针对生产使用进行强化,应仅用作开发辅助工具”。没有那么强烈的措辞。所以它可以用纯 django 甚至记录在案,只是我猜它是“不受支持”的使用。只有serve 函数始终可用,但static 辅助函数在生产中会自动禁用。【参考方案2】:

白噪声

发布 v4.0

http://whitenoise.evans.io/en/stable/changelog.html#v4-0

Django 的 WSGI 集成选项(涉及编辑 wsgi.py)已被删除。相反,您应该将 WhiteNoise 添加到 settings.py 中的中间件列表中,并从 wsgi.py 中删除对 WhiteNoise 的任何引用。有关更多详细信息,请参阅文档。 (纯 WSGI 集成仍然可用于非 Django 应用程序。)

Pre v4.0

Heroku 推荐这种方法在:https://devcenter.heroku.com/articles/django-assets:

您的应用程序现在将直接从 Gunicorn 在生产环境中提供静态资源。这对于大多数应用程序来说已经足够了,但是***应用程序可能想要探索使用带有 Django-Storages 的 CDN。

安装方式:

pip install whitenoise
pip freeze > requirements.txt

wsgi.py:

import os
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "free_books.settings")
application = get_wsgi_application()
application = DjangoWhiteNoise(application)

在 Django 1.9 上测试。

【讨论】:

因此,这再次意味着 WSGI 应用程序正在提供静态文件。不是独角兽。 pip freeze > requirements.txt 会覆盖以前的要求,我会推荐pip freeze | grep whitenoise >> requirements.txt 上述说明自 whitenoise 4.0 版起已弃用。 whitenoise.evans.io/en/stable/changelog.html#v4-0【参考方案3】:

gunicorn 应该用于为 python“应用程序”本身提供服务,而静态文件由静态文件服务器(例如 Nginx)提供服务。

这是我的一个配置的摘录:

upstream app_server_djangoapp 
    server localhost:8000 fail_timeout=0;


server 
    listen < server port goes here >;
    server_name < server name goes here >;

    access_log  /var/log/nginx/guni-access.log;
    error_log  /var/log/nginx/guni-error.log info;

    keepalive_timeout 5;

    root < application root directory goes here >;

    location /static     
        autoindex on;    
        alias < static folder directory goes here >;    
    

    location /media 
       autoindex on;
       alias < user uploaded media file directory goes here >;
    

    location / 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) 
            proxy_pass http://app_server_djangoapp;
            break;
        
    

一些注意事项:

静态根目录、媒体根目录、静态文件路径前缀和媒体文件路径前缀在你的settings.py中设置 将 nginx 设置为从静态内容目录提供服务后,您需要在项目根目录中运行“python manage.py collectstatic”,以便将各种应用程序中的静态文件复制到静态文件夹中李>

最后:虽然可以从 gunicorn 提供静态文件(通过启用仅调试的静态文件服务视图),但这在生产中被认为是不好的做法。

【讨论】:

是的,我知道。我将在生产中的 nginx 下使用它。我只是在生产前在我的本地主机中进行测试。 当你说“虽然可以从 gunicorn 提供静态文件”时,你的意思是说“gunicorn 将 间接 如果它委托的 WSGI 应用程序提供静态文件请求提供静态文件”?【参考方案4】:

我已将它用于我的开发环境(使用 gunicorn):

from django.conf import settings
from django.contrib.staticfiles.handlers import StaticFilesHandler
from django.core.wsgi import get_wsgi_application


if settings.DEBUG:
    application = StaticFilesHandler(get_wsgi_application())
else:
    application = get_wsgi_application()

然后运行gunicorn myapp.wsgi。这类似于@rantanplan's answer,但是,它在运行静态文件时不运行任何中间件。

【讨论】:

这就是我一直在寻找的答案!!非常感谢。它奏效了。 有时我们正在处理内部应用程序,“网络规模”并不重要。对于这些情况,这是一个很好的答案。【参考方案5】:

为了提供静态文件,如Jamie Hewland says,通常使用 Nginx 将所有请求路由到 /static/

location /statis/ 

    alias /path/to/static/files;


换句话说,就像coreyward says 关于 Gunicorn / Unicorn

并非旨在解决服务中涉及的一系列问题 文件给客户

如果您考虑使用其他 WSGI 服务器(如 uWSGI)而不是 Gunicorn,则同样适用。在uWSGI documentation

通过 uWSGI 提供静态文件效率低下。相反,为他们服务 直接来自 Nginx 并完全绕过 uWSGI


更简单的方法是使用 Python 使用 WhiteNoise 库提供静态文件,该库非常易于设置(您可能希望使用 CDN,以便大多数请求不会到达 Python 应用程序)。作为Miguel de Matos says,你只需要

    收集静态的

     python manage.py collectstatic
    

    安装白噪声

     pip install whitenoise
    

    在settings.py中添加如下STATICFILES_STORAGE

     STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
    

    在 settings.py 中将以下内容添加到您的MIDDLEWARE(如mracette 注释,“根据白噪声文档,您应该将中间件放在django.middleware.security.SecurityMiddleware 之后”)

     `MIDDLEWARE = [
       'django.middleware.security.SecurityMiddleware',
       'whitenoise.middleware.WhiteNoiseMiddleware',
       ...
     ]
    

【讨论】:

根据白噪声文档,您应该将中间件放在 'django.middleware.security.SecurityMiddleware' whitenoise.evans.io/en/stable 之后【参考方案6】:

从 Django 1.3 开始,django/conf/urls/static.py 在 DEBUG 模式下处理静态文件:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

阅读更多https://docs.djangoproject.com/en/2.0/howto/static-files/#serving-static-files-during-development

【讨论】:

以上是关于如何让 Django 使用 Gunicorn 提供静态文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Traefik 时如何使用 Nginx 和 Django Gunicorn 提供静态内容

如何使用 Gunicorn 查看 Django 错误的详细信息?

Django 不使用 NGINX + GUNICORN 提供静态文件

使用 Docker、nginx 和 gunicorn 提供 Django 静态文件

Heroku 上带有 gunicorn 服务器的 Django 项目不提供静态文件

django 和 gunicorn 在 docker 容器内运行时,无法在 ec2 上使用 nginx 提供静态文件