在生产中加载静态文件但不在开发中加载
Static files loading in production but not development
通常我遇到这个问题恰恰相反!
在我的开发环境中,我的 Django 应用程序不会加载我的一些静态文件,特别是我自己添加的静态文件:也就是说,我添加到我的应用程序中的两个包(admin
和 ckeditor
) 都可以正常加载,但是找不到我自己创建并链接的两个文件夹(img
和 css
)。这是我的目录的地图:
root
|-- blog (this is the name of my app)
|-- mysite (name of my site)
|-- settings.py
|-- urls.py
|-- media
|-- static
|-- admin
|-- ckeditor
|-- css
|-- img
如前所述,ckeditor
和 admin
可以正常加载,而其他的则不能。这是调试模式下 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
以下是一些您可能感兴趣的其他信息:
- 它在生产中运行良好!我认为这是因为我在我的 apache 配置中有专用别名,但这并不能解释为什么
admin
和 ckeditor
有效。
- 我以几乎相同的方式路由媒体(请参阅下面的设置文件)并且在开发中工作正常。
- 我正在按照 Django 文档的说明使用模板标记
{% load static %}
。在旧版本中,我使用 {% load staticfiles %}
并且我也尝试过。
- 我在两个环境中都有 运行
collectstatic
。
- 运行
DEBUG=False
在生产中工作正常(加载所有静态文件)但在开发中 DEBUG=False
时根本没有加载静态文件。这是可以预料的,因为在开发中我没有网络服务器来处理这个(为了澄清,我 通常 运行 服务器处于调试模式,但是尝试关闭和打开此设置以查看发生了什么变化)
为了帮助任何人调试我的问题,这里有一些相关的摘录文件:
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.DEBUG
为 True
,并且应加载静态文件。您可以通过使用 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 默认选项,它开箱即用):
- 永远不要将任何东西放入您指定为
STATIC_ROOT
的文件夹中。
- 将特定于应用程序的静态文件放入应用程序内的文件夹
static
。
- 对于不直接属于应用程序的静态文件,在您的项目中创建文件夹
static_files
并添加到您的设置:STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_files'),]
。 当然你可以选择另一个名字,static_files
只是一个建议。
- 用于生产环境 运行
collectstatic
以便 Django 收集您的静态文件(来自第 2 点和第 3 点)并将它们放入您的文件夹中创建于 1.
如果您处于调试模式,则您已完成第 3 步。
在您的案例中,问题是您将静态内容放入 STATIC_ROOT
文件夹中,Django 不会在调试模式下查找内容。
admin
和 ckeditor
工作是因为它们遵循步骤 2.,因此它们的静态文件实际上来自已安装应用程序的文件夹,而不是处于调试模式时来自您的 static
文件夹。
所以,这是解决问题的方法:
- 执行上面的第 3 步。
- 将您的文件夹
img
和 css
移动到在步骤 3 中创建的文件夹。
- (可选)擦除您的
STATIC_ROOT
文件夹。
通常我遇到这个问题恰恰相反!
在我的开发环境中,我的 Django 应用程序不会加载我的一些静态文件,特别是我自己添加的静态文件:也就是说,我添加到我的应用程序中的两个包(admin
和 ckeditor
) 都可以正常加载,但是找不到我自己创建并链接的两个文件夹(img
和 css
)。这是我的目录的地图:
root
|-- blog (this is the name of my app)
|-- mysite (name of my site)
|-- settings.py
|-- urls.py
|-- media
|-- static
|-- admin
|-- ckeditor
|-- css
|-- img
如前所述,ckeditor
和 admin
可以正常加载,而其他的则不能。这是调试模式下 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
以下是一些您可能感兴趣的其他信息:
- 它在生产中运行良好!我认为这是因为我在我的 apache 配置中有专用别名,但这并不能解释为什么
admin
和ckeditor
有效。 - 我以几乎相同的方式路由媒体(请参阅下面的设置文件)并且在开发中工作正常。
- 我正在按照 Django 文档的说明使用模板标记
{% load static %}
。在旧版本中,我使用{% load staticfiles %}
并且我也尝试过。 - 我在两个环境中都有 运行
collectstatic
。 - 运行
DEBUG=False
在生产中工作正常(加载所有静态文件)但在开发中DEBUG=False
时根本没有加载静态文件。这是可以预料的,因为在开发中我没有网络服务器来处理这个(为了澄清,我 通常 运行 服务器处于调试模式,但是尝试关闭和打开此设置以查看发生了什么变化)
为了帮助任何人调试我的问题,这里有一些相关的摘录文件:
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.DEBUG
为 True
,并且应加载静态文件。您可以通过使用 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 默认选项,它开箱即用):
- 永远不要将任何东西放入您指定为
STATIC_ROOT
的文件夹中。 - 将特定于应用程序的静态文件放入应用程序内的文件夹
static
。 - 对于不直接属于应用程序的静态文件,在您的项目中创建文件夹
static_files
并添加到您的设置:STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_files'),]
。 当然你可以选择另一个名字,static_files
只是一个建议。 - 用于生产环境 运行
collectstatic
以便 Django 收集您的静态文件(来自第 2 点和第 3 点)并将它们放入您的文件夹中创建于 1.
如果您处于调试模式,则您已完成第 3 步。
在您的案例中,问题是您将静态内容放入 STATIC_ROOT
文件夹中,Django 不会在调试模式下查找内容。
admin
和 ckeditor
工作是因为它们遵循步骤 2.,因此它们的静态文件实际上来自已安装应用程序的文件夹,而不是处于调试模式时来自您的 static
文件夹。
所以,这是解决问题的方法:
- 执行上面的第 3 步。
- 将您的文件夹
img
和css
移动到在步骤 3 中创建的文件夹。 - (可选)擦除您的
STATIC_ROOT
文件夹。