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 給了兩種方案。

  1. 手動通過 django.views.static.serve() 為靜態文件和用戶上傳文件配置提供服務。但這種方法不安全。
  2. 結合 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_ROOTMEDIA_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 中即可正常顯示。

【完】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM