Movatterモバイル変換


[0]ホーム

URL:


Packt
Search iconClose icon
Search icon CANCEL
Subscription
0
Cart icon
Your Cart(0 item)
Close icon
You have no products in your basket yet
Save more on your purchases!discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Profile icon
Account
Close icon

Change country

Modal Close icon
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timerSALE ENDS IN
0Days
:
00Hours
:
00Minutes
:
00Seconds
Home> Web Development> Web Programming> Django 4 By Example
Django 4 By Example
Django 4 By Example

Django 4 By Example: Build powerful and reliable Python web applications from scratch , Fourth Edition

Arrow left icon
Profile Icon Antonio Melé
Arrow right icon
€26.98€29.99
Full star iconFull star iconFull star iconFull star iconHalf star icon4.6(45 Ratings)
eBookAug 2022766 pages4th Edition
eBook
€26.98 €29.99
Paperback
€37.99
Subscription
Free Trial
Renews at €18.99p/m
eBook
€26.98 €29.99
Paperback
€37.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Table of content iconView table of contentsPreview book icon Preview Book

Django 4 By Example

Building a Blog Application

In this book, you will learn how to build professional Django projects. This chapter will teach you how to build a Django application using the main components of the framework. If you haven’t installed Django yet, you will discover how to do so in the first part of this chapter.

Before starting our first Django project, let’s take a moment to see what you will learn. This chapter will give you a general overview of the framework. The chapter will guide you through the different major components to create a fully functional web application: models, templates, views, and URLs. After reading it, you will have a good understanding of how Django works and how the different framework components interact.

In this chapter, you will learn the difference between Django projects and applications, and you will learn the most important Django settings. You will build a simple blog application that allows users to navigate through all published posts and read single posts. You will also create a simple administration interface to manage and publish posts. In the next two chapters, you will extend the blog application with more advanced functionalities.

This chapter should serve as a guide to build a complete Django application and shall provide an insight into how the framework works. Don’t be concerned if you don’t understand all the aspects of the framework. The different framework components will be explored in detail throughout this book.

This chapter will cover the following topics:

  • Installing Python
  • Creating a Python virtual environment
  • Installing Django
  • Creating and configuring a Django project
  • Building a Django application
  • Designing data models
  • Creating and applying model migrations
  • Creating an administration site for your models
  • Working withQuerySets and model managers
  • Building views, templates, and URLs
  • Understanding the Django request/response cycle

Installing Python

Django 4.1 supportsPython 3.8, 3.9, and 3.10. In the examples in this book, we will use Python 3.10.6.

If you’re using Linux or macOS, you probably have Python installed. If you’re using Windows, you candownload a Python installer fromhttps://www.python.org/downloads/windows/.

Open the command-line shell prompt of your machine. If you are using macOS, open the/Applications/Utilities directory in theFinder, then double-clickTerminal. If you are using Windows, open theStartmenu and typecmd into the search box. Then click on theCommand Prompt application to open it.

Verify that Python is installed on your machine by typing the following command in the shell prompt:

python

If you see something like the following, then Python is installed on your computer:

Python 3.10.6 (v3.10.6:9c7b4bd164, Aug  1 2022, 17:13:48) [Clang 13.0.0 (clang-1300.0.29.30)] on darwinType "help", "copyright", "credits" or "license" for more information.

If your installed Python version is lower than 3.10, or if Python is not installed on your computer, download Python 3.10.6 fromhttps://www.python.org/downloads/ and follow the instructions to install it. On the download site, you can find Python installers for Windows, macOS, and Linux.

Throughout this book, when Python is referenced in the shell prompt, we will be usingpython, though some systems may require usingpython3. If you are using Linux or macOS and your system’s Python is Python 2 you will need to usepython3 to use the Python 3 version you installed.

In Windows,python is the Python executable of your default Python installation, whereaspy is the Python launcher. The Python launcher for Windows was introduced in Python 3.3. It detectswhat Python versions are installed on your machine and it automatically delegates to the latest version. If you use Windows, it’s recommended that you replacepython with thepy command. You can read more about theWindows Python launcher athttps://docs.python.org/3/using/windows.html#launcher.

Creating a Python virtual environment

When you write Python applications, you will usually use packages and modules that are not included in thestandard Python library. You may have Python applications that require a different version of the same module. However, only a specific version of a module can be installed system-wide. If you upgrade a module version for an application, you might end up breaking other applications that require an older version of that module.

To address this issue, you can use Python virtual environments. With virtual environments, you can install Python modules in an isolated location rather than installing them globally. Each virtual environment has its own Python binary and can have its own independent set of installed Python packages in its site directories.

Since version 3.3, Python comes with thevenv library, which provides support for creating lightweight virtual environments. By using the Pythonvenv module to create isolated Python environments, you can use different package versions for different projects. Another advantage of usingvenv is that you won’t need any administration privileges to install Python packages.

If you are using Linux or macOS, create an isolated environment with the following command:

python -m venv my_env

Remember to usepython3 instead ofpython if your system comes with Python 2 and you installed Python 3.

If you are using Windows, use the following command instead:

py -m venv my_env

This will use the Python launcher in Windows.

The previous command will create a Python environment in a new directory namedmy_env/. Any Python libraries you install while your virtual environment is active will go into themy_env/lib/python3.10/site-packages directory.

If you areusing Linux or macOS, run the following command to activate your virtual environment:

source my_env/bin/activate

If you are using Windows, use the following command instead:

.\my_env\Scripts\activate

The shell prompt will include the name of the active virtual environment enclosed in parentheses like this:

(my_env) zenx@pc:~ zenx$

You can deactivate your environment at any time with thedeactivate command. You can findmore information aboutvenv athttps://docs.python.org/3/library/venv.html.

Installing Django

If you havealready installed Django 4.1, you can skip this section and jump directly to theCreating your first project section.

Django comes as a Python module and thus can be installed in any Python environment. If you haven’t installed Django yet, the following is a quick guide to installing it on your machine.

Installing Django with pip

Thepip packagemanagement system is the preferred method of installing Django. Python 3.10 comes withpip preinstalled, but you can findpip installationinstructions athttps://pip.pypa.io/en/stable/installing/.

Run the following command at the shell prompt to install Django withpip:

pip install Django~=4.1.0

This will install Django’s latest 4.1 version in the Pythonsite-packages/ directory of your virtual environment.

Now we will check whether Django has been successfully installed. Run the following command in a shell prompt:

python -m django --version

If you get the output4.1.X, Django has been successfully installed on your machine. If you get the messageNo module named Django, Django is not installed on your machine. If you have issuesinstalling Django, you can review the different installation options described inhttps://docs.djangoproject.com/en/4.1/intro/install/.

Django can be installed in different ways. You can find the different installation options athttps://docs.djangoproject.com/en/4.1/topics/install/.

All Python packages used in this chapter are included in therequirements.txt file in the source code for the chapter. You can follow the instructions to install each Python package in the following sections, or you can install all requirements at once with the commandpip install -r requirements.txt.

New features in Django 4

Django 4 introduces a collection of new features, including some backward-incompatible changes, while deprecating other features and eliminating old functionalities. Beinga time-based release, there is no drastic change in Django 4, and it is easy to migrate Django 3 applications to the 4.1 release. While Django 3 included for the first timeAsynchronous Server Gateway Interface (ASGI) support, Django 4.0 adds several features such as functional unique constraints for Djangomodels, built-in support for caching data with Redis, a new default timezone implementation using the standard Python packagezoneinfo, a newscrypt password hasher, template-based rendering for forms, as well as other new minor features. Django 4.0 drops support for Python 3.6 and 3.7. It also dropssupport for PostgreSQL 9.6, Oracle 12.2, and Oracle 18c. Django 4.1 introduces asynchronous handlers for class-based views, an asynchronous ORM interface, new validation of model constraints and new templates for rendering forms. The 4.1 version drops support for PostgreSQL 10 and MariaDB 10.2.

You can read the completelist of changes in the Django 4.0 release notes athttps://docs.djangoproject.com/en/dev/releases/4.0/ and the Django 4.1 release notes athttps://docs.djangoproject.com/en/4.1/releases/4.1/.

Django overview

Django is a frameworkconsisting of a set of components that solve common web development problems. Django components are loosely coupled, which means they can be managed independently. This helps separate the responsibilities of the different layers of the framework; the database layer knows nothing about how the data is displayed, the template system knows nothing about web requests, and so on.

Django offers maximum code reusability by following theDRY (don’t repeat yourself) principle. Django also fosters rapid development and allows you to use less code by taking advantage of Python’s dynamic capabilities, such as introspection.

You can read moreabout Django’s design philosophies athttps://docs.djangoproject.com/en/4.1/misc/design-philosophies/.

Main framework components

Django followstheMTV (Model-Template-View) pattern. It is a slightly similar pattern to thewell-knownMVC (Model-View-Controller) pattern, wherethe Template acts as View and the framework itself acts as the Controller.

The responsibilities in the Django MTV pattern are divided as follows:

  • Model – Defines the logical data structure and is the data handler between the database and the View.
  • Template – Is the presentation layer. Django uses a plain-text template system that keeps everything that the browser renders.
  • View – Communicates with the database via the Model and transfers the data to the Template for viewing.

