Static files là asset đi kèm code (CSS, JS, ảnh trong app/static/). Media files là file user upload lúc runtime (avatar, attachment).
python
# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles' # collectstatic gom về đây
STATICFILES_DIRS = [BASE_DIR / 'assets'] # source dev
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media' # user upload save về đây- Flow production gồm 3 bước.
- Bước build chạy
python manage.py collectstatic --noinputđể gom tất cả file static vềSTATIC_ROOT. - Bước serve để nginx lo
/static/từSTATIC_ROOTvà/media/từMEDIA_ROOT, không cho Django xử lý. - Hoặc thay nginx bằng CDN: dùng
django-storagespush static lên S3/CloudFront, setSTORAGES['default']cho media vàSTORAGES['staticfiles']cho static (Django 4.2+).
python
# Hash filename để cache-bust khi deploy
STORAGES = {
'staticfiles': {
'BACKEND': 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage',
},
}Khác biệt quan trọng cần nhớ: static có thể cache vĩnh viễn vì filename có hash, mỗi deploy đổi hash → browser tự fetch lại.
- Media thì cần kiểm soát access — đừng mở public
MEDIA_ROOTlên S3 cho mọi file, vì invoice hay avatar có thể leak ra ngoài. - Tài liệu private phải cấp signed URL có hạn.
- Và đừng để Django serve media ở prod —
serve()của Django docs nói rõ chỉ dành cho dev.