Book Image

A Blueprint for Production-Ready Web Applications

By : Dr. Philip Jones
Book Image

A Blueprint for Production-Ready Web Applications

By: Dr. Philip Jones

Overview of this book

A Blueprint for Production-Ready Web Applications will help you expand upon your coding knowledge and teach you how to create a complete web application. Unlike other guides that focus solely on a singular technology or process, this book shows you how to combine different technologies and processes as needed to meet industry standards. You’ll begin by learning how to set up your development environment, and use Quart and React to create the backend and frontend, respectively. This book then helps you get to grips with managing and validating accounts, structuring relational tables, and creating forms to manage data. As you progress through the chapters, you’ll gain a comprehensive understanding of web application development by creating a to-do app, which can be used as a base for your future projects. Finally, you’ll find out how to deploy and monitor your application, along with discovering advanced concepts such as managing database migrations and adding multifactor authentication. By the end of this web development book, you’ll be able to apply the lessons and industry best practices that you’ve learned to both your personal and work projects, allowing you to further develop your coding portfolio.
Table of Contents (13 chapters)
1
Part 1 Setting Up Our System
3
Part 2 Building a To-Do App
8
Part 3 Releasing a Production-Ready App

Installing Python for backend development

There are a variety of languages that are suitable for backend development, and any would be a fine choice for your app. In this book, I’ve chosen to use Python as I find that the code is more accessible and easier to follow than other languages.

As we will be writing the backend for our app in Python, we will need to have it installed locally. While you may have a Python version already installed, I’d recommend you use the one installed by the system package manager, as follows:

brew install python
scoop install python

The package manager we’ve used so far doesn’t know how to install and manage Python packages, so we also need another package manager. There are many choices in Python, and I think PDM is the best. PDM can be installed with the system package manager on Linux and macOS systems, as follows:

brew install pdm

For Windows systems, it can be installed by running the following commands:

scoop bucket add frostming https://github.com/frostming/scoop-frostming.git
scoop install pdm

We’ll keep the backend code separate in a backend folder, so please create a backend folder at the top level of the project with the following folder structure:

tozo
└── backend
    ├── src
    │   └── backend
    └── tests

Next, we need to inform git that there are files that we don’t want to be tracked in the repository and hence it should ignore them by adding the following to backend/.gitignore:

/__pypackages__
/.mypy_cache
.pdm.toml
.pytest_cache
.venv
*.pyc

For PDM to manage our project, we need to run the following command in the backend directory:

pdm init

When prompted, you should choose the Python version installed using the system package manager earlier.

We can now focus on the specific Python tooling for fast development.

Formatting the code

Python does not have an official format or formatter; however, black is the de facto formatter for code and isort is the de facto formatter for imports. We can add both to our project by running the following command in the backend directory:

pdm add --dev black isort

The dev flag

We use the --dev flag here as these tools are only required for developing the backend and therefore do not need to be installed when running in production.

black and isort require the following configuration to work well together. This should be added to the end of the backend/pyproject.toml file (you may have to change the target-version if you are using a version of Python other than 3.10) as follows:

[tool.black]  
target-version = ["py310"] 
[tool.isort]
profile = "black"

The following commands will run black and isort on our code in the src and tests folders:

pdm run black src tests
pdm run isort src tests

We’ll be using Jinja templates for emails sent by our app. While these templates are code, they are not Python and hence require a different formatter. Thankfully, djhtml can be used to format the templates and is added by running the following command in the backend folder:

pdm add --dev djhtml

The following command will run djhtml on our template code:

djhtml src/backend/templates --tabwidth 2 --check

We’ve now installed the tooling we need to format the code in the backend. Next, we can install the tooling we need to lint the code.

Linting the code

Python supports type hints that describe the expected types of variables, functions, and so on. We’ll use type hints and tooling to check that we haven’t introduced any type-related bugs. The most popular type checking tool for Python is mypy. It is installed by running the following command in the backend directory:

