Django: difference between MEDIA_ROOT and STATIC_ROOT

Django: difference between MEDIA_ROOT and STATIC_ROOT



In web development, particularly when working with Django, managing assets such as images, videos, CSS, and JavaScript files is a critical component of building a robust and efficient web application. Two key settings in Django, MEDIA_ROOT and STATIC_ROOT, that often cause confusion among developers, especially those new to the framework. Despite their seemingly similar roles in handling files, these settings serve distinct purposes and are configured differently within a Django project. Understanding the differences between MEDIA_ROOT and STATIC_ROOT is essential for organizing and deploying your web application’s static and media content effectively. In this discussion, we will delve into the definitions, uses, and distinctions of MEDIA_ROOT and STATIC_ROOT, providing clarity on how each contributes to the file management strategy of a Django project.


    • Purpose: It is the directory where all static files are collected (using the collectstatic management command: python collectstatic) for deployment.
    • Use Case: Static files are typically assets like CSS, JavaScript, and images that are part of your application’s front-end and do not change frequently.
    • Settings:
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

    • Purpose: It is the directory where user-uploaded files are stored. This includes files uploaded via forms, such as profile pictures or documents.
    • Use Case: Media files are usually content that can change, such as user uploads or files generated by the application.
    • Settings:
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Key Differences

  1. Nature of Files:

    • STATIC_ROOT: Contains static assets that are part of your codebase and are typically versioned with your application.
    • MEDIA_ROOT: Contains media files uploaded by users or dynamically generated by the application.
  2. File Management:

    • STATIC_ROOT: Files are collected here during deployment using collectstatic.
    • MEDIA_ROOT: Files are stored directly when uploaded, without needing a collection step.
  3. URL Serving:

    • STATIC_URL: URL prefix for accessing static files.
    • MEDIA_URL: URL prefix for accessing media files.
  4. Access Control:

    • STATIC_ROOT: Usually public and accessible to all users.
    • MEDIA_ROOT: Access can be restricted and managed more granularly depending on the application needs.

Using upload_to with MEDIA_ROOT

When you specify upload_to in a model field, it creates a subdirectory in the MEDIA_ROOT where the file will be stored.

Example with Model

from django.db import models class Picture(models.Model): photo = models.ImageField(upload_to='images/')
Enter fullscreen mode
Exit fullscreen mode

Settings Example

Here’s an example of how you might set up MEDIA_ROOT in your


import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Enter fullscreen mode
Exit fullscreen mode

In this setup:

  • MEDIA_ROOT points to the media directory in your project’s base directory.
  • upload_to='images/' means the file will be saved in media/images/.

How it Works with File Uploads

  1. Saving a File:
    When a user uploads a file, Django will save it in the MEDIA_ROOT directory, under the subdirectory specified by upload_to.

  2. Path Example:
    If a file named example.jpg is uploaded through a model field with upload_to='images/', the file path would be:

Enter fullscreen mode
Exit fullscreen mode

Serving Media Files

In development, Django can serve media files using the following settings in your


from django.conf import settings
from django.conf.urls.static import static urlpatterns = [ # Your URL patterns...
] if settings.DEBUG: urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Enter fullscreen mode
Exit fullscreen mode

In production, you typically configure your web server (e.g., Nginx or Apache) to serve files from MEDIA_ROOT.

Recommended Structure

It’s typically recommended to separate media files from static files:

  • Static Files:

    • Directory: static/
    • Path: STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
  • Media Files:

    • Directory: media/
    • Path: MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

This helps maintain a clean and manageable structure for your project’s file assets.

Directory Structure Example

# project tree myproject/
├── static/
│ └── staticfiles/ # Collected static files (after running `collectstatic`)
├── media/
│ └── images/ # Uploaded media files (via `MEDIA_ROOT`)
├── myproject/
│ ├──
│ ├──
│ ├──
│ └──
├── app/
│ ├──
│ ├──
│ ├──
│ ├──
│ ├──
│ └── templates/
│ └── projects.html
Enter fullscreen mode
Exit fullscreen mode

Example Model with Media Files

Assuming you have the following models:


from django.db import models class Project(models.Model): title = models.CharField(max_length=200) category = models.CharField(max_length=100) # Other fields...

class Picture(models.Model): project = models.ForeignKey(Project, related_name='pictures', on_delete=models.CASCADE) photo = models.ImageField(upload_to='images/') description = models.TextField() # Other fields...
Enter fullscreen mode
Exit fullscreen mode

Create a Class-Based-View (CBV) for the template

from django.views.generic import ListView from app.models import Project class PortfolioView(ListView): model = Project template_name = "app/projects.html" # default Django name: project_list.html
 context_object_name = "projects"
Enter fullscreen mode
Exit fullscreen mode

Using the Template to Display Media Files

Here’s how you can update your template to display the media files:

# projects.html {% for project in projects %} <div> <h4>{{ project.title }}</h4> <p>{{ project.category }}</p> {% for picture in %} <img src="{{ }}" alt="{{ project.title }}"> {% endfor %} </div>
{% endfor %}
Enter fullscreen mode
Exit fullscreen mode

In this setup:

  • You access the media file URL in the template using {{ }}, which Django handles based on the MEDIA_URL.

Final Considerations

  1. Development vs. Production:

    • During development, Django can serve static and media files directly.
    • In production, it’s recommended to use a web server (like Nginx or Apache) to serve static and media files.
  2. Security:

    • Ensure that media files are served securely, especially if they contain sensitive information.
    • You may need to set appropriate permissions and access controls based on your application’s requirements.

By following these guidelines, you can efficiently manage and serve static and media files in your Django project.

Discover more from Coursity

Subscribe to get the latest posts sent to your email.


No comments yet. Why don’t you start the discussion?

    Leave a Reply

    Your email address will not be published. Required fields are marked *