Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Django in Production

You're reading from  Django in Production

Product type Book
Published in Apr 2024
Publisher Packt
ISBN-13 9781804610480
Pages 348 pages
Edition 1st Edition
Languages
Author (1):
Arghya Saha Arghya Saha
Profile icon Arghya Saha

Table of Contents (21) Chapters

Preface 1. Part 1 – Using Django and DRF to Build Modern Web Application
2. Chapter 1: Setting Up Django with DRF 3. Chapter 2: Exploring Django ORM, Models, and Migrations 4. Chapter 3: Serializing Data with DRF 5. Chapter 4: Exploring Django Admin and Management Commands 6. Chapter 5: Mastering Django Authentication and Authorization 7. Part 2 – Using the Advanced Concepts of Django
8. Chapter 6: Caching, Logging, and Throttling 9. Chapter 7: Using Pagination, Django Signals, and Custom Middleware 10. Chapter 8: Using Celery with Django 11. Chapter 9: Writing Tests in Django 12. Chapter 10: Exploring Conventions in Django 13. Part 3 – Dockerizing and Setting Up a CI Pipeline for Django Application
14. Chapter 11: Dockerizing Django Applications 15. Chapter 12: Working with Git and CI Pipelines Using Django 16. Part 4 – Deploying and Monitoring Django Applications in Production
17. Chapter 13: Deploying Django in AWS 18. Chapter 14: Monitoring Django Application 19. Index 20. Other Books You May Enjoy

Creating a “Hello World” web app with Django and DRF

As mentioned previously, Django is a Python-based web framework, so we need to write the code using the Python programming language. If you are already using Linux or macOS-based systems, then Python comes preinstalled. However, for Windows systems, you have to install it by following the instructions on the official Python website: https://www.python.org/downloads/.

We shall also use virtualenv as our preferred tool to manage different environments for multiple projects, allowing us to create isolated Python environments.

Important note

We are not going to deep dive into virtualenv since we expect you to know how and why we use virtualenv for different projects. You can find details about virtualenv on its official website: https://virtualenv.pypa.io/en/latest/index.html.

First, let’s create a virtual environment with the latest Python version (preferably >3.12.0). The following commands will work for Linux/Unix/macOS; for Windows, please check the next section:

pip install virtualenv
virtualenv -p python3 v_env
source /path to v_env/v_env/bin/activate

Now, we will break down what the code means:

  • pip install virtualenv installs virtualenv on the system. pip is the built-in package manager that comes with Python and is already preinstalled on Mac and most Linux environments.
  • virtualenv -p python3 v_env creates a new virtual environment with the name v_env (this is just the name we have given to our virtual environment; you can give another relevant name). The -p python3 flag is used to tell us which interpreter should be used to create the virtual environment.
  • source /path to v_env/v_env/bin/activate executes the activate script, which loads the virtual Python interpreter as our default Python interpreter in the shell.

Now that the Python virtual environment has been set up, we shall focus on managing the package dependency. To install the latest release of Django, run the following command:

pip install Django==5.0.2

For Windows systems, download Python 3.12 or higher from https://www.python.org/downloads/windows/ and install it by following the wizard. Remember to click the Add python.exe to PATH checkbox in the installation step.

To verify your Python installation, use the following command in the terminal:

C:\Users\argo\> python --version
Python 3.12.0

Once Python has been installed successfully, you can use the following command to set up a virtual environment and install Django:

py -m pip install --user virtualenv
py -m venv venv
.\<path to venv created>\venv\Scripts\activate
// to install Django
pip install Django==5.0.2

The explanation for the Windows-specific commands is the same as what we explained for Linux/MacOS systems.

Important note

We are not using poetry, PDM, pipenv, or any other dependency and package management tools to avoid overcomplicating the initial setup.

Furthermore, we prefer to use a Docker environment to create more isolation and provide a better developer experience. We shall learn more about Docker in Chapter 10.

With the previous command, our local Python and Django development environments are ready. Now, it’s time to create our basic Django project.

Creating our Django hello_world project

We all love the django-admin command and all the boilerplate code it gives us when we create a new project or application. However, when working on a larger project, the default project structure is not so helpful. This is because when we work with Django in production, we have many other moving parts that need to be incorporated into the project. Project structure and other utilities that are used with a project are always opinionated; what might work for you in your current project might not work in the next project you create a year down the line.

Important note

There are plenty of resources available on the internet that will suggest different project structures. One of my favorites is django-cookiecutter. It gives you a lot of tools integrated into the project and gives you a structure that you can follow, but it can be daunting for any new beginner to start since it integrates a lot of third-party tools that you might not use, along with a few configurations that you might not understand. But instead of worrying about that, you can just follow along with this book!

