Django
Django is a high-level Python web framework used for building web applications quickly and easily. It provides a variety of tools and libraries for handling common web development tasks, such as managing databases, handling user authentication and permissions, and handling requests and responses.
Django follows the Model-View-Controller (MVC) architectural pattern, and provides an Object-Relational Mapping (ORM) system that allows developers to work with databases using Python objects. This makes it easy to create and manage databases and data models in web applications.
Django also includes a variety of built-in tools for handling common web development tasks, such as managing user authentication and permissions, handling forms and input validation, and handling static and media files. It also includes a powerful templating system that makes it easy to create dynamic and responsive web pages.
Django is a popular choice for web development in Python due to its ease of use, flexibility, and powerful features. It is used by many organizations and companies for building web applications, from small startups to large-scale enterprise applications.
MTV architecture
In a model-template-views pattern as used in Django, the model is used to interact with a database, the templates are used to define the rendered HTML, and the views are used as a glue between them, doing the processing. Other useful tools are forms, that define a way to quickly validate data coming from the outside, and the admin site that allows to easily browse the data contained in the models once configured.
Django can also be used as a backend REST server, usually with the help of Django REST framework that provides tools to easily define a REST API without much more code than the models (if the API is simple).
Basic Usage
Create Project
To create a mysite
project, run :
django-admin startproject mysite
This command will create the following directory structure :
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
Create App
To create a polls
app, run in the mysite
folder :
./manage.py startapp polls
This command will create the following directory structure :
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
urls.py
views.py
Run development Server
./manage.py runserver
This launches a development server at http://localhost:8000/
by default.
A useful tool for development is the Django debug toolbar that allows to easily see what route, view and SQL was used for requests. It adds a sidebar to every HTML page that includes a </body>
tag.
To get debug information about pages without a closing </body>
tag, you can use the history tab in the toolbar of another page running on the same development server.
Create a model
Every model class corresponds to a table in your database. A primary key is created automatically, named id
and of type BigIntegerField
. It is used for relations created with ForeignKey
, OneToOneField
and ManyToManyField
.
A simple model looks like this:
from django.db import models
class Book(models.Model):
# define the fields here
title = models.CharField(max_length=255)
page_count = models.PositiveIntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2, null=True)
personal_comment = models.TextField(blank=True)
DecimalField
are nice to get exact fractional values that cannot be represented by floating point numbers. They are fixed point numbers and require the decimal place to be fixed in place.
The null
parameter is False
by default. To allow the value to be a SQL NULL
, aka python's None
, you need to add null=True
to the field definition.
For textual fields, the blank
parameter allows the value to be the empty string, it is False
by default. It is not recommended to use both null=True
and blank=True
on a field as there are then two representation of "empty" for that field, which makes it harder to query for empty values.
After editing any model you need to create the migration files by running:
./manage.py makemigrations
You then need to apply all created migrations to the database by running the following command:
./manage.py migrate
Foreign keys
When referencing a model in another model, one might use a foreign key field. In the following example, Authors write Articles, Articles are created in different Categories, and Comments are made to Articles.
class Author(models.Model):
name = models.CharField(max_length=255)
class Category(models.Model):
title = models.CharField(max_length=255)
class Article(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
author = models.ForeignKey(Category, null=True on_delete=models.SET_NULL)
class Comment(models.Model):
content = models.CharField(max_length=255)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
We expect different behaviors when the referenced object is deleted.
SET_NULL
: When anAuthor
is deleted, we want to keep any article referencing that author as an authorless article. TheArticle
author field is set tonull
, indicating an unknown author.CASCADE
: When anArticle
is deleted, the associated comments are meaningless : anyComment
referencing this article therefore self-destructs.PROTECT
: When a category is deleted, anyArticle
referencing thisCategory
will prevent the deletion of the said category.
More actions are possible for more specific situations.
Simple Lookups
Django filter
method take one or more Field lookup as an argument.
From django docs : Multiple parameters are joined via AND in the underlying SQL statement.
Book.objects.filter(price=12.56) # price == 12.56
Book.objects.filter(price__range=(10, 15)) # 10 <= price <= 15
Book.objects.filter(price__gte=15) # price <= 15
# price > 15, and no title ending with a question mark
Book.objects.filter(price__lt=15).exclude(title__endswith="?")
# price > 10 AND price < 15
Book.objects.filter(price__gt=10, price__lt=15)
# Title contains "nuit", case insensitive.
Book.objects.filter(title__icontains="nuit")
More complex lookups
Using Q objects is the recommended way of doing more complex lookups.
# A cheap book (price<3) OR a small book (page_count<50)
# That starts with "The tales of..."
Book.objects.filter(
Q(page_count__lt=50) | Q(price__lt=2),
title__startswith="The tales of"
)
From django docs : Lookup functions can mix the use of Q objects and keyword arguments. All arguments provided to a lookup function (be they keyword arguments or Q objects) are “AND”ed together. However, if a Q object is provided, it must precede the definition of any keyword arguments.
The Django template engine
Django has its own template engine that is very similar to Jinja. See the Jinja cheatsheet for more info about the template syntax.
Some features from Jinja are not available, notably the ability to remove whitespace before and after jinja tags with the -
prefix/suffix. It is possible to use the Jinja engine instead of the Django engine by changing the template configuration in the settings.