Django Python Advanced

Tags: Docker

Create an advanced REST API with Python, Django REST Framework and Docker using Test Driven Development (TDD)

Last updated 2022-01-10 | 4.6

- Setting up a local development server with Docker
- Writing a Python project using Test Driven Development
- Building a REST API with advanced features such as uploading and viewing images

What you'll learn

Setting up a local development server with Docker
Writing a Python project using Test Driven Development
Building a REST API with advanced features such as uploading and viewing images
Creating a backend that can be used a base for your future projects or MVP
Hands on experience applying best practice principles such as PEP-8 and unit tests
Configure Travis-CI to automate code checks

* Requirements

* Basic knowledge of programming and building simple applications
* Familiar with Django
* Comfortable using command line tools (Terminal/Command Prompt)
* macOS
* Linux or Windows machine capable of running Docker (This excludes Windows 10 Home)
* Positive attitude and willingness to learn!

Description

Welcome to the advanced course on how to Build a Backend REST API using Python, Django (2.0), Django REST Framework (3.9), Docker, Travis CI, Postgres and Test Driven Development!

Whether you’re a freelance programmer, tech entrepreneur, or just starting out building backends - this course will help lay the foundation of your knowledge base and give you the tools to advance your skills with some of the most in-demand programming languages today.

APIs are the unsung heroes behind the technologies that we all love and use religiously.

One of the most critical components for any tech-based business is an API. So knowing how to create an API from start to finish is a vital skill to have as a developer. You cannot build a successful app without a backend REST API!

In this course I’ll show you how to build an advanced API that handles creating and updating user profiles, changing passwords, creating objects, uploading images, filtering and searching objects, and more.

The best way to learn anything is to do it. So the practical application of the course -- the project that you’ll build along side me -- is an API. A recipe API, to be specific.

You will learn how to build an advanced recipe API that allows you to upload and store some of your favourite recipes from photos and the web.

You’ll learn how to create objects i.e. recipes with titles, price points, cooking times, ingredients and tags like “comfort food”, “vegan” or “dessert”. Think of it as a virtual recipe box.

By the end of this course you will have built a fully functioning REST API that can handle:

  • User authentication

  • Creating objects

  • Filtering and sorting objects

  • Uploading and viewing images

You’ll also learn, in detail how to:

  • Setup a project with Docker and Docker-Compose

  • Configure Travis-CI to automatically run linting and unit tests

  • Write unit tests using the Django Test Framework

  • Apply best practice principles including Test Driven Development  

  • Handle uploading media files with Django

  • Customize the Django admin

  • Configure a Postgres database

This course has one singular focus: To teach you how to create an advanced API from start to finish using best practice principles and Test Driven Development.

This course is NOT FOR YOU:

  • If you’re looking for a course to build an API, a front end, and deployment

  • If you’re looking to build 10 different apps in one course

  • If you want to learn lots of different technologies and approaches to app development in general

This is a hands-on course, with a bit of theory and lots of opportunities to test your knowledge.

The content is challenging but rewarding. Ready for it? Let’s dive in!

**PLEASE NOTE: You cannot run Docker on Windows 10 Home edition. This is because Windows 10 Pro or Enterprise is required in order to use Hyper-V which Docker uses for virtualization. To take this course you have two options. These are covered in Lecture 6, which is free to preview before purchasing the course.

Who this course is for:

  • Intermediate programmers who already have some understanding of Python and want to skill up
  • Developers proficient in other languages but looking to add Python to their toolkit

Course content

17 sections • 83 lectures

Welcome to Build a Backend API with Django REST Framework - Advanced Preview 02:20

Intro to the course Preview 02:24

Course structure Preview 01:03

How to get the most out of this course Preview 00:54

How to get help Preview 01:25

Windows 10 Home Workaround Preview 00:36

You cannot run Docker on Windows 10 Home edition. This is because Windows 10 Pro or Enterprise is required in order to use Hyper-V which Docker uses for virtualization. If you happen to have Windows 10 Home, you have two options.

