Django

Topics related to Django:

Getting started with Django

Django advertises itself as "the web framework for perfectionists with deadlines" and "Django makes it easier to build better Web apps more quickly and with less code". It can be seen as an MVC architecture. At it's core it has:

  • a lightweight and standalone web server for development and testing
  • a form serialization and validation system that can translate between HTML forms and values suitable for storage in the database
  • a template system that utilizes the concept of inheritance borrowed from object-oriented programming
  • a caching framework that can use any of several cache methods support for middleware classes that can intervene at various stages of request processing and carry out custom functions
  • an internal dispatcher system that allows components of an application to communicate events to each other via pre-defined signals
  • an internationalization system, including translations of Django's own components into a variety of languages
  • a serialization system that can produce and read XML and/or JSON representations of Django model instances
  • a system for extending the capabilities of the template engine
  • an interface to Python's built in unit test framework

Context Processors

Use context processors to add variables that are accessible anywhere in your templates.

Specify a function, or functions that return dicts of the variables you want, then add those functions to TEMPLATE_CONTEXT_PROCESSORS.

Templating

Models

Settings

Migrations

Extending or Substituting User Model

Forms

Administration

Class based views

When using CBV we often need to know exactly what methods we can overwrite for each generic class. This page of the django documentation lists all the generic classes with all of their methods flattened and the class attributes we can use.

In addition, Classy Class Based View website provides the same information with a nice interactive interface.

Form Widgets

Logging

Unit Testing

Querysets

Authentication Backends

Template Tags and Filters

Custom Managers and Querysets

Management Commands

Management commands can be called either from:

  • django-admin <command> [options]
  • python -m django <command> [options]
  • python manage.py <command> [options]
  • ./manage.py <command> [options] if manage.py has execution permissions (chmod +x manage.py)

To use management commands with Cron:

*/10 * * * * pythonuser /var/www/dev/env/bin/python /var/www/dev/manage.py <command> [options] > /dev/null

ArrayField - a PostgreSQL-specific field

Note that although the size parameter is passed to PostgreSQL, PostgreSQL will not enforce it.

When using ArrayFields one should keep in mind this word of warning from the Postgresql arrays documentation.

Tip: Arrays are not sets; searching for specific array elements can be a sign of database misdesign. Consider using a separate table with a row for each item that would be an array element. This will be easier to search, and is likely to scale better for a large number of elements.

Middleware

JSONField - a PostgreSQL specific field

Many-to-many relationships

Signals

Now, the details.

Django signals is a way to inform your app of certain tasks (such as a model pre- or post-save or delete) when it takes place.

These signals allow you to perform actions of your choice immediately that signal is released.

For instance, anytime a new Django User is created, the User Model releases a signal, with associating params such as sender=User allowing you to specifically target your listening of signals to a specific activity that happens, in this case, a new user creation.

In the above example, the intention is to have a UserProfile object created, immediately after a User object is created. Therefore, by listening to a post_save signal from the User model (the default Django User Model) specifically, we create a UserProfile object just after a new User is created.

The Django Documentation provides extensive documentation on all the possible signals available.

However, the above example is to explain in practical terms a typical use case when using Signals can be a useful addition.

"With great power, comes great responsibility". It can be tempting to having signals scattered across your entire app or project just because they're awesome. Well, Don't. Because they're cool doesn't make them the go-to solution for every simple situation that comes to mind.

Signals are great for, as usual, not everything. Login/Logouts, signals are great. Key models releasing signs, like the User Model, if fine.

Creating signals for each and every model in your app can get overwhelming at a point, and defeat the whole idea of the sparring use of Django Signals.

Do not use signals when (based on Two Scoops of Django book):

  • The signal relates to one particular model and can be moved into one of that model’s methods, possibly called by save().
  • The signal can be replaced with a custom model manager method.
  • The signal relates to a particular view and can be moved into that view

