I read the documentation about MEDIA_ROOT and MEDIA_URL then I could understand them a little bit but not much.
MEDIA_ROOT:
- Absolute filesystem path to the directory that will hold user-uploaded files.
MEDIA_URL:
- URL that handles the media served from MEDIA_ROOT, used for managing stored files. It must end in a slash if set to a non-empty value. You will need to configure these files to be served in both development and production environments.
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?
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:
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":
And set the code below to "urls.py":
And set the model "Image" as shown below:
And set the code below to "admin.py":
Then, upload the file "orange.jpg":
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:
Then, upload more files:
In addition, we can display the file "orange.jpg" by clicking on "orange.jpg" on "Change image" page of the file as shown below:
Then, the file "orange.jpg" is displayed as shown below:
Be careful, if you remove the code below from "urls.py":
Then, the file "orange.jpg" is not displayed. Instead, there is an error as shown below:
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:
And, add "upload_to='images/fruits'" to "models.ImageField()" as shown below:
Then, uploaded files are stored in "C:\Users\kai\django-project\media\images\fruits" in Windows in my case as shown below:
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:
And set no arguments to "models.ImageField()" as shown below:
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:
In addition, if we don't set "MEDIA_ROOT" as shown below:
Or set an empty string to the second argument of "os.path.join()" as shown below:
Or don't set the second argument of "os.path.join()" as shown below:
And set no arguments to "models.ImageField()" as shown below:
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:
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":
And, set "upload_to='images/fruits'" to "models.ImageField()" as shown below:
Then, upload the file "orange.jpg":
Then, click on "images/fruits/orange.jpg" on "Change image" page of the file as shown below:
Then, the file "orange.jpg" is displayed as shown below:
Now, we change "MEDIA_ROOT" from "os.path.join(BASE_DIR, 'media')" to "os.path.join(BASE_DIR, 'hello/world')":
Then again, click on "images/fruits/orange.jpg" on "Change image" page of the file as shown below:
Then, the file "orange.jpg" is not displayed. Instead, there is an error as shown below:
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')":
And, change "models.ImageField(upload_to='images/fruits')" to "models.ImageField(upload_to='hello/world')":
Then again, click on "images/fruits/orange.jpg" on "Change image" page of the file as shown below:
Then, the file "orange.jpg" is displayed as shown below:
<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:
For example, we set '/media/' to "MEDIA_URL":
And set no arguments to "models.ImageField()" as shown below:
Then, upload the file "orange.jpg":
Then, go to "Change image" page of the file then click on "orange.jpg":
Then, the URL of the file is displayed as shown below:
As you can see, the directory part "media" is set between the host part "localhost:8000" and the file part "orange.jpg"
And, this URL below is in this case of "www.example.com" with "https":
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:
Then, click on "orange.jpg" again:
Then, the directory part "media" is changed to "image/fruits" as shown below:
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:
And add "upload_to='images/fruits'" to "models.ImageField()" as shown below:
Then, upload the file "orange.jpg":
Then, go to "Change image" page of the file then click on "images/fruits/orange.jpg":
Then, the URL of the file is displayed as shown below:
Then, the directory part is:
Now, we change "MEDIA_URL" from '/media/' to '/hello/world/':
And, change "models.ImageField(upload_to='images/fruits')" to "models.ImageField(upload_to='hey/earth')":
Then, click on "images/fruits/orange.jpg" again:
Then, the URL of the file is displayed as shown below:
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":
In addition, if we don't set "MEDIA_URL" as shown below:
Or set an empty string to "MEDIA_URL" as shown below:
Or set one or more slashes to "MEDIA_URL" as shown below:
And set no arguments to "models.ImageField()" as shown below:
Then, no directory part is set between the host part "localhost:8000" and the file part "orange.jpg" as shown below: