In this article we will see how to run search queries using The Movie Database API with Python.
After we obtained our API key from the platform, we can store it in a .env
file to use in our application.
API_KEY=chiave_api
We need to install the modules python-dotenv (to read the .env
file) and requests (to make HTTP requests to the API).
Once this is done, we define the specifications of our application, which will:
- accept a search term as user input and validate it in advance
- make a GET request to a specific endpoint of The Movie Database API and return any results obtained
- format the JSON output to have the movie title, release year, and story in readable text format.
As a first step, we define the data retrieval logic with a specific function.
import sys
import os
import requests
from dotenv import load_dotenv
load_dotenv()
def get_tmdb_api_data(endpoint=None, query=None):
if endpoint is None:
return None
api_url = f'https://api.themoviedb.org/3/{endpoint}'
params = {'api_key': os.getenv('API_KEY')}
if query is not None:
params['query'] = query
try:
response = requests.get(api_url, params=params, allow_redirects=True)
return response.json()
except requests.exceptions.RequestException:
return None
The initial call to the load_dotenv()
function is used to load into memory the environment variable API_KEY
obtained from the previously created .env
file. Then the value of that variable will be available by invoking the getenv()
method of the os
core module.
Our function will return the value None
if the mandatory API endpoint is not provided or if the HTTP request throws an exception. Otherwise, values in JSON format are returned. Since we may want to reuse our function for other requests other than search in the future, the query
parameter has been made optional.
Now we need to define the code run the remote search with the term provided by the user.
def search_tmdb_api(search_term=None):
movies = []
if search_term is None:
return None
if len(search_term) == 0:
return None
results = get_tmdb_api_data('search/movie', search_term)
if results is None:
return None
data = results.get('results')
if data is None or len(data) == 0:
return movies
for datum in data:
movie = {'title': datum.get('title'), 'plot': datum.get(
'overview'), 'date': datum.get('release_date')}
movies.append(movie)
return movies
If the search term is undefined or empty, None
is returned. Conversely, if the JSON output accessible as a dictionary does not have the results
key or if this key is an empty list, an empty list is returned indicating in this case that there are no results.
At this point we loop through the data
list and populate the output list with dictionaries having as values the title, date and plot of the current movie. Finally, we return the previously populated list.
Now we have to format the results eventually obtained in textual format.
def format_tmdb_api_results(results=None):
if isinstance(results, list) and len(results) > 0:
output = []
for result in results:
date = result.get('date')
year = ''
if date is not None:
date_parts = date.split('-')
year = date_parts[0]
entry = f'{result.get("title", "")}\n{year}\n{result.get("plot", "")}'
output.append(entry)
return '\n\n'.join(output)
return ''
We return an empty string if the function input is not a list or if such a list is empty. Otherwise, we loop through the input list populating an output list which we will finally transform into a string by extracting the release year of the film from the date
key which is in the format yyyy-mm- dd
and therefore can be easily separated into its components. In this case, a preliminary conversion into a date object to obtain the year would have unnecessarily burdened the execution of the code, especially if one bears in mind that the final output is a string.
Finally, let's define our main function:
def main():
search_term = input('Query: ')
results = search_tmdb_api(search_term)
if results is None:
print('Request error')
sys.exit(1)
if len(results) == 0:
print('No results')
sys.exit(1)
print(format_tmdb_api_results(results))
sys.exit(0)
if __name__ == '__main__':
main()
It is always good practice to communicate the result of executing our code using a standard exit code, which in this case is 1 in case of error or no results and 0 in case of success.