The framework itselfacts as the Controller. It sends a request to the appropriate view, according to the DjangoURL configuration.

When developing any Django project, you will always work with models, views, templates, and URLs. In this chapter, you will learn how they fit together.

The Django architecture

Figure 1.1 shows how Django processesrequests and how the request/response cycle is managed with the different main Django components: URLs, views, models, and templates:

Figure 1.1: The Django architecture

This is how Django handles HTTP requests and generates responses:

  1. A web browser requests a page by its URL and the web server passes the HTTP request to Django.
  2. Django runs through its configured URL patterns and stops at the first one that matches the requested URL.
  3. Django executes the view that corresponds to the matched URL pattern.
  4. The view potentially uses data models to retrieve information from the database.
  5. Data models provide the data definition and behaviors. They are used to query the database.
  6. The view renders a template (usually HTML) to display the data and returns it with an HTTP response.

We will get back to the Django request/response cycle at the end of this chapter in theThe request/response cycle section.

Django also includeshooks in the request/response process, which are called middleware. Middleware has been intentionally left out of this diagram for the sake of simplicity. You will use middleware in different examples of this book, and you will learn how to create custom middleware inChapter 17,Going Live.

Creating your first project

Your first Django project will consist of a blog application. We will start by creating the Django project anda Django application for the blog. We will then create our data models and synchronize them to the database.

Django provides a command that allows you to create an initial project file structure. Run the following command in your shell prompt:

django-admin startproject mysite

This will create a Django project with the namemysite.

Avoid naming projects after built-in Python or Django modules in order to avoid conflicts.

Let’s take a look at the generated project structure:

mysite/    manage.py    mysite/      __init__.py      asgi.py      settings.py      urls.py      wsgi.py

The outermysite/ directory isthe container for our project. It contains the following files:

  • manage.py: This is a command-line utility used to interact with your project. You don’t need to edit this file.
  • mysite/: This is the Python package for your project, which consists of the following files:
    • __init__.py: An empty file that tells Python to treat themysite directory as a Python module.
    • asgi.py: This is the configuration to run your project as anAsynchronous Server Gateway Interface (ASGI) application with ASGI-compatibleweb servers. ASGI is the emerging Python standard for asynchronous web servers and applications.
    • settings.py: This indicates settings and configuration for your project and contains initial default settings.
    • urls.py: This is the place where your URL patterns live. Each URL defined here is mapped to a view.
    • wsgi.py: This isthe configuration to run your project as aWeb Server Gateway Interface (WSGI) application with WSGI-compatible web servers.

Applying initial database migrations

Django applications require a database to store data. Thesettings.py file contains the database configurationfor your project in theDATABASES setting. The default configuration is an SQLite3 database. SQLite comes bundled with Python 3 and can be used in any of your Python applications. SQLite is a lightweight database that you can use with Django for development. If you plan to deploy your application in a production environment, you should use a full-featured database, such as PostgreSQL, MySQL, or Oracle. You can find more information about how to get your database running with Django athttps://docs.djangoproject.com/en/4.1/topics/install/#database-installation.

Yoursettings.py file also includes a list namedINSTALLED_APPS that contains common Django applications that are added to your project by default. We will go through these applications later in theProject settings section.

Django applications contain data models that are mapped to database tables. You will create your own models in theCreating the blog data models section. To complete the project setup, you need to create the tables associated with the models of the default Djangoapplications included in theINSTALLED_APPS setting. Django comes with a system that helps you manage database migrations.

Open the shell prompt and run the following commands:

cd mysitepython manage.py migrate

You will see an output that ends with the following lines:

Applying contenttypes.0001_initial... OKApplying auth.0001_initial... OKApplying admin.0001_initial... OKApplying admin.0002_logentry_remove_auto_add... OKApplying admin.0003_logentry_add_action_flag_choices... OKApplying contenttypes.0002_remove_content_type_name... OKApplying auth.0002_alter_permission_name_max_length... OKApplying auth.0003_alter_user_email_max_length... OKApplying auth.0004_alter_user_username_opts... OKApplying auth.0005_alter_user_last_login_null... OKApplying auth.0006_require_contenttypes_0002... OKApplying auth.0007_alter_validators_add_error_messages... OKApplying auth.0008_alter_user_username_max_length... OKApplying auth.0009_alter_user_last_name_max_length... OKApplying auth.0010_alter_group_name_max_length... OKApplying auth.0011_update_proxy_permissions... OKApplying auth.0012_alter_user_first_name_max_length... OKApplying sessions.0001_initial... OK

The preceding lines are the database migrations that are applied by Django. By applying the initial migrations, the tables for the applications listed in theINSTALLED_APPS setting are created in the database.

You will learn more about themigrate management command in theCreating and applying migrations section of this chapter.

Running the development server

Django comes with a lightweight web server to run your code quickly, without needing to spend timeconfiguring a production server. When you run the Django development server, it keeps checking for changes in your code. It reloads automatically, freeing you from manually reloading it after code changes. However, it might not notice some actions, such as adding new files to your project, so you will have to restart the server manually in these cases.

Start the development server by typing the following command in the shell prompt:

python manage.py runserver

You should see something like this:

Watching for file changes with StatReloaderPerforming system checks...System check identified no issues (0 silenced).January 01, 2022 - 10:00:00Django version 4.0, using settings 'mysite.settings'Starting development server at http://127.0.0.1:8000/Quit the server with CONTROL-C.

Now openhttp://127.0.0.1:8000/ in your browser. You should see a page stating that the project is successfully running, as shown in theFigure 1.2:

Figure 1.2: The default page of the Django development server

The preceding screenshot indicates that Django is running. If you take a look at your console, you will see theGET request performed by your browser:

[01/Jan/2022 17:20:30] "GET / HTTP/1.1" 200 16351

Each HTTP requestis logged in the console by the development server. Any error that occurs while running the development server will also appear in the console.

You can run the Django development server on a custom host and port or tell Django to load a specific settings file, as follows:

python manage.py runserver 127.0.0.1:8001 --settings=mysite.settings

When you have to deal with multiple environments that require different configurations, you can create a different settings file for each environment.

This server is only intended for development and is not suitable for production use. To deploy Django in a production environment, you should run it as a WSGI application using a webserver, such as Apache, Gunicorn, or uWSGI, or as an ASGI application using a server such as Daphne or Uvicorn. You can find more information on how to deploy Django with different web servers athttps://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/.

Chapter 17,Going Live, explains how to set up a production environment for your Django projects.

Project settings

Let’s open thesettings.py file and take a look at the configuration of the project. There are several settings that Django includes in this file, but these are only part of all the available Django settings. You cansee all the settings and theirdefault values athttps://docs.djangoproject.com/en/4.1/ref/settings/.

Let’s review some of the project settings:

  • DEBUG is a Boolean that turns the debug mode of the project on and off. If it is set toTrue, Django will display detailed error pages when an uncaught exception is thrown by your application. When you move to a production environment, remember that you have to set it toFalse. Never deploy a site into production withDEBUG turned on because you will expose sensitive project-related data.
  • ALLOWED_HOSTS is not applied while debug mode is on or when the tests are run. Once you move your site to production and setDEBUG toFalse, you will have to add your domain/host to this setting to allow it to serve your Django site.
  • INSTALLED_APPS is a setting you will have to edit for all projects. This setting tells Django which applications are active for this site. By default, Django includes the following applications:
    • django.contrib.admin: An administration site
    • django.contrib.auth: An authentication framework
    • django.contrib.contenttypes: A framework for handling content types
    • django.contrib.sessions: A session framework
    • django.contrib.messages: A messaging framework
    • django.contrib.staticfiles: A framework for managing static files
  • MIDDLEWARE is a list that contains middleware to be executed.
  • ROOT_URLCONF indicates the Python module where the root URL patterns of your application are defined.
  • DATABASES is a dictionary that contains the settings for all the databases to be used in the project. There must always be a default database. The default configuration uses an SQLite3 database.
  • LANGUAGE_CODE defines the default language code for this Django site.
  • USE_TZ tells Django to activate/deactivate timezone support. Django comes with support for timezone-awaredatetimes. This setting is set toTrue when you create a new project using thestartproject management command.

Don’t worry if you don’t understand much about what you’re seeing here. You will learn more about the different Django settings in the following chapters.

Projects and applications

Throughout this book, you will encounter the termsproject andapplication over and over. In Django, a project is considered a Django installation with some settings. An application is a groupof models, views, templates, and URLs. Applications interact with the framework to provide specific functionalities and may be reused in various projects. You can think of a project as your website, which contains several applications, such as a blog, wiki, or forum, that can also be used by other Django projects.

Figure 1.3 showsthe structure of a Django project:

Figure 1.3: The Django project/application structure

Creating an application

Let’s create ourfirst Django application. We will build a blog application from scratch.

Run the following command in the shell prompt from the project’s root directory:

python manage.py startapp blog

This will create the basic structure of the application, which will look like this:

blog/    __init__.py    admin.py    apps.py    migrations/        __init__.py    models.py    tests.py    views.py

