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:
Use context processors to add variables that are accessible anywhere in your templates.
Specify a function, or functions that return dict
s of the variables you want, then add those functions to TEMPLATE_CONTEXT_PROCESSORS
.
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.
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
Note that although the size
parameter is passed to PostgreSQL, PostgreSQL will not enforce it.
When using ArrayField
s 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 needs to be added to your settings.py MIDDLEWARE_CLASSES
list before it will be included in execution. The default list that Django provides when creating a new project is as follows:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
These are all functions that will run in order on every request (once before it reaches your view code in views.py
and once in reverse order for process_response
callback, before version 1.10). They do a variety of things such as injecting the Cross Site Request Forgery (csrf) token.
The order matters because if some middleware does a redirect, then the all the subsequent middleware will never run. Or if a middleware expects the csrf token to be there, it has to run after the CsrfViewMiddleware
.
Django's JSONField
actually stores the data in a Postgres JSONB
column, which is only available in Postgres 9.4 and later.
JSONField
is great when you want a more flexible schema. For example if you want to change the keys without having to do any data migrations, or if not all your objects have the same structure.
If you're storing data with static keys, consider using multiple normal fields instead of JSONField
s instead, as querying JSONField
can get quite tedious sometimes.
You can chain queries together. For example, if a dictionary exists inside a list, add two underscores and your dictionary query.
Don't forget to separate queries with double underscores.
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):
save()
.It might be okay to use signals when:
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.save()
functionUsing 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"
Pdb
Pdb can also print out all existing variables in global or local scope, by typing globals()
or locals()
in (Pdb) prompt respectively.
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.
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
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.
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.