Have you ever struggled to decide which TV show or movie to watch next? Making a decision about your next binge-watch is never easy because there are so many options accessible on different streaming providers.
When deciding on our next movie, we primarily rely on reviews and ratings from several rating agencies (like IMDB). However, choosing which rating to believe in might be difficult given the abundance of these institutions.
Having said that, it is frequently safer to view a movie that has received good marks from a number of these organizations. But isn’t finding such a movie difficult? Yes, it is!
In this three-blog series, we will be creating a software solution to solve this exact problem! This Django application, which we will be calling Flix-Finder, would allow its user to filter movies based on ratings from several rating agencies.
We will use BrightData’s services to grab the required data for our application.
So without further ado, let's start building Flix-Finder.
Before starting with this section, do ensure that Django is installed in your system!
The following command should work if Django is installed in your system.
python3 -m django --version
Use pip to install Django if it is not installed in your system!
python3 -m pip install Django
Let us begin by setting up our Django project. Create a new project using the following command.
rishabh@my-ubuntu:~/projects$ python3 -m django startproject flix_finder
Change the directory to the newly created project directory flix_finder
. Open your favorite code editor here. You should see the following files in this directory automatically created by Django.
rishabh@my-ubuntu:~/projects/flix_finder$ tree .
.
├── flix_finder
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
1 directory, 6 files
To know more about these files, refer to this explanation provided by Django.
Try running the Django server and accessing localhost:8000
to ensure that the setup was completed properly!
rishabh@my-ubuntu:~/projects/flix_finder$ python3 manage.py runserver
A Django app (or Django application) refers to a component of a larger Django project that encapsulates an individual feature or functionality. Django apps are reusable and independent components. They consist of models, views, templates, tests, and other files.
All of the recommender logic for our project would reside in an application called recommender
. To create this app, run the following command.
rishabh@my-ubuntu:~/projects/flix_finder$ python3 manage.py startapp recommender
The above command will create a new folder named recommender
. All of our application’s logic would go inside this folder.
There is one more step remaining before we can say that our application is created successfully. Go ahead and add the name of the newly created app in the INSTALLED_APPS
list present under flix_finder/settings.py
.
# flix_finder/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'recommender'
]
With this, we have successfully created our recommender
app.
Now, let us create our first view.
In Django, views are Python functions that receive HTTP requests and return HTTP responses. Views play an important role in presenting data to users based on some business logic.
Create a new method under recommender/views.py
. This method would serve requests coming through localhost:8000/
. For now, this endpoint simply returns a hello message.
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello From Recommender!")
We have created the view method for handling the request, but we haven’t specified (in our project) which endpoints correspond to this view. We do this in the urls.py
files.
Create a new file inside the recommender app, and name it urls.py
. Here, we specify this correspondence between the URL and the view method.
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name = "index")
]
We now need to make Django aware of this new URL’s file. Update the file flix_finder/urls.py
to the following.
from django.urls import path, include
urlpatterns = [
path('', include("recommender.urls")),
path('admin/', admin.site.urls),
]
Start your server, if not already, and open localhost:8000
on your browser. You should see the hello message.
Congratulations, you just completed creating your first view!
Let us agree… sending a string as a response is not the coolest of things. We should instead send a proper HTML response. And for this exact purpose, we will be using Django Templates.
Create a directory templates
under the recommender
director. The name of this newly created folder is special as Django by-default searches for HTML files in the directories named templates
.
Create a new file named index.html
inside the newly created directory. Inside this file, we will write the HTML that we want to render when users visit localhost:8000
.
Since writing HTML is not the main focus here, I will skip explaining that part and you can simply copy the HTML from here.
Here are some of the things that you need to know about this HTML file (or Django template) -
(1) This HTML displays four things on the webpage - Navigation bar, Carousel, Movie Search Form, and Movie Search Results.
(2) It uses the Django template language to allow the use of Python variables directly inside the HTML.
(3) It expects featured_movies
variable in the context (data passed to template) and will use it to display the carousel.
(4) It expects the form
variable to be filled with a Django Form object and will use it to display the Movie Search Form.
(5) It expects the filtered_movie_list
variable and will use it to display the results of search.
(6) It also expects no_result_error
variable that indicates if the search resulted in an empty response.
We will also need to add some CSS for styling. Create a directory static
under the recommender
directory. This folder will hold all the static files.
Create a new file named style.css
, and paste the CSS from this URL.
With this, we have all the required HTML and CSS in place. Next, we need to create the Movie Search form.
Since our template requires us to provide a form object, we will need to create one.
Not sure what are Django Forms? Read ChatGPT explain this -
Django forms are a module in the Django framework used to create and work with HTML forms. They provide several advantages over using plain HTML forms:
Create a file named forms.py
inside the recommender’s app directory. Add the following code to it.
from django import forms
class MovieSearchForm(forms.Form):
imdb_rating = forms.DecimalField(min_value=0.1, max_value=9.9, required=True, label='Minimum IMDB Rating')
release_year = forms.IntegerField(required=True)
What we just did is created a form class for our Movie Search Form. This form will contain two fields as described in the class. If you want to know more about forms, check out this.
With all the things required for templates set, now we need to update our view method to use this newly created template.
from .forms import MovieSearchForm
# We use a hard-code list here, we will make it dynamic in subsequent parts
featured_movie_list = [
{
"img_src": "https://images.thedirect.com/media/article_full/amazing-spider-man-3-andrew-garfield-movie-mcu.jpg",
"img_alt": "...",
"active": True
},
{
"img_src": "https://static1.colliderimages.com/wordpress/wp-content/uploads/2022/11/avatar-the-way-of-water-poster.jpg",
"img_alt": "...",
"active": False
}
]
def index(request):
context = {
"featured_movies": featured_movie_list,
"form": MovieSearchForm()
}
return render(request, 'index.html', context)
Start your server, and head to localhost:8000
. You should see the following page.
With all of the views, URLs, templates, and forms in place, we can now consider the data that our application will operate on. Our program would require data from multiple rating agencies (IMDB, to begin with).
Unfortunately, there is no well-defined API via which we may retrieve this data. One method for obtaining this information is to create our own scrapers using Python Selenium. However, this would require more work, and not everyone is comfortable with such technologies.
A better solution is to use third-party services like BrightData. BrightData makes it easy to obtain all of this information.
For this 1st part, we will be using a pre-curated IMDB dataset from BrightData. This is one of the many datasets that are available on BrightData. This is how we can get it.
(1) Signup for an account on BrightData.
(2) Either go to brightdata.com/cp/datasets
from the browser or open Datasets & WebScraper IDE
menu from the left.
(3) Go to Dataset Marketplace, and search for IMDB media dataset
.
(4) Click on View Dataset, and download the sample dataset in CSV format.
Once downloaded, rename the file to IMDB.csv
, and place it inside the recommender/static
folder. This sample CSV contains 28 IMDB attributes for 1000+ movies. Our application will work on this IMDB dataset for this part.
Let us update the view method to process search requests.
All the search requests from the form arrive as POST requests. After confirming that the form is properly filled, we will list out all the movies from the downloaded CSV file and filter out those that do not match the filter criteria. Here is how the updated code looks.
def index(request):
if request.method == 'POST':
form = MovieSearchForm(request.POST)
if form.is_valid():
movie_list = _getIMDBMovieDataList()
filtered_movie_list = _filter_imdb_movie_list(movie_list, form)
context = {
"featured_movies": featured_movie_list,
"form": MovieSearchForm(),
"filtered_movie_list": filtered_movie_list,
"no_result_error": len(filtered_movie_list)==0
}
return render(request, 'index.html', context)
context = {
"featured_movies": featured_movie_list,
"form": MovieSearchForm()
}
return render(request, 'index.html', context)
The implementation of the methods _getIMDBMovieDataList
and _filter_imdb_movie_list
is nothing specific to Django and is just pure Python. I thus skip talking about that here. The entire views.py
file can be found here.
Congratulations on reaching this point. If you have followed all steps properly, you should be able to run the server and perform searches through UI. Here is how the search results would look.
All code created as a part of this series will be available on this GitHub repository. The final result of this part is contained in this branch named Part1
.
It is always a good idea to cross-check your code with the one present on the repo to check if something is wrong.
With this, we come to the end of the first part of this three-part series. In the next part, we will use BrightData’s WebScraper IDE to collect data from other rating agencies. We will then update our form, thus allowing users to perform more complex searches.
We will also be making the Carousel component dynamic!
See you next time… Till then, Happy Learning! 🙂