These files are as follows:

  • __init__.py: An empty file that tells Python to treat theblog directory as a Python module.
  • admin.py: This is where you register models to include them in the Django administration site—using this site is optional.
  • apps.py: This includes the main configuration of theblog application.
  • migrations: This directory will contain database migrations of the application. Migrations allow Django to track your model changes and synchronize the database accordingly. This directory contains an empty__init__.py file.
  • models.py: This includes the data models of your application; all Django applications need to have amodels.py file but it can be left empty.
  • tests.py: This is whereyou can add tests for your application.
  • views.py: The logic of your application goes here; each view receives an HTTP request, processes it, and returns a response.

With the application structure ready, we can start building the data models for the blog.

Creating the blog data models

Remember that a Python object is a collection of data and methods. Classes are the blueprint for bundlingdata and functionality together. Creating a new class creates a new type of object, allowing you to create instances of that type.

A Django model is a source of information and behaviors of your data. It consists of a Python class that subclassesdjango.db.models.Model. Each model maps to a single database table, where each attribute of the class represents a database field. When you create a model, Django will provide you with a practical API to query objects in the database easily.

We will define the database models for our blog application. Then, we will generate the database migrations for the models to create the corresponding database tables. When applying the migrations, Django will create a table for each model defined in themodels.py file of the application.

Creating the Post model

First, we willdefine aPost model that will allow us tostore blog posts in the database.

Add the following lines to themodels.py file of theblog application. The new lines are highlighted in bold:

from django.dbimport modelsclassPost(models.Model):    title = models.CharField(max_length=250)    slug = models.SlugField(max_length=250)    body = models.TextField()def__str__(self):return self.title

This is the data model for blog posts. Posts will have a title, a short label calledslug, and a body. Let’s take a look at the fields of this model:

  • title: This is the field for the post title. This is aCharField field that translates into aVARCHAR column in the SQL database.
  • slug: This is aSlugField field that translates into aVARCHAR column in the SQL database. A slug is a short label that contains only letters, numbers, underscores, or hyphens. A post with the titleDjango Reinhardt: A legend of Jazzcould have a slug likedjango-reinhardt-legend-jazz. We will use theslug field to build beautiful, SEO-friendly URLs for blog posts inChapter 2, Enhancing Your Blog with Advanced Features.
  • body: This is the field for storing the body of the post. This is aTextField field that translates into aTEXT column in the SQL database.

We have also added a__str__() method to the model class. This is the default Python method to return a string with the human-readable representation of the object. Django will use this method to display the name of the object in many places, such as the Django administration site.

If you have been using Python 2.x, note that in Python 3, all strings are natively considered Unicode; therefore, weonly use the__str__() method. The__unicode__() method fromPython 2.x is obsolete.

Let’s take a look at how the model and its fields will be translated into a database table and columns. The following diagram shows thePost model and the corresponding database table that Django will create when we synchronize the model to the database:

Figure 1.4: Initial Post model and database table correspondence

Django will create a database column for each of the model fields:title,slug, andbody. You can see how each field type corresponds to a database data type.

By default, Django adds an auto-incrementing primary key field to each model. The field type for this field isspecified in each application configurationor globally in theDEFAULT_AUTO_FIELD setting. When creating an application with thestartapp command, the default value forDEFAULT_AUTO_FIELD isBigAutoField. This is a 64-bit integer that automatically increments according to available IDs. If you don’t specify a primary key for your model, Django adds this field automatically. You can also define one of the model fields to be the primary key by settingprimary_key=True on it.

We will expand thePost model with additional fields and behaviors. Once complete, we will synchronize it to the database by creating a database migration and applying it.

Adding datetime fields

We will continue by adding different datetime fields to thePost model. Each post will be published at aspecific date and time. Therefore, we need a field to store thepublication date and time. We also want to store the date and time when thePost object was created, and when it was last modified.

Edit themodels.py file of theblog application to make it look like this. The new lines are highlighted in bold:

from django.dbimport modelsfrom django.utilsimport timezoneclassPost(models.Model):    title = models.CharField(max_length=250)    slug = models.SlugField(max_length=250)    body = models.TextField()    publish = models.DateTimeField(default=timezone.now)    created = models.DateTimeField(auto_now_add=True)    updated = models.DateTimeField(auto_now=True)def__str__(self):return self.title

We have added the following fields to thePost model:

  • publish: This is aDateTimeField field that translates into aDATETIME column in the SQL database. We will use it to store the date and time when the post was published. We use Django’stimezone.now method as the default value for the field. Note that we imported thetimezone module to use this method.timezone.now returns the current datetime in a timezone-aware format. You can think of it as a timezone-aware version of the standard Pythondatetime.now method.
  • created: This is aDateTimeField field. We will use it to store the date and time when the post was created. By usingauto_now_add, the date will be saved automatically when creating an object.
  • updated: This is aDateTimeField field. We will use it to store the last date and time when the post was updated. By usingauto_now, the date will be updated automatically when saving an object.

Defining a default sort order

Blog posts areusually displayed in reverse chronologicalorder (from newest to oldest). We will define a default ordering for our model. The default order will apply when obtaining objects from the database when no order is specified in the query.

Edit themodels.py file of theblog application to make it look like this. The new lines are highlighted in bold:

from django.dbimport modelsfrom django.utilsimport timezoneclassPost(models.Model):    title = models.CharField(max_length=250)    slug = models.SlugField(max_length=250)    body = models.TextField()    publish = models.DateTimeField(default=timezone.now)    created = models.DateTimeField(auto_now_add=True)    updated = models.DateTimeField(auto_now=True)classMeta:        ordering = ['-publish']def__str__(self):return self.title

We have added aMeta class inside the model. This class defines metadata for the model. We use theordering attribute to tell Django that it should sort results by thepublish field. This ordering will apply by default for database queries when no specific order is provided in the query. We indicate descending order by using a hyphen before the field name,-publish. Posts will be returned in reverse chronological order by default.

Adding a database index

Let’s define a database index for thepublish field. This will improve performance for queries filteringor ordering results by this field. We expect many queriesto take advantage of this index since we are using thepublish field to order results by default.

Edit themodels.py file of theblog application and make it look like this. The new lines are highlighted in bold:

from django.dbimport modelsfrom django.utilsimport timezoneclassPost(models.Model):    title = models.CharField(max_length=250)    slug = models.SlugField(max_length=250)    body = models.TextField()    publish = models.DateTimeField(default=timezone.now)    created = models.DateTimeField(auto_now_add=True)    updated = models.DateTimeField(auto_now=True)classMeta:        ordering = ['-publish']        indexes = [            models.Index(fields=['-publish']),        ]def__str__(self):return self.title

We have added theindexes option to the model’sMeta class. This option allows you to define database indexes for your model, which could comprise one or multiple fields, in ascending ordescending order, or functional expressions and database functions. We haveadded an index for thepublish field. We use a hyphen before the field name to define the index in descending order. The creation of this index will be included in the database migrations that we will generate later for our blog models.

Index ordering is not supported on MySQL. If you use MySQL for the database, a descending index will be created as a normal index.

You can readmore information about how to define indexes for models athttps://docs.djangoproject.com/en/4.1/ref/models/indexes/.

Activating the application

We need toactivate theblog application in the project, for Django to keep track of the application and be able to create database tables for its models.

Edit thesettings.py file and addblog.apps.BlogConfig to theINSTALLED_APPS setting. It should look like this. The new lines are highlighted in bold:

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','blog.apps.BlogConfig',]

TheBlogConfig class is the application configuration. Now Django knows that the application is active for this project and will be able to load the application models.

Adding a status field

A common functionalityfor blogs is to save posts as a draft until ready forpublication. We will add astatus field to our model that will allow us to manage the status of blog posts. We will be usingDraft andPublished statuses for posts.

Edit themodels.py fileof theblog application to make it look as follows. The new linesare highlighted in bold:

from django.dbimport modelsfrom django.utilsimport timezoneclassPost(models.Model):classStatus(models.TextChoices):        DRAFT ='DF','Draft'        PUBLISHED ='PB','Published'    title = models.CharField(max_length=250)    slug = models.SlugField(max_length=250)    body = models.TextField()    publish = models.DateTimeField(default=timezone.now)    created = models.DateTimeField(auto_now_add=True)    updated = models.DateTimeField(auto_now=True)    status = models.CharField(max_length=2,                              choices=Status.choices,                              default=Status.DRAFT)classMeta:        ordering = ['-publish']        indexes = [            models.Index(fields=['-publish']),        ]def__str__(self):return self.title

We have defined the enumeration classStatus by subclassingmodels.TextChoices. The available choices for the post status areDRAFT andPUBLISHED. Their respective values areDF andPB, and their labels or readable names areDraft andPublished.

Django provides enumeration types that you can subclass to define choices simply. These are basedon theenum object of Python’s standard library. You can read more aboutenum athttps://docs.python.org/3/library/enum.html.

Django enumeration types present some modifications overenum. You can learn about those differences athttps://docs.djangoproject.com/en/4.1/ref/models/fields/#enumeration-types.

We can accessPost.Status.choices to obtain the available choices,Post.Status.labels to obtain the human-readable names, andPost.Status.values to obtain the actual values of the choices.