Setup new GitHub project Preview 02:50

Setup a new project using GitHub and clone to our local machine.

Add Dockerfile Preview 09:56

Create a new Dockerfile that we can use to build the image for our project.

Configure Docker Compose Preview 05:22

Configure docker compose to run our project.

Custom configuration for Linux users Preview 01:21

Create Django project Preview 02:56

Create a new Django project using our docker compose file.

Enable Travis-CI for project Preview 01:41

Login to Travis-CI and enable our project for automation.

Create Travis-CI configuration file Preview 07:15

Create a configuration file that tells Travis-CI how to run our unit tests and linting.

UPDATE: Travis-CI Docker Pull Issue Preview 01:17

Travis-CI

Test your Travis-CI knowledge

Writing a simple unit test Preview 05:47

Write a very simple unit test to demonstrate the process of unit testing code using Django.

Writing a unit test with TDD Preview 05:08

Write another very simple unit test, but this time we will follow the Test Driven Development (TDD) method.

Django Unit Tests

Test your knowledge on Django Unit Tests

Create core app Preview 02:52

Use the Django management script to create a new app within our project. The app will be called 'core' and it will be used to hold all code that is central to our project (such as database models and the admin page).

Add tests for custom user model Preview 05:41

Here we will create a custom user model for our project. The custom user model will replace Django's built in user model. The purpose of customising the model is to support handling registration and authentication using an email instead of username.

Implement custom user model Preview 10:23

Implement the user model to make the tests pass.

Normalize email addresses Preview 03:25

Next we will implement a change to our custom user manager that ensures emails are normalized. Normalizing the email means ensuring the domain part is all lowercase.

Add validation for email field Preview 02:36

Here we will add an extra validation step to our create_user function, so it will raise a validation error if a blank or null email field is passed in. We do this so a correct error message is displayed when using this function.

Add support for creating superusers Preview 05:20

Now we will add support for creating superusers using the create_superuser function on our custom user manager. The create_superuser function is used by the Django createsuperuser management command, so it's required for creating admin using the CLI, which we will be doing later in the course.

Django custom user model

Test your knowledge on the Django custom user model

Add tests for listing users in Django admin Preview 09:30

Now we need to configure our Django admin to work with our custom user model. To do this, we need to make some modifications to the fields that Django displays in the default Django admin. In this video we setup the tests to test that our Django admin is working correctly.

Modify Django admin to list our custom user model Preview 02:27

Now we will modify the Django admin to support listing users from our custom user model. This should make the tests from the previous video pass successfully.

Modify Django admin to support changing user model Preview 07:48

Here we modify the Django admin to support changing the custom user model. We start by adding a test to ensure the 'user change page' loads successfully, then we implement the feature by modifying the fieldsets of the default Django UserAdmin class.

Modify Django admin to support creating users Preview 04:56

Finally we can modify our Django admin to support creating new users. We start by testing the create user page, and end by making the necessary modifications to the add_fieldsets variable in our UserAdmin class.

Add postgres to docker compose Preview 05:25

Here we will prepare our docker-compose.yml for running PostgreSQL Database 10 as our application database. In this video we start the setup by setting some environment variables for authentication with the database, and also adding our db service.

Add postgres support to Dockerfile Preview 05:43

Before our docker container will support connecting to PostgreSQL, we need to make a few minor modifications. First we will add the psycopg2 package to our requirements.txt file, then we will update our Dockerfile to support installing and using the client for our application.

Configure database in Django Preview 02:52

Now we can configure our database within the Django settings.py file. We will do this by updating the DATABASES settings and pulling in some environment variables.

Mocking with unittests Preview 01:30

Add tests for wait_for_db command Preview 11:43

A common issue when using PostgreSQL with Django is that the application starts before the database. This causes it to fail with an OperationalError saying that the database is unavailable. To get around this, we will create a management command which we can use to delay starting our app until the database is up. We start by adding unit tests for our command. The unit tests will ensure the command works as expected when the database is and is not available.

