I start learning Django, DRF about a few months ago. After finishing a simple eCommerce project I wanna deploy it on Heroku because it is free. But on Heroku, I got several problems as a beginner as usual. Serving static files, Images on Heroku when DEBUG=FALSE on setting.py file.
It takes about 1 week to solve how to do it properly without using any additional static or media files dedicated server (like AWS s3, Nginx, apache server). I read several StackOverflow articles, websites, Youtube videos, Django official website that how to serve static files but I did not get any proper solution.
Some link is here:
https://docs.djangoproject.com/en/3.2/howto/static-files/
https://docs.djangoproject.com/en/3.2/howto/static-files/deployment/
https://docs.djangoproject.com/en/3.2/ref/contrib/staticfiles/
above all links did not fix my issue
In Stackoverflow everybody says Django doesn't serve static files on production anymore when DEBUG=False. So you have to use this and that in this or that way. I try a lot but finally failed whether in the local development server or Heroku production server.
After that, A senior Django developer help to fix this. So I think it will help those who are in the same situation just stop using this way of serving images or static files:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# if settings.DEBUG:
# urlpatterns += static(settings.MEDIA_URL,
# document_root=settings.MEDIA_ROOT)
Use This way
urls.py
from django.conf import settings
from django.contrib import admin
from django.urls import re_path
from django.views.static import serve
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
]
settings.py (only important lines)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DEBUG = False
MIDDLEWARE = [
#...
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # whitenoise
#...
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'frontend/build')
],
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
os.path.join(BASE_DIR, 'frontend/build/static'),
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # media files upload directory
MEDIA_URL = '/media/' # media files retrive directory
Some Django Heroku Deploying Rules
https://devcenter.heroku.com/articles/django-app-configuration
https://devcenter.heroku.com/articles/django-assets
Note: Heroku Image and static serving problem, Django version: 3.2 Python: 3.9.4