We have also added a newstatus field to the model that is an instance ofCharField. It includes achoices parameterto limit the value of the field to the choices inStatus.choices. We havealso set a default value for the field using thedefault parameter. We useDRAFT as the default choice for this field.

It’s a good practice to define choices inside the model class and use the enumeration types. This will allow you to easily reference choice labels, values, or names from anywhere in your code. You can import thePost model and usePost.Status.DRAFT as a reference for theDraft status anywhere in your code.

Let’s take a look at how to interact with the status choices.

Run the following command in the shell prompt to open the Python shell:

python manage.py shell

Then, type the following lines:

>>>from blog.modelsimport Post>>>Post.Status.choices

You will obtain the enum choices with value-label pairs like this:

[('DF', 'Draft'), ('PB', 'Published')]

Type the following line:

>>>Post.Status.labels

You will get the human-readable names of the enum members as follows:

['Draft', 'Published']

Type the following line:

>>>Post.Status.values

You will get the valuesof the enum members as follows. These are the values thatcan be stored in the database for thestatus field:

['DF', 'PB']

Type the following line:

>>>Post.Status.names

You will get the names of the choices like this:

['DRAFT', 'PUBLISHED']

You can access a specific lookup enumeration member withPost.Status.PUBLISHED and you can access its.name and.value properties as well.

Adding a many-to-one relationship

Posts are always written by an author. We will create a relationship between users and posts that willindicate which user wrotewhich posts. Django comes with an authentication framework that handles user accounts. The Django authentication framework comes in thedjango.contrib.auth package and contains aUser model. We will use theUser model from the Django authentication framework to create a relationship between users and posts.

Edit themodels.py file of theblog application to make it look like this. The new lines are highlighted in bold:

from django.dbimport modelsfrom django.utilsimport timezonefrom django.contrib.auth.modelsimport UserclassPost(models.Model):classStatus(models.TextChoices):        DRAFT ='DF','Draft'        PUBLISHED ='PB','Published'    title = models.CharField(max_length=250)    slug = models.SlugField(max_length=250)    author = models.ForeignKey(User,                               on_delete=models.CASCADE,                               related_name='blog_posts')    body = models.TextField()    publish = models.DateTimeField(default=timezone.now)    created = models.DateTimeField(auto_now_add=True)    updated = models.DateTimeField(auto_now=True)    status = models.CharField(max_length=2,                              choices=Status.choices,                              default=Status.DRAFT)classMeta:        ordering = ['-publish']        indexes = [            models.Index(fields=['-publish']),        ]def__str__(self):return self.title

We have imported theUser model from thedjango.contrib.auth.models module and we have added anauthor field to thePost model. This field defines a many-to-one relationship, meaningthat each post is written by auser, and a user can write any number of posts. For this field, Django will create a foreign key in the database using the primary key of the related model.

Theon_delete parameter specifies the behavior to adopt when the referenced object is deleted. This is not specific to Django; it is an SQL standard. UsingCASCADE, you specify that when the referenced user is deleted, the database will also delete all related blog posts. You can take a look at all the possible options athttps://docs.djangoproject.com/en/4.1/ref/models/fields/#django.db.models.ForeignKey.on_delete.

We userelated_name to specify the name of the reverse relationship, fromUser toPost. This will allow us to access related objects easily from a user object by using theuser.blog_posts notation. We will learn more about this later.

Django comes with different types of fields that you can use to define your models. You canfind all field types athttps://docs.djangoproject.com/en/4.1/ref/models/fields/.

ThePost model is nowcomplete, and we cannow synchronize it to the database. But before that, we need to activate theblog application in our Django project.

Creating and applying migrations

Now that we have a data model for blog posts, we need to create the corresponding databasetable. Django comes with a migration system thattracks the changes made tomodels andenables them to propagate into the database.

Themigrate command applies migrations for all applications listed inINSTALLED_APPS. It synchronizes the database with the current models and existing migrations.

First, we will need to create an initial migration for ourPost model.

Run the following command in the shell prompt from the root directory of your project:

python manage.py makemigrations blog

You should get an output similar to the following one:

Migrations for 'blog':    blog/migrations/0001_initial.py        - Create model Post        - Create index blog_post_publish_bb7600_idx on field(s)          -publish of model post

Django just created the0001_initial.py file inside themigrations directory of theblog application. This migrationcontains the SQL statementsto create the database tablefor thePost model and the definition of the databaseindex for thepublish field.

You can take a look at the file contents to see how the migration is defined. A migration specifies dependencies on other migrations and operations to perform in the database to synchronize it with model changes.

Let’s take a look at the SQL code that Django will execute in the database to create the table for your model. Thesqlmigrate command takes the migration names and returns their SQL without executing it.

Run the following command from the shell prompt to inspect the SQL output of your first migration:

python manage.py sqlmigrate blog 0001

The output should look as follows:

BEGIN;---- Create model Post--CREATE TABLE "blog_post" (  "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,  "title" varchar(250) NOT NULL,  "slug" varchar(250) NOT NULL,  "body" text NOT NULL,  "publish" datetime NOT NULL,  "created" datetime NOT NULL,  "updated" datetime NOT NULL,  "status" varchar(10) NOT NULL,  "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);---- Create blog_post_publish_bb7600_idx on field(s) -publish of model post--CREATE INDEX "blog_post_publish_bb7600_idx" ON "blog_post" ("publish" DESC);CREATE INDEX "blog_post_slug_b95473f2" ON "blog_post" ("slug");CREATE INDEX "blog_post_author_id_dd7a8485" ON "blog_post" ("author_id");COMMIT;

The exact output depends on the database you are using. The preceding output is generatedfor SQLite. As you can see in the output, Djangogenerates the table names by combining the applicationname and the lowercase name of the model (blog_post), but youcan also specify a custom database name for your model in theMeta class of the model using thedb_table attribute.

Django creates an auto-incrementalid column used as the primary key for each model, but you can also override this by specifyingprimary_key=True on one of your model fields. The defaultid column consists of an integer that is incremented automatically. This column corresponds to theid field that is automatically added to your model.

The following three database indexes are created:

  • An index with descending order on thepublish column. This is the index we explicitly defined with theindexes option of the model’sMeta class.
  • An index on theslug column becauseSlugField fields imply an index by default.
  • An index on theauthor_id column becauseForeignKey fields imply an index by default.

Let’s compare thePost model with its corresponding databaseblog_post table:

Figure 1.5: Complete Post model and database table correspondence

Figure 1.5 showshow the model fields correspondto databasetable columns.

Let’s sync thedatabase with the new model.

Execute the following command in the shell prompt to apply existing migrations:

python manage.py migrate

You will get an output that ends with the following line:

Applying blog.0001_initial... OK

We just applied migrations for the applications listed inINSTALLED_APPS, including theblog application. After applying the migrations, the database reflects the current status of the models.

If you edit themodels.py file in order to add, remove, or change the fields of existing models, or if you add new models, you will have to create a new migration using themakemigrations command. Each migration allows Django to keep track of model changes. Then, you willhave to apply the migrationusing themigrate command to keep thedatabase insync with your models.

Creating an administration site for models

Now that thePost model isin sync with the database, we cancreate a simple administration site to manage blog posts.

Django comes with a built-in administration interface that is very useful for editing content. The Django site is built dynamically by reading the model metadata and providing a production-ready interface for editing content. You can use it out of the box, configuring how you want your models to be displayed in it.

Thedjango.contrib.admin application is already included in theINSTALLED_APPS setting, so you don’t need to add it.

Creating a superuser

First, you willneed to create a user to manage the administration site. Run the following command:

python manage.py createsuperuser

You will see the following output. Enter your desired username, email, and password, as follows:

Username (leave blank to use 'admin'): adminEmail address: admin@admin.comPassword: ********Password (again): ********

Then you will see the following success message:

Superuser created successfully.

We just created an administrator user with the highest permissions.

The Django administration site

Start the development server with the following command:

python manage.py runserver

Openhttp://127.0.0.1:8000/admin/ in your browser. You should see the administrationlogin page, as shown inFigure 1.6:

Figure 1.6: The Django administration site login screen

Log in using the credentials of the user you created in the preceding step. You will see the administration site index page, as shown inFigure 1.7:

Figure 1.7: The Django administration site index page

TheGroup andUser models that you can see in the preceding screenshot are part of the Django authenticationframework located indjango.contrib.auth. If you click onUsers, you will see the user you created previously.

Adding models to the administration site

Let’s add your blog models to theadministrationsite. Edit theadmin.py file of theblog application and make it look like this. The new lines are highlighted in bold:

from django.contribimport adminfrom .modelsimport Postadmin.site.register(Post)

Now reload the administration site in your browser. You should see yourPost model on the site, as follows:

Figure 1.8: The Post model of the blog application included in the Django administration site index page

That was easy, right? When you register a model in the Django administration site, you get a user-friendly interface generated by introspecting your models that allows you to list, edit, create, and delete objects in a simple way.

Click on theAdd link besidePosts to add a new post. You will note the form that Django has generated dynamically for your model, as shown inFigure 1.9:

Figure 1.9: The Django administration site edit form for the Post model

