Django 项目设置 Debug=False 后静态文件和上传文件404错误问题解决
注:该方法适用于 Django 项目、静态文件和上传文件在同一台设备中。如静态文件在专用服务器或使用CDN,请参考 https://docs.djangoproject.com/zh-hans/3.0/howto/static-files/deployment/
静态文件和用户上传文件的相关配置本文不再赘述,直入主题吧。
默认配置下,Django 会在 DEBUG=True
时通过 django.contrib.staticfiles
app 自动发现静态文件,用户上传文件则需要下面代码去实现自动配置。
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
然而当 DEBUG=False
后再次访问项目时,会发现静态文件和用户上传文件(如用户头像)均报404错误。这是因为该方法对于 DEBUG=False
不适用。
对于静态文件和用户上传文件的部署,Django 给了两种方案。
- 手动通过
django.views.static.serve()
为静态文件和用户上传文件配置提供服务。但这种方法不安全。 - 结合 Django 项目的部署 ,通过配置 Web 服务器(如:Nginx),使其在
STATIC_URL
下为STATIC_ROOT
目录下的文件提供静态文件服务,用户上传文件类似。官网推荐使用该方法。
环境
centos 7
nginx = 1.2
django = 2.2
python = 3.7
方案一:手动通过django.views.static.serve()
为静态文件和上传文件配置服务
settings.py
中配置静态文件和上传文件
# settings.py
DEBUG = False
# 静态文件
STATIC_URL = '/static/'
STATIC_ROOT=os.path.join(BASE_DIR,"/static/") # 使用 collectstatic后收集的静态文件的存放绝对路径
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # 存放静态文件的目录,其中也可以包含url
# 文件上传
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
project/project/urls.py
中为静态文件和上传文件配置URL
# urls.py
from django.urls import path, include, re_path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
...
re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}, name='static'),
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media')
]
- 收集静态文件,并将已发现静态文件复制到
settings.STATUS_ROOT
目录中
# 终端
python manage.py collectstatic
- 启动服务,会发现静态文件和上传文件均显示成功
python manage.py runserver 0:8000
此后,若静态文件发生改变后再出现404错误,再次执行
python manage.py collectstatic
即可
方案二:通过配置 Web 服务器提供静态文件服务
该方案会涉及 Nginx + uwsgi + Django 的部署(本次为单机部署),本次解决的问题是静态文件和用户上传文件404错误问题,部署的相关知识后期会陆续补充。
先看部署框架
我们的目的是当用户访问 /static
和 /media
后会正常访问静态资源和用户上传文件。Let's begin
- Nginx 服务器中新建静态文件和用户上传文件的保存目录,并修改权限(不修改会爆403错误)
mkdir -P /var/www/finance/static
mkdir -P /var/www/finance/media
chmod 777 /var/www/finance/static
chmod 777 /var/www/finance/media
- 修改
settings.py
,将STATOC_ROOT
和MEDIA_ROOOT
设置为 Nginx 服务器中保存静态文件和用户上传文件的位置
# 静态文件
STATIC_URL = '/static/'
STATIC_ROOT="/var/www/finance/static"
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
# 文件上传
MEDIA_URL = '/media/'
MEDIA_ROOT = "/var/www/finance/media/"
注意:
MEDIA_ROOT
发生改变后,用户上传文件的存放路径也会随之改变。如果开发环境中已上传用户数据,那么需要将这些数据一并复制到MEDIA_ROOT
下才能保证页面的正常显示
- 收集静态文件,将项目涉及的所有静态文件收集到
STATIC_ROOT
目录下
# 终端
python manage.py collectstatic
- 重启 uwsgi 服务器
uwsgi --stop uwsgi.pid
uwsgi --ini uwsgi.ini
- 配置 Nginx 服务器
/etc/nginx/nginx.conf
...
server {
...
location / {
# 包含uwsgi的请求参数
include /etc/nginx/uwsgi_params;
# 转交请求给uwsgi
uwsgi_pass 127.0.0.1:8000;
}
location /static {
# 指定静态文件存放的目录
alias /var/www/finance/static/;
}
location /media {
# 指定用户上传存放目录
alias /var/www/finance/media/;
}
...
}
配置
/static
和/media
的转发规则,URL 字段可以根据项目需求自行更改
- 重启 Nginx 服务,浏览器中打开项目,会发现静态文件和上传文件均显示成功
systemctl restart nginx
此后,若静态文件在项目中发生改变,再次执行
python manage.py collectstatic
将其转移至STATIC_ROOT
中即可正常显示。
【完】