How to Secure Media Files In Django?

We all had visited many websites where we can’t view some media or pdf files without logging in. So how do they restrict it? how do they validate the file? how do they secure the media files in Django?. So all this we will learn here, yes you are reading it correctly it is possible in Django to secure your media. We will be using the login required decorator, File Response, File Extension Validator, and get_object_or_404 objects in our project. Let’s Understand the meaning of each term stated above.

File Response

FileResponse accepts any file-like object with binary content, the file will be closed automatically, so there is no need to open it with a context manager.

Get_object_or_404

Get_object_or_404 is used to raise http404 error.

How to Secure Media Files In Django?

FileExtensionValidator

FileExtensionValidator raises an error if the file extension is not the same as provided.

Login Required Decorator

login_required() decorator does the following things:-

  1. Execute normally the view if the user is logged in.
  2. Redirect the user to the login_url path if the user is not logged in.

Django REST Framework is a robust and flexible toolkit for building Web APIs. Django provides the user to work at their ease. So let’s get started with this beautiful framework and understand the step-by-step procedure about how to secure media files in Django.

Step 1. Create Django Project

We are first going to create a Django project, an app inside that project by following the below steps:-

  1. Create a Django project by running the given command in the cmd or terminal.
django admin startproject bloglogindecorator
  1. Create app in that django-project.
python manage.py startapp logindecorator
  1. Add your app name in installed apps.

Settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'logindecorator'
]

Step 2. Add files and Folder to the Django Project

We need to create a template folder in the Django folder and a urls.py file in the app folder. In addition to this, we also need to create a media room so that we can provide a path to the uploaded media files in our project

  1. Create a new folder in the Django folder(here, bloglogindecorator) save it with the name template.
  2. Add the path for this template folder in bloglogindecorator> settings.py.

Settings.py

import os
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'template')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

3. Create a new file in the app folder(here, login decorator) save it with the name urls.py.

4. Add the path for this url.py file in bloglogindecorator > urls.py.

Urls.py

from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('logindecorator.urls'))
]

5. Provide a new folder where you are going to store all media files uploaded by the user or uploaded to the database, by adding the following command in the respective files.

Settings.py

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

Urls.py

from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('logindecorator.urls'))
] 
urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Step 3.  Secure media

We are first going to add our database to our project. In settings.py add the below code according to your database in DATABASES.

  1. Add database

Settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'bloglogindecorator',
        'USER': 'postgres',
        'PASSWORD':"2320",
        'HOST': 'localhost'
    }
}

2. Create a model in-app folder > models.py with the fields of your choice, here I had used FileExtensionValidator which helps me to collect only those files which have .pdf extension.

Models.py

from django.db import models
from django.core.validators import FileExtensionValidator
# Create your models here.
class mediafiles(models.Model):
    title=models.CharField(max_length=50)
    pdf=models.FileField(upload_to='path/',validators=[FileExtensionValidator(['pdf'])])

3. Migrate the Model by, running the below code to migrate your model into your database.

python manage.py makemigrations
python manage.py migrate

4. Add function in app folder >views.py 

Get_object_or_404 is used to raise http404 error.

FileResponse accepts any file-like object with binary content, the file will be closed automatically, so there is no need to open it with a context manager.

Here the function blogsecuremodel is just to render the HTML page and provide model content on the HTML page.

The function secure will first check whether the person is authorized or not with the help of a login decorator and if the person is authorized it will just open the pdf file otherwise it will give an http404 error to the user.

Views.py

#from django.http.response import FileResponse
from django.shortcuts import get_object_or_404, render
from .models import mediafiles
from django.http import FileResponse
from django.contrib.auth.decorators import login_required
import os 
def blogsecuremodel(request):
    object=mediafiles.objects.all()
    return render(request,'blogsecuremedia.html',{'object':object})
@login_required
def secure(request,file):
    document=get_object_or_404(mediafiles,path="path/"+file)
    path,file_name=os.path.split(file)
    response=FileResponse(document.pdf)
    return response

5. Create Url path for the function in logindecorator(your_app_name)>urls.py.

Urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('blogsecuremodel',views.blogsecuremodel,name="blogsecuremodel"),
    path('media/path/<str:file>',views.secure,name="secure")
]

6. Create an HTML file here, there is an anchor (<a>) tag that passes the URL of the pdf file, so that when a user clicks this link he will be redirected to the secure function in views.py.

Blogsecuremodel.html

<html>
<head>
    <title>BlogSecureMedia</title>
</head>
<body>
    <h1>Blog Secure Model</h1>
    {% for i in object %}
    <h1>Title:</h1>
    <p>{{object.title}}</p><br>
    <h1>pdf file:</h1><button><a href="{{i.pdf.url}}">Click to view</a></button><br>
    {% endfor %}
</body>
</html>

Output :-

How to Secure Media Files In Django?
Html PAGE
How to Secure Media Files In Django?
If Unauthorized user try to access the page this page will be shown

Quick Revision:-

  1. Create your Django project folder.
  2. Create an app folder in the Django project folder.
  3. Add template folder in the Django folder and provide its path in django_folder > settings.py .
  4. Add a file named urls.py in the app folder and provide its path in django_project > urls.py.
  5. Provide a media folder path
  6.  Add the function in app_folder > views.py.
  7. Provide the URL path in app> urls.py to the functions created in views.py.
  8. Add restriction to pages in html code in django_project > template > blogsecuremodel.html.

Conclusion:-

Hope you find this blog useful and able to understand each and every step. I hope I am able to clear all your doubts. Best of luck and Thank You.