It might be okay to use signals when:

  • Your signal receiver needs to make changes to more than one model.
  • You want to dispatch the same signal from multiple apps and have them handled the same way by a common receiver.
  • You want to invalidate a cache after a model save.
  • You have an unusual scenario that needs a callback, and there’s no other way to handle it besides using a signal. For example, you want to trigger something based on the save() or init() of a third-party app's model. You can't modify the third-party code and extending it might be impossible, so a signal provides a trigger for a callback.

Internationalization

RangeFields - a group of PostgreSQL specific fields

Mapping strings to strings with HStoreField - a PostgreSQL specific field

F() expressions

Deployment

Security

URL routing

Database Routers

Model Field Reference

  • You can write your own fields if you find it necessary
  • You can override functions of the base model class, most commonly the save() function

Model Aggregations

Using Redis with Django - Caching Backend

Using django-redis-cache or django-redis are both effective solutions for storing all cached items. While it is certainly possible for Redis to be setup directly as a SESSION_ENGINE, one effective strategy is to setup the caching (as above) and declare your default cache as a SESSION_ENGINE. While this is really the topic for another documentaiton article, its relevance leads to inclusion.

Simply add the following to settings.py:

SESSION_ENGINE = "django.contrib.sessions.backends.cache"

Project Structure

Django and Social Networks

Database Setup

Debugging

Pdb

Pdb can also print out all existing variables in global or local scope, by typing globals() or locals() in (Pdb) prompt respectively.

Meta: Documentation Guidelines

This is an extension of Python's "Meta: Documentation Guidelines" for Django.

These are just proposals, not recommendations. Feel free to edit anything here if you disagree or have something else to mention.

How to use Django with Cookiecutter?

Async Tasks (Celery)

Celery is a task queue which can run background or scheduled jobs and integrates with Django pretty well. Celery requires something known as message broker to pass messages from invocation to the workers. This message broker can be redis, rabbitmq or even Django ORM/db although that is not a recommended approach.

Before you get started with the example, You will have to configure celery. To configure celery, create a celery_config.py file in the main app, parallel to the settings.py file.

from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings

# broker url 
BROKER_URL = 'redis://localhost:6379/0'

# Indicate Celery to use the default Django settings module
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')

app = Celery('config')
app.config_from_object('django.conf:settings')
# if you do not need to keep track of results, this can be turned off
app.conf.update(
    CELERY_RESULT_BACKEND=BROKER_URL,
)

# This line will tell Celery to autodiscover all your tasks.py that are in your app folders
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

And in the main app's __init__.py file import the celery app. like this

# -*- coding: utf-8 -*- 
# Not required for Python 3. 
from __future__ import absolute_import

from .celery_config import app as celery_app  # noqa

To run celery worker, use this command at the level where manage.py is.

# pros is your django project, 
celery -A proj worker -l info

Database transactions

Django from the command line.

While Django is primarily for web apps it has a powerful and easy to use ORM that can be used for command line apps and scripts too. There are two different approaches that can be used. The first being to create a custom management command and the second to initialize the Django environment at the start of your script.

Continuous Integration With Jenkins

Formsets

django-filter

Running Celery with Supervisor

CRUD in Django

Django Rest Framework

Views

Generic Views

These examples show that generic views generally make standardized tasks much simpler. Instead of programming everything from scratch, you configure what other people have already programmed for you. This makes sense in many situations, as it allows you concentrate more on the design of your projects rather than the processes in the background.

So, should you always use them? No. They only make sense as long as your tasks are fairly standardizes (loading, editig, deleting objects) and the more repetitive your tasks are. Using one specific generic view only once and then override all its methods to perform very speficic tasks may not make sense. You may be better off with a functional view here.

However, if you have plenty of views that require this functionality or if your tasks match excatly the defined tasks of a specific generic view, then generic views are exactly what you need in order to make your life simpler.

How to reset django migrations

Timezones