Django usesdifferent form widgets for each typeof field. Even complex fields, such as theDateTimeField, are displayed with an easy interface, such as a JavaScript date picker.

Fill in the form and click on theSAVE button. You should be redirected to the post list page with a successmessage and the post youjust created, as shown inFigure 1.10:

Figure 1.10: The Django administration site list view for the Post model with an added successfully message

Customizing how models are displayed

Now, we willtake a look at how to customize the administration site.

Edit theadmin.py file of yourblog application and change it, as follows. The new lines are highlighted in bold:

from django.contribimport adminfrom .modelsimport Post@admin.register(Post)classPostAdmin(admin.ModelAdmin):    list_display = ['title','slug','author','publish','status']

We are telling the Django administration site that the model is registered in the site using a custom class that inherits fromModelAdmin. In this class, we can include information about how to display the model on the site and how to interact with it.

Thelist_display attribute allows you to set the fields of your model that you want to display on the administration object list page. The@admin.register() decorator performs the same function as theadmin.site.register() function that you replaced, registering theModelAdmin class that it decorates.

Let’s customize theadmin model with some more options.

Edit theadmin.py fileof yourblog application and change it, as follows. The new lines are highlighted in bold:

from django.contribimport adminfrom .modelsimport Post@admin.register(Post)classPostAdmin(admin.ModelAdmin):    list_display = ['title','slug','author','publish','status']    list_filter = ['status','created','publish','author']    search_fields = ['title','body']    prepopulated_fields = {'slug': ('title',)}    raw_id_fields = ['author']    date_hierarchy ='publish'    ordering = ['status','publish']

Return to your browser and reload the post list page. Now, it will look like this:

Figure 1.11: The Django administration site custom list view for the Post model

You can see that the fields displayed on the post list page are the ones we specified in thelist_display attribute. The list page now includes a right sidebar that allows you to filter the results by the fields included in thelist_filter attribute.

A search bar has appeared on the page. This is because we have defined a list of searchable fields using thesearch_fields attribute. Just below the search bar, there are navigation linksto navigate through a date hierarchy; this has been defined by thedate_hierarchy attribute. You can also see that the posts are ordered bySTATUS andPUBLISH columns by default. We have specified the default sorting criteria using theordering attribute.

Next, click on theADD POST link. You will also note some changes here. As you type the title of a new post, theslug field is filled in automatically. You have told Django to prepopulate theslug field with the input of thetitle field using theprepopulated_fields attribute:

Figure 1.12: The slug model is now automatically prepopulated as you type in the title

Also, theauthor field is now displayed with a lookup widget, which can be much better than a drop-down select input when you have thousands of users. This is achieved with theraw_id_fields attribute and it looks like this:

Figure 1.13: The widget to select related objects for the author field of the Post model

With a few lines of code, we have customized the way the model is displayed on the administration site. Thereare plenty of ways to customize and extend the Django administration site; you will learn more about this later in this book.

You can findmore information about the Django administration site athttps://docs.djangoproject.com/en/4.1/ref/contrib/admin/.

Working with QuerySets and managers

Now that we havea fully functional administration site to manage blog posts, it is a goodtime to learn how to read and write content to the database programmatically.

The Djangoobject-relational mapper (ORM) is a powerful database abstraction API that lets you create, retrieve, update, and delete objects easily. An ORM allows you to generate SQL queriesusing the object-oriented paradigm of Python. You can think of it as a way to interact with your database in pythonic fashion instead of writing raw SQL queries.

The ORM maps your models to database tables and provides you with a simple pythonic interface to interact with your database. The ORM generates SQL queries and maps the results to model objects. The Django ORM is compatible with MySQL, PostgreSQL, SQLite, Oracle, and MariaDB.

Remember that you can define the database of your project in theDATABASES setting of your project’ssettings.py file. Django can work with multiple databases at a time, and you can program database routers to create custom data routing schemes.

Once you have created your data models, Django gives you a free API to interact with them. You can find the data model reference of the official documentation athttps://docs.djangoproject.com/en/4.1/ref/models/.

The Django ORM is based on QuerySets. A QuerySet is a collection of database queries to retrieve objectsfrom your database. You can apply filters to QuerySets to narrow down the query results based on given parameters.

Creating objects

Run the followingcommand in the shell prompt to open the Python shell:

python manage.py shell

Then, type the following lines:

>>>from django.contrib.auth.modelsimport User>>>from blog.modelsimport Post>>>user = User.objects.get(username='admin')>>>post = Post(title='Another post',...            slug='another-post',...            body='Post body.',...            author=user)>>>post.save()

Let’s analyze what this code does.

First, we are retrieving theuser object with the usernameadmin:

user = User.objects.get(username='admin')

Theget() method allows you to retrieve a single object from the database. Note that this method expects a result that matches the query. If no results are returned by the database, this method will raise aDoesNotExist exception, and if the database returns more than one result, it will raise aMultipleObjectsReturned exception. Both exceptions are attributes of the model class that the query is being performed on.

Then, we are creating aPost instance with a custom title, slug, and body, and set the user that we previously retrieved as the author of the post:

post = Post(title='Another post', slug='another-post', body='Post body.', author=user)

This object is in memory and not persisted to the database; we created a Python object that can be used during runtime but that is not saved into the database.

Finally, we are saving thePost object to the database using thesave() method:

post.save()

The preceding action performs anINSERT SQL statement behind the scenes.

We created an object in memory first and then persisted it to the database. You can also create the object andpersist it into the database in a single operation using thecreate() method, as follows:

Post.objects.create(title='One more post',                    slug='one-more-post',                    body='Post body.',                    author=user)

Updating objects

Now, change the title ofthe post to something different and save the object again:

>>>post.title ='New title'>>>post.save()

This time, thesave() method performs anUPDATE SQL statement.

The changes you make to amodel object are not persisted to the database until you call thesave() method.

Retrieving objects

You already know how to retrieve a single object from the database using theget() method. We accessed thismethod usingPost.objects.get(). Each Django model has at least one manager, and the default manager is calledobjects. You get aQuerySet object using your model manager.

To retrieve all objects from a table, we use theall() method on the default objects manager, like this:

>>>all_posts = Post.objects.all()

This is how we create aQuerySet that returns all objects in the database. Note that thisQuerySet has not been executed yet. DjangoQuerySets arelazy, which means they are only evaluated when they are forced to. This behavior makesQuerySets very efficient. If you don’t assign theQuerySet to a variable but instead write it directly on the Python shell, the SQL statement of theQuerySet is executed because you are forcing it to generate output:

>>>Post.objects.all()<QuerySet [<Post: Who was Django Reinhardt?>, <Post: New title>]>

Using the filter() method

To filter aQuerySet, youcan use thefilter() method of themanager. For example, you can retrieve all posts published in the year 2022 using the followingQuerySet:

>>>Post.objects.filter(publish__year=2022)

You can also filter by multiple fields. For example, you can retrieve all posts published in 2022 by the author with the usernameadmin:

>>>Post.objects.filter(publish__year=2022, author__username='admin')

This equates to building the sameQuerySet chaining multiple filters:

>>>Post.objects.filter(publish__year=2022) \>>>            .filter(author__username='admin')

Queries with field lookup methods are built using two underscores, for example,publish__year, but the same notation is also used for accessing fields of related models, such asauthor__username.

Using exclude()

You can excludecertain results fromyourQuerySet using theexclude() method of the manager. For example, you can retrieve all posts published in 2022 whose titles don’t start withWhy:

>>>Post.objects.filter(publish__year=2022) \>>>            .exclude(title__startswith='Why')

Using order_by()

You can orderresults by different fieldsusing theorder_by() method of the manager. For example, you can retrieve all objects ordered by theirtitle, as follows:

>>>Post.objects.order_by('title')

Ascending orderis implied. You can indicatedescending order with a negative sign prefix, like this:

>>>Post.objects.order_by('-title')

Deleting objects

If you want to deletean object, you can do it from the object instance using thedelete() method:

>>>post = Post.objects.get(id=1)>>>post.delete()

Note that deleting objects will also delete any dependent relationships forForeignKey objects defined withon_delete set toCASCADE.

When QuerySets are evaluated

Creating a QuerySet doesn’t involve any database activity until it is evaluated. QuerySets usually return anotherunevaluated QuerySet. You can concatenate as many filters as you like to a QuerySet, and you will not hit the database until the QuerySet is evaluated. When a QuerySet is evaluated, it translates into an SQL query to the database.

QuerySets are only evaluated in the following cases:

  • The first time you iterate over them
  • When you slice them, for instance,Post.objects.all()[:3]
  • When you pickle or cache them
  • When you callrepr() orlen() on them
  • When you explicitly calllist() on them
  • When you test them in a statement, such asbool(),or,and, orif

Creating model managers

The default manager forevery model is theobjects manager. This manager retrieves all the objects in the database. However, we can define custom managers for models.

Let’s create a custom manager to retrieve all posts that have aPUBLISHED status.

There are two ways to add or customize managers for your models: you can add extra manager methods to an existing manager or create a new manager by modifying the initialQuerySet that the manager returns. The first method provides you with aQuerySet notation likePost.objects.my_manager(), and the latter provides you with aQuerySet notation likePost.my_manager.all().