Add wait_for_db command Preview 07:30

Now we have our tests failing, we can go ahead and make them pass by creating our wait_for_db command.

Make docker compose wait for db Preview 02:51

Finally we can update our docker-compose.yml file to run our wait_for_db management command before starting our app. While we are doing that, we will also add migrate to run our migrations when we start our docker container.

UPDATE: Make Travis-CI wait for db Preview 00:44

Test in browser Preview 03:01

Finally we can update our docker-compose.yml file to run our wait_for_db management command before starting our app. While we are doing that, we will also add migrate to run our migrations when we start our docker container.

Mocking

Test your knowledge on mocking

Create users app Preview 03:29

Next we are going to add our user management endpoints to our app. This will allow us to manage the users by performing tasks such as creating users, updating users, generating authentication tokens and changing the users password. We will start by creating a new app called 'user' which will contain all of our user code.

Add tests for create user API Preview 16:43

Now we have our app, we can go ahead and create our user API. We start by adding some tests that validate creating a user, attempting to create a user with a duplicate email and creating a user with a password less than five characters.

Add create user API Preview 13:52

Now we will make our tests pass by implementing our user API. For this, we need to create a Serializer to handle converting our user object from Python to JSON (and vice versa). Then we will create a View that handles creating users, and finally we will wire it up to a URL to make it accessible.

UPDATE: Fix for testing password too short Preview 00:36

Add tests for creating a new token Preview 10:39

Next we can move on to adding a create token API which will be used for authenticating users in future APIs. We start by adding some tests for creating a token, trying to create a token with invalid credentials, creating a token for users that don't exist and creating a token with a missing field.

Add create token API Preview 13:53

Next we update our code to make our tests pass by implementing the AuthTokenSerializer and ObtainAuthToken view. We then add the URL for our endpoint and ensure it works by running our tests. At the end of the video, we will test our code in the browser to ensure it works.

Add tests for manage user endpoint Preview 11:50

The last endpoint we need to add for our user management API is the manage user endpoint. This will allow users to manage their account by changing their password and updating various fields.

Add manage user endpoint Preview 11:23

Next we will add the manage user endpoint. This endpoint will allow the user to update their profile or change their password. We will start by creating a view to handle the request, and re-use the UserSerializer we created previously. Finally, we will connect our view to a URL, run our tests and test in the browser.

Create recipe app Preview 02:15

In this section we will create our recipe app. The recipe app will be responsible for handling anything related to recipes within our system. This includes recipes, tags and ingredients. We start in this video by using the Django management startapp command to create our app.

Add tag model Preview 08:09

We will start by adding a simple tag model to our project. First we will create a test for our model, simply to confirm that it translates a tag to a string representation. Then we will create our model and model migration, as well as enable it in the Django admin. Finally we will run our tests to ensure our model has been created successfully.

Add tests for listing tags Preview 12:08

Now we have our model, we can move onto creating our list tags API. We'll start by adding some unit tests and setting up our test structure for our tags. The tests we will write will: ensure that authentication is enabled, check we can retrieve a list of tags, and check that the tags listed are owned by the authenticated user.

Add feature to list tags Preview 12:12

Next we will add our list tags feature. This will consist of a ModelSerializer called TagSerializer and a GenericViewSet with the ListModelMixin.

Add create tags feature Preview 07:07

Next we will add our create tags feature. We will start by adding a test to ensure that a tag is created successfully when making an HTTP POST request to the tags URL, and confirming that the test fails. Then we will modify our TagViewSet to support creating new models by adding the CreateModelMixin. We will also override the perform_create() function to ensure that tags are assigned to the correct user.

Add ingredient model Preview 04:08

Add tests for listing ingredients Preview 10:29

Implement feature for listing ingredients Preview 05:04