We shall create our own minimalistic project structure and have other tools integrated with our project in incremental steps. First, let’s create our hello_world project with Django:

mkdir hello_world && cd hello_world
mkdir backend && cd backend
django-admin startproject config .

Here, we have created our project folder, hello_world, and then created a subfolder called backend inside of it. We are using the backend folder to keep all the Django-related code; we shall create more folders at the same level as the backend subfolder as we learn more about the CI/CD features and incorporate more tools into the project. Finally, we used the Django management command to create our project.

Important note

Note the . (dot), which we have appended to the startproject command; this tells the Django management command to create the project in the current folder rather than create a separate folder config with the project. By default, if you don’t add ., then Django will create an additional folder called config in which the following project structure will be created. For better understanding, you can test the command with and without . to get a clear idea of how it impacts the structure.

After executing these commands, we should be able to see the project structure shown here:

Figure 1.1: Expected project structure after executing the commands

Figure 1.1: Expected project structure after executing the commands

Now that our project structure is ready, let’s run python manage.py runserver to verify our Django project. We should see the following output in our shell:

Figure 1.2: The python manage.py runserver command’s output in the shell

Figure 1.2: The python manage.py runserver command’s output in the shell

Please ignore the unapplied migrations warning stating You have 18 unapplied migrations(s) displayed in red in the console; we shall discuss this in detail in the next chapter when we learn more about the database, models, and migrations.

Now, go to your browser and open http://localhost:8000 or http://127.0.0.1:8000 (if the former fails to load). We shall see the following screen as shown in Figure 1.3, which verifies

that our server is running successfully:

Please note

You can use http://localhost:8000 or http://127.0.0.1:8000 to open the Django project in your browser. If you face any error for http://localhost:8000, then please try using http://127.0.0.1:8000 for all the URLs mentioned in this book.

Figure 1.3: Our Django server running successfully with port 8000

Figure 1.3: Our Django server running successfully with port 8000

Now, let’s create our first hello_world view. To do this, follow these steps:

  1. Open the config/urls.py file.
  2. Add a new view function in hello_world.
  3. Link the hello_world view function to the hello-world path.

    Our config/urls.py file should look like the following code snippet:

    from django.contrib import admin
    from django.http import HttpResponse
    from django.urls import path
    def hello_world(request):
        return HttpResponse('hello world')
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('hello-world/', hello_world)
    ]
  4. Open http://127.0.0.1:8000/hello-world/ to get the result shown in Figure 1.4:
Figure 1.4: http://127.0.0.1:8000/hello-world/ browser response

Figure 1.4: http://127.0.0.1:8000/hello-world/ browser response

So far, we have seen how to create the project folder structure and create our first view in Django. The example we have used is one of the smallest Django project examples that doesn’t involve an app. So, let’s see how we can create apps in Django that can help us manage our project better.

Creating our first app in Django

A Django app can be considered a small package performing one individual functionality in a large project. Django provides management commands to create a new app in a project; these are built-in commands that are used to perform repetitive and complex tasks. The Django community loves management commands since they take away a lot of manual effort and encapsulate a lot of complicated tasks, such as migrations and more. We shall learn more about Django management commands in the following chapters, where we will create a custom management command. However, whenever you see a command followed by manage.py, that is a Django management command.

So, let’s create a new demo_app using the Django management command interface:

python manage.py startapp demo_app

Running this command will create the folder structure shown here:

Figure 1.5: Project structure with demo_app added

Figure 1.5: Project structure with demo_app added

We can see that a demo_app folder has been created that contains the boilerplate code generated by Django for a new app.

Important note

One important step we must do whenever we create a new app is to tell Django about the new app. Unfortunately, this doesn’t happen automatically when you create a new app using the Django management command. It is a manual process where you need to add the details of the new app in the INSTALLED_APPS list in the settings.py file. Django uses this to identify all the dependency apps added to the project and check for any database-related changes or even register for signals and receivers.

Though adding a new app to the INSTALLED_APPS list is not required for us currently, since we are not using models for Django to automatically identify any database-related changes, it is still good practice to do so. Our INSTALLED_APPS list should look like this:

INSTALLED_APPS = [
    ...
    'django.contrib.staticfiles',
    'demo_app',
]

Remember to put a comma (,) after every entry of a new app; this is one of the most common mistakes developers make and it causes Django to append two app names into one and generate a syntax error before finally correcting it.

Important note

In Django, third-party app integrations are also done via INSTALLED_APPS, so we shall see best practices around how to maintain INSTALLED_APPS in the following sections.