We will choose the second method to implement a manager that will allow us to retrieve posts using the notationPost.published.all().

Edit themodels.py file of yourblog application to add the custom manager as follows. The new lines are highlighted in bold:

classPublishedManager(models.Manager):defget_queryset(self):returnsuper().get_queryset()\                     .filter(status=Post.Status.PUBLISHED)classPost(models.Model):# model fields# ...    objects = models.Manager()# The default manager.    published = PublishedManager()# Our custom manager.classMeta:        ordering = ['-publish']def__str__(self):return self.title

The first manager declared in a model becomes the default manager. You can use theMeta attributedefault_manager_name to specify a different default manager. If no manager is defined in the model, Django automatically creates theobjects default manager for it. If you declare any managers for your model, but you want to keep theobjects manager as well, you have to add it explicitly to your model. In the preceding code, we have added the defaultobjects manager and thepublished custom manager to thePost model.

Theget_queryset() method of a manager returns theQuerySet that will be executed. We have overriddenthis method to build a customQuerySet that filters posts by their status and returns a successiveQuerySet that only includes posts with thePUBLISHED status.

We have now defined a custom manager for thePost model. Let’s test it!

Start the development server again with the following command in the shell prompt:

python manage.py shell

Now, you can import thePost model and retrieve all published posts whose title starts withWho, executing the followingQuerySet:

>>>from blog.modelsimport Post>>>Post.published.filter(title__startswith='Who')

To obtain results for thisQuerySet, make sure to set thestatus field toPUBLISHED in thePost object whosetitle starts with the stringWho.

Building list and detail views

Now that you understand how to use the ORM, you are ready to build the views of theblog application. A Djangoview is just a Python function that receives a webrequest and returns a web response. All the logic to return the desired response goes inside the view.

First, you will create your application views, then you will define a URL pattern for each view, and finally, you will create HTML templates to render the data generated by the views. Each view will render a template, passing variables to it, and will return an HTTP response with the rendered output.

Creating list and detail views

Let’s start by creatinga view to display the list of posts.

Edit theviews.py file oftheblog application and make it look like this. The new lines are highlighted in bold:

from django.shortcutsimport renderfrom .modelsimport Postdefpost_list(request):    posts = Post.published.all()return render(request,'blog/post/list.html',                 {'posts': posts})

This is our very first Django view. Thepost_list view takes therequest object as the only parameter. This parameter is required by all views.

In this view, we retrieveall the posts with thePUBLISHED statususing thepublished manager that we created previously.

Finally, we use therender() shortcut provided by Django to render the list of posts with the given template. This function takes therequest object, the template path, and the context variables to render the given template. It returns anHttpResponse object with the rendered text (normally HTML code).

Therender() shortcut takes the request context into account, so any variable set by the template context processors is accessible by the given template. Template context processors are just callables that set variables into the context. You will learn how to use context processors inChapter 4,Building a Social Website.

Let’s create a second view to display a single post. Add the following function to theviews.py file:

from django.httpimport Http404defpost_detail(request,id):try:        post = Post.published.get(id=id)except Post.DoesNotExist:raise Http404("No Post found.")return render(request,'blog/post/detail.html',                  {'post': post})

This is the post detail view. This view takes theid argument of a post. In the view, we try to retrieve thePost object with the givenid by calling theget() method on the defaultobjects manager. Weraise anHttp404 exception to return an HTTP 404 error ifthe modelDoesNotExist exception is raised, because no result is found.

Finally, we use therender() shortcut to render the retrieved post using a template.

Using the get_object_or_404 shortcut

Django provides ashortcut to callget() on a given model managerand raises anHttp404 exception instead of aDoesNotExist exception when no object is found.

Edit theviews.py file to import theget_object_or_404 shortcut and change thepost_detail view as follows. The new code is highlighted in bold:

from django.shortcutsimport render, get_object_or_404# ...defpost_detail(request,id):    post = get_object_or_404(Post,id=id,                             status=Post.Status.PUBLISHED)return render(request,'blog/post/detail.html',                  {'post': post})

In the detail view, we now use theget_object_or_404() shortcut to retrieve the desired post. This function retrieves the object that matches the given parameters or an HTTP 404 (not found) exception if no object is found.

Adding URL patterns for your views

URL patterns allow you to map URLs to views. A URL pattern is composed of a string pattern, a view, and, optionally, a name that allows you to name the URL project-wide. Django runs througheach URL pattern and stops at the first one thatmatches the requested URL. Then, Django imports the view of the matching URL pattern and executes it, passing an instance of theHttpRequest class and the keyword or positional arguments.

Create aurls.py file in the directory of theblog application and add the following lines to it:

