Building SPAs with Django and HTML Over the Wire

By Andros Fenollosa
    What do you get with a Packt Subscription?

  • Instant access to this title and 7,500+ eBooks & Videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Free Chapter
    Chapter 1: Setting up the Virtual Environment

About this book

The HTML over WebSockets approach simplifies single-page application (SPA) development and lets you bypass learning a JavaScript rendering framework such as React, Vue, or Angular, moving the logic to Python. This web application development book provides you with all the Django tools you need to simplify your developments with real-time results.

You’ll learn state-of-the-art WebSocket techniques to realize real-time applications with minimal reliance on JavaScript. This book will also show you how to create a project with Docker from the ground up, test it, and deploy it on a server. You’ll learn how to create a project, add Docker, and discover development libraries, Django channels, and bidirectional communication, and from then, on you’ll create real projects of all kinds using HTML over WebSockets as a chat app or a blog with real-time comments. In addition, you’ll modernize your development techniques by moving from using an SSR model to creating web pages using WebSockets over HTML. With Django, you’ll be able to create SPAs with professional real-time projects where the logic is in Python.

By the end of this Django book, you’ll be able to build real-time applications, as well as gaining a solid understanding of WebSockets with Django.

Publication date:
August 2022
Publisher
Packt
Pages
264
ISBN
9781803240190

 

Chapter 1: Setting up the Virtual Environment

A good programmer is not afraid of technology because their confidence doesn’t lie in the programming language, but in their own skills and experience. Tools only make them more productive. We can’t build even the simplest website in an acceptable amount of time without the right software. Building websites with Python is possible on any modern operating system, regardless of the hardware behind it. The core team that maintains this fantastic language already takes care of some of the more tedious tasks, such as compiling it and optimizing it for the processor you’re using.

However, building a web application in Python, even if we only respond with plain text, requires a great deal of knowledge, including of servers and web applications as well as the WSGI or ASGI interface. We need to abstract that complexity to respond to requests, environments, asynchrony, WebSocket, database connections, and the other elements that define a current web application. That’s why we’re going to set up a desktop with everything you need to be a productive modern Django developer. We will build different real-time applications using the technology offered by Channels, a Django extension (developed by the same Django team), which includes a WebSocket server and WebSocket integrations. The architecture of the applications will differ from how server-side rendering works. The communication path between the server and the client will be bidirectional, allowing us to use it to receive or send events and/or HTML. My intention is that upon finishing the chapter, your focus will be on the code and not on complex configurations that may distract you. To achieve this, we will make use of Docker, the famous container manager, which will open up the possibility of adding all kinds of software already precooked to launch without investing practically any time: databases, web servers, mail servers, and caches, among others. Don’t worry if you have no experience with Docker. I’ll teach you the basics without going into low-level details. After a few tweaks, you’ll practically forget that it’s running in the background.

It’s important not only that we know how to write Python and create real-time infrastructures with Django but also that we have the skills to be independent of the operating system when deploying or working in a team. By virtualizing (or isolating) the processes, we can remain unconcerned about the operating system where it runs, making the project easy to continue for any specialist, and we can anticipate future problems that may occur when deploying to a production server.

In this chapter, we’ll be covering the following topics:

  • Exploring the software required
  • Adding dependencies
  • Configuring the IDE
  • Installing Django
  • Creating our project
 

Exploring the software required

In this section, we will take a look at the software that we’ll be using throughout the book and how to install it. The code for this chapter can be found at https://github.com/PacktPublishing/Building-SPAs-with-Django-and-HTML-Over-the-Wire/tree/main/chapter-1.

Operating system

You should work on an operating system that supports Docker, such as one of the following:

  • Linux distribution, preferably Ubuntu or Debian
  • macOS in its latest version
  • Windows 10 or higher, preferably with the Linux subsystem active and Ubuntu or Debian installed
  • BSD descendants, preferably FreeBSD

