在生产中加载静态文件但不在开发中加载

Static files loading in production but not development

通常我遇到这个问题恰恰相反!

在我的开发环境中,我的 Django 应用程序不会加载我的一些静态文件,特别是我自己添加的静态文件:也就是说,我添加到我的应用程序中的两个包(adminckeditor) 都可以正常加载,但是找不到我自己创建并链接的两个文件夹(imgcss)。这是我的目录的地图:

root
 |-- blog    (this is the name of my app)
 |-- mysite  (name of my site)
      |-- settings.py
      |-- urls.py
 |-- media
 |-- static
      |-- admin
      |-- ckeditor
      |-- css
      |-- img

如前所述,ckeditoradmin 可以正常加载,而其他的则不能。这是调试模式下 runserver 输出的示例(static/css/base.css 处的文件存在于我的文件树中):

GET /static/ckeditor/ckeditor/ckeditor.js HTTP/1.1" 200 690627
GET /static/admin/css/fonts.css HTTP/1.1" 200 423
GET /static/admin/css/widgets.css HTTP/1.1" 200 10340
GET /static/css/base.css HTTP/1.1" 404 1761
GET /static/img/brand.png HTTP/1.1" 404 1764

以下是一些您可能感兴趣的其他信息:

为了帮助任何人调试我的问题,这里有一些相关的摘录文件:

settings.py

DEBUG = True
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    'ckeditor',
    'ckeditor_uploader',
]
...
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

urls.py

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('', include('blog.urls')),
    path('admin/', admin.site.urls),
    path('ckeditor', include('ckeditor_uploader.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

您的 urlpatterns 是正确的,这意味着问题很可能是设置文件中的 settings.DEBUG = False。确保 settings.DEBUGTrue,并且应加载静态文件。您可以通过使用 manage.py shell 并检查 DEBUG 标志的值来验证这一点。

唯一要查找的其他问题是您是否通过验证 ROOT_URLCONF 设置指向设置中正确的 urls 文件,以及您的 BASE_DIR 是否指向 static目录。这两个值也可以在 shell.

中验证

例如,如果您的设置文件位于 /path/to/root/blog/settings.py,那么您将 BASE_DIR 设置为:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

因为你的应用程序列表中有 'django.contrib.staticfiles',当 DEBUG 为 True 时,Django 实际上不会从 STATIC_ROOT 加载文件。

当 DEBUG 启用时,Django 使用 STATICFILES_FINDERS 选项,默认情况下是:

[
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

FileSystemFinder 将查找存储在 STATICFILES_DIRS 设置中的文件 AppDirectoriesFinder 正在每个应用程序的 static 子目录中查找文件。

这就是文件夹 admin 和 ckeditor 工作的原因 - 当 DEBUG 为 True 时,Django 根本不使用您的 /root/static 文件夹。相反,它通过 AppDirectoriesFinder 从 apps static 子目录中获取文件。 像 .../3.5/lib/python3.5/site-packages/django-ckeditor/static/...

当您 运行 collectstatic 命令时,它会收集 STATICFILES_FINDERS 可以找到的所有静态文件并将它们复制到您的 STATIC_ROOT (/root/static/) 和如果 DEBUG 是 False Django 只使用这个文件夹而不是 STATICFILES_FINDERS

那么如何让它在启用调试的情况下工作。只需创建一个文件夹并将其添加到 STATICFILES_DIRS,如下所示:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'some_new_static_folder'),
]

您也可以从 /root/static/ 中删除所有文件,您不需要在此文件夹中手动创建任何内容,collectstatic 将自动执行生产。

本地文件也有一些问题,这对我的情况有所帮助。

我将我的静态文件存储在 S3 上,但您可以调整图像位置 URL。

if DEBUG == False:
    STATICFILES_LOCATION = 'static'
    STATIC_URL = "//%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)
    MEDIAFILES_LOCATION = 'media'
    MEDIA_URL = "//%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
else:
    MEDIA_URL = '/media/'
    STATIC_URL = '/static/'

这是一种在 Django 中处理静态文件的简单方法(如果您使用 Django 默认选项,它开箱即用):

  1. 永远不要将任何东西放入您指定为 STATIC_ROOT 的文件夹中。
  2. 将特定于应用程序的静态文件放入应用程序内的文件夹 static
  3. 对于不直接属于应用程序的静态文件,在您的项目中创建文件夹 static_files 并添加到您的设置:STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_files'),]当然你可以选择另一个名字,static_files只是一个建议。
  4. 用于生产环境 运行 collectstatic 以便 Django 收集您的静态文件(来自第 2 点和第 3 点)并将它们放入您的文件夹中创建于 1.

如果您处于调试模式,则您已完成第 3 步。


在您的案例中,问题是您将静态内容放入 STATIC_ROOT 文件夹中,Django 不会在调试模式下查找内容。 adminckeditor 工作是因为它们遵循步骤 2.,因此它们的静态文件实际上来自已安装应用程序的文件夹,而不是处于调试模式时来自您的 static 文件夹。


所以,这是解决问题的方法

  • 执行上面的第 3 步。
  • 将您的文件夹 imgcss 移动到在步骤 3 中创建的文件夹。
  • (可选)擦除您的 STATIC_ROOT 文件夹。