Web Application Development

Jakub Klinkovský

:: Czech Technical University in Prague
:: Faculty of Nuclear Sciences and Physical Engineering
:: Department of Software Engineering

Academic Year 2024-2025

Django Framework

Django – Overview

Django is a framework for developing web applications based on the Python language.

Provided features:

  • URL mapping (routing)
  • templates
  • forms
  • databases (models)
  • user authentication and authorization, administrative interface
  • creation of multilingual pages (internationalization)
  • security features

Django – Installation

One of the following commands (depending on the Python installation):

  • pip install django – if the pip command is available
  • pip3 install django – if the pip3 command is available
  • python -m pip install django – using the pip module
  • py -m pip install django – if the Python interpreter is available as py

Verification:

  • django-admin --version command in the terminal,
  • or python -m django --version command – using the django module,
  • or py -m django --version command – if the Python interpreter is available as py instead of python

Note: after the installation, it may be necessary (e.g. in Windows) to close the terminal and open a new one

Django – Creating a Project

In the directory where you want to create the project, run the command:

django-admin startproject mysite

Note: If the django-admin command is not available, the same can be achieved using the django module:

python -m django startproject mysite

Alternatively, use python3 or py instead of python.

Project Structure

The startproject command creates the following file structure:

mysite/
├── manage.py
└── mysite
    ├── asgi.py
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Note on directory names:

  • The outer mysite directory represents the entire project, and the name can be easily changed at any time.
  • The inner mysite directory contains the project configuration, and it is not easy to change the name after generation (it is used in the created files).

Role of the default files in the project

  • manage.py: program/script for project management
  • mysite/__init__.py: an empty file that marks the given directory as a package for the Python language
  • mysite/settings.py: file with project configuration
  • mysite/urls.py: file with declarations that map URLs to Python functions
  • mysite/asgi.py: entry script for the web server using the ASGI standard
  • mysite/wsgi.py: entry script for the web server using the WSGI standard

Adding an Application to the Project

A Django project consists of several applications (app) that can represent, for example, complete components of a web application.

An application named demo is created using the manage.py script:

python manage.py startapp demo

Alternatively, use python3 or py instead of python.

Note: the command must be run in the project directory, i.e. the outer mysite directory.

Project Structure with an Application

The previous command creates the demo directory in the outer mysite directory:

mysite/
├── manage.py
├── mysite
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── demo
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

Running the Development Server

Using the manage.py script, run the runserver subcommand:

python manage.py runserver

The web server starts and the empty application is available at the default address http://localhost:8000/

Note: This web server is intended for development and not for production deployment. It is not very efficient, but it provides useful features that facilitate programming the application (e.g. automatic refresh/restart of the application after changes in the code).

Note: After starting, a __pycache__ directory is created in the project, which contains pre-compiled files (bytecode) for more efficient application execution.

Components of the Django Framework

Diagram of Request Processing and Response Creation

center

Further access directly to the disk (uploaded files), static files (CSS, JS), ...

Django Middleware

Middleware in the Django framework refers to a piece of code that stands between the application's own code and the outside world. It handles pre-processing and post-processing of requests/responses.

Individual middleware are ordered and processing occurs as follows:

center

More About Middleware

Important information from the Middleware documentation:

  • configuration in the settings.py file – MIDDLEWARE list
  • order matters – see recommendations for built-in middleware
  • middleware can interrupt sequential traversal and return HttpResponse in the process_view method – then the next middleware and view function are not called, and the process_response method is called
  • the process_exception method is called only if an exception occurs in the view
  • the process_template_response method is called only if the object returned from the view function has a render method – e.g. TemplateResponse (allows modifying rendering in decorators or in middleware)
  • it is possible to define custom middleware (if decorators for the view function are not sufficient...)

URL Dispatcher