from django.urlsimport pathfrom .import viewsapp_name ='blog'urlpatterns = [# post views    path('', views.post_list, name='post_list'),    path('<int:id>/', views.post_detail, name='post_detail'),]

In the preceding code, you define an application namespace with theapp_name variable. This allows you to organize URLs by application and use the name when referring to them. You definetwo different patterns using thepath() function. The firstURL pattern doesn’t take any arguments and is mapped to thepost_list view. The second pattern is mapped to thepost_detail view and takes only one argumentid, which matches an integer, set by the path converterint.

You use angle brackets to capture the values from the URL. Any value specified in the URL pattern as<parameter> is captured as a string. You use path converters, such as<int:year>, to specifically match and return an integer. For example<slug:post> would specifically match a slug (a string that can only contain letters, numbers, underscores, or hyphens). You can see all path converters provided by Django athttps://docs.djangoproject.com/en/4.1/topics/http/urls/#path-converters.

If usingpath() and converters isn’t sufficient for you, you can usere_path() instead to define complex URL patterns with Python regular expressions. You can learn more about defining URL patterns with regular expressions athttps://docs.djangoproject.com/en/4.1/ref/urls/#django.urls.re_path. If you haven’t worked with regular expressions before, you might want to take a look at theRegular Expression HOWTO located athttps://docs.python.org/3/howto/regex.html first.

Creating aurls.py file for each application is the best way to make your applications reusable by other projects.

Next, you have to include the URL patterns of theblog application in the main URL patterns of the project.

Edit theurls.py file located in themysite directory of your project and make it look like the following. The new code is highlighted in bold:

from django.contribimport adminfrom django.urlsimport path, includeurlpatterns = [    path('admin/', admin.site.urls),    path('blog/', include('blog.urls', namespace='blog')),]

The new URL pattern defined withinclude refers to the URL patterns defined in theblog application so that they are included under theblog/ path. You include these patterns under thenamespaceblog. Namespaces have to be unique acrossyour entire project. Later, you will refer to your blog URLs easily by using the namespace followed by a colon and the URL name, for example,blog:post_list andblog:post_detail. You can learn moreabout URL namespaces athttps://docs.djangoproject.com/en/4.1/topics/http/urls/#url-namespaces.

Creating templates for your views

You have created views and URL patterns for theblog application. URL patterns map URLs to views, andviews decide which data gets returned to the user. Templates define how the data is displayed; they are usually written in HTML in combination with the Django template language. You canfind more information about the Django template language athttps://docs.djangoproject.com/en/4.1/ref/templates/language/.

Let’s add templates to your application to display posts in a user-friendly manner.

Create the following directories and files inside yourblog application directory:

templates/    blog/        base.html        post/            list.html            detail.html

The preceding structure will be the file structure for your templates. Thebase.html file will include themain HTML structure of the website and divide the content into the main content area and a sidebar. Thelist.html anddetail.html files will inherit from thebase.html file to render the blog post list and detail views, respectively.

Django has a powerful template language that allows you to specify how data is displayed. It is based ontemplate tags,template variables, andtemplate filters:

  • Template tags control the rendering of the template and look like{% tag %}
  • Template variables get replaced with values when the template is rendered and look like{{ variable }}
  • Template filters allow you to modify variables for display and look like{{ variable|filter }}

You can seeall built-in template tags and filters athttps://docs.djangoproject.com/en/4.1/ref/templates/builtins/.

Creating a base template

Edit thebase.html fileand add the followingcode:

{% load static %}<!DOCTYPEhtml><html><head><title>{% block title %}{% endblock %}</title><linkhref="{% static "css/blog.css" %}"rel="stylesheet"></head><body><divid="content">    {% block content %}    {% endblock %}</div><divid="sidebar"><h2>My blog</h2><p>This is my blog.</p></div></body></html>

{% load static %} tells Django to load thestatic template tags that are provided by thedjango.contrib.staticfiles application, which is contained in theINSTALLED_APPS setting. After loading them, you can use the{% static %} template tag throughout thistemplate. With this template tag, you caninclude the static files, such as theblog.css file, which you will find in the code of this example under thestatic/ directory of theblog application. Copy thestatic/ directory from the code that comes along with this chapter into the same location as your project to apply the CSS styles to the templates. You can find the directory’s contents athttps://github.com/PacktPublishing/Django-4-by-Example/tree/master/Chapter01/mysite/blog/static.

You can see that there are two{% block %} tags. These tell Django that you want to define a block in that area. Templates that inherit from this template can fill in the blocks with content. You have defined a block calledtitle and a block calledcontent.

Creating the post list template

Let’s edit thepost/list.html fileand make it look likethe following:

{% extends "blog/base.html" %}{% block title %}My Blog{% endblock %}{% block content %}<h1>My Blog</h1>  {% for post in posts %}<h2><ahref="{% url 'blog:post_detail' post.id %}">        {{ post.title }}</a></h2><pclass="date">      Published {{ post.publish }} by {{ post.author }}</p>    {{ post.body|truncatewords:30|linebreaks }}  {% endfor %}{% endblock %}

With the{% extends %} template tag, you tell Django to inherit from theblog/base.html template. Then, you fill thetitle andcontent blocks of the base templatewith content. You iterate through the posts and display their title, date, author, and body, including a link in the title to the detail URL of the post. We buildthe URL using the{% url %} template tag provided by Django.

This template tag allows you to build URLs dynamically by their name. We useblog:post_detail to refer to thepost_detail URL in theblog namespace. We pass the requiredpost.id parameter to build the URL for each post.

Always use the{% url %} template tag to build URLs in your templates instead of writing hardcoded URLs. This will make your URLs more maintainable.

In the body of the post, we apply two template filters:truncatewords truncates the value to the number of words specified, andlinebreaks converts the output into HTML line breaks. You can concatenate as many template filters as you wish; each one will be applied to the output generated by the preceding one.

Accessing our application

Open the shelland execute the following command to start the development server:

python manage.py runserver

Openhttp://127.0.0.1:8000/blog/ in your browser; you will see everything running. Note that you need to have some posts with thePUBLISHED status to show them here. You should see something like this:

Figure 1.14: The page for the post list view

Creating the post detail template

Next, edit thepost/detail.html file:

{% extends "blog/base.html" %}{% block title %}{{ post.title }}{% endblock %}{% block content %}<h1>{{ post.title }}</h1><pclass="date">    Published {{ post.publish }} by {{ post.author }}</p>  {{ post.body|linebreaks }}{% endblock %}

Next, you can return to your browser and click on one of the post titles to take a look at the detail view of the post. You should see something like this:

Figure 1.15: The page for the post’s detail view

Take a look at the URL—it should include the auto-generated post ID like/blog/1/.

The request/response cycle

Let’s review therequest/response cycle of Django with the application we built. The following schema shows a simplified example of how Django processes HTTP requests and generates HTTP responses:

Figure 1.16: The Django request/response cycle

Let’s review the Django request/response process:

  1. A web browser requests a page by its URL, for example,https://domain.com/blog/33/. The web server receives the HTTP request and passes it over to Django.
  2. Django runs through each URL pattern defined in the URL patterns configuration. The framework checks each pattern against the given URL path, in order of appearance, and stops at the first one that matches the requested URL. In this case, the pattern/blog/<id>/ matches the path/blog/33/.
  3. Django imports the view of the matching URL pattern and executes it, passing an instance of theHttpRequest class and the keyword or positional arguments. The view uses the models to retrieve information from the database. Using the Django ORM QuerySets are translated into SQL and executed in the database.
  4. The view uses therender() function to render an HTML template passing thePost object as a context variable.
  5. The rendered content is returned as aHttpResponse object by the view with thetext/html content type by default.

You can always use thisschema as the basic reference for how Django processes requests. This schema doesn’t include Django middleware for the sake of simplicity. You will use middleware in different examples of this book, and you will learn how to create custom middleware inChapter 17,Going Live.

Additional resources

The following resourcesprovide additional information related to the topics covered in this chapter:

Summary

In this chapter, you learned the basics of the Django web framework by creating a simple blog application. You designed the data models and applied migrations to the database. You also created the views, templates, and URLs for your blog.

In the next chapter, you will learn how to create canonical URLs for models and how to build SEO-friendly URLs for blog posts. You will also learn how to implement object pagination and how to build class-based views. You will also implement Django forms to let your users recommend posts by email and comment on posts.

Join us on Discord

Read this book alongside other users and the author.

Ask questions, provide solutions to other readers, chat with the author viaAsk Me Anything sessions, and much more. Scan the QR code or visit the link to join the book community.

https://packt.link/django

Left arrow icon

Page1 of 17

Right arrow icon
Download code iconDownload Code

Key benefits

  • Implement advanced functionalities, such as full-text search engines, user activity streams, payment gateways, and recommendation engines
  • Integrate JavaScript, PostgreSQL, Redis, Celery, and Memcached into your applications
  • Add real-time features with Django Channels and WebSockets

Description

Django 4 By Example is the 4th edition of the best-selling franchise that helps you build web apps. This book will walk you through the creation of real-world applications, solving common problems, and implementing best practices using a step-by-step approach.You'll cover a wide range of web app development topics as you build four different apps:A blog application: Create data models, views, and URLs and implement an admin site for your blog. Create sitemaps and RSS feeds and implement a full-text search engine with PostgreSQL.A social website: Implement authentication with Facebook, Twitter, and Google. Create user profiles, image thumbnails, a bookmarklet, and an activity stream. Implement a user follower system and add infinite scroll pagination to your website.An e-commerce application: Build a product catalog, a shopping cart, and asynchronous tasks with Celery and RabbitMQ. Process payments with Stripe and manage payment notifications via webhooks. Build a product recommendation engine with Redis. Create PDF invoices and export orders to CSV.An e-learning platform: Create a content management system to manage polymorphic content. Cache content with Memcached and Redis. Build and consume a RESTful API. Implement a real-time chat using WebSockets with ASGI. Create a production environment using NGINX, uWSGI and Daphne with Docker Compose.This is a practical book that will have you creating web apps quickly.

Who is this book for?

This book is for readers with basic Python knowledge and programmers transitioning from other web frameworks who wish to learn Django by doing. If you already use Django or have in the past, and want to learn best practices and integrate other technologies to scale your applications, then this book is for you too. This book will help you master the most relevant areas of the framework by building practical projects from scratch. Some previous knowledge of HTML and JavaScript is assumed.

What you will learn

  • Learn Django essentials, including models, ORM, views, templates, URLs, forms, authentication, signals and middleware
  • Implement different modules of the Django framework to solve specific problems
  • Integrate third-party Django applications into your project
  • Build asynchronous (ASGI) applications with Django
  • Set up a production environment for your projects
  • Easily create complex web applications to solve real use cases

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date :Aug 29, 2022
Length:766 pages
Edition :4th
Language :English
ISBN-13 :9781801810449
Vendor :
Django
Languages :
Tools :

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Product Details

Publication date :Aug 29, 2022
Length:766 pages
Edition :4th
Language :English
ISBN-13 :9781801810449
Vendor :
Django
Category :
Languages :
Concepts :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99billed monthly
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconSimple pricing, no contract
€189.99billed annually
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick iconExclusive print discounts
€264.99billed in 18 months
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick iconExclusive print discounts

Frequently bought together


Responsive Web Design with HTML5 and CSS
Responsive Web Design with HTML5 and CSS
Read more
Sep 2022504 pages
Full star icon4.5 (57)
eBook
eBook
€23.99€26.99
€33.99
Django 4 By Example
Django 4 By Example
Read more
Aug 2022766 pages
Full star icon4.6 (45)
eBook
eBook
€26.98€29.99
€37.99
Django 4 for the Impatient
Django 4 for the Impatient
Read more
Jun 2022190 pages
Full star icon3.8 (10)
eBook
eBook
€24.99€27.99
€34.99
Stars icon
Total106.97
Responsive Web Design with HTML5 and CSS
€33.99
Django 4 By Example
€37.99
Django 4 for the Impatient
€34.99
Total106.97Stars icon

Table of Contents

19 Chapters
Building a Blog ApplicationChevron down iconChevron up icon
Building a Blog Application
Installing Python
Creating a Python virtual environment
Installing Django
Django overview
Main framework components
The Django architecture
Creating your first project
Creating the blog data models
Creating an administration site for models
Working with QuerySets and managers
Building list and detail views
Creating templates for your views
The request/response cycle
Additional resources
Summary
Join us on Discord.
Enhancing Your Blog with Advanced FeaturesChevron down iconChevron up icon
Enhancing Your Blog with Advanced Features
Using canonical URLs for models
Creating SEO-friendly URLs for posts
Modifying the URL patterns
Modifying the views
Modifying the canonical URL for posts
Adding pagination
Building class-based views
Recommending posts by email
Creating a comment system
Additional resources
Summary
Extending Your Blog ApplicationChevron down iconChevron up icon
Extending Your Blog Application
Adding the tagging functionality
Retrieving posts by similarity
Creating custom template tags and filters
Adding a sitemap to the site
Creating feeds for blog posts
Adding full-text search to the blog
Additional resources
Summary
Building a Social WebsiteChevron down iconChevron up icon
Building a Social Website
Creating a social website project
Using the Django authentication framework
User registration and user profiles
Building a custom authentication backend
Additional resources
Summary
Join us on Discord.
Implementing Social AuthenticationChevron down iconChevron up icon
Implementing Social Authentication
Adding social authentication to your site
Additional resources
Summary
Sharing Content on Your WebsiteChevron down iconChevron up icon
Sharing Content on Your Website
Creating an image bookmarking website
Posting content from other websites
Creating a detail view for images
Creating image thumbnails using easy-thumbnails
Adding asynchronous actions with JavaScript
Adding infinite scroll pagination to the image list
Additional resources
Summary
Tracking User ActionsChevron down iconChevron up icon
Tracking User Actions
Building a follow system
Building a generic activity stream application
Using signals for denormalizing counts
Using Django Debug Toolbar
Counting image views with Redis
Additional resources
Summary
Building an Online ShopChevron down iconChevron up icon
Building an Online Shop
Creating an online shop project
Building a shopping cart
Registering customer orders
Asynchronous tasks
Additional resources
Summary
Join us on Discord.
Managing Payments and OrdersChevron down iconChevron up icon
Managing Payments and Orders
Integrating a payment gateway
Exporting orders to CSV files
Extending the administration site with custom views
Generating PDF invoices dynamically
Additional resources
Summary
Extending Your ShopChevron down iconChevron up icon
Extending Your Shop
Creating a coupon system
Building a recommendation engine
Additional resources
Summary
Adding Internationalization to Your ShopChevron down iconChevron up icon
Adding Internationalization to Your Shop
Internationalization with Django
Preparing your project for internationalization
Translating Python code
Translating templates
Using the Rosetta translation interface
Fuzzy translations
URL patterns for internationalization
Allowing users to switch language
Translating models with django-parler
Format localization
Using django-localflavor to validate form fields
Additional resources
Summary
Building an E-Learning PlatformChevron down iconChevron up icon
Building an E-Learning Platform
Setting up the e-learning project
Serving media files
Building the course models
Creating models for polymorphic content
Adding authentication views
Additional resources
Summary
Join us on Discord.
Creating a Content Management SystemChevron down iconChevron up icon
Creating a Content Management System
Creating a CMS
Managing course modules and their contents
Additional resources
Summary
Rendering and Caching ContentChevron down iconChevron up icon
Rendering and Caching Content
Displaying courses
Adding student registration
Accessing the course contents
Using the cache framework
Additional resources
Summary
Building an APIChevron down iconChevron up icon
Building an API
Building a RESTful API
Additional resources
Summary
Building a Chat ServerChevron down iconChevron up icon
Building a Chat Server
Creating a chat application
Real-time Django with Channels
Installing Channels
Writing a consumer
Routing
Implementing the WebSocket client
Enabling a channel layer
Modifying the consumer to be fully asynchronous
Integrating the chat application with existing views
Additional resources
Summary
Going LiveChevron down iconChevron up icon
Going Live
Creating a production environment
Using Docker Compose
Serving Django through WSGI and NGINX
Securing your site with SSL/TLS
Using Daphne for Django Channels
Creating a custom middleware
Implementing custom management commands
Additional resources
Summary
Other Books You May EnjoyChevron down iconChevron up icon
Other Books You May Enjoy
IndexChevron down iconChevron up icon
Index

Recommendations for you

Left arrow icon
Full-Stack Flask and React
Full-Stack Flask and React
Read more
Oct 2023408 pages
Full star icon3.8 (5)
eBook
eBook
€20.99€23.99
€29.99
C# 13 and .NET 9 – Modern Cross-Platform Development Fundamentals
C# 13 and .NET 9 – Modern Cross-Platform Development Fundamentals
Read more
Nov 2024828 pages
Full star icon4.4 (5)
eBook
eBook
€26.98€29.99
€37.99
Real-World Web Development with .NET 9
Real-World Web Development with .NET 9
Read more
Dec 2024578 pages
Full star icon3.5 (4)
eBook
eBook
€26.98€29.99
€37.99
Django 5 By Example
Django 5 By Example
Read more
Apr 2024820 pages
Full star icon4.6 (41)
eBook
eBook
€26.98€29.99
€37.99
React and React Native
React and React Native
Read more
Apr 2024518 pages
Full star icon4.3 (10)
eBook
eBook
€23.99€26.99
€32.99
Scalable Application Development with NestJS
Scalable Application Development with NestJS
Read more
Jan 2025612 pages
Full star icon4.5 (6)
eBook
eBook
€20.99€23.99
€29.99
C# 12 and .NET 8 – Modern Cross-Platform Development Fundamentals
C# 12 and .NET 8 – Modern Cross-Platform Development Fundamentals
Read more
Nov 2023828 pages
Full star icon4.4 (74)
eBook
eBook
€31.99€35.99
€44.99
Responsive Web Design with HTML5 and CSS
Responsive Web Design with HTML5 and CSS
Read more
Sep 2022504 pages
Full star icon4.5 (57)
eBook
eBook
€23.99€26.99
€33.99
Modern Full-Stack React Projects
Modern Full-Stack React Projects
Read more
Jun 2024506 pages
Full star icon4.8 (9)
eBook
eBook
€23.99€26.99
€33.99
Learning Angular
Learning Angular
Read more
Jan 2025494 pages
Full star icon4.1 (7)
eBook
eBook
€23.99€26.99
€33.99
Right arrow icon

Customer reviews

Top Reviews
Rating distribution
Full star iconFull star iconFull star iconFull star iconHalf star icon4.6
(45 Ratings)
5 star82.2%
4 star11.1%
3 star0%
2 star2.2%
1 star4.4%
Filter icon Filter
Top Reviews

Filter reviews by




RobertJan 09, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
This book does a great job of walking the reader step-by-step through through several sizeable Django projects. I did not have any background in Django prior to reading this and found it fairly easy to contextually figure a lot of things out. This is a great resource for anyone who learns by doing or just wants to build some larger scale projects than what most introductory books on Django would deal with.
Subscriber reviewPackt
N/AJan 29, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Feefo Verified reviewFeefo
MaeSep 21, 2022
Full star iconFull star iconFull star iconFull star iconFull star icon5
The media could not be loaded. This book is the most practical resource to learn Django. The book teaches you Django by building 4 complete projects that include integration with other technologies like Redis, Celery, Memcached and multiple Python libraries and third-party Django applications.This book does the best job covering the basics of Django and much more than that. The book is easy to follow but assumes you some basic Python and web development knowledge (HTML, CSS, JavaScript). I love the examples to create a recommendation engine, a Facebook-like user activity feed and real-time async chat application using channels.
Amazon Verified reviewAmazon
A. J. SalazarSep 02, 2022
Full star iconFull star iconFull star iconFull star iconFull star icon5
With a wide range of practical applications and in depth code implementation, this book is a must-have for the aspiring Django pros.
Amazon Verified reviewAmazon
Nina OrtegaDec 19, 2022
Full star iconFull star iconFull star iconFull star iconFull star icon5
For people like me, who learn best from reading instructions, this is the perfect all-inclusive, detailed, and clear manual on how to learn and code with Django.Although the technical jargon can be difficult at the beginning it is worth the effort.Definitely something worth spending money on.
Amazon Verified reviewAmazon
  • Arrow left icon Previous
  • 1
  • 2
  • 3
  • 4
  • 5
  • ...
  • Arrow right icon Next

People who bought this also bought

Left arrow icon
C# 11 and .NET 7 – Modern Cross-Platform Development Fundamentals
C# 11 and .NET 7 – Modern Cross-Platform Development Fundamentals
Read more
Nov 2022818 pages
Full star icon4.1 (54)
eBook
eBook
€26.98€29.99
€37.99
C# 12 and .NET 8 – Modern Cross-Platform Development Fundamentals
C# 12 and .NET 8 – Modern Cross-Platform Development Fundamentals
Read more
Nov 2023828 pages
Full star icon4.4 (74)
eBook
eBook
€31.99€35.99
€44.99
Responsive Web Design with HTML5 and CSS
Responsive Web Design with HTML5 and CSS
Read more
Sep 2022504 pages
Full star icon4.5 (57)
eBook
eBook
€23.99€26.99
€33.99
React and React Native
React and React Native
Read more
May 2022606 pages
Full star icon4.6 (17)
eBook
eBook
€26.98€29.99
€37.99
Building Python Microservices with FastAPI
Building Python Microservices with FastAPI
Read more
Aug 2022420 pages
Full star icon3.9 (9)
eBook
eBook
€25.99€28.99
€35.99
Right arrow icon

About the author

Profile icon Antonio Melé
Antonio Melé
LinkedIn iconGithub icon
Antonio Melé has been crafting Django projects since 2006, for clients spanning multiple industries. He is Engineering Director at Backbase, a leading global fintech firm dedicated to facilitating the digital transformation of financial institutions. He co-founded Nucoro, a digital wealth management platform.In 2009 Antonio founded Zenx IT, a company specialized in developing digital products. He has been working as CTO and consultant for several tech-centric startups. He has also managed development teams building projects for large enterprise clients. He has an MSc in Computer Science from Universidad Pontificia Comillas and completed the Advanced Management Program at MIT Sloan. His father inspired his passion for computers and coding.
Read more
See other products by Antonio Melé
Getfree access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook?Chevron down iconChevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website?Chevron down iconChevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook?Chevron down iconChevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support?Chevron down iconChevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks?Chevron down iconChevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook?Chevron down iconChevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.


[8]ページ先頭

©2009-2025 Movatter.jp