Now that we have created a new Django app with the boilerplate code, we can link the app view with urls.py.

Linking app views using urls.py

In this section, we shall link views.py, which was created by the Django management command. views.py is used to add business logic to the application endpoints. Just like we added the hello_world functional view in the previous section, we can add different functional or class-based views in the views.py file.

Let’s create a simple hello_world functional view in our demo_app/views.py file:

from django.http import HttpResponse
def hello_world(request, *args, **kwargs):
    return HttpResponse('hello world')

As our project grows and the number of apps increases, our main urls.py file will become more and more cluttered, with hundreds of URL patterns in a single file. So, it is favorable to break down the main config/urls.py file into smaller urls.py files for each app, which improves the maintainability of the project.

Now, we will create a new file called backend/demo_app/urls.py where we shall add all the routes related to demo_app. Subsequently, when we add more apps to the project, we shall create individual urls.py files for each app.

Important note

The urls.py filename can be anything, but we are keeping this as-is to be consistent with the Django convention.

Add the following code inside the backend/demo_app/urls.py file:

from django.urls import path
from demo_app import views
urlpatterns = [
    path('hello-world/', views.hello_world)
]

Here, we are defining the URL pattern for the hello-world path, which links to the basic functional view we created earlier.

Opinionated note

We are using absolute import to import our demo_app views. This is a convention we shall follow throughout this book and we also recommend it for other projects. The advantage of using absolute import over relative import is that it is straightforward and clear to read. With just a glance, someone can easily tell what resource has been imported. Also, PEP-8 explicitly recommends using absolute imports.

Now, let’s connect the demo_app/urls.py file to the main project config/urls.py file:

from django.contrib import admin
from django.urls import include
from django.urls import path
urlpatterns = [
    path('admin/', admin.site.urls),
    path('demo-app/', include('demo_app.urls'))
]

Next, open http://127.0.0.1:8000/demo-app/hello-world/ in your browser to make sure our demo-app view is linked with Django. You should be able to see hello world displayed on the screen, just as we saw earlier in Figure 1.4.

So far, we have worked with plain vanilla Django, but now, we’ll see how we can integrate DRF into our project.

Integrating DRF

In the API-first world of development, where developers create APIs day in, day out for every feature they build, DRF is a powerful and flexible toolkit for building APIs using Django.

Important note

If you are not familiar with the basics of DRF, we will be going through the basics in this book. However, you can find more information here: https://www.django-rest-framework.org/tutorial/quickstart/.

Now, let’s integrate DRF into our hello_world project. First, we need to install DRF in the virtual environment:

pip install djangorestframework

Now, go to settings.py and add rest_framework to INSTALLED_APPS. As you may recall, when we were integrating demo_app into the project, we mentioned that as the project grows, the INSTALLED_APPS list will also grow. To manage this better, we shall split our INSTALLED_APPS list into three sections:

  • DJANGO_APPS: This will contain a list of all the default Django apps and any new Django built-in apps we shall add to the project
  • THIRD_PARTY_APPS: Here, we shall maintain all the third-party apps we are integrating into the project, such as rest_framework
  • CUSTOM_APPS: We shall add all the apps we are creating for the project to this list – in our case, demo_app

Here is an example of how your INSTALLED_APPS list will look in the settings.py file:

DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
THIRD_PARTY_APPS = [
    'rest_framework',
]
CUSTOM_APPS = [
    'demo_app',
]
INSTALLED_APPS = DJANGO_APPS + CUSTOM_APPS + THIRD_PARTY_APPS

So far, we have been using Django HttpResponse. Now, we shall integrate the DRF response into our view. So, go to the demo_app/views.py file and add the following code:

from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def hello_world_drf(request, *args, **kwargs):
    return Response(data={'msg':'hello world'})

The integration of the DRF function-based view will change the UI completely for our endpoint. If you open http://127.0.0.1:8000/demo-app/hello-world-drf/, it will have a much more verbose UI, giving us a lot more information than before. This is particularly helpful when we start working with HTTP requests other than GET requests.

Here is our basic Django project integrated with DRF:

Figure 1.6: Using the DRF response in our hello-world-drf view

Figure 1.6: Using the DRF response in our hello-world-drf view

Now that we have a working project in Django, let’s learn some good practices that can help you go the extra mile without making mistakes yourself, rather than learning from the ones you have made earlier. DRF is the most popular Django package as it helps developers create REST endpoints. Now, let’s see what some good practices are for creating REST APIs.

You have been reading a chapter from
Django in Production
Published in: Apr 2024 Publisher: Packt ISBN-13: 9781804610480
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at ₹800/month. Cancel anytime}