Code editor

I assume that if you are reading this book, you already have experience with Python and you have an IDE or rich editor that is ready. If you need to change the IDE, I have recommended, from most to least highly recommended, in the following list some that I consider perfect for working with Python:

  • PyCharm Professional: If you are a student at a recognized school, you can claim a free student license from JetBrains. Otherwise, I encourage you to pay for the license or use their demo. There is a free version of the IDE, PyCharm Community Edition, but you will not be able to use the Docker interpreter, as this is a feature of the Professional version. You can download this editor from https://www.jetbrains.com/pycharm/.
  • Visual Studio Code (VSCode): This is a very popular editor in web development, created and maintained by Microsoft. You can download this editor from https://code.visualstudio.com/.
  • Emacs: This is very easy to use with a preconfigured framework such as Spacemacs or Doom. You can download this editor from https://www.gnu.org/software/emacs/.
  • Sublime Text with the Djaneiro package: This is the easiest option if you are not looking for complications. You can download this editor from https://www.sublimetext.com/.

Don’t force yourself to change. A code editor is a very personal thing, like choosing a brand of underwear: once you find one that fits your way of being, you don’t want to change. I understand that you may not feel like learning new shortcuts or workflows either. Otherwise, if you have no preference, you are free to visit the website of any of the preceding editors to download and install it on your computer.

All the examples, activities, and snippets in the book will work with whatever your editor or IDE of choice is. They will mainly help you with syntax errors, autocompletion, and hints, but your code will be self-contained since it is always stored in plain text. A Python programmer is a Python programmer in any editor but not all editors work well with Python.

Python

You don’t need to install it. You’re reading correctly; the editor didn’t make a mistake in the review. We’ll use Docker to install a Python container capable of launching basic commands in Django, such as creating a project or an app or launching the development server.

