pythonpython-3.xdjangomedia-url

In Django, what are MEDIA_ROOT and MEDIA_URL exactly?


I read the documentation about MEDIA_ROOT and MEDIA_URL then I could understand them a little bit but not much.

MEDIA_ROOT:

MEDIA_URL:

I frequently see them as shown below:

# "settings.py"

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

So, what are MEDIA_ROOT and MEDIA_URL exactly?


Solution

  • First of all, I explain about "MEDIA_ROOT" then "MEDIA_URL".

    <MEDIA_ROOT>

    "MEDIA_ROOT" sets the absolute path to the directory where uploaded files are stored and setting "MEDIA_ROOT" never ever influence to media file URL.

    For example, we have a django project:

    enter image description here

    Then, we set "os.path.join(BASE_DIR, 'media')" which is "C:\Users\kai\django-project\media" in Windows in my case to "MEDIA_ROOT":

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Here
    MEDIA_URL = '/media/'
    

    And set the code below to "urls.py":

    # "core/urls.py"
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

    And set the model "Image" as shown below:

    # "myapp/models.py"
    
    class Image(models.Model):
        image = models.ImageField()
    
        def __str__(self):
            return str(self.image)
    

    And set the code below to "admin.py":

    # "myapp/admin.py"
    
    from .models import Image
    
    admin.site.register(Image)
    

    Then, upload the file "orange.jpg":

    enter image description here

    Then, "media" folder is created at the same level as "db.sqlite3" and "manage.py" which is just under the django project root directory and the uploaded file "orange.jpg" is stored in "media" folder as shown below:

    enter image description here

    Then, upload more files:

    enter image description here

    In addition, we can display the file "orange.jpg" by clicking on "orange.jpg" on "Change image" page of the file as shown below:

    enter image description here

    Then, the file "orange.jpg" is displayed as shown below:

    enter image description here

    Be careful, if you remove the code below from "urls.py":

    # "core/urls.py"
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

    Then, the file "orange.jpg" is not displayed. Instead, there is an error as shown below:

    enter image description here

    Next, you can store uploaded files under more subdirectories and I explain 2 ways to do that and the first way is recommended because it is flexible and the second way is not recommended because it is not flexible at all.

    The first way to store uploaded files under more subdirectories is first, set "os.path.join(BASE_DIR, 'media')" to "MEDIA_ROOT" as shown below:

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Here
    MEDIA_URL = '/media/'
    

    And, add "upload_to='images/fruits'" to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model):    # Here
        image = models.ImageField(upload_to='images/fruits')
    
        def __str__(self):
            return str(self.image)
    

    Then, uploaded files are stored in "C:\Users\kai\django-project\media\images\fruits" in Windows in my case as shown below:

    enter image description here

    The second way to store uploaded files under more subdirectories is first, set 'media/images/fruits' to the second argument of "os.path.join()" as shown below:

    # "core/settings.py"
                                        # Here
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media/images/fruits')
    MEDIA_URL = '/media/'
    

    And set no arguments to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model): 
        image = models.ImageField() # Here
    
        def __str__(self):
            return str(self.image)
    

    Then, uploaded files are stored in "C:\Users\kai\django-project\media\images\fruits" in Windows in my case as shown below but as I said before, the first way is recommended because it is flexible while the second way is not flexible at all:

    enter image description here

    In addition, if we don't set "MEDIA_ROOT" as shown below:

    # "core/settings.py"
    
    # MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Here
    MEDIA_URL = '/media/'
    

    Or set an empty string to the second argument of "os.path.join()" as shown below:

    # "core/settings.py"
                                      
    MEDIA_ROOT = os.path.join(BASE_DIR, '') # Here
    MEDIA_URL = '/media/'
    

    Or don't set the second argument of "os.path.join()" as shown below:

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR) # Here
    MEDIA_URL = '/media/'
    

    And set no arguments to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model): 
        image = models.ImageField() # Here
    
        def __str__(self):
            return str(self.image)
    

    Then, uploaded files are stored at the same level as "db.sqlite3" and "manage.py" which is just under the django project root directory as shown below:

    enter image description here

    In addition, after uploading files if we change "MEDIA_ROOT", we cannot display uploaded files while we can still display uploaded files even if we change "models.ImageField()".

    For example, we set "os.path.join(BASE_DIR, 'media')" to "MEDIA_ROOT":

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Here
    MEDIA_URL = '/media/'
    

    And, set "upload_to='images/fruits'" to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model):    # Here
        image = models.ImageField(upload_to='images/fruits')
    
        def __str__(self):
            return str(self.image)
    

    Then, upload the file "orange.jpg":

    enter image description here

    Then, click on "images/fruits/orange.jpg" on "Change image" page of the file as shown below:

    enter image description here

    Then, the file "orange.jpg" is displayed as shown below:

    enter image description here

    Now, we change "MEDIA_ROOT" from "os.path.join(BASE_DIR, 'media')" to "os.path.join(BASE_DIR, 'hello/world')":

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'hello/world') # Here
    MEDIA_URL = '/media/'
    

    Then again, click on "images/fruits/orange.jpg" on "Change image" page of the file as shown below:

    enter image description here

    Then, the file "orange.jpg" is not displayed. Instead, there is an error as shown below:

    enter image description here

    Then, as I said before, even if we change "models.ImageField()" after uploading files, we can still display uploaded files. So now, we change back "MEDIA_ROOT" from "os.path.join(BASE_DIR, 'hello/world')" to "os.path.join(BASE_DIR, 'media')":

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Here
    MEDIA_URL = '/media/'
    

    And, change "models.ImageField(upload_to='images/fruits')" to "models.ImageField(upload_to='hello/world')":

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model):    # Here
        image = models.ImageField(upload_to='hello/world')
    
        def __str__(self):
            return str(self.image)
    

    Then again, click on "images/fruits/orange.jpg" on "Change image" page of the file as shown below:

    enter image description here

    Then, the file "orange.jpg" is displayed as shown below:

    enter image description here

    <MEDIA_URL>

    Next, I explain about "MEDIA_URL".

    "MEDIA_URL" sets the directory(middle) part of media file URL between the host part and the file part of media file URL as shown below and setting "MEDIA_URL" never ever influence to the absolute path to the directory where uploaded files are stored:

                 Host        Directory      File
                   |             |           |
            <-------------> <----------> <-------->      
    https://www.example.com/media/images/orange.jpg
    

    For example, we set '/media/' to "MEDIA_URL":

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/media/' # Here
    

    And set no arguments to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model): 
        image = models.ImageField() # Here
    
        def __str__(self):
            return str(self.image)
    

    Then, upload the file "orange.jpg":

    enter image description here

    Then, go to "Change image" page of the file then click on "orange.jpg":

    enter image description here

    Then, the URL of the file is displayed as shown below:

    enter image description here

    As you can see, the directory part "media" is set between the host part "localhost:8000" and the file part "orange.jpg"

                Host    Directly   File
                  |         |       |
           <------------> <---> <-------->      
    http://localhost:8000/media/orange.jpg
    

    And, this URL below is in this case of "www.example.com" with "https":

                 Host     Directly   File
                   |          |       |
            <-------------> <---> <-------->      
    https://www.example.com/media/orange.jpg
    

    And, we can change the directory part of URL even after uploading files.

    So, just change "MEDIA_URL" from '/media/' to '/images/fruits/' as shown below:

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/images/fruits/' # Here
    

    Then, click on "orange.jpg" again:

    enter image description here

    Then, the directory part "media" is changed to "image/fruits" as shown below:

    enter image description here

    In addition, we can set the directory part of URL with the combination of "MEDIA_URL" and "models.ImageField()". In this case, we can only change the part of the directory part set by "MEDIA_URL" after uploading files while we cannot change the part of the directory part set by "models.ImageField()" after uploading files:

    For example, we set '/media/' to "MEDIA_URL" as shown below:

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/media/' # Here
    

    And add "upload_to='images/fruits'" to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model):    # Here
        image = models.ImageField(upload_to='images/fruits')
    
        def __str__(self):
            return str(self.image)
    

    Then, upload the file "orange.jpg":

    enter image description here

    Then, go to "Change image" page of the file then click on "images/fruits/orange.jpg":

    enter image description here

    Then, the URL of the file is displayed as shown below:

    enter image description here

    Then, the directory part is:

    media/images/fruits
    

    Now, we change "MEDIA_URL" from '/media/' to '/hello/world/':

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/hello/world/' # Here
    

    And, change "models.ImageField(upload_to='images/fruits')" to "models.ImageField(upload_to='hey/earth')":

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model):              # Here
        image = models.ImageField(upload_to='hey/earth')
    
        def __str__(self):
            return str(self.image)
    

    Then, click on "images/fruits/orange.jpg" again:

    enter image description here

    Then, the URL of the file is displayed as shown below:

    enter image description here

    Then, we could change the part of the directory part 'media' to 'hello/world' set by "MEDIA_URL" after uploading the file "orange.jpg" while we couldn't change the part of the directory part 'images/fruits' to 'hey/earth' set by "models.ImageField()" after uploading the file "orange.jpg":

    hello/world/images/fruits
    

    In addition, if we don't set "MEDIA_URL" as shown below:

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    # MEDIA_URL = '/media/' # Here
    

    Or set an empty string to "MEDIA_URL" as shown below:

    # "core/settings.py"
                                      
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '' # Here
    

    Or set one or more slashes to "MEDIA_URL" as shown below:

    # "core/settings.py"
    
    MEDIA_ROOT = os.path.join(BASE_DIR)
    MEDIA_URL = '/////' # Here
    

    And set no arguments to "models.ImageField()" as shown below:

    # "myapp/models.py"
    
    from django.db import models  
    
    class Image(models.Model): 
        image = models.ImageField() # Here
    
        def __str__(self):
            return str(self.image)
    

    Then, no directory part is set between the host part "localhost:8000" and the file part "orange.jpg" as shown below:

    enter image description here

    http://localhost:8000/orange.jpg