Static

Creating Folders

Create a folder named 'static' in your root directory with 2 child folders of css and js to keep your static files separated and easy to manage. In the static/css folder you can create your CSS files, usually starting with base.css.

Create a separate 'media' folder in your root directory to store any images that you will use in your website.

Updating settings.py

To ensure that Django can find your CSS, JS, and media files, you will need to make sure that the paths are defined in settings.py correctly. This can be done under the Static files section.

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/

STATIC_URL = 'static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Now when you link your CSS files at the top of your HTML files you can use the {% static %} templating function that will utilise the STATIC_URL in your settings.py file.

To link your media files to your pages during development you will need to add the static() function to the end of your urlpatterns in the project level urls.py file. This specifically handles uploaded files during development (DEBUG = True). It tells Django's built-in development server where to look for files requested under /media/.

urlpatterns = [
    path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

External Hosting of Images and Static Files

When your website is deployed, you will not have access to the files you stored in your media folder, so you will need somewhere to host these online.

Imgur

One option is Imgur where you can create an account, upload an image privately and link the src in your project to the image URL.

Cloudinary

Another option is Cloundinary , another image hosting website. Create an account here and upload your images.

On your Cloudinary dashboard you will be able to find your:

  • Cloud Name
  • API Key
  • API Secret

In your terminal, install Cloudinary:

pip install cloudinary django-cloudinary-storage

Then update your settings.py with:

# Add required cloudinary imports
import cloudinary
import cloudinary.uploader
import cloudinary.api

# Add cloudinary to installed apps
INSTALLED_APPS  [
    "cloudinary",
    "cloudinary_storage",
]

Then add in the Cloudinary variables from your Cloudinary dashboard. I keep these at the top of the Static files section. For security you should define these in your env.py file and access them from there.

CLOUDINARY_NAME = os.getenv('CLOUDINARY_NAME')
CLOUDINARY_API_KEY = os.getenv('CLOUDINARY_API_KEY')
CLOUDINARY_SECRET_KEY = os.getenv('CLOUDINARY_SECRET_KEY')

CLOUDINARY_STORAGE = {
    "CLOUD_NAME": CLOUDINARY_NAME,
    "API_KEY": CLOUDINARY_API_KEY,
    "API_SECRET": CLOUDINARY_SECRET_KEY
}

# Create a DEFAULT_FILE_STORAGE variable
DEFAULT_FILE_STORAGE = "cloudinary_storage.storage.MediaCloudinaryStorage"

Update your MEDIA_URL to have local files in development and externally hosted images during production.

if DEBUG:
    # Local development settings
    MEDIA_URL = '/media/'
    MEDIA_ROOT = BASE_DIR / 'media'
else:
    # Production (Cloudinary)
    MEDIA_URL = f"https://res.cloudinary.com/{CLOUDINARY_NAME}/image/upload/f_auto,q_auto/"
    MEDIA_URL_VIDEOS = f"https://res.cloudinary.com/{CLOUDINARY_NAME}/video/upload/"

When accessing the image sources in your website, you can copy the URL of the image in your Cloudinary dashboard, notice most of it is the same as your MEDIA_URL variable and just tack on the rest e.g.

#index-hero {
    background-image: url("{{ MEDIA_URL }}hero-image_nntk8s.webp");
}

Whitenoise

Whitenoise is perfect for storing your static files for deployment on services such as Heroku. It converts your static files to staticfiles where Heroku will look for them by default. Start by installing whitenoise from your terminal.

pip3 install whitenoise

Then update your settings.py file:

  • Add whitenoise to your INSTALLED_APPS
  • In your static files section add a STATICFILES_STORAGE variable linking to whitenoise.
  • Update your STATIC_ROOT variable to access staticfiles
  • Add whitenoise to MIDDLEWARE
INSTALLED_APPS = [
    # File storage
    'whitenoise',
]

STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",  # Add this
    ...
]

Now when you have made changes to your static files you can go ahead and run the following in your terminal.

python manage.py collectstatic