The URLconf module is responsible for mapping URLs to the correct view function.

  • settings.py file – ROOT_URLCONF parameter (in our case mysite.urls)
  • the urlpatterns variable is used from the set module, e.g.:
    urlpatterns = [
        path("articles/2003/", views.special_case_2003),
        path("articles/<int:year>/", views.year_archive),
        path("articles/<int:year>/<int:month>/", views.month_archive),
        path("articles/<int:year>/<int:month>/<slug:slug>/", views.article_detail),
    ]
    
  • the listed patterns are processed sequentially, the first successful one is used
  • only the path part of the URL part is compared (parts like query string are ignored)
  • the path() function processes simple patterns,
    the re_path() function processes regular expressions
  • it is possible to recursively reference other urls modules (e.g. in applications)

URL Dispatcher – Example

views.py:

from django.http import HttpResponse

def index(request):
    return HttpResponse("<b>Hello, world!</b>")

urls.py:

from django.contrib import admin
from django.urls import path

from demo import views

urlpatterns = [
    path("", views.index),
    path('admin/', admin.site.urls),
]

Task 1

Modify the index view in the demo application to display the current date and time (according to the server's processing of the request).

Bonus: Also display the holiday corresponding to the given day.

HTTP Protocol in the Django Framework

HttpRequest and HttpResponse Objects

The index function from slide 16 has a request parameter (an object of type HttpRequest), and returns an object of type HttpResponse.

These objects are used to abstract data transmitted using the HTTP(S) protocol.

More information about the objects in the Django documentation.

Attributes of the HttpRequest Object

Only read-only attributes:

  • HttpRequest.scheme – request scheme (typically "http" or "https")
  • HttpRequest.method – HTTP protocol method (e.g. "GET" or "POST")
  • HttpRequest.path –the path to the given document (part of the URL)
  • HttpRequest.GET – dictionary with parameters sent using the GET method
    (corresponds to the so-called query string part of the URL: e.g. ?a=123&b=4)
  • HttpRequest.POST – dictionary with parameters sent using the POST method
    (typically encoded in the request body, Django takes care of the decoding)
  • HttpRequest.headers – dictionary with request headers (case-insensitive keys)
  • others: HttpRequest.COOKIES, HttpRequest.FILES, HttpRequest.META

Parameters of the HttpResponse Object

Shape of the constructor of the object:

HttpResponse.__init__(content=b'', content_type=None, status=None, reason=None, charset=None, headers=None)
  • content – response body (typically a string containing the document in the HTML format)
  • content_type – default value "text/html; charset=utf-8"
  • status – status code (number or object http.HTTPStatus)
  • reason – status phrase of the response (default value is selected according to the status code)
  • charset – response encoding (default value is parsed from content_type)
  • headers – dictionary with response headers

Methods of the HttpResponse Object

  • HttpResponse.write() – used to gradually construct the response body, e.g.:
    response = HttpResponse()
    response.write("<p>Here's the text of the web page.</p>")
    response.write("<p>Here's another paragraph.</p>")
    
  • [] operator – used to manipulate response headers, e.g.:
    response = HttpResponse()
    if "Age" not in response:
        response["Age"] = 120
    if "Expires" in response:
        del response["Expires"]
    
  • others: see documentation

Demo: Displaying Request Information

A function that sends data received in the request in the response.

Django Template System

Template System for Document Creation

  • creating an HTML document by gradually constructing a string is cumbersome and error-prone (in previous examples, we also did not construct the entire HTML document, but only the <body> part)
  • to simplify the development, web frameworks typically provide some way of creating documents based on templates, into which dynamic content is added
  • in the Django framework, you can use either Django template language or Jinja2
  • principle: separation of presentation (document structure) from program logic

Adding a Template to Your Own Application

  1. Create a directory for templates: it is demo/templates/demo/ for the demo application (the inner demo directory allows for namespacing templates specific to the given application using a relative path with respect to templates)
  2. Create templates, e.g. base.html and some_page.html:
    └── demo
        ├── admin.py
        ├── apps.py
        ├── __init__.py
        ├── migrations
        │   ├── __init__.py
        ├── models.py
        ├── templates
        │   └── demo
        │       ├── base.html
        │       └── some_page.html
        ├── tests.py
        └── views.py
    

Adding a Template to Your Own Application

  1. In the settings.py file, register the given application, e.g.
    INSTALLED_APPS = [
        "demo",
        ...
    ]
    
  2. In the views.py file, use the given template using the render() function, e.g.
    from django.shortcuts import render
    
    def some_page(request):
        context = {
            "some_parameters": {"key": "value"},
        }
        return render(request, "demo/some_page.html", context)
    

Example – base.html Template

{% load static %}

<!DOCTYPE html>
<html lang="{{ lang | default:'en' }}">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{% block title %}{% endblock %}</title>
        <link rel="stylesheet" type="text/css" href="{% static "demo/demo.css" %}">
        {% block head %}
        {% endblock %}
    </head>
    <body>
        <header>
            <nav>
                <a href="{% url 'some_page' %}">Home</a>
                <a href="{% url 'some_page' %}/subpage-1">Subpage 1</a>
                <a href="{% url 'some_page' %}/subpage-2">Subpage 2</a>
            </nav>
        </header>
        <main id="content">
            {% block content %}
            <article id="content-left">
                {% block content_left %}
                {% endblock %}
            </article>
            <aside id="sidebar">
                {% block sidebar %}
                {% endblock %}
            </aside>
            {% endblock %}
        </main>
        <footer>
            <p>Powered by <a href="https://www.djangoproject.com/">Django</a>.</p>
        </footer>
    </body>
</html>

Example – some_page.html Template

{% extends "demo/base.html" %}
{% load static %}

{% block title %}
Some page title
{% endblock %}

{% block head %}
    <link rel="stylesheet" type="text/css" href="{% static 'demo/some_page.css' %}">
{% endblock %}

{% block content %}
<article>
<section>
    <p>Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. ...</p>
    <p>At solmen va esser necessi far uniform grammatica, pronunciation e plu commun paroles. ...</p>
</section>
<section>
    <h2>Using Variables in the Template</h2>
    <dl>
    {% for key, value in some_parameters.items %}
        <dt>{{ key }}</dt>
        <dd>{{ value }}</dd>
    {% endfor %}
    </dl>
</section>
</article>
{% endblock %}

Syntax of the Django Template Language

  1. Variables: {{ variable }}, {{ object.attribute }}, etc.
  2. Filters: {{ value|default:"nothing" }}, {{ value|filesizeformat }}, etc.
    See list of built-in filters
  3. Tags: {% tag %}, where tag is e.g. extends, loads, block, for, if, ...
    See list of built-in tags
  4. Comments: {# this is a comment #}
  5. Inheritance: using the extends and block tags (see previous examples)
  6. Automatic HTML Escaping – can be disabled using a filter ({{var|safe}}) or using a tag ({% autoescape off %} ... {% endautoescape %})

For more details, see the documentation.

Adding Static Files to Your Own Application

  1. Create a directory for static files: similar to templates, for the demo application, it is demo/static/demo/ (the inner demo directory allows for unambiguous identification of static files of the given application using a relative path with respect to static, e.g. demo/some_page.css)
  2. Create static files, e.g. demo/static/demo/some_page.css
  3. Use static files in the appropriate templates, e.g.
    {% load static %}
    
    ...
    <link rel="stylesheet" type="text/css" href="{% static "demo/some_page.css" %}">
    ...
    
  4. For deploying the website in practice, additional steps are required, which we will not cover here.

Task 2

Add the following to the Django demo application:

  • at least 2 different functions in views.py with corresponding mapping in urls.py, where at least 1 function receives parameters from the URL using simple patterns or regular expressions
  • at least 2 templates connected using inheritance
  • all pages contain a navigation menu with a link to the main page ("home") using the url tag: e.g. <a href="{% url 'some_page' %}">Home</a>
  • all pages use semantic tags (main, article, section, etc.)
  • all elements are styled appropriately using CSS

Task 3

On one of the previous pages, practice generating "dynamic" content:

  • in the function in the views.py file, create appropriate data structures, e.g. a list of strings, a dictionary, a list of dictionaries, etc.
  • pass these structures as variables to a certain template
  • in the template, convert the data to HTML format – create at least one numbered list, at least one definition list (the <dl> tag), and at least one table
  • style all elements appropriately using CSS

according to headers)