Django在DEBUG中不提供STATIC_ROOT

Dan*_*tik 8 python django static

我正在使用Python 3.5和Django 1.10来运行开发服务器:

./manage.py runserver 0.0.0.0:8000
Run Code Online (Sandbox Code Playgroud)

在我的settings.py身上:

DEBUG       = True
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL  = '/static/'
Run Code Online (Sandbox Code Playgroud)

和一个app目录,static其静态文件的子目录:

proj/
    proj/
        ...
    app/
        static/
            a.txt
        ...
    static/
        b.txt
Run Code Online (Sandbox Code Playgroud)

很标准.

但是:Django没有服务的STATIC_ROOT时候DEBUG = True.它返回app/static/a.txt/static/a.txt还好,但不static/b.txt/static/b.txt.

修改settings.py为:

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
Run Code Online (Sandbox Code Playgroud)

作品 - 但我必须发表评论STATIC_ROOT(否则Django抱怨它不能进入STATICFILES_DIRS).

现在,我不能只是"使用不同的外部静态目录",例如static2,因为我正在使用django-sass-processor,它将.sass文件编译成.css文件,并将这些.css文件放入STATIC_ROOT(正如我所说,这是无法访问的).

我试过的事情:

  1. 设置NGINX以服务该目录(如在生产环境中).工作,但必须有另一种方式.

  2. 配置django-sass-processor.css文件写入所述"不同的外部静态目录",例如static2并将其包括在内STATICFILES_DIRS.再次,工作,但它不能那么复杂!

  3. 手动添加静态文件URL urls.py:

    if settings.DEBUG:
        urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    
    Run Code Online (Sandbox Code Playgroud)

    这个是一次旅行,所以我想我会分享它以拯救其他人的麻烦:事实证明,Django 无论如何都会这样做,并且实际上会覆盖我的网址 - 但正如我所说,它只包括我的应用程序'静态目录和那些STATICFILES_DIRS.

    我甚DEBUG至改变False并删除了if- 但是这也没有用,因为那时django.conf.urls.static.static函数实际上返回一个空列表.所以,我自己使用它来实现它django.views.static.serve,它终于工作了,但是再次 - 我没有必要关闭调试并手动实现服务静态文件.

更新

  1. 如果您正在处理django-sass-processor并遇到类似的问题,他们实际上已经提供了我刚刚在他们的文档中注意到的解决方案:一个特殊的静态查找器,您可以添加到您的settings.py喜欢中:

    STATICFILES_FINDERS = [
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
        'sass_processor.finders.CssFinder',
    ]
    
    Run Code Online (Sandbox Code Playgroud)

    (前两个是Django的默认查找器,所以当你覆盖这个配置时,你应该手动包含它们).

    但即使是现在,对于任何其他.css文件时,STATIC_ROOT实际上是只有静态目录通过不可访问/static/,我觉得这很奇怪.所以,我仍然想解决(或至少理解......)它.

小智 7

乍一看似乎很奇怪Django不提供文件STATIC_ROOT,但是当你考虑Django打算用于静态文件的工作流程时它是有意义的.Django希望您将静态文件与应用程序捆绑在一起,并将项目级静态文件保存在检入版本控制的单独目录中.然后,当您运行时manage.py collectstatic,STATICFILES_FINDERS用于将所有文件收集到一个目录中(应该在版本控制中),因此可以将它们部署到AWS S3或其他任何目录.

因此,静态文件查找器有两个工作:

  1. 通过路径查找文件,用于DEBUG模式静态文件服务
  2. 列出用于collectstatic的所有可用文件

如果你能够包含STATIC_ROOT在你的STATICFILES_DIRS那个中,那么collectstatic命令可能会陷入循环中.此外,Django开发人员不打算保存文件,STATIC_ROOT因为它不应该检入版本控制.

但是,有时您确实想要提供文件STATIC_ROOT.在我的例子中,我有一个Celery任务,它创建上传图像的缩略图并将它们保存到静态文件存储中.在生产中最终可以保存在可以提供服务的AWS S3上.

因此,如果您有一个有效的用例来提供文件,STATIC_ROOT只需定义您自己的文件查找器并将其路径添加到STATICFILES_FINDERS:

from django.contrib.staticfiles.finders import BaseFinder
from django.contrib.staticfiles.storage import staticfiles_storage

class StaticRootFinder(BaseFinder):
    """
    For debug mode only. Serves files from STATIC_ROOT.
    """
    def find(self, path, all=False):
        full_path = staticfiles_storage.path(path)
        if staticfiles_storage.exists(full_path):
            return [full_path] if all else full_path
        return []

    def list(self, ignore_patterns):
        return iter(())
Run Code Online (Sandbox Code Playgroud)