I assume that if you are here, it is because you feel comfortable programming with Python. If not, I would recommend you read some of Packt’s books:

  • Learn Python Programming – Third Edition, Fabrizio Romano and Heinrich Kruger, Packt Publishing (https://bit.ly/3yikXfg)
  • Expert Python Programming – Fourth Edition, Michał Jaworski and Tarek Ziadé, Packt Publishing (https://bit.ly/3pUi9kZ)

Docker

The fastest way to install Docker is through Docker Desktop.. It’s available on Windows, macOS, and Linux (in beta as I write this). Just go to the official website, download, and install:

https://www.docker.com/get-started

In the case that you want to install it directly through the terminal, you will need to search for Docker Engine (https://docs.docker.com/engine/). This is highly recommended if you use Linux or BSD.

Also install Docker Compose, which will simplify the declaration and management of images and services:

https://docs.docker.com/compose/install/

Git

There is no development that does not involve a versioning system. Git is the most popular option and is almost mandatory to learn.

If you have no knowledge or relatively basic experience with it, I recommend looking at another of Packt’s books, such as Git Essentials – Second Edition, Ferdinando Santacroce, Packt Publishing (https://bit.ly/3rYVvKL).

Alternatively, you can opt to review the more extensive documentation from the official Git website:

https://git-scm.com/

Browser

We will avoid focusing on the visual aspect of the browser, which means frontend implementation features such as CSS compatibility or JavaScript features do not matter. The most important thing is to feel comfortable when debugging the backend. Most of the time, we will be in the console checking that the requests (GET, POST, and the like) work as expected, watching the communication over WebSocket to make it smooth, and sporadically manipulating the rendered HTML.

WebSocket

WebSocket is a bidirectional communication protocol, different from HTTP, which facilitates the sending of data in real time between a server and a client, in our case, between a Django server and a frontend client.

In this book, I will use the Firefox Developer Edition (https://www.mozilla.org/en-US/firefox/developer/) browser because it is so convenient to manage the aspects mentioned using it. You are free to use any other browser, such as Chrome, Safari, or Edge, but I’m not sure whether all the features I will use are available with those browsers.

With the software installed, we can start working with the preparations around Python and Docker to run Django or future Python code.

 

Adding dependencies

We’re going to run Python via Docker and a configuration file. That way, any developer can replicate our code regardless of whether they have Python installed on their machine and they will be able to run the associated services with just one command.

First, we will create a Python file called hello.py with the following content:

print(“Wow, I have run in a Docker container!”)

The code is ready. We can continue.

The goal will be to configure Docker to run the file. Sounds easy, doesn’t it? Here we go!

We’ll create a file called Dockerfile with the following code:

# Image
FROM python:3.10
 
# Display the Python output through the terminal
ENV PYTHONUNBUFFERED: 1
# Set work directory
WORKDIR /usr/src/app
 
# Add Python dependencies
## Update pip
RUN pip install --upgrade pip
## Copy requirements
COPY requirements.txt ./requirements.txt
## Install requirements
RUN pip3 install -r requirements.txt

This file is used to create a Docker image, or template, with instructions that will be cached. Since they are precached, their launch will be almost instantaneous. Let’s check out what’s going on in the code:

  • With FROM python:3.10, we are using another existing image as a base. We are extending the work already done. But... where is it? Docker has a repository full of images, or templates, called Docker Hub (https://hub.docker.com/), a place where developers selflessly upload their work. There is an official image called python and we mark it with a tag to use version 3.10. If you have worked with Docker before, you might be wondering why we are not using the Alpine version, the famous operating system that saves so much space in servers around the world. For two reasons: Python is slower (https://pythonspeed.com/articles/alpine-docker-python/) and it doesn’t have the ability to compile dependencies. The Slim version also exacerbates the last problem and is recommended only for production versions that are short of space.
  • ENV PYTHONUNBUFFERED: 1 shows us the Python messages, for example, when we use print(). If it was not added, they would go directly to the Docker log.
  • By adding WORKDIR /usr/src/app, we define the path in which the commands will be executed inside the Docker container, not inside our operating system. This is equivalent to changing the directory with cd.
  • We will also take the opportunity to install the Python dependencies that we will be adding in the future inside requirements.txt. We update pip with RUN pip install --upgrade pip, copy the list of dependencies from the folder to the image with COPY requirements.txt ./requirements. Txt, and finally, run pip to install everything with RUN pip3 install -r requirements.txt.
  • At the root of the project, we create another file called docker-compose.yaml with the following content:
    version: '3.8'
     
    services:
     
      python:
        build:
          context: ./
          dockerfile: ./Dockerfile
        entrypoint: python3 hello.py
        volumes:
          - .:/usr/src/app/

This is the orchestrator, a file where we define each service and its configurations. In this case, we are only going to have a service called python. With build, we tell Docker to use the image that we just defined in the Dockerfile. With entrypoint, we indicate what it should do when the service is launched: python3 hello.py. Finally, in volumes, we tell it to mount the root directory, represented by a single dot, with /usr/src/app/, which is an internal directory of the image. This way, the service will have access to all the files in the folder.

  • Next, we create an empty file called requirements.txt. We will not add a single line, though the file must be present.

We’re ready to go! Open the terminal, go to the working folder, and tell docker-compose to pull up the services:

cd [your folder]
docker-compose up

Docker will gradually perform several tasks: it will download the base python image, build its own image by executing the instructions we have defined, and raise the python service. It will print 2 lines per console, as in the following:

python_1 | Wow, I have run in a Docker container!
python_1 exited with code 0

We’ve executed the Python file! Victory!

With the recent ability to run Python using Docker, it’s time to integrate it into an IDE to make it easier to run without using the terminal.

 

Configuring the IDE

PyCharm is highly popular because it’s a tool specially prepared to work with Python and it also includes interesting integrations with databases, Git, HTTP clients, environments, and the like. One of the most used is certainly the one related to Docker, so I will use this fantastic IDE in future examples. However, as I said before, it is not mandatory to use it; there are enough alternatives to please everyone. All code and activities shown in this chapter will work independently of the editor.

To set up the IDE, follow these steps:

  1. Open the folder where you want to work using PyCharm (File | Open). A directory tree will be displayed on the left.
  2. Click on the Python file (hello.py). It’s not possible to run the Python code if you don’t use the terminal; PyCharm doesn’t know where the Python interpreter, or executable, is otherwise. It’s inside a Docker image that the operating system can’t access, for now.
Figure 1.1 – Open the Python file

Figure 1.1 – Open the Python file

  1. PyCharm may open a popup that suggests creating a virtual environment. You can skip this step or close the window; we will use Docker for the job. If you don’t see the window, you can continue without fear.
  2. We then check whether we have the Docker plugin installed. Go to File | Settings | Plugins and look for Docker.
  3. If it is installed, it will appear in the Installed tab. If not, you will have to look for it in Marketplace and then click on the Install button. Then, restart PyCharm. Ensure you do this. Otherwise, we won’t be able to continue.
Figure 1.2 – Installing the Docker plugin

Figure 1.2 – Installing the Docker plugin

  1. Now open File | Settings | Build, Execution, Deployment | Docker and press the + button. Then, search for Docker.
Figure 1.3 – Connecting with Docker

Figure 1.3 – Connecting with Docker

  1. Enter Docker in the Name field, for example, and activate Unix socket. At the bottom, you will see the Connection successful message.
  2. We only need to tell PyCharm not to look for the Python interpreter, or executable, on the machine (if there is one) and to use the Docker service we have created instead.
  3. Go to File | Settings | Project: Executable Python. Here, we deploy the Python Interpreter, select Remote Python xxx Docker Compose, and click on Apply. The interpreter name may change depending on the folder name.
Figure 1.4 – Adding the Python interpreter

Figure 1.4 – Adding the Python interpreter

  1. It will automatically detect the dependencies that are already installed on the machine but we will ignore them. By the way, this is a good place to manage all Python dependencies visually.
  2. Now, it’s time to run the Python code using the configuration you just made.
  3. Close Settings and focus on the directory tree (on the left side). Right-click on hello.py and then Run ‘hello’.
Figure 1.5 – Running Python with PyCharm

Figure 1.5 – Running Python with PyCharm

  1. At the bottom of the editor, an area with the log of the execution will open. As proof that it has been done successfully, we can see the print statement.
Figure 1.6 – Viewing the Python execution log through Docker integration

Figure 1.6 – Viewing the Python execution log through Docker integration

  1. Also, if we open the docker-compose.yaml file, we can run the containers individually.
Figure 1.7 – Launching containers through Docker integration

Figure 1.7 – Launching containers through Docker integration

  1. On line 5 in Figure 1.7, you can see a green arrow; when you click on it, it will launch the service and, again, the Python code.

PyCharm is already integrated with Docker and is able to launch Python with its dependencies in isolation from the operating system. We are ready to work directly with Django. We are going to create a simple project using the official Django client to have a minimal structure when developing.

 

Installing Django

We already have a base with which to work with Python; now, it’s time to install the minimum dependencies and tools that will be practical in Django.

We will add the following content to requirements.txt, which is currently empty:

# Django
django===4.0
# Django Server
daphne===3.0.2
asgiref===3.4.1
# Manipulate images
Pillow===8.2.0
# Kit utilities
django-extensions===3.1.3
# PostgreSQL driver
psycopg2===2.9.1
# Django Channels
channels===3.0.4
# Redis Layer
channels_redis===3.2.0

You may not know some of them since they are part of the project that adds WebSocket to Django. Let’s review each one:

  • Django: This automates many important tasks, such as database connections, migrations, HTML rendering, sessions, and forms. In addition, being one of the most used and active frameworks, it gives us a high degree of security.
  • Daphne: An asynchronous server maintained by the Django team itself. We’ll need it to work with WebSocket, to emit or receive data without blocking the app.
  • asgiref: An ASGI library that needs Channels to work.
  • Pillow: The mandatory Django library for manipulating images.
  • django-extensions: A set of extensions that adds elements, such as jobs, script execution, database synchronization, and static storage in S3.
  • Psycopg2: The driver to connect to PostgreSQL, the database that we will use and is most recommended to use with Django.
  • Channels: Adds protocols and functionality for working with WebSocket to the heart of Django.
  • channels_redis: We must have a record of the connections that we have active and the groups to which they belong. Using a database that writes to the hard disk is an inefficient way to manage it. To solve this, we’ll connect with a Redis service later, as it works on volatile memory and is incredibly fast.

PyCharm may suggest you install a plugin, as shown in the following screenshot:

Figure 1.8 – PyCharm asking whether you want to install the new dependencies

Figure 1.8 – PyCharm asking whether you want to install the new dependencies

If you click on Install plugins, it will show you a window, like so:

Figure 1.9 – PyCharm asking whether you want to install the requirements plugin

Figure 1.9 – PyCharm asking whether you want to install the requirements plugin

By clicking on the OK button, we can enjoy color codes for requirements.txt.

Figure 1.10 – Color codes thanks to the plugin

Figure 1.10 – Color codes thanks to the plugin

Now, we will recompile the image so that all the dependencies we have added are installed.

With PyCharm, this can be done in a visual way. Go to Dockerfile, right-click on the double arrow shown in the following screenshot, and select Build Image for ‘Dockerfile’:

Figure 1.11 – Compiling a Dockerfile image using PyCharm

Figure 1.11 – Compiling a Dockerfile image using PyCharm

If you are using the terminal or another editor, we will use docker-compose in the directory:

docker-compose build

By recreating the image, we’ve integrated all the dependencies inside the image; now, Django has everything we need. To check that it’s installed and we have version 4, we’ll temporarily modify entrypoint:

Entrypoint: django-admin --version

And then, we’ll run the service.

Remember that you can do this by clicking on the green arrow next to Python (line 5 in Figure 1.12) or through docker-compose.

docker-compose up
Figure 1.12 – Checking which version of Django is installed

Figure 1.12 – Checking which version of Django is installed

In both cases, you can see that it returns 4.0 or the version specified in requirements.txt. We are ready!

All this work can serve as a template for future Python developments. Don’t lose it!

After creating a minimal template through the Django client, we’re going to configure it to launch the test server every time the service is up.

 

Creating our project

Django needs its own directory and file structure to work. That’s why we need to generate a project via django-admin, a terminal client built to launch Django tasks. Don’t worry! You don’t have to install anything new; it was added when we added the Django dependency.

Let’s build a file with shell instructions to perform all the tasks in one go. We create a file called start-project.sh, where we are working with the following content:

# Create the 'hello-word' project
django-admin startproject hello_world 
# Create a folder to host the future App with the name 
    'simple-app'.
mkdir -p app/simple_app
# Create the 'simple-app' App
django-admin startapp simple_app app/simple_app

Here is what we are doing:

  • With the first instruction, django-admin startproject hello_world ., we’re creating a project (startproject) called hello_world and, with the final dot, we’re telling it to make it in the directory where we’re running it.
  • When we launch mkdir -p app/simple_app, we create a directory called simple_app which is inside app. The goal is to organize the apps, saving them all in the same directory; we also create the folder in which the first app will be saved: simple_app.
  • Finally, we create the app with django-admin startapp simple_app app/simple_app. The simple_app and app/simple_app parameters define the app’s name and its location, respectively, which we created with the previous command.
  • In short, we’ll call the project hello_world, and inside it, we’ll have a single app with the original name simple_app.

PyCharm may suggest that you install a plugin to check for syntax problems; it’s a good idea to do so.

Figure 1.13 – PyCharm suggests installing a syntax checker for shell files

Figure 1.13 – PyCharm suggests installing a syntax checker for shell files

To execute the script, we again must temporarily modify entrypoint with bash start-project.sh:

version: '3.8'
 
services:
 
  python:
    build:
      context: ./
      dockerfile: ./Dockerfile
        entrypoint: bash start-project.sh
    volumes:
      - .:/usr/src/app/

We launch the container as we have already learned to: open the docker-compose.yaml file and click on the double green arrow in services or the single arrow in python.

If you are using the terminal or another editor, we will use docker-compose in the directory:

docker-compose up

When Docker finishes, the new files and directories will appear. Be patient if you don’t see them in PyCharm; sometimes it has a hard time refreshing when new files appear. You can wait or right-click on any file and click Reload from Disk.

Figure 1.14 – The newly generated Django project

Figure 1.14 – The newly generated Django project

It’s time to modify entrypoint one last time. Let’s get the development server up. It’s time to reap the fruits of our labor.

Modify it by adding the following:

python3 manage.py runserver 0.0.0.0.0:8000

If you haven’t worked with Django before, manage.py is equivalent to using django-admin. The advantage of the former is that it uses the project’s configuration, while django-admin is more general and you have to tell it where the configuration is; so, it’s more practical to use manage.py as soon as the project exists.

The action we want to launch is to raise a development server with runserver. The 0.0.0.0.0:8000 parameter indicates that we are open to any IP that makes the request and finally, we will use port 8000 to accept connections.

On the other hand, for Docker to route port 8000 from the service to the outside, we will add ports 8000:8000 somewhere inside the service.

Altogether, it will look like this:

version: '3.8'
 
services:
 
  python:
    build:
      context: ./
      dockerfile: ./Dockerfile
    entrypoint: python3 manage.py runserver 0.0.0.0:8000
    ports:
      - “8000:8000”
    volumes:
      - .:/usr/src/app/

We launch the service again. Now, open your favorite browser and enter 127.0.0.1:8000. You’ll find the Django welcome web page.

Figure 1.15 – The Django default page

Figure 1.15 – The Django default page

We’ve done it! Django is running on Docker.

As a last detail, if you are using the terminal, you will find that the container never stops. That’s because the web server, as a good server, is constantly running and waiting for requests until we tell it otherwise. Press Ctrl + C if you want to close it. In PyCharm, you should click on the red Stop square.

Figure 1.16 – Stopping Docker services via PyCharm and its integration

Figure 1.16 – Stopping Docker services via PyCharm and its integration

 

Summary

We have just acquired the skills to configure and build a Python project using Docker containers. We started with the basics, creating an image that runs a Python script and also installs all the dependencies we declared in requirements.txt. Then, we automated the creation of a Django project with a simple script and set up the development server.

On the other hand, to make container management easier, we have integrated an IDE into the flow, in our case, PyCharm. It gives us the possibility to launch some of the functionalities that we will use the most: building a custom image, executing a container composition (now we only have a service for Python), visualizing the log, and restarting and stopping containers. But let’s not forget that all these tasks are accessible from the terminal, using docker-compose.

In the next chapter, we will build a complete project in Django with various databases, a web server, and other tools that we will need to build a complete project. In addition, we will integrate Django’s configuration with Docker to facilitate its deployment with different configurations.

About the Author

  • Andros Fenollosa

    Andros Fenollosa is a custom programming expert that works as a teacher, full stack developer, and mobile developer. He's a Web Designer, Web Programmer, and Apps Programmer, among other things ( PWA, Android and iOS ). He has a plethora of commercial expertise, having worked on projects in a variety of locales throughout the world.

    Browse publications by this author
Building SPAs with Django and HTML Over the Wire
Unlock this book and the full library FREE for 7 days
Start now