Now we have our tests we can go ahead and implement our list ingredients feature. For this we need to add a new serializer, view and URL to make our API available.

Implement feature for creating ingredients Preview 07:38

Now we have our tests we can go ahead and implement our list ingredients feature. For this we need to add a new serializer, view and URL to make our API available.

Re-factor tags and ingredients viewsets Preview 07:04

The great thing about Test Driven Development is that we can re-factor our code with confidence that it won't have an adverse affect on other parts of the project. Since a lot of our ingredients and tags API are similar, we are going re-factor this to improve our source code. We'll do this by creating a new class which contains the common functionality for both tags and ingredients.

Add recipe model Preview 12:50

Now we are going to move onto the main part of our API, the recipe endpoints. We'll start by creating a new model to store our recipes in the database.

Add tests for listing recipes Preview 15:16

Next we will create our API for listing recipes. For our tests, we are going to start by creating some helper functions for creating recipes, tags and ingredients. This will make our testing smoother by reducing the duplicate code.

Implement feature for listing recipes Preview 08:38

Now that we have our tests we can implement our feature to make them pass. We will start by adding a new serializer to handle recipe objects. Then we'll create a view which we will connect up to our URLs.

Add tests for retrieving recipe detail Preview 09:11

Now we can list recipes we can add support for retrieving the details of a recipe. When designing APIs it's often a good idea to limit the data displayed in the list view, but make it accessible using a detail view. This helps to keep the API fast and gives the consumer of the endpoint flexibility to retrieve the data they require at the time. When listing recipes we are only going to show the IDs of the tags and ingredients that are assigned, and in the detail view we will display the rest of the details such as ingredient and tag name.

Implement feature for retrieving recipe detail Preview 07:06

Next we can implement our recipe detail endpoint and make our tests pass. We'll do this by creating a serializer for our recipe detail view, and override our get_serializer_class() function to return the detail serializer when retrieving specific items.

Add tests for creating recipes Preview 11:26

Next we will add the ability to create recipes.

Implement feature for creating recipes Preview 04:22

Now we have our tests created we can implement the feature and make them pass. Because of the greatness of Django REST Framework, this is surprisingly easy to do. The only thing we need to do is override the perform_create() function in our ModelViewSet.

Add tests for updating recipes Preview 09:42

Next we are going to add a few more tests for updating recipe model objects.

Add Pillow requirement Preview 12:15

In this section, we are going to add the ability to upload images for our recipes. For this, we need to add a new requirement to our project so we can use Django's ImageField to save our file. We'll also change our Django configuration file to support storing our staticfiles in our docker container.

Modify recipe model Preview 11:53

Next we can add our new field to our recipe model. We'll start by adding a test to ensure that the image is saved with the correct filename. We are going to generate a uuid for each image to ensure the filename is unique.

Add tests for uploading image to recipe Preview 13:29

Next we are going to add tests for uploading images to our recipe model.

Add feature to upload image Preview 11:17

Next we will implement the feature to upload images, to make our tests pass. We'll do this by adding a new action to our Recipe viewset. We'll also create a custom serializer, and modify our get_serializer_class() function to return the correct serializer when using our upload image action.

Add tests for filtering recipes Preview 08:57

Next we will modify our API to support filtering recipes using ingredients and tags. We start by adding some unit tests for ensuring the filters are applied correctly.

Implement feature to filter recipes Preview 09:19

As per our unit tests, filtering will be done using query parameters passed into the get requests. We'll implement this in this video and ensure the tests pass.

Add tests for filtering tags and ingredients Preview 12:59

In this video we will add an option to our tags and ingredients API that allows the user to filter by items assigned to recipes. This allows users to exclude any ingredients that are not being used, which may help the API user when listing tag/ingredient options to filter by.

Implement feature for filtering tags and ingredients Preview 06:31

Now we will implement our feature for filtering tags and ingredients, by checking for the assigned_only query parameter.

What was covered in this course Preview 00:52