pdm add --dev mypy

The following command will run mypy over the backend code:

pdm run mypy src/backend/ tests/

With mypy helping us find type errors, we can add Flake8 to help us find other bugs. Flake8 is installed with pdm as follows:

pdm add --dev flake8

Flake8 must be configured to work with black and mypy by adding the following to backend/setup.cfg:

[flake8] 
max-line-length = 88
extend-ignore = E203

Flake8 is used by running the following command:

pdm run flake8 src/ tests/

There is another type of bug that we can use tooling to help us find, and these are related to security. A good example would be checking for a SQL injection vulnerability. Bandit is another linter that helps identify these bugs, and it is installed by running the following command in the backend directory:

pdm add --dev bandit

Bandit only needs to lint the src code as the test code does not run during production. To run Bandit over the src code, the following command is used:

pdm run bandit -r src/

Bandit ModuleNotFoundErrors

Bandit may fail to run with the error ModuleNotFoundError: No module named ‘pkg_resources’. If this happens, then run pdm add --dev setuptools to add the missing module.

We now have tooling looking for bugs, but we can also add tooling to look for unused code. This is helpful as code can often be forgotten during refactoring, leaving files that are much more complex to read and understand than they should be. I like to use vulture to find unused code, and it is installed by running the following command in the backend directory:

pdm add --dev vulture

Unfortunately, vulture can report false positives, so I like to configure it to be 100% confident when reporting issues by adding the following configuration to backend/pyproject.toml:

[tool.vulture]
min_confidence = 100

Like Bandit, it is best to run vulture over the src code only (not the tests) via the following command:

pdm run vulture src/

Now, let’s look at what we need to test the code.

Testing the code

Python has unittest as part of its standard library, however, I think using pytest is superior. pytest is very feature-rich and allows for very simple and clear tests, such as the following small example that tests that a simple addition is correct:

def test_addition():
    assert 1 + 1 == 2

pytest requires the pytest-asyncio plugin to test async code, and they are both installed with pdm as follows:

pdm add --dev pytest pytest-asyncio 

pytest is best configured to show local variables on test failure as this makes it much easier to understand why the test is failing. In addition, the asyncio mode should be set to auto to make writing async tests easier. The following configuration should be placed in backend/pyproject.toml:

[tool.pytest.ini_options]
addopts = "--showlocals"
asyncio_mode = "auto"
pythonpath = ["src"]

To run the tests, pytest is invoked with the tests path as follows:

pdm run pytest tests

Now that we’ve installed all of the tooling, we need some simple commands to run it.

Scripting the commands

We’ve added a lot of useful tooling to our project; however, each one had a different unique command that we’d have to remember. This is something we can simplify by making use of PDM’s scripting feature as it can be used to map PDM commands to the required commands. We will add the following three PDM scripting commands:

  • pdm run format to run the formatting tooling and format the code
  • pdm run lint to run the linting tooling and lint the code
  • pdm run test to run the tests

PDM’s scripting requires these script commands to be added to the backend/pyproject.toml file as follows:

[tool.pdm.scripts]
format-black = "black src/ tests/"
format-djhtml = "djhtml src/backend/templates -t 2 --in-place"
format-isort = "isort src tests"
format = {composite = ["format-black", "format-djhtml", "format-isort"]}
lint-bandit = "bandit -r src/"
lint-black = "black --check --diff src/ tests/"
lint-djhtml = "djhtml src/backend/templates -t 2 --check"
lint-flake8 = "flake8 src/ tests/"
lint-isort = "isort --check --diff src tests"
lint-mypy = "mypy src/backend tests"
lint-vulture = "vulture src"
lint = {composite = ["lint-bandit", "lint-black", "lint-djhtml", "lint-flake8", "lint-isort", "lint-mypy", "lint-vulture"]}
test = "pytest tests/"

With the backend tooling in place and accessible via easy-to-remember commands, we can now do the same for the frontend.