Django Documentation

Release 1.9.9.dev20160729020115

Django Software Foundation and contributors

Jul 29, 2016

Django documentation contents

- Getting started

- Django at a glance

- Design your model

- Install it

- Enjoy the free API

- A dynamic admin interface: it’s not just scaffolding – it’s the whole house

- Design your URLs

- Write your views

- Design your templates

- This is just the surface

- Quick install guide

- Install Python

- Set up a database

- Remove any old versions of Django

- Install Django

- Verifying

- That’s it!

- Writing your first Django app, part 1

- Creating a project

- The development server

- Creating the Polls app

- Write your first view

- Writing your first Django app, part 2

- Database setup

- Creating models

- Activating models

- Playing with the API

- Introducing the Django Admin

- Writing your first Django app, part 3

- Overview

- Writing more views

- Write views that actually do something

- Raising a 404 error

- Use the template system

- Removing hardcoded URLs in templates

- Namespacing URL names

- Writing your first Django app, part 4

- Write a simple form

- Use generic views: Less code is better

- Writing your first Django app, part 5

- Introducing automated testing

- Basic testing strategies

- Writing our first test

- Test a view

- When testing, more is better

- Further testing

- What’s next?

- Writing your first Django app, part 6

- Customize your app’s look and feel

- Adding a background-image

- Writing your first Django app, part 7

- Customize the admin form

- Adding related objects

- Customize the admin change list

- Customize the admin look and feel

- Customize the admin index page

- What’s next?

- Advanced tutorial: How to write reusable apps

- Reusability matters

- Your project and your reusable app

- Installing some prerequisites

- Packaging your app

- Using your own package

- Publishing your app

- Installing Python packages with virtualenv

- What to read next

- Finding documentation

- How the documentation is organized

- How documentation is updated

- Where to get it

- Differences between versions

- Writing your first patch for Django

- Introduction

- Code of Conduct

- Installing Git

- Getting a copy of Django’s development version

- Rolling back to a previous revision of Django

- Running Django’s test suite for the first time

- Writing some tests for your ticket

- Writing the code for your ticket

- Running Django’s test suite for the second time

- Writing Documentation

- Generating a patch for your changes

- So what do I do next?

- Using Django

- How to install Django

- Install Python

- Install Apache and mod_wsgi

- Get your database running

- Remove any old versions of Django

- Install the Django code

- Models and databases

- Models

- Making queries

- Aggregation

- Managers

- Performing raw SQL queries

- Database transactions

- Multiple databases

- Tablespaces

- Database access optimization

- Examples of model relationship API usage

- Handling HTTP requests

- URL dispatcher

- Writing views

- View decorators

- File Uploads

- Django shortcut functions

- Generic views

- Middleware

- How to use sessions

- Working with forms

- HTML forms

- Django’s role in forms

- Forms in Django

- Building a form

- More about Django Form classes

- Working with form templates

- Further topics

- Templates

- Support for template engines

- The Django template language

- Class-based views

- Introduction to class-based views

- Built-in class-based generic views

- Form handling with class-based views

- Using mixins with class-based views

- Basic examples

- Simple usage in your URLconf

- Subclassing generic views

- Migrations

- The Commands

- Backend Support

- Workflow

- Dependencies

- Migration files

- Adding migrations to apps

- Historical models

- Considerations when removing model fields

- Data Migrations

- Squashing migrations

- Serializing values

- Supporting Python 2 and 3

- Supporting multiple Django versions

- Managing files

- Using files in models

- The File object

- File storage

- Testing in Django

- Writing and running tests

- Testing tools

- Advanced testing topics

- User authentication in Django

- Overview

- Installation

- Usage

- Django’s cache framework

- Setting up the cache

- The per-site cache

- The per-view cache

- Template fragment caching

- The low-level cache API

- Downstream caches

- Using Vary headers

- Controlling cache: Using other headers

- Order of MIDDLEWARE_CLASSES

- Conditional View Processing

- The condition decorator

- Shortcuts for only computing one value

- Using the decorators with other HTTP methods

- Comparison with middleware conditional processing

- Cryptographic signing

- Protecting the SECRET_KEY

- Using the low-level API

- Sending email

- Quick example

- send_mail()

- send_mass_mail()

- mail_admins()

- mail_managers()

- Examples

- Preventing header injection

- The EmailMessage class

- Email backends

- Configuring email for development

- Internationalization and localization

- Overview

- Definitions

- Logging

- A quick logging primer

- Using logging

- Configuring logging

- Django’s logging extensions

- Django’s default logging configuration

- Pagination

- Example

- Using Paginator in a view

- Paginator objects

- InvalidPage exceptions

- Page objects

- Porting to Python 3

- Philosophy

- Porting tips

- Coding guidelines

- Security in Django

- Cross site scripting (XSS) protection

- Cross site request forgery (CSRF) protection

- SQL injection protection

- Clickjacking protection

- SSL/HTTPS

- Host header validation

- Session security

- User-uploaded content

- Additional security topics

- Performance and optimization

- Introduction

- General approaches

- Caching

- Understanding laziness

- Databases

- HTTP performance

- Template performance

- Using different versions of available software

- Serializing Django objects

- Serializing data

- Deserializing data

- Serialization formats

- Natural keys

- Django settings

- The basics

- Designating the settings

- Default settings

- Using settings in Python code

- Altering settings at runtime

- Security

- Available settings

- Creating your own settings

- Using settings without setting DJANGO_SETTINGS_MODULE

- Signals

- Listening to signals

- Defining and sending signals

- Disconnecting signals

- System check framework

- Writing your own checks

- External packages

- Localflavor

- Comments

- Formtools

- “How-to” guides

- Authentication using REMOTE_USER

- Configuration

- Using REMOTE_USER on login pages only

- Writing custom django-admin commands

- Accepting optional arguments

- Management commands and locales

- Testing

- Command objects

- Writing custom model fields

- Introduction

- Background theory

- Writing a field subclass

- Writing a FileField subclass

- Custom Lookups

- A simple lookup example

- A simple transformer example

- Writing an efficient abs__lt lookup

- A bilateral transformer example

- Writing alternative implementations for existing lookups

- How Django determines the lookups and transforms which are used

- Custom template tags and filters

- Code layout

- Writing custom template filters

- Writing custom template tags

- Writing a custom storage system

- Deploying Django

- How to deploy with WSGI

- Deployment checklist

- Upgrading Django to a newer version

- Required Reading

- Dependencies

- Resolving deprecation warnings

- Installation

- Testing

- Deployment

- Error reporting

- Email reports

- Filtering error reports

- Providing initial data for models

- Providing initial data with fixtures

- Running Django on Jython

- Installing Jython

- Creating a servlet container

- Installing Django

- Installing Jython platform support libraries

- Differences with Django on Jython

- Integrating Django with a legacy database

- Give Django your database parameters

- Auto-generate the models

- Install the core Django tables

- Test and tweak

- Outputting CSV with Django

- Using the Python CSV library

- Using the template system

- Other text-based formats

- Outputting PDFs with Django

- Install ReportLab

- Write your view

- Complex PDFs

- Further resources

- Other formats

- Managing static files (e.g. images, JavaScript, CSS)

- Configuring static files

- Serving static files during development

- Serving files uploaded by a user during development

- Testing

- Deployment

- Learn more

- Deploying static files

- Serving static files in production

- Learn more

- How to install Django on Windows

- Install Python

- About pip

- Install virtualenv and virtualenvwrapper

- Install Django

- Common pitfalls

- Writing database migrations

- Data migrations and multiple databases

- Migrations that add unique fields

- Controlling the order of migrations

- Migrating data between third-party apps

- Django FAQ

- FAQ: General

- Why does this project exist?

- What does “Django” mean, and how do you pronounce it?

- Is Django stable?

- Does Django scale?

- Who’s behind this?

- Which sites use Django?

- Django appears to be a MVC framework, but you call the Controller the “view”, and the View the “template”. How come you don’t use the standard names?

- <Framework X> does <feature Y> – why doesn’t Django?

- Why did you write all of Django from scratch, instead of using other Python libraries?

- Is Django a content-management-system (CMS)?

- How can I download the Django documentation to read it offline?

- Where can I find Django developers for hire?

- How do I cite Django?

- FAQ: Installation

- How do I get started?

- What are Django’s prerequisites?

- What Python version can I use with Django?

- What Python version should I use with Django?

- Should I use the stable version or development version?

- FAQ: Using Django

- Why do I get an error about importing DJANGO_SETTINGS_MODULE?

- I can’t stand your template language. Do I have to use it?

- Do I have to use your model/database layer?

- How do I use image and file fields?

- How do I make a variable available to all my templates?

- FAQ: Getting Help

- How do I do X? Why doesn’t Y work? Where can I go to get help?

- Why hasn’t my message appeared on django-users?

- Nobody on django-users answered my question! What should I do?

- I think I’ve found a bug! What should I do?

- I think I’ve found a security problem! What should I do?

- FAQ: Databases and models

- How can I see the raw SQL queries Django is running?

- Can I use Django with a pre-existing database?

- If I make changes to a model, how do I update the database?

- Do Django models support multiple-column primary keys?

- Does Django support NoSQL databases?

- How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?

- FAQ: The admin

- I can’t log in. When I enter a valid username and password, it just brings up the login page again, with no error messages.

- I can’t log in. When I enter a valid username and password, it brings up the login page again, with a “Please enter a correct username and password” error.

- How do I automatically set a field’s value to the user who last edited the object in the admin?

- How do I limit admin access so that objects can only be edited by the users who created them?

- My admin-site CSS and images showed up fine using the development server, but they’re not displaying when using mod_wsgi.

- My “list_filter” contains a ManyToManyField, but the filter doesn’t display.

- Some objects aren’t appearing in the admin.

- How can I customize the functionality of the admin interface?

- The dynamically-generated admin site is ugly! How can I change it?

- What browsers are supported for using the admin?

- FAQ: Contributing code

- How can I get started contributing code to Django?

- I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?

- When and how might I remind the core team of a patch I care about?

- But I’ve reminded you several times and you keep ignoring my patch!

- Troubleshooting

- Problems running django-admin

- Miscellaneous

- API Reference

- Applications

- Projects and applications

- Configuring applications

- Application configuration

- Application registry

- Initialization process

- System check framework

- API Reference

- Builtin checks

- Built-in class-based views API

- Base views

- Generic display views

- Generic editing views

- Generic date views

- Class-based views mixins

- Class-based generic views - flattened index

- Specification

- Base vs Generic views

- Clickjacking Protection

- An example of clickjacking

- Preventing clickjacking

- How to use it

- Limitations

- contrib packages

- The Django admin site

- django.contrib.auth

- The contenttypes framework

- The flatpages app

- GeoDjango

- django.contrib.humanize

- The messages framework

- django.contrib.postgres

- The redirects app

- The sitemap framework

- The “sites” framework

- The staticfiles app

- The syndication feed framework

- django.contrib.webdesign

- admin

- auth

- contenttypes

- flatpages

- gis

- humanize

- messages

- postgres

- redirects

- sessions

- sites

- sitemaps

- syndication

- webdesign

- Other add-ons

- Cross Site Request Forgery protection

- How to use it

- Rejected requests

- How it works

- Caching

- Testing

- Limitations

- Edge cases

- Contrib and reusable apps

- Settings

- Frequently Asked Questions

- Databases

- General notes

- PostgreSQL notes

- MySQL notes

- SQLite notes

- Oracle notes

- Using a 3rd-party database backend

- django-admin and manage.py

- Usage

- Available commands

- Commands provided by applications

- Default options

- Extra niceties

- Running management commands from your code

- Output redirection

- Django Exceptions

- Django Core Exceptions

- URL Resolver exceptions

- Database Exceptions

- Http Exceptions

- Transaction Exceptions

- Testing Framework Exceptions

- Python Exceptions

- File handling

- The File object

- File storage API

- Uploaded Files and Upload Handlers

- Forms

- The Forms API

- Form fields

- Model Form Functions

- Formset Functions

- Widgets

- Form and field validation

- Middleware

- Available middleware

- Middleware ordering

- Migration Operations

- Schema Operations

- Special Operations

- Writing your own

- Models

- Model field reference

- Field attribute reference

- Model _meta API

- Related objects reference

- Model class reference

- Model Meta options

- Model instance reference

- QuerySet API reference

- Lookup API reference

- Query Expressions

- Conditional Expressions

- Database Functions

- Request and response objects

- Quick overview

- HttpRequest objects

- QueryDict objects

- HttpResponse objects

- JsonResponse objects

- StreamingHttpResponse objects

- FileResponse objects

- SchemaEditor

- Methods

- Attributes

- Settings

- Core Settings

- Auth

- Messages

- Sessions

- Sites

- Static Files

- Core Settings Topical Index

- Signals

- Model signals

- Management signals

- Request/response signals

- Test signals

- Database Wrappers

- Templates

- The Django template language

- Built-in template tags and filters

- The Django template language: for Python programmers

- Upgrading templates to Django 1.8

- TemplateResponse and SimpleTemplateResponse

- SimpleTemplateResponse objects

- TemplateResponse objects

- The rendering process

- Using TemplateResponse and SimpleTemplateResponse

- Unicode data

- Creating the database

- General string handling

- Models

- The database API

- Templates

- Files

- Email

- Form submission

- django.core.urlresolvers utility functions

- reverse()

- reverse_lazy()

- resolve()

- get_script_prefix()

- django.conf.urls utility functions

- patterns()

- static()

- url()

- include()

- handler400

- handler403

- handler404

- handler500

- Django Utils

- django.utils.cache

- django.utils.dateparse

- django.utils.decorators

- django.utils.encoding

- django.utils.feedgenerator

- django.utils.functional

- django.utils.html

- django.utils.http

- django.utils.module_loading

- django.utils.safestring

- django.utils.text

- django.utils.timezone

- django.utils.translation

- Validators

- Writing validators

- How validators are run

- Built-in validators

- Built-in Views

- Serving files in development

- Error views

- Meta-documentation and miscellany

- API stability

- What “stable” means

- Stable APIs

- Exceptions

- Design philosophies

- Overall

- Models

- Database API

- URL design

- Template system

- Views

- Cache Framework

- Third-party distributions of Django

- For distributors

- Glossary

- Release notes

- Final releases

- 1.9 release

- 1.8 release

- 1.7 release

- 1.6 release

- 1.5 release

- 1.4 release

- 1.3 release

- 1.2 release

- 1.1 release

- 1.0 release

- Pre-1.0 releases

- Security releases

- Django internals

- Contributing to Django

- Advice for new contributors

- Reporting bugs and requesting features

- Triaging tickets

- Writing code

- Writing documentation

- Localizing Django

- Committing code

- Mailing lists

- django-users

- django-core-mentorship

- django-developers

- django-i18n

- django-announce

- django-updates

- Organization of the Django Project

- Principles

- Core team

- Technical board

- Changing the organization

- Django team

- The original team

- The current team

- Past team members

- Roles

- Technical board

- Committers

- Security team

- Releasers

- Ops team

- Django’s security policies

- Reporting security issues

- Supported versions

- How Django discloses security issues

- Who receives advance notification

- Requesting notifications

- Django’s release process

- Official releases

- Release cadence

- Deprecation policy

- Supported versions

- Release process

- Django Deprecation Timeline

- 2.0

- 1.10

- 1.9

- 1.8

- 1.7

- 1.6

- 1.5

- 1.4

- 1.3

- The Django source code repository

- High-level overview

- The master branch

- Other branches

- Tags

- How is Django Formed?

- Overview

- Prerequisites

- Pre-release tasks

- Preparing for release

- Actually rolling the release

- Making the release(s) available to the public

- Post-release

- New stable branch tasks

- Notes on setting the VERSION tuple

Indices, glossary and tables

- Index

- Module Index

- Glossary

Django documentation

Everything you need to know about Django.

Getting help

Having trouble? We’d like to help!

- Try the FAQ – it’s got answers to many common questions.

- Looking for specific information? Try the Index, Module Index or the detailed table of contents.

- Search for information in the archives of the django-users mailing list, or post a question.

- Ask a question in the #django IRC channel, or search the IRC logs to see if it’s been asked before.

- Report bugs with Django in our ticket tracker.

How the documentation is organized

Django has a lot of documentation. A high-level overview of how it’s organized will help you know where to look for certain things:

- Tutorials take you by the hand through a series of steps to create a Web application. Start here if you’re new to Django or Web application development. Also look at the “First steps” below.

- Topic guides discuss key topics and concepts at a fairly high level and provide useful background information and explanation.

- Reference guides contain technical reference for APIs and other aspects of Django’s machinery. They describe how it works and how to use it but assume that you have a basic understanding of key concepts.

- How-to guides are recipes. They guide you through the steps involved in addressing key problems and use-cases. They are more advanced than tutorials and assume some knowledge of how Django works.

First steps

Are you new to Django or to programming? This is the place to start!

- From scratch: Overview | Installation

- Tutorial: Part 1: Requests and responses | Part 2: Models and the admin site | Part 3: Views and templates | Part 4: Forms and generic views | Part 5: Testing | Part 6: Static files | Part 7: Customizing the admin site

- Advanced Tutorials: How to write reusable apps | Writing your first patch for Django

The model layer

Django provides an abstraction layer (the “models”) for structuring and manipulating the data of your Web application. Learn more about it below:

- Models: Introduction to models | Field types | Meta options | Model class

- QuerySets: Executing queries | QuerySet method reference | Lookup expressions

- Model instances: Instance methods | Accessing related objects

- Migrations: Introduction to Migrations | Operations reference | SchemaEditor | Writing migrations

- Advanced: Managers | Raw SQL | Transactions | Aggregation | Custom fields | Multiple databases | Custom lookups | Query Expressions | Conditional Expressions | Database Functions

- Other: Supported databases | Legacy databases | Providing initial data | Optimize database access | PostgreSQL specific features

The view layer

Django has the concept of “views” to encapsulate the logic responsible for processing a user’s request and for returning the response. Find all you need to know about views via the links below:

- The basics: URLconfs | View functions | Shortcuts | Decorators

- Reference: Built-in Views | Request/response objects | TemplateResponse objects

- File uploads: Overview | File objects | Storage API | Managing files | Custom storage

- Class-based views: Overview | Built-in display views | Built-in editing views | Using mixins | API reference | Flattened index

- Advanced: Generating CSV | Generating PDF

- Middleware: Overview | Built-in middleware classes

The template layer

The template layer provides a designer-friendly syntax for rendering the information to be presented to the user. Learn how this syntax can be used by designers and how it can be extended by programmers:

- The basics: Overview

- For designers: Language overview | Built-in tags and filters | Humanization

- For programmers: Template API | Custom tags and filters

Forms

Django provides a rich framework to facilitate the creation of forms and the manipulation of form data.

- The basics: Overview | Form API | Built-in fields | Built-in widgets

- Advanced: Forms for models | Integrating media | Formsets | Customizing validation

The development process

Learn about the various components and tools to help you in the development and testing of Django applications:

- Settings: Overview | Full list of settings

- Applications: Overview

- Exceptions: Overview

- django-admin and manage.py: Overview | Adding custom commands

- Testing: Introduction | Writing and running tests | Included testing tools | Advanced topics

- Deployment: Overview | WSGI servers | Deploying static files | Tracking code errors by email

The admin

Find all you need to know about the automated admin interface, one of Django’s most popular features:

- Admin site

- Admin actions

- Admin documentation generator

Security

Security is a topic of paramount importance in the development of Web applications and Django provides multiple protection tools and mechanisms:

- Security overview

- Disclosed security issues in Django

- Clickjacking protection

- Cross Site Request Forgery protection

- Cryptographic signing

- Security Middleware

Internationalization and localization

Django offers a robust internationalization and localization framework to assist you in the development of applications for multiple languages and world regions:

- Overview | Internationalization | Localization | Localized Web UI formatting and form input

- Time zones

Performance and optimization

There are a variety of techniques and tools that can help get your code running more efficiently - faster, and using fewer system resources.

- Performance and optimization overview

Python compatibility

Django aims to be compatible with multiple different flavors and versions of Python:

- Jython support

- Python 3 compatibility

Geographic framework

GeoDjango intends to be a world-class geographic Web framework. Its goal is to make it as easy as possible to build GIS Web applications and harness the power of spatially enabled data.

Common Web application tools

Django offers multiple tools commonly needed in the development of Web applications:

- Authentication: Overview | Using the authentication system | Password management | Customizing authentication | API Reference

- Caching

- Logging

- Sending emails

- Syndication feeds (RSS/Atom)

- Pagination

- Messages framework

- Serialization

- Sessions

- Sitemaps

- Static files management

- Data validation

Other core functionalities

Learn about some other core functionalities of the Django framework:

- Conditional content processing

- Content types and generic relations

- Flatpages

- Redirects

- Signals

- System check framework

- The sites framework

- Unicode in Django

The Django open-source project

Learn about the development process for the Django project itself and about how you can contribute:

- Community: How to get involved | The release process | Team organization | Meet the team | Current roles | The Django source code repository | Security policies | Mailing lists

- Design philosophies: Overview

- Documentation: About this documentation

- Third-party distributions: Overview

- Django over time: API stability | Release notes and upgrading instructions | Deprecation Timeline

Getting started

New to Django? Or to Web development in general? Well, you came to the right place: read this material to quickly get up and running.

- Django at a glance

- Quick install guide

- Writing your first Django app, part 1

- Writing your first Django app, part 2

- Writing your first Django app, part 3

- Writing your first Django app, part 4

- Writing your first Django app, part 5

- Writing your first Django app, part 6

- Writing your first Django app, part 7

- Advanced tutorial: How to write reusable apps

- What to read next

- Writing your first patch for Django

See also

If you’re new to Python, you might want to start by getting an idea of what the language is like. Django is 100% Python, so if you’ve got minimal comfort with Python you’ll probably get a lot more out of Django.

If you’re new to programming entirely, you might want to start with this list of Python resources for non-programmers

If you already know a few other languages and want to get up to speed with Python quickly, we recommend Dive Into Python. If that’s not quite your style, there are many other books about Python.

Django at a glance

Because Django was developed in a fast-paced newsroom environment, it was designed to make common Web-development tasks fast and easy. Here’s an informal overview of how to write a database-driven Web app with Django.

The goal of this document is to give you enough technical specifics to understand how Django works, but this isn’t intended to be a tutorial or reference – but we’ve got both! When you’re ready to start a project, you can start with the tutorial or dive right into more detailed documentation.

Design your model

Although you can use Django without a database, it comes with an object-relational mapper in which you describe your database layout in Python code.

The data-model syntax offers many rich ways of representing your models – so far, it’s been solving many years’ worth of database-schema problems. Here’s a quick example:

mysite/news/models.py

from django.db import models

class Reporter(models.Model):
full_name = models.CharField(max_length=70)

def __str__(self):              # __unicode__ on Python 2
return self.full_name

class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

def __str__(self):              # __unicode__ on Python 2
return self.headline

Install it

Next, run the Django command-line utility to create the database tables automatically:

$ python manage.py migrate

The migrate command looks at all your available models and creates tables in your database for whichever tables don’t already exist, as well as optionally providing much richer schema control.

Enjoy the free API

With that, you’ve got a free, and rich, Python API to access your data. The API is created on the fly, no code generation necessary:

# Import the models we created from our "news" app
>>> from news.models import Reporter, Article

# No reporters are in the system yet.
>>> Reporter.objects.all()
[]

# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')

# Save the object into the database. You have to call save() explicitly.
>>> r.save()

# Now it has an ID.
>>> r.id
1

# Now the new reporter is in the database.
>>> Reporter.objects.all()
[<Reporter: John Smith>]

# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'

# Django provides a rich database lookup API.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist.

# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

# Now the article is in the database.
>>> Article.objects.all()
[<Article: Django is cool>]

# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'

# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
[<Article: Django is cool>]

# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
[<Article: Django is cool>]

# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()

# Delete an object with delete().
>>> r.delete()

A dynamic admin interface: it’s not just scaffolding – it’s the whole house

Once your models are defined, Django can automatically create a professional, production ready administrative interface – a website that lets authenticated users add, change and delete objects. It’s as easy as registering your model in the admin site:

mysite/news/models.py

from django.db import models

class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

mysite/news/admin.py

from django.contrib import admin

from . import models

admin.site.register(models.Article)

The philosophy here is that your site is edited by a staff, or a client, or maybe just you – and you don’t want to have to deal with creating backend interfaces just to manage content.

One typical workflow in creating Django apps is to create models and get the admin sites up and running as fast as possible, so your staff (or clients) can start populating data. Then, develop the way data is presented to the public.

Design your URLs

A clean, elegant URL scheme is an important detail in a high-quality Web application. Django encourages beautiful URL design and doesn’t put any cruft in URLs, like .php or .asp.

To design URLs for an app, you create a Python module called a URLconf. A table of contents for your app, it contains a simple mapping between URL patterns and Python callback functions. URLconfs also serve to decouple URLs from Python code.

Here’s what a URLconf might look like for the Reporter/Article example above:

mysite/news/urls.py

from django.conf.urls import url

from . import views

urlpatterns = [
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

The code above maps URLs, as simple regular expressions, to the location of Python callback functions (“views”). The regular expressions use parenthesis to “capture” values from the URLs. When a user requests a page, Django runs through each pattern, in order, and stops at the first one that matches the requested URL. (If none of them matches, Django calls a special-case 404 view.) This is blazingly fast, because the regular expressions are compiled at load time.

Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function. Each view gets passed a request object – which contains request metadata – and the values captured in the regex.

For example, if a user requested the URL “/articles/2005/05/39323/”, Django would call the function news.views.article_detail(request, '2005', '05', '39323').

Write your views

Each view is responsible for doing one of two things: Returning an HttpResponse object containing the content for the requested page, or raising an exception such as Http404. The rest is up to you.

Generally, a view retrieves data according to the parameters, loads a template and renders the template with the retrieved data. Here’s an example view for year_archive from above:

mysite/news/views.py

from django.shortcuts import render

from .models import Article

def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
context = {'year': year, 'article_list': a_list}
return render(request, 'news/year_archive.html', context)

This example uses Django’s template system, which has several powerful features but strives to stay simple enough for non-programmers to use.

Design your templates

The code above loads the news/year_archive.html template.

Django has a template search path, which allows you to minimize redundancy among templates. In your Django settings, you specify a list of directories to check for templates with DIRS. If a template doesn’t exist in the first directory, it checks the second, and so on.

Let’s say the news/year_archive.html template was found. Here’s what that might look like:

mysite/news/templates/news/year_archive.html

{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

Variables are surrounded by double-curly braces. {{ article.headline }} means “Output the value of the article’s headline attribute.” But dots aren’t used only for attribute lookup. They also can do dictionary-key lookup, index lookup and function calls.

Note {{ article.pub_date|date:"F j, Y" }} uses a Unix-style “pipe” (the “|” character). This is called a template filter, and it’s a way to filter the value of a variable. In this case, the date filter formats a Python datetime object in the given format (as found in PHP’s date function).

You can chain together as many filters as you’d like. You can write custom template filters. You can write custom template tags, which run custom Python code behind the scenes.

Finally, Django uses the concept of “template inheritance”. That’s what the {% extends "base.html" %} does. It means “First load the template called ‘base’, which has defined a bunch of blocks, and fill the blocks with the following blocks.” In short, that lets you dramatically cut down on redundancy in templates: each template has to define only what’s unique to that template.

Here’s what the “base.html” template, including the use of static files, might look like:

mysite/templates/base.html

{% load staticfiles %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="{% static "images/sitelogo.png" %}" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>

Simplistically, it defines the look-and-feel of the site (with the site’s logo), and provides “holes” for child templates to fill. This makes a site redesign as easy as changing a single file – the base template.

It also lets you create multiple versions of a site, with different base templates, while reusing child templates. Django’s creators have used this technique to create strikingly different mobile versions of sites – simply by creating a new base template.

Note that you don’t have to use Django’s template system if you prefer another system. While Django’s template system is particularly well-integrated with Django’s model layer, nothing forces you to use it. For that matter, you don’t have to use Django’s database API, either. You can use another database abstraction layer, you can read XML files, you can read files off disk, or anything you want. Each piece of Django – models, views, templates – is decoupled from the next.

This is just the surface

This has been only a quick overview of Django’s functionality. Some more useful features:

- A caching framework that integrates with memcached or other backends.

- A syndication framework that makes creating RSS and Atom feeds as easy as writing a small Python class.

- More sexy automatically-generated admin features – this overview barely scratched the surface.

The next obvious steps are for you to download Django, read the tutorial and join the community. Thanks for your interest!

Quick install guide

Before you can use Django, you’ll need to get it installed. We have a complete installation guide that covers all the possibilities; this guide will guide you to a simple, minimal installation that’ll work while you walk through the introduction.

Install Python

Being a Python Web framework, Django requires Python. See What Python version can I use with Django? for details. Python includes a lightweight database called SQLite so you won’t need to set up a database just yet.

Get the latest version of Python at https://www.python.org/download/ or with your operating system’s package manager.

Django on Jython

If you use Jython (a Python implementation for the Java platform), you’ll need to follow a few additional steps. See Running Django on Jython for details.

You can verify that Python is installed by typing python from your shell; you should see something like:

Python 3.4.x
[GCC 4.x] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Set up a database

This step is only necessary if you’d like to work with a “large” database engine like PostgreSQL, MySQL, or Oracle. To install such a database, consult the database installation information.

Remove any old versions of Django

If you are upgrading your installation of Django from a previous version, you will need to uninstall the old Django version before installing the new version.

Install Django

You’ve got three easy options to install Django:

- Install a version of Django provided by your operating system distribution. This is the quickest option for those who have operating systems that distribute Django.

- Install an official release. This is the best approach for most users.

- Install the latest development version. This option is for enthusiasts who want the latest-and-greatest features and aren’t afraid of running brand new code. You might encounter new bugs in the development version, but reporting them helps the development of Django. Also, releases of third-party packages are less likely to be compatible with the development version than with the latest stable release.

Always refer to the documentation that corresponds to the version of Django you’re using!

If you do either of the first two steps, keep an eye out for parts of the documentation marked new in development version. That phrase flags features that are only available in development versions of Django, and they likely won’t work with an official release.

Verifying

To verify that Django can be seen by Python, type python from your shell. Then at the Python prompt, try to import Django:

>>> import django
>>> print(django.get_version())
1.9

You may have another version of Django installed.

That’s it!

That’s it – you can now move onto the tutorial.

Writing your first Django app, part 1

Let’s learn by example.

Throughout this tutorial, we’ll walk you through the creation of a basic poll application.

It’ll consist of two parts:

- A public site that lets people view polls and vote in them.

- An admin site that lets you add, change, and delete polls.

We’ll assume you have Django installed already. You can tell Django is installed and which version by running the following command:

$ python -m django --version

If Django is installed, you should see the version of your installation. If it isn’t, you’ll get an error telling “No module named django”.

This tutorial is written for Django 1.9 and Python 3.4 or later. If the Django version doesn’t match, you can refer to the tutorial for your version of Django by using the version switcher at the bottom right corner of this page, or update Django to the newest version. If you are still using Python 2.7, you will need to adjust the code samples slightly, as described in comments.

See How to install Django for advice on how to remove older versions of Django and install a newer one.

Where to get help:

If you’re having trouble going through this tutorial, please post a message to django-users or drop by #django on irc.freenode.net to chat with other Django users who might be able to help.

Creating a project

If this is your first time using Django, you’ll have to take care of some initial setup. Namely, you’ll need to auto-generate some code that establishes a Django project – a collection of settings for an instance of Django, including database configuration, Django-specific options and application-specific settings.

From the command line, cd into a directory where you’d like to store your code, then run the following command:

$ django-admin startproject mysite

This will create a mysite directory in your current directory. If it didn’t work, see Problems running django-admin.

Note

You’ll need to avoid naming projects after built-in Python or Django components. In particular, this means you should avoid using names like django (which will conflict with Django itself) or test (which conflicts with a built-in Python package).

Where should this code live?

If your background is in plain old PHP (with no use of modern frameworks), you’re probably used to putting code under the Web server’s document root (in a place such as /var/www). With Django, you don’t do that. It’s not a good idea to put any of this Python code within your Web server’s document root, because it risks the possibility that people may be able to view your code over the Web. That’s not good for security.

Put your code in some directory outside of the document root, such as /home/mycode.

Let’s look at what startproject created:

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

These files are:

- The outer mysite/ root directory is just a container for your project. Its name doesn’t matter to Django; you can rename it to anything you like.

- manage.py: A command-line utility that lets you interact with this Django project in various ways. You can read all the details about manage.py in django-admin and manage.py.

- The inner mysite/ directory is the actual Python package for your project. Its name is the Python package name you’ll need to use to import anything inside it (e.g. mysite.urls).

- mysite/__init__.py: An empty file that tells Python that this directory should be considered a Python package. If you’re a Python beginner, read more about packages in the official Python docs.

- mysite/settings.py: Settings/configuration for this Django project. Django settings will tell you all about how settings work.

- mysite/urls.py: The URL declarations for this Django project; a “table of contents” of your Django-powered site. You can read more about URLs in URL dispatcher.

- mysite/wsgi.py: An entry-point for WSGI-compatible web servers to serve your project. See How to deploy with WSGI for more details.

The development server

Let’s verify your Django project works. Change into the outer mysite directory, if you haven’t already, and run the following commands:

$ python manage.py runserver

You’ll see the following output on the command line:

Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

July 29, 2016 - 15:50:53
Django version 1.9, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Note

Ignore the warning about unapplied database migrations for now; we’ll deal with the database shortly.

You’ve started the Django development server, a lightweight Web server written purely in Python. We’ve included this with Django so you can develop things rapidly, without having to deal with configuring a production server – such as Apache – until you’re ready for production.

Now’s a good time to note: don’t use this server in anything resembling a production environment. It’s intended only for use while developing. (We’re in the business of making Web frameworks, not Web servers.)

Now that the server’s running, visit http://127.0.0.1:8000/ with your Web browser. You’ll see a “Welcome to Django” page, in pleasant, light-blue pastel. It worked!

Changing the port

By default, the runserver command starts the development server on the internal IP at port 8000.

If you want to change the server’s port, pass it as a command-line argument. For instance, this command starts the server on port 8080:

$ python manage.py runserver 8080

If you want to change the server’s IP, pass it along with the port. So to listen on all public IPs (useful if you want to show off your work on other computers on your network), use:

$ python manage.py runserver 0.0.0.0:8000

Full docs for the development server can be found in the runserver reference.

Automatic reloading of runserver

The development server automatically reloads Python code for each request as needed. You don’t need to restart the server for code changes to take effect. However, some actions like adding files don’t trigger a restart, so you’ll have to restart the server in these cases.

Creating the Polls app

Now that your environment – a “project” – is set up, you’re set to start doing work.

Each application you write in Django consists of a Python package that follows a certain convention. Django comes with a utility that automatically generates the basic directory structure of an app, so you can focus on writing code rather than creating directories.

Projects vs. apps

What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a simple poll app. A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.

Your apps can live anywhere on your Python path. In this tutorial, we’ll create our poll app right next to your manage.py file so that it can be imported as its own top-level module, rather than a submodule of mysite.

To create your app, make sure you’re in the same directory as manage.py and type this command:

$ python manage.py startapp polls

That’ll create a directory polls, which is laid out like this:

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

This directory structure will house the poll application.

Write your first view

Let’s write the first view. Open the file polls/views.py and put the following Python code in it:

polls/views.py

from django.http import HttpResponse

def index(request):
return HttpResponse("Hello, world. You're at the polls index.")

This is the simplest view possible in Django. To call the view, we need to map it to a URL - and for this we need a URLconf.

To create a URLconf in the polls directory, create a file called urls.py. Your app directory should now look like:

polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
urls.py
views.py

In the polls/urls.py file include the following code:

polls/urls.py

from django.conf.urls import url

from . import views

urlpatterns = [
url(r'^$', views.index, name='index'),
]

The next step is to point the root URLconf at the polls.urls module. In mysite/urls.py, add an import for django.conf.urls.include and insert an include() in the urlpatterns list, so you have:

mysite/urls.py

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
url(r'^polls/', include('polls.urls')),
url(r'^admin/', admin.site.urls),
]

The include() function allows referencing other URLconfs. Note that the regular expressions for the include() function doesn’t have a $ (end-of-string match character) but rather a trailing slash. Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

The idea behind include() is to make it easy to plug-and-play URLs. Since polls are in their own URLconf (polls/urls.py), they can be placed under “/polls/”, or under “/fun_polls/”, or under “/content/polls/”, or any other path root, and the app will still work.

When to use include()

You should always use include() when you include other URL patterns. admin.site.urls is the only exception to this.

Doesn’t match what you see?

If you’re seeing include(admin.site.urls) instead of just admin.site.urls, you’re probably using a version of Django that doesn’t match this tutorial version. You’ll want to either switch to the older tutorial or the newer Django version.

You have now wired an index view into the URLconf. Lets verify it’s working, run the following command:

$ python manage.py runserver

Go to http://localhost:8000/polls/ in your browser, and you should see the text “Hello, world. You’re at the polls index.”, which you defined in the index view.

The url() function is passed four arguments, two required: regex and view, and two optional: kwargs, and name. At this point, it’s worth reviewing what these arguments are for.

url() argument: regex

The term “regex” is a commonly used short form meaning “regular expression”, which is a syntax for matching patterns in strings, or in this case, url patterns. Django starts at the first regular expression and makes its way down the list, comparing the requested URL against each regular expression until it finds one that matches.

Note that these regular expressions do not search GET and POST parameters, or the domain name. For example, in a request to https://www.example.com/myapp/, the URLconf will look for myapp/. In a request to https://www.example.com/myapp/?page=3, the URLconf will also look for myapp/.

If you need help with regular expressions, see Wikipedia’s entry and the documentation of the re module. Also, the O’Reilly book “Mastering Regular Expressions” by Jeffrey Friedl is fantastic. In practice, however, you don’t need to be an expert on regular expressions, as you really only need to know how to capture simple patterns. In fact, complex regexes can have poor lookup performance, so you probably shouldn’t rely on the full power of regexes.

Finally, a performance note: these regular expressions are compiled the first time the URLconf module is loaded. They’re super fast (as long as the lookups aren’t too complex as noted above).

url() argument: view

When Django finds a regular expression match, Django calls the specified view function, with an HttpRequest object as the first argument and any “captured” values from the regular expression as other arguments. If the regex uses simple captures, values are passed as positional arguments; if it uses named captures, values are passed as keyword arguments. We’ll give an example of this in a bit.

url() argument: kwargs

Arbitrary keyword arguments can be passed in a dictionary to the target view. We aren’t going to use this feature of Django in the tutorial.

url() argument: name

Naming your URL lets you refer to it unambiguously from elsewhere in Django, especially from within templates. This powerful feature allows you to make global changes to the URL patterns of your project while only touching a single file.

When you’re comfortable with the basic request and response flow, read part 2 of this tutorial to start working with the database.

Writing your first Django app, part 2

This tutorial begins where Tutorial 1 left off. We’ll setup the database, create your first model, and get a quick introduction to Django’s automatically-generated admin site.

Database setup

Now, open up mysite/settings.py. It’s a normal Python module with module-level variables representing Django settings.

By default, the configuration uses SQLite. If you’re new to databases, or you’re just interested in trying Django, this is the easiest choice. SQLite is included in Python, so you won’t need to install anything else to support your database. When starting your first real project, however, you may want to use a more robust database like PostgreSQL, to avoid database-switching headaches down the road.

If you wish to use another database, install the appropriate database bindings and change the following keys in the DATABASES 'default' item to match your database connection settings:

- ENGINE – Either 'django.db.backends.sqlite3', 'django.db.backends.postgresql', 'django.db.backends.mysql', or 'django.db.backends.oracle'. Other backends are also available.

- NAME – The name of your database. If you’re using SQLite, the database will be a file on your computer; in that case, NAME should be the full absolute path, including filename, of that file. The default value, os.path.join(BASE_DIR, 'db.sqlite3'), will store the file in your project directory.

If you are not using SQLite as your database, additional settings such as USER, PASSWORD, and HOST must be added. For more details, see the reference documentation for DATABASES.

For databases other than SQLite

If you’re using a database besides SQLite, make sure you’ve created a database by this point. Do that with “CREATE DATABASE database_name;” within your database’s interactive prompt.

Also make sure that the database user provided in mysite/settings.py has “create database” privileges. This allows automatic creation of a test database which will be needed in a later tutorial.

If you’re using SQLite, you don’t need to create anything beforehand - the database file will be created automatically when it is needed.

While you’re editing mysite/settings.py, set TIME_ZONE to your time zone.

Also, note the INSTALLED_APPS setting at the top of the file. That holds the names of all Django applications that are activated in this Django instance. Apps can be used in multiple projects, and you can package and distribute them for use by others in their projects.

By default, INSTALLED_APPS contains the following apps, all of which come with Django:

- django.contrib.admin – The admin site. You’ll use it shortly.

- django.contrib.auth – An authentication system.

- django.contrib.contenttypes – A framework for content types.

- django.contrib.sessions – A session framework.

- django.contrib.messages – A messaging framework.

- django.contrib.staticfiles – A framework for managing static files.

These applications are included by default as a convenience for the common case.

Some of these applications make use of at least one database table, though, so we need to create the tables in the database before we can use them. To do that, run the following command:

$ python manage.py migrate

The migrate command looks at the INSTALLED_APPS setting and creates any necessary database tables according to the database settings in your mysite/settings.py file and the database migrations shipped with the app (we’ll cover those later). You’ll see a message for each migration it applies. If you’re interested, run the command-line client for your database and type \dt (PostgreSQL), SHOW TABLES; (MySQL), .schema (SQLite), or SELECT TABLE_NAME FROM USER_TABLES; (Oracle) to display the tables Django created.

For the minimalists

Like we said above, the default applications are included for the common case, but not everybody needs them. If you don’t need any or all of them, feel free to comment-out or delete the appropriate line(s) from INSTALLED_APPS before running migrate. The migrate command will only run migrations for apps in INSTALLED_APPS.

Creating models

Now we’ll define your models – essentially, your database layout, with additional metadata.

Philosophy

A model is the single, definitive source of truth about your data. It contains the essential fields and behaviors of the data you’re storing. Django follows the DRY Principle. The goal is to define your data model in one place and automatically derive things from it.

This includes the migrations - unlike in Ruby On Rails, for example, migrations are entirely derived from your models file, and are essentially just a history that Django can roll through to update your database schema to match your current models.

In our simple poll app, we’ll create two models: Question and Choice. A Question has a question and a publication date. A Choice has two fields: the text of the choice and a vote tally. Each Choice is associated with a Question.

These concepts are represented by simple Python classes. Edit the polls/models.py file so it looks like this:

polls/models.py

from django.db import models

class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')

class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

The code is straightforward. Each model is represented by a class that subclasses django.db.models.Model. Each model has a number of class variables, each of which represents a database field in the model.

Each field is represented by an instance of a Field class – e.g., CharField for character fields and DateTimeField for datetimes. This tells Django what type of data each field holds.

The name of each Field instance (e.g. question_text or pub_date) is the field’s name, in machine-friendly format. You’ll use this value in your Python code, and your database will use it as the column name.

You can use an optional first positional argument to a Field to designate a human-readable name. That’s used in a couple of introspective parts of Django, and it doubles as documentation. If this field isn’t provided, Django will use the machine-readable name. In this example, we’ve only defined a human-readable name for Question.pub_date. For all other fields in this model, the field’s machine-readable name will suffice as its human-readable name.

Some Field classes have required arguments. CharField, for example, requires that you give it a max_length. That’s used not only in the database schema, but in validation, as we’ll soon see.

A Field can also have various optional arguments; in this case, we’ve set the default value of votes to 0.

Finally, note a relationship is defined, using ForeignKey. That tells Django each Choice is related to a single Question. Django supports all the common database relationships: many-to-one, many-to-many, and one-to-one.

Activating models

That small bit of model code gives Django a lot of information. With it, Django is able to:

- Create a database schema (CREATE TABLE statements) for this app.

- Create a Python database-access API for accessing Question and Choice objects.

But first we need to tell our project that the polls app is installed.

Philosophy

Django apps are “pluggable”: You can use an app in multiple projects, and you can distribute apps, because they don’t have to be tied to a given Django installation.

Edit the mysite/settings.py file again, and change the INSTALLED_APPS setting to include the string 'polls.apps.PollsConfig'. It’ll look like this:

mysite/settings.py

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

Now Django knows to include the polls app. Let’s run another command:

$ python manage.py makemigrations polls

You should see something similar to the following:

Migrations for 'polls':
0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice

By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.

Migrations are how Django stores changes to your models (and thus your database schema) - they’re just files on disk. You can read the migration for your new model if you like; it’s the file polls/migrations/0001_initial.py. Don’t worry, you’re not expected to read them every time Django makes one, but they’re designed to be human-editable in case you want to manually tweak how Django changes things.

There’s a command that will run the migrations for you and manage your database schema automatically - that’s called migrate, and we’ll come to it in a moment - but first, let’s see what SQL that migration would run. The sqlmigrate command takes migration names and returns their SQL:

$ python manage.py sqlmigrate polls 0001

You should see something similar to the following (we’ve reformatted it for readability):

BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;

COMMIT;

Note the following:

- The exact output will vary depending on the database you are using. The example above is generated for PostgreSQL.

- Table names are automatically generated by combining the name of the app (polls) and the lowercase name of the model – question and choice. (You can override this behavior.)

- Primary keys (IDs) are added automatically. (You can override this, too.)

- By convention, Django appends "_id" to the foreign key field name. (Yes, you can override this, as well.)

- The foreign key relationship is made explicit by a FOREIGN KEY constraint. Don’t worry about the DEFERRABLE parts; that’s just telling PostgreSQL to not enforce the foreign key until the end of the transaction.

- It’s tailored to the database you’re using, so database-specific field types such as auto_increment (MySQL), serial (PostgreSQL), or integer primary key autoincrement (SQLite) are handled for you automatically. Same goes for the quoting of field names – e.g., using double quotes or single quotes.

- The sqlmigrate command doesn’t actually run the migration on your database - it just prints it to the screen so that you can see what SQL Django thinks is required. It’s useful for checking what Django is going to do or if you have database administrators who require SQL scripts for changes.

If you’re interested, you can also run python manage.py check; this checks for any problems in your project without making migrations or touching the database.

Now, run migrate again to create those model tables in your database:

$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, contenttypes, polls, auth, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK

The migrate command takes all the migrations that haven’t been applied (Django tracks which ones are applied using a special table in your database called django_migrations) and runs them against your database - essentially, synchronizing the changes you made to your models with the schema in the database.

Migrations are very powerful and let you change your models over time, as you develop your project, without the need to delete your database or tables and make new ones - it specializes in upgrading your database live, without losing data. We’ll cover them in more depth in a later part of the tutorial, but for now, remember the three-step guide to making model changes:

- Change your models (in models.py).

- Run python manage.py makemigrations to create migrations for those changes

- Run python manage.py migrate to apply those changes to the database.

The reason that there are separate commands to make and apply migrations is because you’ll commit migrations to your version control system and ship them with your app; they not only make your development easier, they’re also useable by other developers and in production.

Read the django-admin documentation for full information on what the manage.py utility can do.

Playing with the API

Now, let’s hop into the interactive Python shell and play around with the free API Django gives you. To invoke the Python shell, use this command:

$ python manage.py shell

We’re using this instead of simply typing “python”, because manage.py sets the DJANGO_SETTINGS_MODULE environment variable, which gives Django the Python import path to your mysite/settings.py file.

Bypassing manage.py

If you’d rather not use manage.py, no problem. Just set the DJANGO_SETTINGS_MODULE environment variable to mysite.settings, start a plain Python shell, and set up Django:

>>> import django
>>> django.setup()

If this raises an AttributeError, you’re probably using a version of Django that doesn’t match this tutorial version. You’ll want to either switch to the older tutorial or the newer Django version.

You must run python from the same directory manage.py is in, or ensure that directory is on the Python path, so that import mysite works.

For more information on all of this, see the django-admin documentation.

Once you’re in the shell, explore the database API:

>>> from polls.models import Question, Choice   # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
[]

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID. Note that this might say "1L" instead of "1", depending
# on which database you're using. That's no biggie; it just means your
# database backend prefers to return integers as Python long integer
# objects.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.
>>> Question.objects.all()
[<Question: Question object>]

Wait a minute. <Question: Question object> is, utterly, an unhelpful representation of this object. Let’s fix that by editing the Question model (in the polls/models.py file) and adding a __str__() method to both Question and Choice:

polls/models.py

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible  # only if you need to support Python 2
class Question(models.Model):
# ...
def __str__(self):
return self.question_text

@python_2_unicode_compatible  # only if you need to support Python 2
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text

It’s important to add __str__() methods to your models, not only for your own convenience when dealing with the interactive prompt, but also because objects’ representations are used throughout Django’s automatically-generated admin.

Note these are normal Python methods. Let’s add a custom method, just for demonstration:

polls/models.py

import datetime

from django.db import models
from django.utils import timezone

class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

Note the addition of import datetime and from django.utils import timezone, to reference Python’s standard datetime module and Django’s time-zone-related utilities in django.utils.timezone, respectively. If you aren’t familiar with time zone handling in Python, you can learn more in the time zone support docs.

Save these changes and start a new Python interactive shell by running python manage.py shell again:

>>> from polls.models import Question, Choice

# Make sure our __str__() addition worked.
>>> Question.objects.all()
[<Question: What's up?>]

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
[<Question: What's up?>]
>>> Question.objects.filter(question_text__startswith='What')
[<Question: What's up?>]

# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
[]

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

For more information on model relations, see Accessing related objects. For more on how to use double underscores to perform field lookups via the API, see Field lookups. For full details on the database API, see our Database API reference.

Introducing the Django Admin

Philosophy

Generating admin sites for your staff or clients to add, change, and delete content is tedious work that doesn’t require much creativity. For that reason, Django entirely automates creation of admin interfaces for models.

Django was written in a newsroom environment, with a very clear separation between “content publishers” and the “public” site. Site managers use the system to add news stories, events, sports scores, etc., and that content is displayed on the public site. Django solves the problem of creating a unified interface for site administrators to edit content.

The admin isn’t intended to be used by site visitors. It’s for site managers.

Creating an admin user

First we’ll need to create a user who can login to the admin site. Run the following command:

$ python manage.py createsuperuser

Enter your desired username and press enter.

Username: admin

You will then be prompted for your desired email address:

Email address: admin@example.com

The final step is to enter your password. You will be asked to enter your password twice, the second time as a confirmation of the first.

Password: **********
Password (again): *********
Superuser created successfully.

Start the development server

The Django admin site is activated by default. Let’s start the development server and explore it.

If the server is not running start it like so:

$ python manage.py runserver

Now, open a Web browser and go to “/admin/” on your local domain – e.g., http://127.0.0.1:8000/admin/. You should see the admin’s login screen:

Since translation is turned on by default, the login screen may be displayed in your own language, depending on your browser’s settings and if Django has a translation for this language.

Enter the admin site

Now, try logging in with the superuser account you created in the previous step. You should see the Django admin index page:

You should see a few types of editable content: groups and users. They are provided by django.contrib.auth, the authentication framework shipped by Django.

Make the poll app modifiable in the admin

But where’s our poll app? It’s not displayed on the admin index page.

Just one thing to do: we need to tell the admin that Question objects have an admin interface. To do this, open the polls/admin.py file, and edit it to look like this:

polls/admin.py

from django.contrib import admin

from .models import Question

admin.site.register(Question)

Explore the free admin functionality

Now that we’ve registered Question, Django knows that it should be displayed on the admin index page:

Click “Questions”. Now you’re at the “change list” page for questions. This page displays all the questions in the database and lets you choose one to change it. There’s the “What’s up?” question we created earlier:

Click the “What’s up?” question to edit it:

Things to note here:

- The form is automatically generated from the Question model.

- The different model field types (DateTimeField, CharField) correspond to the appropriate HTML input widget. Each type of field knows how to display itself in the Django admin.

- Each DateTimeField gets free JavaScript shortcuts. Dates get a “Today” shortcut and calendar popup, and times get a “Now” shortcut and a convenient popup that lists commonly entered times.

The bottom part of the page gives you a couple of options:

- Save – Saves changes and returns to the change-list page for this type of object.

- Save and continue editing – Saves changes and reloads the admin page for this object.

- Save and add another – Saves changes and loads a new, blank form for this type of object.

- Delete – Displays a delete confirmation page.

If the value of “Date published” doesn’t match the time when you created the question in Tutorial 1, it probably means you forgot to set the correct value for the TIME_ZONE setting. Change it, reload the page and check that the correct value appears.

Change the “Date published” by clicking the “Today” and “Now” shortcuts. Then click “Save and continue editing.” Then click “History” in the upper right. You’ll see a page listing all changes made to this object via the Django admin, with the timestamp and username of the person who made the change:

When you’re comfortable with the models API and have familiarized yourself with the admin site, read part 3 of this tutorial to learn about how to add more views to our polls app.

Writing your first Django app, part 3

This tutorial begins where Tutorial 2 left off. We’re continuing the Web-poll application and will focus on creating the public interface – “views.”

Overview

A view is a “type” of Web page in your Django application that generally serves a specific function and has a specific template. For example, in a blog application, you might have the following views:

- Blog homepage – displays the latest few entries.

- Entry “detail” page – permalink page for a single entry.

- Year-based archive page – displays all months with entries in the given year.

- Month-based archive page – displays all days with entries in the given month.

- Day-based archive page – displays all entries in the given day.

- Comment action – handles posting comments to a given entry.

In our poll application, we’ll have the following four views:

- Question “index” page – displays the latest few questions.

- Question “detail” page – displays a question text, with no results but with a form to vote.

- Question “results” page – displays results for a particular question.

- Vote action – handles voting for a particular choice in a particular question.

In Django, web pages and other content are delivered by views. Each view is represented by a simple Python function (or method, in the case of class-based views). Django will choose a view by examining the URL that’s requested (to be precise, the part of the URL after the domain name).

Now in your time on the web you may have come across such beauties as “ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B”. You will be pleased to know that Django allows us much more elegant URL patterns than that.

A URL pattern is simply the general form of a URL - for example: /newsarchive/<year>/<month>/.

To get from a URL to a view, Django uses what are known as ‘URLconfs’. A URLconf maps URL patterns (described as regular expressions) to views.

This tutorial provides basic instruction in the use of URLconfs, and you can refer to django.core.urlresolvers for more information.

Writing more views

Now let’s add a few more views to polls/views.py. These views are slightly different, because they take an argument:

polls/views.py

def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)

def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)

Wire these new views into the polls.urls module by adding the following url() calls:

polls/urls.py

from django.conf.urls import url

from . import views

urlpatterns = [
# ex: /polls/
url(r'^$', views.index, name='index'),
# ex: /polls/5/
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

Take a look in your browser, at “/polls/34/”. It’ll run the detail() method and display whatever ID you provide in the URL. Try “/polls/34/results/” and “/polls/34/vote/” too – these will display the placeholder results and voting pages.

When somebody requests a page from your website – say, “/polls/34/”, Django will load the mysite.urls Python module because it’s pointed to by the ROOT_URLCONF setting. It finds the variable named urlpatterns and traverses the regular expressions in order. After finding the match at '^polls/', it strips off the matching text ("polls/") and sends the remaining text – "34/" – to the ‘polls.urls’ URLconf for further processing. There it matches r'^(?P<question_id>[0-9]+)/$', resulting in a call to the detail() view like so:

detail(request=<HttpRequest object>, question_id='34')

The question_id='34' part comes from (?P<question_id>[0-9]+). Using parentheses around a pattern “captures” the text matched by that pattern and sends it as an argument to the view function; ?P<question_id> defines the name that will be used to identify the matched pattern; and [0-9]+ is a regular expression to match a sequence of digits (i.e., a number).

Because the URL patterns are regular expressions, there really is no limit on what you can do with them. And there’s no need to add URL cruft such as .html – unless you want to, in which case you can do something like this:

url(r'^polls/latest\.html$', views.index),

But, don’t do that. It’s silly.

Write views that actually do something

Each view is responsible for doing one of two things: returning an HttpResponse object containing the content for the requested page, or raising an exception such as Http404. The rest is up to you.

Your view can read records from a database, or not. It can use a template system such as Django’s – or a third-party Python template system – or not. It can generate a PDF file, output XML, create a ZIP file on the fly, anything you want, using whatever Python libraries you want.

All Django wants is that HttpResponse. Or an exception.

Because it’s convenient, let’s use Django’s own database API, which we covered in Tutorial 2. Here’s one stab at a new index() view, which displays the latest 5 poll questions in the system, separated by commas, according to publication date:

polls/views.py

from django.http import HttpResponse

from .models import Question

def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)

# Leave the rest of the views (detail, results, vote) unchanged

There’s a problem here, though: the page’s design is hard-coded in the view. If you want to change the way the page looks, you’ll have to edit this Python code. So let’s use Django’s template system to separate the design from Python by creating a template that the view can use.

First, create a directory called templates in your polls directory. Django will look for templates in there.

Your project’s TEMPLATES setting describes how Django will load and render templates. The default settings file configures a DjangoTemplates backend whose APP_DIRS option is set to True. By convention DjangoTemplates looks for a “templates” subdirectory in each of the INSTALLED_APPS.

Within the templates directory you have just created, create another directory called polls, and within that create a file called index.html. In other words, your template should be at polls/templates/polls/index.html. Because of how the app_directories template loader works as described above, you can refer to this template within Django simply as polls/index.html.

Template namespacing

Now we might be able to get away with putting our templates directly in polls/templates (rather than creating another polls subdirectory), but it would actually be a bad idea. Django will choose the first template it finds whose name matches, and if you had a template with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those templates inside another directory named for the application itself.

Put the following code in that template:

polls/templates/polls/index.html

{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}

Now let’s update our index view in polls/views.py to use the template:

polls/views.py

from django.http import HttpResponse
from django.template import loader

from .models import Question

def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context, request))

That code loads the template called polls/index.html and passes it a context. The context is a dictionary mapping template variable names to Python objects.

Load the page by pointing your browser at “/polls/”, and you should see a bulleted-list containing the “What’s up” question from Tutorial 2. The link points to the question’s detail page.

A shortcut: render()

It’s a very common idiom to load a template, fill a context and return an HttpResponse object with the result of the rendered template. Django provides a shortcut. Here’s the full index() view, rewritten:

polls/views.py

from django.shortcuts import render

from .models import Question

def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)

Note that once we’ve done this in all these views, we no longer need to import loader and HttpResponse (you’ll want to keep HttpResponse if you still have the stub methods for detail, results, and vote).

The render() function takes the request object as its first argument, a template name as its second argument and a dictionary as its optional third argument. It returns an HttpResponse object of the given template rendered with the given context.

Raising a 404 error

Now, let’s tackle the question detail view – the page that displays the question text for a given poll. Here’s the view:

polls/views.py

from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})

The new concept here: The view raises the Http404 exception if a question with the requested ID doesn’t exist.

We’ll discuss what you could put in that polls/detail.html template a bit later, but if you’d like to quickly get the above example working, a file containing just:

polls/templates/polls/detail.html

{{ question }}

will get you started for now.

A shortcut: get_object_or_404()

It’s a very common idiom to use get() and raise Http404 if the object doesn’t exist. Django provides a shortcut. Here’s the detail() view, rewritten:

polls/views.py

from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})

The get_object_or_404() function takes a Django model as its first argument and an arbitrary number of keyword arguments, which it passes to the get() function of the model’s manager. It raises Http404 if the object doesn’t exist.

Philosophy

Why do we use a helper function get_object_or_404() instead of automatically catching the ObjectDoesNotExist exceptions at a higher level, or having the model API raise Http404 instead of ObjectDoesNotExist?

Because that would couple the model layer to the view layer. One of the foremost design goals of Django is to maintain loose coupling. Some controlled coupling is introduced in the django.shortcuts module.

There’s also a get_list_or_404() function, which works just as get_object_or_404() – except using filter() instead of get(). It raises Http404 if the list is empty.

Use the template system

Back to the detail() view for our poll application. Given the context variable question, here’s what the polls/detail.html template might look like:

polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

The template system uses dot-lookup syntax to access variable attributes. In the example of {{ question.question_text }}, first Django does a dictionary lookup on the object question. Failing that, it tries an attribute lookup – which works, in this case. If attribute lookup had failed, it would’ve tried a list-index lookup.

Method-calling happens in the {% for %} loop: question.choice_set.all is interpreted as the Python code question.choice_set.all(), which returns an iterable of Choice objects and is suitable for use in the {% for %} tag.

See the template guide for more about templates.

Removing hardcoded URLs in templates

Remember, when we wrote the link to a question in the polls/index.html template, the link was partially hardcoded like this:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

The problem with this hardcoded, tightly-coupled approach is that it becomes challenging to change URLs on projects with a lot of templates. However, since you defined the name argument in the url() functions in the polls.urls module, you can remove a reliance on specific URL paths defined in your url configurations by using the {% url %} template tag:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

The way this works is by looking up the URL definition as specified in the polls.urls module. You can see exactly where the URL name of ‘detail’ is defined below:

...
# the 'name' value as called by the {% url %} template tag
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
...

If you want to change the URL of the polls detail view to something else, perhaps to something like polls/specifics/12/ instead of doing it in the template (or templates) you would change it in polls/urls.py:

...
# added the word 'specifics'
url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
...

Namespacing URL names

The tutorial project has just one app, polls. In real Django projects, there might be five, ten, twenty apps or more. How does Django differentiate the URL names between them? For example, the polls app has a detail view, and so might an app on the same project that is for a blog. How does one make it so that Django knows which app view to create for a url when using the {% url %} template tag?

The answer is to add namespaces to your URLconf. In the polls/urls.py file, go ahead and add an app_name to set the application namespace:

polls/urls.py

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

Now change your polls/index.html template from:

polls/templates/polls/index.html

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

to point at the namespaced detail view:

polls/templates/polls/index.html

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

When you’re comfortable with writing views, read part 4 of this tutorial to learn about simple form processing and generic views.

Writing your first Django app, part 4

This tutorial begins where Tutorial 3 left off. We’re continuing the Web-poll application and will focus on simple form processing and cutting down our code.

Write a simple form

Let’s update our poll detail template (“polls/detail.html”) from the last tutorial, so that the template contains an HTML <form> element:

polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

A quick rundown:

- The above template displays a radio button for each question choice. The value of each radio button is the associated question choice’s ID. The name of each radio button is "choice". That means, when somebody selects one of the radio buttons and submits the form, it’ll send the POST data choice=# where # is the ID of the selected choice. This is the basic concept of HTML forms.

- We set the form’s action to {% url 'polls:vote' question.id %}, and we set method="post". Using method="post" (as opposed to method="get") is very important, because the act of submitting this form will alter data server-side. Whenever you create a form that alters data server-side, use method="post". This tip isn’t specific to Django; it’s just good Web development practice.

- forloop.counter indicates how many times the for tag has gone through its loop

- Since we’re creating a POST form (which can have the effect of modifying data), we need to worry about Cross Site Request Forgeries. Thankfully, you don’t have to worry too hard, because Django comes with a very easy-to-use system for protecting against it. In short, all POST forms that are targeted at internal URLs should use the {% csrf_token %} template tag.

Now, let’s create a Django view that handles the submitted data and does something with it. Remember, in Tutorial 3, we created a URLconf for the polls application that includes this line:

polls/urls.py

url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

We also created a dummy implementation of the vote() function. Let’s create a real version. Add the following to polls/views.py:

polls/views.py

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse

from .models import Choice, Question
# ...
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

This code includes a few things we haven’t covered yet in this tutorial:

- request.POST is a dictionary-like object that lets you access submitted data by key name. In this case, request.POST['choice'] returns the ID of the selected choice, as a string. request.POST values are always strings.

Note that Django also provides request.GET for accessing GET data in the same way – but we’re explicitly using request.POST in our code, to ensure that data is only altered via a POST call.

- request.POST['choice'] will raise KeyError if choice wasn’t provided in POST data. The above code checks for KeyError and redisplays the question form with an error message if choice isn’t given.

- After incrementing the choice count, the code returns an HttpResponseRedirect rather than a normal HttpResponse. HttpResponseRedirect takes a single argument: the URL to which the user will be redirected (see the following point for how we construct the URL in this case).

As the Python comment above points out, you should always return an HttpResponseRedirect after successfully dealing with POST data. This tip isn’t specific to Django; it’s just good Web development practice.

- We are using the reverse() function in the HttpResponseRedirect constructor in this example. This function helps avoid having to hardcode a URL in the view function. It is given the name of the view that we want to pass control to and the variable portion of the URL pattern that points to that view. In this case, using the URLconf we set up in Tutorial 3, this reverse() call will return a string like

'/polls/3/results/'

where the 3 is the value of question.id. This redirected URL will then call the 'results' view to display the final page.

As mentioned in Tutorial 3, request is an HttpRequest object. For more on HttpRequest objects, see the request and response documentation.

After somebody votes in a question, the vote() view redirects to the results page for the question. Let’s write that view:

polls/views.py

from django.shortcuts import get_object_or_404, render

def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})

This is almost exactly the same as the detail() view from Tutorial 3. The only difference is the template name. We’ll fix this redundancy later.

Now, create a polls/results.html template:

polls/templates/polls/results.html

<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

Now, go to /polls/1/ in your browser and vote in the question. You should see a results page that gets updated each time you vote. If you submit the form without having chosen a choice, you should see the error message.

Note

The code for our vote() view does have a small problem. It first gets the selected_choice object from the database, then computes the new value of votes, and then saves it back to the database. If two users of your website try to vote at exactly the same time, this might go wrong: The same value, let’s say 42, will be retrieved for votes. Then, for both users the new value of 43 is computed and saved, but 44 would be the expected value.

This is called a race condition. If you are interested, you can read Avoiding race conditions using F() to learn how you can solve this issue.

Use generic views: Less code is better

The detail() (from Tutorial 3) and results() views are very simple – and, as mentioned above, redundant. The index() view, which displays a list of polls, is similar.

These views represent a common case of basic Web development: getting data from the database according to a parameter passed in the URL, loading a template and returning the rendered template. Because this is so common, Django provides a shortcut, called the “generic views” system.

Generic views abstract common patterns to the point where you don’t even need to write Python code to write an app.

Let’s convert our poll app to use the generic views system, so we can delete a bunch of our own code. We’ll just have to take a few steps to make the conversion. We will:

1. Convert the URLconf.

2. Delete some of the old, unneeded views.

3. Introduce new views based on Django’s generic views.

Read on for details.

Why the code-shuffle?

Generally, when writing a Django app, you’ll evaluate whether generic views are a good fit for your problem, and you’ll use them from the beginning, rather than refactoring your code halfway through. But this tutorial intentionally has focused on writing the views “the hard way” until now, to focus on core concepts.

You should know basic math before you start using a calculator.

Amend URLconf

First, open the polls/urls.py URLconf and change it like so:

polls/urls.py

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

Note that the name of the matched pattern in the regexes of the second and third patterns has changed from <question_id> to <pk>.

Amend views

Next, we’re going to remove our old index, detail, and results views and use Django’s generic views instead. To do so, open the polls/views.py file and change it like so:

polls/views.py

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic

from .models import Choice, Question

class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'

def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by('-pub_date')[:5]

class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'

class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'

def vote(request, question_id):
... # same as above, no changes needed.

We’re using two generic views here: ListView and DetailView. Respectively, those two views abstract the concepts of “display a list of objects” and “display a detail page for a particular type of object.”

- Each generic view needs to know what model it will be acting upon. This is provided using the model attribute.

- The DetailView generic view expects the primary key value captured from the URL to be called "pk", so we’ve changed question_id to pk for the generic views.

By default, the DetailView generic view uses a template called <app name>/<model name>_detail.html. In our case, it would use the template "polls/question_detail.html". The template_name attribute is used to tell Django to use a specific template name instead of the autogenerated default template name. We also specify the template_name for the results list view – this ensures that the results view and the detail view have a different appearance when rendered, even though they’re both a DetailView behind the scenes.

Similarly, the ListView generic view uses a default template called <app name>/<model name>_list.html; we use template_name to tell ListView to use our existing "polls/index.html" template.

In previous parts of the tutorial, the templates have been provided with a context that contains the question and latest_question_list context variables. For DetailView the question variable is provided automatically – since we’re using a Django model (Question), Django is able to determine an appropriate name for the context variable. However, for ListView, the automatically generated context variable is question_list. To override this we provide the context_object_name attribute, specifying that we want to use latest_question_list instead. As an alternative approach, you could change your templates to match the new default context variables – but it’s a lot easier to just tell Django to use the variable you want.

Run the server, and use your new polling app based on generic views.

For full details on generic views, see the generic views documentation.

When you’re comfortable with forms and generic views, read part 5 of this tutorial to learn about testing our polls app.

Writing your first Django app, part 5

This tutorial begins where Tutorial 4 left off. We’ve built a Web-poll application, and we’ll now create some automated tests for it.

Introducing automated testing

What are automated tests?

Tests are simple routines that check the operation of your code.

Testing operates at different levels. Some tests might apply to a tiny detail (does a particular model method return values as expected?) while others examine the overall operation of the software (does a sequence of user inputs on the site produce the desired result?). That’s no different from the kind of testing you did earlier in Tutorial 2, using the shell to examine the behavior of a method, or running the application and entering data to check how it behaves.

What’s different in automated tests is that the testing work is done for you by the system. You create a set of tests once, and then as you make changes to your app, you can check that your code still works as you originally intended, without having to perform time consuming manual testing.

Why you need to create tests

So why create tests, and why now?

You may feel that you have quite enough on your plate just learning Python/Django, and having yet another thing to learn and do may seem overwhelming and perhaps unnecessary. After all, our polls application is working quite happily now; going through the trouble of creating automated tests is not going to make it work any better. If creating the polls application is the last bit of Django programming you will ever do, then true, you don’t need to know how to create automated tests. But, if that’s not the case, now is an excellent time to learn.

Tests will save you time

Up to a certain point, ‘checking that it seems to work’ will be a satisfactory test. In a more sophisticated application, you might have dozens of complex interactions between components.

A change in any of those components could have unexpected consequences on the application’s behavior. Checking that it still ‘seems to work’ could mean running through your code’s functionality with twenty different variations of your test data just to make sure you haven’t broken something - not a good use of your time.

That’s especially true when automated tests could do this for you in seconds. If something’s gone wrong, tests will also assist in identifying the code that’s causing the unexpected behavior.

Sometimes it may seem a chore to tear yourself away from your productive, creative programming work to face the unglamorous and unexciting business of writing tests, particularly when you know your code is working properly.

However, the task of writing tests is a lot more fulfilling than spending hours testing your application manually or trying to identify the cause of a newly-introduced problem.

Tests don’t just identify problems, they prevent them

It’s a mistake to think of tests merely as a negative aspect of development.

Without tests, the purpose or intended behavior of an application might be rather opaque. Even when it’s your own code, you will sometimes find yourself poking around in it trying to find out what exactly it’s doing.

Tests change that; they light up your code from the inside, and when something goes wrong, they focus light on the part that has gone wrong - even if you hadn’t even realized it had gone wrong.

Tests make your code more attractive

You might have created a brilliant piece of software, but you will find that many other developers will simply refuse to look at it because it lacks tests; without tests, they won’t trust it. Jacob Kaplan-Moss, one of Django’s original developers, says “Code without tests is broken by design.”

That other developers want to see tests in your software before they take it seriously is yet another reason for you to start writing tests.

Tests help teams work together

The previous points are written from the point of view of a single developer maintaining an application. Complex applications will be maintained by teams. Tests guarantee that colleagues don’t inadvertently break your code (and that you don’t break theirs without knowing). If you want to make a living as a Django programmer, you must be good at writing tests!

Basic testing strategies

There are many ways to approach writing tests.

Some programmers follow a discipline called “test-driven development”; they actually write their tests before they write their code. This might seem counter-intuitive, but in fact it’s similar to what most people will often do anyway: they describe a problem, then create some code to solve it. Test-driven development simply formalizes the problem in a Python test case.

More often, a newcomer to testing will create some code and later decide that it should have some tests. Perhaps it would have been better to write some tests earlier, but it’s never too late to get started.

Sometimes it’s difficult to figure out where to get started with writing tests. If you have written several thousand lines of Python, choosing something to test might not be easy. In such a case, it’s fruitful to write your first test the next time you make a change, either when you add a new feature or fix a bug.

So let’s do that right away.

Writing our first test

We identify a bug

Fortunately, there’s a little bug in the polls application for us to fix right away: the Question.was_published_recently() method returns True if the Question was published within the last day (which is correct) but also if the Question’s pub_date field is in the future (which certainly isn’t).

To check if the bug really exists, using the Admin create a question whose date lies in the future and check the method using the shell:

>>> import datetime
>>> from django.utils import timezone
>>> from polls.models import Question
>>> # create a Question instance with pub_date 30 days in the future
>>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
>>> # was it published recently?
>>> future_question.was_published_recently()
True

Since things in the future are not ‘recent’, this is clearly wrong.

Create a test to expose the bug

What we’ve just done in the shell to test for the problem is exactly what we can do in an automated test, so let’s turn that into an automated test.

A conventional place for an application’s tests is in the application’s tests.py file; the testing system will automatically find tests in any file whose name begins with test.

Put the following in the tests.py file in the polls application:

polls/tests.py

import datetime

from django.utils import timezone
from django.test import TestCase

from .models import Question

class QuestionMethodTests(TestCase):

def test_was_published_recently_with_future_question(self):
"""
was_published_recently() should return False for questions whose
pub_date is in the future.
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertEqual(future_question.was_published_recently(), False)

What we have done here is created a django.test.TestCase subclass with a method that creates a Question instance with a pub_date in the future. We then check the output of was_published_recently() - which ought to be False.

Running tests

In the terminal, we can run our test:

$ python manage.py test polls

and you’ll see something like:

Creating test database for alias 'default'...
F
======================================================================
FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionMethodTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/path/to/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_question
self.assertEqual(future_question.was_published_recently(), False)
AssertionError: True != False

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)
Destroying test database for alias 'default'...

What happened is this:

- python manage.py test polls looked for tests in the polls application

- it found a subclass of the django.test.TestCase class

- it created a special database for the purpose of testing

- it looked for test methods - ones whose names begin with test

- in test_was_published_recently_with_future_question it created a Question instance whose pub_date field is 30 days in the future

- ... and using the assertEqual() method, it discovered that its was_published_recently() returns True, though we wanted it to return False

The test informs us which test failed and even the line on which the failure occurred.

Fixing the bug

We already know what the problem is: Question.was_published_recently() should return False if its pub_date is in the future. Amend the method in models.py, so that it will only return True if the date is also in the past:

polls/models.py

def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now

and run the test again:

Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Destroying test database for alias 'default'...

After identifying a bug, we wrote a test that exposes it and corrected the bug in the code so our test passes.

Many other things might go wrong with our application in the future, but we can be sure that we won’t inadvertently reintroduce this bug, because simply running the test will warn us immediately. We can consider this little portion of the application pinned down safely forever.

More comprehensive tests

While we’re here, we can further pin down the was_published_recently() method; in fact, it would be positively embarrassing if in fixing one bug we had introduced another.

Add two more test methods to the same class, to test the behavior of the method more comprehensively:

polls/tests.py

def test_was_published_recently_with_old_question(self):
"""
was_published_recently() should return False for questions whose
pub_date is older than 1 day.
"""
time = timezone.now() - datetime.timedelta(days=30)
old_question = Question(pub_date=time)
self.assertEqual(old_question.was_published_recently(), False)

def test_was_published_recently_with_recent_question(self):
"""
was_published_recently() should return True for questions whose
pub_date is within the last day.
"""
time = timezone.now() - datetime.timedelta(hours=1)
recent_question = Question(pub_date=time)
self.assertEqual(recent_question.was_published_recently(), True)

And now we have three tests that confirm that Question.was_published_recently() returns sensible values for past, recent, and future questions.

Again, polls is a simple application, but however complex it grows in the future and whatever other code it interacts with, we now have some guarantee that the method we have written tests for will behave in expected ways.

Test a view

The polls application is fairly undiscriminating: it will publish any question, including ones whose pub_date field lies in the future. We should improve this. Setting a pub_date in the future should mean that the Question is published at that moment, but invisible until then.

A test for a view

When we fixed the bug above, we wrote the test first and then the code to fix it. In fact that was a simple example of test-driven development, but it doesn’t really matter in which order we do the work.

In our first test, we focused closely on the internal behavior of the code. For this test, we want to check its behavior as it would be experienced by a user through a web browser.

Before we try to fix anything, let’s have a look at the tools at our disposal.

The Django test client

Django provides a test Client to simulate a user interacting with the code at the view level. We can use it in tests.py or even in the shell.

We will start again with the shell, where we need to do a couple of things that won’t be necessary in tests.py. The first is to set up the test environment in the shell:

>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()

setup_test_environment() installs a template renderer which will allow us to examine some additional attributes on responses such as response.context that otherwise wouldn’t be available. Note that this method does not setup a test database, so the following will be run against the existing database and the output may differ slightly depending on what questions you already created.

Next we need to import the test client class (later in tests.py we will use the django.test.TestCase class, which comes with its own client, so this won’t be required):

>>> from django.test import Client
>>> # create an instance of the client for our use
>>> client = Client()

With that ready, we can ask the client to do some work for us:

>>> # get a response from '/'
>>> response = client.get('/')
>>> # we should expect a 404 from that address
>>> response.status_code
404
>>> # on the other hand we should expect to find something at '/polls/'
>>> # we'll use 'reverse()' rather than a hardcoded URL
>>> from django.core.urlresolvers import reverse
>>> response = client.get(reverse('polls:index'))
>>> response.status_code
200
>>> response.content
b'\n\n\n    <p>No polls are available.</p>\n\n'
>>> # note - you might get unexpected results if your ``TIME_ZONE``
>>> # in ``settings.py`` is not correct. If you need to change it,
>>> # you will also need to restart your shell session
>>> from polls.models import Question
>>> from django.utils import timezone
>>> # create a Question and save it
>>> q = Question(question_text="Who is your favorite Beatle?", pub_date=timezone.now())
>>> q.save()
>>> # check the response once again
>>> response = client.get('/polls/')
>>> response.content
b'\n\n\n    <ul>\n    \n        <li><a href="/polls/1/">Who is your favorite Beatle?</a></li>\n    \n    </ul>\n\n'
>>> # If the following doesn't work, you probably omitted the call to
>>> # setup_test_environment() described above
>>> response.context['latest_question_list']
[<Question: Who is your favorite Beatle?>]

Improving our view

The list of polls shows polls that aren’t published yet (i.e. those that have a pub_date in the future). Let’s fix that.

In Tutorial 4 we introduced a class-based view, based on ListView:

polls/views.py

class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'

def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by('-pub_date')[:5]

We need to amend the get_queryset() method and change it so that it also checks the date by comparing it with timezone.now(). First we need to add an import:

polls/views.py

from django.utils import timezone

and then we must amend the get_queryset method like so:

polls/views.py

def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Question.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]

Question.objects.filter(pub_date__lte=timezone.now()) returns a queryset containing Questions whose pub_date is less than or equal to - that is, earlier than or equal to - timezone.now.

Testing our new view

Now you can satisfy yourself that this behaves as expected by firing up the runserver, loading the site in your browser, creating Questions with dates in the past and future, and checking that only those that have been published are listed. You don’t want to have to do that every single time you make any change that might affect this - so let’s also create a test, based on our shell session above.

Add the following to polls/tests.py:

polls/tests.py

from django.core.urlresolvers import reverse

and we’ll create a shortcut function to create questions as well as a new test class:

polls/tests.py

def create_question(question_text, days):
"""
Creates a question with the given `question_text` and published the
given number of `days` offset to now (negative for questions published
in the past, positive for questions that have yet to be published).
"""
time = timezone.now() + datetime.timedelta(days=days)
return Question.objects.create(question_text=question_text, pub_date=time)

class QuestionViewTests(TestCase):
def test_index_view_with_no_questions(self):
"""
If no questions exist, an appropriate message should be displayed.
"""
response = self.client.get(reverse('polls:index'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])

def test_index_view_with_a_past_question(self):
"""
Questions with a pub_date in the past should be displayed on the
index page.
"""
create_question(question_text="Past question.", days=-30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)

def test_index_view_with_a_future_question(self):
"""
Questions with a pub_date in the future should not be displayed on
the index page.
"""
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])

def test_index_view_with_future_question_and_past_question(self):
"""
Even if both past and future questions exist, only past questions
should be displayed.
"""
create_question(question_text="Past question.", days=-30)
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)

def test_index_view_with_two_past_questions(self):
"""
The questions index page may display multiple questions.
"""
create_question(question_text="Past question 1.", days=-30)
create_question(question_text="Past question 2.", days=-5)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question 2.>', '<Question: Past question 1.>']
)

Let’s look at some of these more closely.

First is a question shortcut function, create_question, to take some repetition out of the process of creating questions.

test_index_view_with_no_questions doesn’t create any questions, but checks the message: “No polls are available.” and verifies the latest_question_list is empty. Note that the django.test.TestCase class provides some additional assertion methods. In these examples, we use assertContains() and assertQuerysetEqual().

In test_index_view_with_a_past_question, we create a question and verify that it appears in the list.

In test_index_view_with_a_future_question, we create a question with a pub_date in the future. The database is reset for each test method, so the first question is no longer there, and so again the index shouldn’t have any questions in it.

And so on. In effect, we are using the tests to tell a story of admin input and user experience on the site, and checking that at every state and for every new change in the state of the system, the expected results are published.

Testing the DetailView

What we have works well; however, even though future questions don’t appear in the index, users can still reach them if they know or guess the right URL. So we need to add a similar constraint to DetailView:

polls/views.py

class DetailView(generic.DetailView):
...
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Question.objects.filter(pub_date__lte=timezone.now())

And of course, we will add some tests, to check that a Question whose pub_date is in the past can be displayed, and that one with a pub_date in the future is not:

polls/tests.py

class QuestionIndexDetailTests(TestCase):
def test_detail_view_with_a_future_question(self):
"""
The detail view of a question with a pub_date in the future should
return a 404 not found.
"""
future_question = create_question(question_text='Future question.', days=5)
url = reverse('polls:detail', args=(future_question.id,))
response = self.client.get(url)
self.assertEqual(response.status_code, 404)

def test_detail_view_with_a_past_question(self):
"""
The detail view of a question with a pub_date in the past should
display the question's text.
"""
past_question = create_question(question_text='Past Question.', days=-5)
url = reverse('polls:detail', args=(past_question.id,))
response = self.client.get(url)
self.assertContains(response, past_question.question_text)

Ideas for more tests

We ought to add a similar get_queryset method to ResultsView and create a new test class for that view. It’ll be very similar to what we have just created; in fact there will be a lot of repetition.

We could also improve our application in other ways, adding tests along the way. For example, it’s silly that Questions can be published on the site that have no Choices. So, our views could check for this, and exclude such Questions. Our tests would create a Question without Choices and then test that it’s not published, as well as create a similar Question with Choices, and test that it is published.

Perhaps logged-in admin users should be allowed to see unpublished Questions, but not ordinary visitors. Again: whatever needs to be added to the software to accomplish this should be accompanied by a test, whether you write the test first and then make the code pass the test, or work out the logic in your code first and then write a test to prove it.

At a certain point you are bound to look at your tests and wonder whether your code is suffering from test bloat, which brings us to:

When testing, more is better

It might seem that our tests are growing out of control. At this rate there will soon be more code in our tests than in our application, and the repetition is unaesthetic, compared to the elegant conciseness of the rest of our code.

It doesn’t matter. Let them grow. For the most part, you can write a test once and then forget about it. It will continue performing its useful function as you continue to develop your program.

Sometimes tests will need to be updated. Suppose that we amend our views so that only Questions with Choices are published. In that case, many of our existing tests will fail - telling us exactly which tests need to be amended to bring them up to date, so to that extent tests help look after themselves.

At worst, as you continue developing, you might find that you have some tests that are now redundant. Even that’s not a problem; in testing redundancy is a good thing.

As long as your tests are sensibly arranged, they won’t become unmanageable. Good rules-of-thumb include having:

- a separate TestClass for each model or view

- a separate test method for each set of conditions you want to test

- test method names that describe their function

Further testing

This tutorial only introduces some of the basics of testing. There’s a great deal more you can do, and a number of very useful tools at your disposal to achieve some very clever things.

For example, while our tests here have covered some of the internal logic of a model and the way our views publish information, you can use an “in-browser” framework such as Selenium to test the way your HTML actually renders in a browser. These tools allow you to check not just the behavior of your Django code, but also, for example, of your JavaScript. It’s quite something to see the tests launch a browser, and start interacting with your site, as if a human being were driving it! Django includes LiveServerTestCase to facilitate integration with tools like Selenium.

If you have a complex application, you may want to run tests automatically with every commit for the purposes of continuous integration, so that quality control is itself - at least partially - automated.

A good way to spot untested parts of your application is to check code coverage. This also helps identify fragile or even dead code. If you can’t test a piece of code, it usually means that code should be refactored or removed. Coverage will help to identify dead code. See Integration with coverage.py for details.

Testing in Django has comprehensive information about testing.

What’s next?

For full details on testing, see Testing in Django.

When you’re comfortable with testing Django views, read part 6 of this tutorial to learn about static files management.

Writing your first Django app, part 6

This tutorial begins where Tutorial 5 left off. We’ve built a tested Web-poll application, and we’ll now add a stylesheet and an image.

Aside from the HTML generated by the server, web applications generally need to serve additional files — such as images, JavaScript, or CSS — necessary to render the complete web page. In Django, we refer to these files as “static files”.

For small projects, this isn’t a big deal, because you can just keep the static files somewhere your web server can find it. However, in bigger projects – especially those comprised of multiple apps – dealing with the multiple sets of static files provided by each application starts to get tricky.

That’s what django.contrib.staticfiles is for: it collects static files from each of your applications (and any other places you specify) into a single location that can easily be served in production.

Customize your app’s look and feel

First, create a directory called static in your polls directory. Django will look for static files there, similarly to how Django finds templates inside polls/templates/.

Django’s STATICFILES_FINDERS setting contains a list of finders that know how to discover static files from various sources. One of the defaults is AppDirectoriesFinder which looks for a “static” subdirectory in each of the INSTALLED_APPS, like the one in polls we just created. The admin site uses the same directory structure for its static files.

Within the static directory you have just created, create another directory called polls and within that create a file called style.css. In other words, your stylesheet should be at polls/static/polls/style.css. Because of how the AppDirectoriesFinder staticfile finder works, you can refer to this static file in Django simply as polls/style.css, similar to how you reference the path for templates.

Static file namespacing

Just like templates, we might be able to get away with putting our static files directly in polls/static (rather than creating another polls subdirectory), but it would actually be a bad idea. Django will choose the first static file it finds whose name matches, and if you had a static file with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those static files inside another directory named for the application itself.

Put the following code in that stylesheet (polls/static/polls/style.css):

polls/static/polls/style.css

li a {
color: green;
}

Next, add the following at the top of polls/templates/polls/index.html:

polls/templates/polls/index.html

{% load staticfiles %}

<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />

{% load staticfiles %} loads the {% static %} template tag from the staticfiles template library. The {% static %} template tag generates the absolute URL of the static file.

That’s all you need to do for development. Reload http://localhost:8000/polls/ and you should see that the question links are green (Django style!) which means that your stylesheet was properly loaded.

Adding a background-image

Next, we’ll create a subdirectory for images. Create an images subdirectory in the polls/static/polls/ directory. Inside this directory, put an image called background.gif. In other words, put your image in polls/static/polls/images/background.gif.

Then, add to your stylesheet (polls/static/polls/style.css):

polls/static/polls/style.css

body {
background: white url("images/background.gif") no-repeat right bottom;
}

Reload http://localhost:8000/polls/ and you should see the background loaded in the bottom right of the screen.

Warning

Of course the {% static %} template tag is not available for use in static files like your stylesheet which aren’t generated by Django. You should always use relative paths to link your static files between each other, because then you can change STATIC_URL (used by the static template tag to generate its URLs) without having to modify a bunch of paths in your static files as well.

These are the basics. For more details on settings and other bits included with the framework see the static files howto and the staticfiles reference. Deploying static files discusses how to use static files on a real server.

When you’re comfortable with the static files, read part 7 of this tutorial to learn how to customize Django’s automatically-generated admin site.

Writing your first Django app, part 7

This tutorial begins where Tutorial 6 left off. We’re continuing the Web-poll application and will focus on customizing Django’s automatically-generated admin site that we first explored in Tutorial 2.

Customize the admin form

By registering the Question model with admin.site.register(Question), Django was able to construct a default form representation. Often, you’ll want to customize how the admin form looks and works. You’ll do this by telling Django the options you want when you register the object.

Let’s see how this works by reordering the fields on the edit form. Replace the admin.site.register(Question) line with:

polls/admin.py

from django.contrib import admin

from .models import Question

class QuestionAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question_text']

admin.site.register(Question, QuestionAdmin)

You’ll follow this pattern – create a model admin class, then pass it as the second argument to admin.site.register() – any time you need to change the admin options for a model.

This particular change above makes the “Publication date” come before the “Question” field:

This isn’t impressive with only two fields, but for admin forms with dozens of fields, choosing an intuitive order is an important usability detail.

And speaking of forms with dozens of fields, you might want to split the form up into fieldsets:

polls/admin.py

from django.contrib import admin

from .models import Question

class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None,               {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]

admin.site.register(Question, QuestionAdmin)

The first element of each tuple in fieldsets is the title of the fieldset. Here’s what our form looks like now:

Adding related objects

OK, we have our Question admin page, but a Question has multiple Choices, and the admin page doesn’t display choices.

Yet.

There are two ways to solve this problem. The first is to register Choice with the admin just as we did with Question. That’s easy:

polls/admin.py

from django.contrib import admin

from .models import Choice, Question
# ...
admin.site.register(Choice)

Now “Choices” is an available option in the Django admin. The “Add choice” form looks like this:

In that form, the “Question” field is a select box containing every question in the database. Django knows that a ForeignKey should be represented in the admin as a <select> box. In our case, only one question exists at this point.

Also note the “Add Another” link next to “Question.” Every object with a ForeignKey relationship to another gets this for free. When you click “Add Another”, you’ll get a popup window with the “Add question” form. If you add a question in that window and click “Save”, Django will save the question to the database and dynamically add it as the selected choice on the “Add choice” form you’re looking at.

But, really, this is an inefficient way of adding Choice objects to the system. It’d be better if you could add a bunch of Choices directly when you create the Question object. Let’s make that happen.

Remove the register() call for the Choice model. Then, edit the Question registration code to read:

polls/admin.py

from django.contrib import admin

from .models import Choice, Question

class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3

class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None,               {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)

This tells Django: “Choice objects are edited on the Question admin page. By default, provide enough fields for 3 choices.”

Load the “Add question” page to see how that looks:

It works like this: There are three slots for related Choices – as specified by extra – and each time you come back to the “Change” page for an already-created object, you get another three extra slots.

At the end of the three current slots you will find an “Add another Choice” link. If you click on it, a new slot will be added. If you want to remove the added slot, you can click on the X to the top right of the added slot. Note that you can’t remove the original three slots. This image shows an added slot:

One small problem, though. It takes a lot of screen space to display all the fields for entering related Choice objects. For that reason, Django offers a tabular way of displaying inline related objects; you just need to change the ChoiceInline declaration to read:

polls/admin.py

class ChoiceInline(admin.TabularInline):
#...

With that TabularInline (instead of StackedInline), the related objects are displayed in a more compact, table-based format:

Note that there is an extra “Delete?” column that allows removing rows added using the “Add Another Choice” button and rows that have already been saved.

Customize the admin change list

Now that the Question admin page is looking good, let’s make some tweaks to the “change list” page – the one that displays all the questions in the system.

Here’s what it looks like at this point:

By default, Django displays the str() of each object. But sometimes it’d be more helpful if we could display individual fields. To do that, use the list_display admin option, which is a tuple of field names to display, as columns, on the change list page for the object:

polls/admin.py

class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date')

Just for good measure, let’s also include the was_published_recently() method from Tutorial 2:

polls/admin.py

class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date', 'was_published_recently')

Now the question change list page looks like this:

You can click on the column headers to sort by those values – except in the case of the was_published_recently header, because sorting by the output of an arbitrary method is not supported. Also note that the column header for was_published_recently is, by default, the name of the method (with underscores replaced with spaces), and that each line contains the string representation of the output.

You can improve that by giving that method (in polls/models.py) a few attributes, as follows:

polls/models.py

class Question(models.Model):
# ...
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'

For more information on these method properties, see list_display.

Edit your polls/admin.py file again and add an improvement to the Question change list page: filters using the list_filter. Add the following line to QuestionAdmin:

list_filter = ['pub_date']

That adds a “Filter” sidebar that lets people filter the change list by the pub_date field:

The type of filter displayed depends on the type of field you’re filtering on. Because pub_date is a DateTimeField, Django knows to give appropriate filter options: “Any date”, “Today”, “Past 7 days”, “This month”, “This year”.

This is shaping up well. Let’s add some search capability:

search_fields = ['question_text']

That adds a search box at the top of the change list. When somebody enters search terms, Django will search the question_text field. You can use as many fields as you’d like – although because it uses a LIKE query behind the scenes, limiting the number of search fields to a reasonable number will make it easier for your database to do the search.

Now’s also a good time to note that change lists give you free pagination. The default is to display 100 items per page. Change list pagination, search boxes, filters, date-hierarchies, and column-header-ordering all work together like you think they should.

Customize the admin look and feel

Clearly, having “Django administration” at the top of each admin page is ridiculous. It’s just placeholder text.

That’s easy to change, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system.

Customizing your project’s templates

Create a templates directory in your project directory (the one that contains manage.py). Templates can live anywhere on your filesystem that Django can access. (Django runs as whatever user your server runs.) However, keeping your templates within the project is a good convention to follow.

Open your settings file (mysite/settings.py, remember) and add a DIRS option in the TEMPLATES setting:

mysite/settings.py

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

DIRS is a list of filesystem directories to check when loading Django templates; it’s a search path.

Organizing templates

Just like the static files, we could have all our templates together, in one big templates directory, and it would work perfectly well. However, templates that belong to a particular application should be placed in that application’s template directory (e.g. polls/templates) rather than the project’s (templates). We’ll discuss in more detail in the reusable apps tutorial why we do this.

Now create a directory called admin inside templates, and copy the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into that directory.

Where are the Django source files?

If you have difficulty finding where the Django source files are located on your system, run the following command:

$ python -c "import django; print(django.__path__)"

Then, just edit the file and replace {{ site_header|default:_('Django administration') }} (including the curly braces) with your own site’s name as you see fit. You should end up with a section of code like:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

We use this approach to teach you how to override templates. In an actual project, you would probably use the django.contrib.admin.AdminSite.site_header attribute to more easily make this particular customization.

This template file contains lots of text like {% block branding %} and {{ title }}. The {% and {{ tags are part of Django’s template language. When Django renders admin/base_site.html, this template language will be evaluated to produce the final HTML page, just like we saw in Tutorial 3.

Note that any of Django’s default admin templates can be overridden. To override a template, just do the same thing you did with base_site.html – copy it from the default directory into your custom directory, and make changes.

Customizing your application’s templates

Astute readers will ask: But if DIRS was empty by default, how was Django finding the default admin templates? The answer is that, since APP_DIRS is set to True, Django automatically looks for a templates/ subdirectory within each application package, for use as a fallback (don’t forget that django.contrib.admin is an application).

Our poll application is not very complex and doesn’t need custom admin templates. But if it grew more sophisticated and required modification of Django’s standard admin templates for some of its functionality, it would be more sensible to modify the application’s templates, rather than those in the project. That way, you could include the polls application in any new project and be assured that it would find the custom templates it needed.

See the template loading documentation for more information about how Django finds its templates.

Customize the admin index page

On a similar note, you might want to customize the look and feel of the Django admin index page.

By default, it displays all the apps in INSTALLED_APPS that have been registered with the admin application, in alphabetical order. You may want to make significant changes to the layout. After all, the index is probably the most important page of the admin, and it should be easy to use.

The template to customize is admin/index.html. (Do the same as with admin/base_site.html in the previous section – copy it from the default directory to your custom template directory). Edit the file, and you’ll see it uses a template variable called app_list. That variable contains every installed Django app. Instead of using that, you can hard-code links to object-specific admin pages in whatever way you think is best.

What’s next?

The beginner tutorial ends here. In the meantime, you might want to check out some pointers on where to go from here.

If you are familiar with Python packaging and interested in learning how to turn polls into a “reusable app”, check out Advanced tutorial: How to write reusable apps.

Advanced tutorial: How to write reusable apps

This advanced tutorial begins where Tutorial 7 left off. We’ll be turning our Web-poll into a standalone Python package you can reuse in new projects and share with other people.

If you haven’t recently completed Tutorials 1–7, we encourage you to review these so that your example project matches the one described below.

Reusability matters

It’s a lot of work to design, build, test and maintain a web application. Many Python and Django projects share common problems. Wouldn’t it be great if we could save some of this repeated work?

Reusability is the way of life in Python. The Python Package Index (PyPI) has a vast range of packages you can use in your own Python programs. Check out Django Packages for existing reusable apps you could incorporate in your project. Django itself is also just a Python package. This means that you can take existing Python packages or Django apps and compose them into your own web project. You only need to write the parts that make your project unique.

Let’s say you were starting a new project that needed a polls app like the one we’ve been working on. How do you make this app reusable? Luckily, you’re well on the way already. In Tutorial 3, we saw how we could decouple polls from the project-level URLconf using an include. In this tutorial, we’ll take further steps to make the app easy to use in new projects and ready to publish for others to install and use.

Package? App?

A Python package provides a way of grouping related Python code for easy reuse. A package contains one or more files of Python code (also known as “modules”).

A package can be imported with import foo.bar or from foo import bar. For a directory (like polls) to form a package, it must contain a special file __init__.py, even if this file is empty.

A Django application is just a Python package that is specifically intended for use in a Django project. An application may use common Django conventions, such as having models, tests, urls, and views submodules.

Later on we use the term packaging to describe the process of making a Python package easy for others to install. It can be a little confusing, we know.

Your project and your reusable app

After the previous tutorials, our project should look like this:

mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
polls/
__init__.py
admin.py
migrations/
__init__.py
0001_initial.py
models.py
static/
polls/
images/
background.gif
style.css
templates/
polls/
detail.html
index.html
results.html
tests.py
urls.py
views.py
templates/
admin/
base_site.html

You created mysite/templates in Tutorial 7, and polls/templates in Tutorial 3. Now perhaps it is clearer why we chose to have separate template directories for the project and application: everything that is part of the polls application is in polls. It makes the application self-contained and easier to drop into a new project.

The polls directory could now be copied into a new Django project and immediately reused. It’s not quite ready to be published though. For that, we need to package the app to make it easy for others to install.

Installing some prerequisites

The current state of Python packaging is a bit muddled with various tools. For this tutorial, we’re going to use setuptools to build our package. It’s the recommended packaging tool (merged with the distribute fork). We’ll also be using pip to install and uninstall it. You should install these two packages now. If you need help, you can refer to how to install Django with pip. You can install setuptools the same way.

Packaging your app

Python packaging refers to preparing your app in a specific format that can be easily installed and used. Django itself is packaged very much like this. For a small app like polls, this process isn’t too difficult.

1. First, create a parent directory for polls, outside of your Django project. Call this directory django-polls.

Choosing a name for your app

When choosing a name for your package, check resources like PyPI to avoid naming conflicts with existing packages. It’s often useful to prepend django- to your module name when creating a package to distribute. This helps others looking for Django apps identify your app as Django specific.

Application labels (that is, the final part of the dotted path to application packages) must be unique in INSTALLED_APPS. Avoid using the same label as any of the Django contrib packages, for example auth, admin, or messages.

2. Move the polls directory into the django-polls directory.

3. Create a file django-polls/README.rst with the following contents:

django-polls/README.rst

=====
Polls
=====

Polls is a simple Django app to conduct Web-based polls. For each
question, visitors can choose between a fixed number of answers.

Detailed documentation is in the "docs" directory.

Quick start
-----------

1. Add "polls" to your INSTALLED_APPS setting like this::

INSTALLED_APPS = [
...
'polls',
]

2. Include the polls URLconf in your project urls.py like this::

url(r'^polls/', include('polls.urls')),

3. Run `python manage.py migrate` to create the polls models.

4. Start the development server and visit http://127.0.0.1:8000/admin/
to create a poll (you'll need the Admin app enabled).

5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.

4. Create a django-polls/LICENSE file. Choosing a license is beyond the scope of this tutorial, but suffice it to say that code released publicly without a license is useless. Django and many Django-compatible apps are distributed under the BSD license; however, you’re free to pick your own license. Just be aware that your licensing choice will affect who is able to use your code.

5. Next we’ll create a setup.py file which provides details about how to build and install the app. A full explanation of this file is beyond the scope of this tutorial, but the setuptools docs have a good explanation. Create a file django-polls/setup.py with the following contents:

django-polls/setup.py

import os
from setuptools import find_packages, setup

with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
README = readme.read()

# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

setup(
name='django-polls',
version='0.1',
packages=find_packages(),
include_package_data=True,
license='BSD License',  # example license
description='A simple Django app to conduct Web-based polls.',
long_description=README,
url='https://www.example.com/',
author='Your Name',
author_email='yourname@example.com',
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: X.Y',  # replace "X.Y" as appropriate
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',  # example license
'Operating System :: OS Independent',
'Programming Language :: Python',
# Replace these appropriately if you are stuck on Python 2.
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)

6. Only Python modules and packages are included in the package by default. To include additional files, we’ll need to create a MANIFEST.in file. The setuptools docs referred to in the previous step discuss this file in more details. To include the templates, the README.rst and our LICENSE file, create a file django-polls/MANIFEST.in with the following contents:

django-polls/MANIFEST.in

include LICENSE
include README.rst
recursive-include polls/static *
recursive-include polls/templates *

7. It’s optional, but recommended, to include detailed documentation with your app. Create an empty directory django-polls/docs for future documentation. Add an additional line to django-polls/MANIFEST.in:

recursive-include docs *

Note that the docs directory won’t be included in your package unless you add some files to it. Many Django apps also provide their documentation online through sites like readthedocs.org.

8. Try building your package with python setup.py sdist (run from inside django-polls). This creates a directory called dist and builds your new package, django-polls-0.1.tar.gz.

For more information on packaging, see Python’s Tutorial on Packaging and Distributing Projects.

Using your own package

Since we moved the polls directory out of the project, it’s no longer working. We’ll now fix this by installing our new django-polls package.

Installing as a user library

The following steps install django-polls as a user library. Per-user installs have a lot of advantages over installing the package system-wide, such as being usable on systems where you don’t have administrator access as well as preventing the package from affecting system services and other users of the machine.

Note that per-user installations can still affect the behavior of system tools that run as that user, so virtualenv is a more robust solution (see below).

1. To install the package, use pip (you already installed it, right?):

pip install --user django-polls/dist/django-polls-0.1.tar.gz

2. With luck, your Django project should now work correctly again. Run the server again to confirm this.

3. To uninstall the package, use pip:

pip uninstall django-polls

Publishing your app

Now that we’ve packaged and tested django-polls, it’s ready to share with the world! If this wasn’t just an example, you could now:

- Email the package to a friend.

- Upload the package on your website.

- Post the package on a public repository, such as the Python Package Index (PyPI). packaging.python.org has a good tutorial for doing this.

Installing Python packages with virtualenv

Earlier, we installed the polls app as a user library. This has some disadvantages:

- Modifying the user libraries can affect other Python software on your system.

- You won’t be able to run multiple versions of this package (or others with the same name).

Typically, these situations only arise once you’re maintaining several Django projects. When they do, the best solution is to use virtualenv. This tool allows you to maintain multiple isolated Python environments, each with its own copy of the libraries and package namespace.

What to read next

So you’ve read all the introductory material and have decided you’d like to keep using Django. We’ve only just scratched the surface with this intro (in fact, if you’ve read every single word, you’ve read about 5% of the overall documentation).

So what’s next?

Well, we’ve always been big fans of learning by doing. At this point you should know enough to start a project of your own and start fooling around. As you need to learn new tricks, come back to the documentation.

We’ve put a lot of effort into making Django’s documentation useful, easy to read and as complete as possible. The rest of this document explains more about how the documentation works so that you can get the most out of it.

(Yes, this is documentation about documentation. Rest assured we have no plans to write a document about how to read the document about documentation.)

Finding documentation

Django’s got a lot of documentation – almost 450,000 words and counting – so finding what you need can sometimes be tricky. A few good places to start are the Search Page and the Index.

Or you can just browse around!

How the documentation is organized

Django’s main documentation is broken up into “chunks” designed to fill different needs:

- The introductory material is designed for people new to Django – or to Web development in general. It doesn’t cover anything in depth, but instead gives a high-level overview of how developing in Django “feels”.

- The topic guides, on the other hand, dive deep into individual parts of Django. There are complete guides to Django’s model system, template engine, forms framework, and much more.

This is probably where you’ll want to spend most of your time; if you work your way through these guides you should come out knowing pretty much everything there is to know about Django.

- Web development is often broad, not deep – problems span many domains. We’ve written a set of how-to guides that answer common “How do I ...?” questions. Here you’ll find information about generating PDFs with Django, writing custom template tags, and more.

Answers to really common questions can also be found in the FAQ.

- The guides and how-to’s don’t cover every single class, function, and method available in Django – that would be overwhelming when you’re trying to learn. Instead, details about individual classes, functions, methods, and modules are kept in the reference. This is where you’ll turn to find the details of a particular function or whatever you need.

- If you are interested in deploying a project for public use, our docs have several guides for various deployment setups as well as a deployment checklist for some things you’ll need to think about.

- Finally, there’s some “specialized” documentation not usually relevant to most developers. This includes the release notes and internals documentation for those who want to add code to Django itself, and a few other things that simply don’t fit elsewhere.

How documentation is updated

Just as the Django code base is developed and improved on a daily basis, our documentation is consistently improving. We improve documentation for several reasons:

- To make content fixes, such as grammar/typo corrections.

- To add information and/or examples to existing sections that need to be expanded.

- To document Django features that aren’t yet documented. (The list of such features is shrinking but exists nonetheless.)

- To add documentation for new features as new features get added, or as Django APIs or behaviors change.

Django’s documentation is kept in the same source control system as its code. It lives in the docs directory of our Git repository. Each document online is a separate text file in the repository.

Where to get it

You can read Django documentation in several ways. They are, in order of preference:

On the Web

The most recent version of the Django documentation lives at https://docs.djangoproject.com/en/dev/. These HTML pages are generated automatically from the text files in source control. That means they reflect the “latest and greatest” in Django – they include the very latest corrections and additions, and they discuss the latest Django features, which may only be available to users of the Django development version. (See “Differences between versions” below.)

We encourage you to help improve the docs by submitting changes, corrections and suggestions in the ticket system. The Django developers actively monitor the ticket system and use your feedback to improve the documentation for everybody.

Note, however, that tickets should explicitly relate to the documentation, rather than asking broad tech-support questions. If you need help with your particular Django setup, try the django-users mailing list or the #django IRC channel instead.

In plain text

For offline reading, or just for convenience, you can read the Django documentation in plain text.

If you’re using an official release of Django, note that the zipped package (tarball) of the code includes a docs/ directory, which contains all the documentation for that release.

If you’re using the development version of Django (aka “trunk”), note that the docs/ directory contains all of the documentation. You can update your Git checkout to get the latest changes.

One low-tech way of taking advantage of the text documentation is by using the Unix grep utility to search for a phrase in all of the documentation. For example, this will show you each mention of the phrase “max_length” in any Django document:

$ grep -r max_length /path/to/django/docs/

As HTML, locally

You can get a local copy of the HTML documentation following a few easy steps:

- Django’s documentation uses a system called Sphinx to convert from plain text to HTML. You’ll need to install Sphinx by either downloading and installing the package from the Sphinx website, or with pip:

$ pip install Sphinx

- Then, just use the included Makefile to turn the documentation into HTML:

$ cd path/to/django/docs
$ make html

You’ll need GNU Make installed for this.

If you’re on Windows you can alternatively use the included batch file:

cd path\to\django\docs
make.bat html

- The HTML documentation will be placed in docs/_build/html.

Note

Generation of the Django documentation will work with Sphinx version 0.6 or newer, but we recommend going straight to Sphinx 1.0.2 or newer.

Differences between versions

As previously mentioned, the text documentation in our Git repository contains the “latest and greatest” changes and additions. These changes often include documentation of new features added in the Django development version – the Git (“trunk”) version of Django. For that reason, it’s worth pointing out our policy on keeping straight the documentation for various versions of the framework.

We follow this policy:

- The primary documentation on djangoproject.com is an HTML version of the latest docs in Git. These docs always correspond to the latest official Django release, plus whatever features we’ve added/changed in the framework since the latest release.

- As we add features to Django’s development version, we try to update the documentation in the same Git commit transaction.

- To distinguish feature changes/additions in the docs, we use the phrase: “New in version X.Y”, being X.Y the next release version (hence, the one being developed).

- Documentation fixes and improvements may be backported to the last release branch, at the discretion of the committer, however, once a version of Django is no longer supported, that version of the docs won’t get any further updates.

- The main documentation Web page includes links to documentation for all previous versions. Be sure you are using the version of the docs corresponding to the version of Django you are using!

Writing your first patch for Django

Introduction

Interested in giving back to the community a little? Maybe you’ve found a bug in Django that you’d like to see fixed, or maybe there’s a small feature you want added.

Contributing back to Django itself is the best way to see your own concerns addressed. This may seem daunting at first, but it’s really pretty simple. We’ll walk you through the entire process, so you can learn by example.

Who’s this tutorial for?

See also

If you are looking for a reference on how to submit patches, see the Submitting patches documentation.

For this tutorial, we expect that you have at least a basic understanding of how Django works. This means you should be comfortable going through the existing tutorials on writing your first Django app. In addition, you should have a good understanding of Python itself. But if you don’t, Dive Into Python is a fantastic (and free) online book for beginning Python programmers.

Those of you who are unfamiliar with version control systems and Trac will find that this tutorial and its links include just enough information to get started. However, you’ll probably want to read some more about these different tools if you plan on contributing to Django regularly.

For the most part though, this tutorial tries to explain as much as possible, so that it can be of use to the widest audience.

Where to get help:

If you’re having trouble going through this tutorial, please post a message to django-developers or drop by #django-dev on irc.freenode.net to chat with other Django users who might be able to help.

What does this tutorial cover?

We’ll be walking you through contributing a patch to Django for the first time. By the end of this tutorial, you should have a basic understanding of both the tools and the processes involved. Specifically, we’ll be covering the following:

- Installing Git.

- How to download a development copy of Django.

- Running Django’s test suite.

- Writing a test for your patch.

- Writing the code for your patch.

- Testing your patch.

- Generating a patch file for your changes.

- Where to look for more information.

Once you’re done with the tutorial, you can look through the rest of Django’s documentation on contributing. It contains lots of great information and is a must read for anyone who’d like to become a regular contributor to Django. If you’ve got questions, it’s probably got the answers.

Python 3 required!

This tutorial assumes you are using Python 3. Get the latest version at Python’s download page or with your operating system’s package manager.

For Windows users

When installing Python on Windows, make sure you check the option “Add python.exe to Path”, so that it is always available on the command line.

Code of Conduct

As a contributor, you can help us keep the Django community open and inclusive. Please read and follow our Code of Conduct.

Installing Git

For this tutorial, you’ll need Git installed to download the current development version of Django and to generate patch files for the changes you make.

To check whether or not you have Git installed, enter git into the command line. If you get messages saying that this command could not be found, you’ll have to download and install it, see Git’s download page.

For Windows users

When installing Git on Windows, it is recommended that you pick the “Git Bash” option so that Git runs in its own shell. This tutorial assumes that’s how you have installed it.

If you’re not that familiar with Git, you can always find out more about its commands (once it’s installed) by typing git help into the command line.

Getting a copy of Django’s development version

The first step to contributing to Django is to get a copy of the source code. From the command line, use the cd command to navigate to the directory where you’ll want your local copy of Django to live.

Download the Django source code repository using the following command:

$ git clone https://github.com/django/django.git

Now that you have a local copy of Django, you can install it just like you would install any package using pip. The most convenient way to do so is by using a virtual environment (or virtualenv) which is a feature built into Python that allows you to keep a separate directory of installed packages for each of your projects so that they don’t interfere with each other.

It’s a good idea to keep all your virtualenvs in one place, for example in .virtualenvs/ in your home directory. Create it if it doesn’t exist yet:

$ mkdir ~/.virtualenvs

Now create a new virtualenv by running:

$ python3 -m venv ~/.virtualenvs/djangodev

The path is where the new environment will be saved on your computer.

For Windows users

Using the built-in venv module will not work if you are also using the Git Bash shell on Windows, since activation scripts are only created for the system shell (.bat) and PowerShell (.ps1). Use the virtualenv package instead:

$ pip install virtualenv
$ virtualenv ~/.virtualenvs/djangodev

For Ubuntu users

On some versions of Ubuntu the above command might fail. Use the virtualenv package instead, first making sure you have pip3:

$ sudo apt-get install python3-pip
$ # Prefix the next command with sudo if it gives a permission denied error
$ pip3 install virtualenv
$ virtualenv --python=`which python3` ~/.virtualenvs/djangodev

The final step in setting up your virtualenv is to activate it:

$ source ~/.virtualenvs/djangodev/bin/activate

If the source command is not available, you can try using a dot instead:

$ . ~/.virtualenvs/djangodev/bin/activate

For Windows users

To activate your virtualenv on Windows, run:

$ source ~/virtualenvs/djangodev/Scripts/activate

You have to activate the virtualenv whenever you open a new terminal window. virtualenvwrapper is a useful tool for making this more convenient.

Anything you install through pip from now on will be installed in your new virtualenv, isolated from other environments and system-wide packages. Also, the name of the currently activated virtualenv is displayed on the command line to help you keep track of which one you are using. Go ahead and install the previously cloned copy of Django:

$ pip install -e /path/to/your/local/clone/django/

The installed version of Django is now pointing at your local copy. You will immediately see any changes you make to it, which is of great help when writing your first patch.

Rolling back to a previous revision of Django

For this tutorial, we’ll be using ticket #24788 as a case study, so we’ll rewind Django’s version history in git to before that ticket’s patch was applied. This will allow us to go through all of the steps involved in writing that patch from scratch, including running Django’s test suite.

Keep in mind that while we’ll be using an older revision of Django’s trunk for the purposes of the tutorial below, you should always use the current development revision of Django when working on your own patch for a ticket!

Note

The patch for this ticket was written by Paweł Marczewski, and it was applied to Django as commit 4df7e8483b2679fc1cba3410f08960bac6f51115. Consequently, we’ll be using the revision of Django just prior to that, commit 4ccfc4439a7add24f8db4ef3960d02ef8ae09887.

Navigate into Django’s root directory (that’s the one that contains django, docs, tests, AUTHORS, etc.). You can then check out the older revision of Django that we’ll be using in the tutorial below:

$ git checkout 4ccfc4439a7add24f8db4ef3960d02ef8ae09887

Running Django’s test suite for the first time

When contributing to Django it’s very important that your code changes don’t introduce bugs into other areas of Django. One way to check that Django still works after you make your changes is by running Django’s test suite. If all the tests still pass, then you can be reasonably sure that your changes haven’t completely broken Django. If you’ve never run Django’s test suite before, it’s a good idea to run it once beforehand just to get familiar with what its output is supposed to look like.

Before running the test suite, install its dependencies by first cd-ing into the Django tests/ directory and then running:

$ pip install -r requirements/py3.txt

Now we are ready to run the test suite. If you’re using GNU/Linux, Mac OS X or some other flavor of Unix, run:

$ ./runtests.py

Now sit back and relax. Django’s entire test suite has over 9,600 different tests, so it can take anywhere from 5 to 15 minutes to run, depending on the speed of your computer.

While Django’s test suite is running, you’ll see a stream of characters representing the status of each test as it’s run. E indicates that an error was raised during a test, and F indicates that a test’s assertions failed. Both of these are considered to be test failures. Meanwhile, x and s indicated expected failures and skipped tests, respectively. Dots indicate passing tests.

Skipped tests are typically due to missing external libraries required to run the test; see Running all the tests for a list of dependencies and be sure to install any for tests related to the changes you are making (we won’t need any for this tutorial).

Once the tests complete, you should be greeted with a message informing you whether the test suite passed or failed. Since you haven’t yet made any changes to Django’s code, the entire test suite should pass. If you get failures or errors make sure you’ve followed all of the previous steps properly. See Running the unit tests for more information. If you’re using Python 3.5+, there will be a couple failures related to deprecation warnings that you can ignore. These failures have since been fixed in Django.

Note that the latest Django trunk may not always be stable. When developing against trunk, you can check Django’s continuous integration builds to determine if the failures are specific to your machine or if they are also present in Django’s official builds. If you click to view a particular build, you can view the “Configuration Matrix” which shows failures broken down by Python version and database backend.

Note

For this tutorial and the ticket we’re working on, testing against SQLite is sufficient, however, it’s possible (and sometimes necessary) to run the tests using a different database.

Writing some tests for your ticket

In most cases, for a patch to be accepted into Django it has to include tests. For bug fix patches, this means writing a regression test to ensure that the bug is never reintroduced into Django later on. A regression test should be written in such a way that it will fail while the bug still exists and pass once the bug has been fixed. For patches containing new features, you’ll need to include tests which ensure that the new features are working correctly. They too should fail when the new feature is not present, and then pass once it has been implemented.

A good way to do this is to write your new tests first, before making any changes to the code. This style of development is called test-driven development and can be applied to both entire projects and single patches. After writing your tests, you then run them to make sure that they do indeed fail (since you haven’t fixed that bug or added that feature yet). If your new tests don’t fail, you’ll need to fix them so that they do. After all, a regression test that passes regardless of whether a bug is present is not very helpful at preventing that bug from reoccurring down the road.

Now for our hands-on example.

Writing some tests for ticket #24788

Ticket #24788 proposes a small feature addition: the ability to specify the class level attribute prefix on Form classes, so that:

[…] forms which ship with apps could effectively namespace themselves such
that N overlapping form fields could be POSTed at once and resolved to the
correct form.

In order to resolve this ticket, we’ll add a prefix attribute to the BaseForm class. When creating instances of this class, passing a prefix to the __init__() method will still set that prefix on the created instance. But not passing a prefix (or passing None) will use the class-level prefix. Before we make those changes though, we’re going to write a couple tests to verify that our modification functions correctly and continues to function correctly in the future.

Navigate to Django’s tests/forms_tests/tests/ folder and open the test_forms.py file. Add the following code on line 1674 right before the test_forms_with_null_boolean function:

def test_class_prefix(self):
# Prefix can be also specified at the class level.
class Person(Form):
first_name = CharField()
prefix = 'foo'

p = Person()
self.assertEqual(p.prefix, 'foo')

p = Person(prefix='bar')
self.assertEqual(p.prefix, 'bar')

This new test checks that setting a class level prefix works as expected, and that passing a prefix parameter when creating an instance still works too.

But this testing thing looks kinda hard...

If you’ve never had to deal with tests before, they can look a little hard to write at first glance. Fortunately, testing is a very big subject in computer programming, so there’s lots of information out there:

- A good first look at writing tests for Django can be found in the documentation on Writing and running tests.

- Dive Into Python (a free online book for beginning Python developers) includes a great introduction to Unit Testing.

- After reading those, if you want something a little meatier to sink your teeth into, there’s always the Python unittest documentation.

Running your new test

Remember that we haven’t actually made any modifications to BaseForm yet, so our tests are going to fail. Let’s run all the tests in the forms_tests folder to make sure that’s really what happens. From the command line, cd into the Django tests/ directory and run:

$ ./runtests.py forms_tests

If the tests ran correctly, you should see one failure corresponding to the test method we added. If all of the tests passed, then you’ll want to make sure that you added the new test shown above to the appropriate folder and class.

Writing the code for your ticket

Next we’ll be adding the functionality described in ticket #24788 to Django.

Writing the code for ticket #24788

Navigate to the django/django/forms/ folder and open the forms.py file. Find the BaseForm class on line 72 and add the prefix class attribute right after the field_order attribute:

class BaseForm(object):
# This is the main implementation of all the Form logic. Note that this
# class is different than Form. See the comments by the Form class for
# more information. Any improvements to the form API should be made to
# *this* class, not to the Form class.
field_order = None
prefix = None

Verifying your test now passes

Once you’re done modifying Django, we need to make sure that the tests we wrote earlier pass, so we can see whether the code we wrote above is working correctly. To run the tests in the forms_tests folder, cd into the Django tests/ directory and run:

$ ./runtests.py forms_tests

Oops, good thing we wrote those tests! You should still see one failure with the following exception:

AssertionError: None != 'foo'

We forgot to add the conditional statement in the __init__ method. Go ahead and change self.prefix = prefix that is now on line 87 of django/forms/forms.py, adding a conditional statement:

if prefix is not None:
self.prefix = prefix

Re-run the tests and everything should pass. If it doesn’t, make sure you correctly modified the BaseForm class as shown above and copied the new test correctly.

Running Django’s test suite for the second time

Once you’ve verified that your patch and your test are working correctly, it’s a good idea to run the entire Django test suite just to verify that your change hasn’t introduced any bugs into other areas of Django. While successfully passing the entire test suite doesn’t guarantee your code is bug free, it does help identify many bugs and regressions that might otherwise go unnoticed.

To run the entire Django test suite, cd into the Django tests/ directory and run:

$ ./runtests.py

As long as you don’t see any failures, you’re good to go.

Writing Documentation

This is a new feature, so it should be documented. Add the following section on line 1068 (at the end of the file) of django/docs/ref/forms/api.txt:

The prefix can also be specified on the form class::

>>> class PersonForm(forms.Form):
...     ...
...     prefix = 'person'

.. versionadded:: 1.9

The ability to specify ``prefix`` on the form class was added.

Since this new feature will be in an upcoming release it is also added to the release notes for Django 1.9, on line 164 under the “Forms” section in the file docs/releases/1.9.txt:

* A form prefix can be specified inside a form class, not only when
instantiating a form. See :ref:`form-prefix` for details.

For more information on writing documentation, including an explanation of what the versionadded bit is all about, see Writing documentation. That page also includes an explanation of how to build a copy of the documentation locally, so you can preview the HTML that will be generated.

Generating a patch for your changes

Now it’s time to generate a patch file that can be uploaded to Trac or applied to another copy of Django. To get a look at the content of your patch, run the following command:

$ git diff

This will display the differences between your current copy of Django (with your changes) and the revision that you initially checked out earlier in the tutorial.

Once you’re done looking at the patch, hit the q key to exit back to the command line. If the patch’s content looked okay, you can run the following command to save the patch file to your current working directory:

$ git diff > 24788.diff

You should now have a file in the root Django directory called 24788.diff. This patch file contains all your changes and should look this:

diff --git a/django/forms/forms.py b/django/forms/forms.py
index 509709f..d1370de 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -75,6 +75,7 @@ class BaseForm(object):
# information. Any improvements to the form API should be made to *this*
# class, not to the Form class.
field_order = None
+    prefix = None

def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
@@ -83,7 +84,8 @@ class BaseForm(object):
self.data = data or {}
self.files = files or {}
self.auto_id = auto_id
-        self.prefix = prefix
+        if prefix is not None:
+            self.prefix = prefix
self.initial = initial or {}
self.error_class = error_class
# Translators: This is the default suffix added to form field labels
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index 3bc39cd..008170d 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -1065,3 +1065,13 @@ You can put several Django forms inside one ``<form>`` tag. To give each
>>> print(father.as_ul())
<li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li>
<li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li>
+
+The prefix can also be specified on the form class::
+
+    >>> class PersonForm(forms.Form):
+    ...     ...
+    ...     prefix = 'person'
+
+.. versionadded:: 1.9
+
+    The ability to specify ``prefix`` on the form class was added.
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index 5b58f79..f9bb9de 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -161,6 +161,9 @@ Forms
:attr:`~django.forms.Form.field_order` attribute, the ``field_order``
constructor argument , or the :meth:`~django.forms.Form.order_fields` method.

+* A form prefix can be specified inside a form class, not only when
+  instantiating a form. See :ref:`form-prefix` for details.
+
Generic Views
^^^^^^^^^^^^^

diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index 690f205..e07fae2 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -1671,6 +1671,18 @@ class FormsTestCase(SimpleTestCase):
self.assertEqual(p.cleaned_data['last_name'], 'Lennon')
self.assertEqual(p.cleaned_data['birthday'], datetime.date(1940, 10, 9))

+    def test_class_prefix(self):
+        # Prefix can be also specified at the class level.
+        class Person(Form):
+            first_name = CharField()
+            prefix = 'foo'
+
+        p = Person()
+        self.assertEqual(p.prefix, 'foo')
+
+        p = Person(prefix='bar')
+        self.assertEqual(p.prefix, 'bar')
+
def test_forms_with_null_boolean(self):
# NullBooleanField is a bit of a special case because its presentation (widget)
# is different than its data. This is handled transparently, though.

So what do I do next?

Congratulations, you’ve generated your very first Django patch! Now that you’ve got that under your belt, you can put those skills to good use by helping to improve Django’s codebase. Generating patches and attaching them to Trac tickets is useful, however, since we are using git - adopting a more git oriented workflow is recommended.

Since we never committed our changes locally, perform the following to get your git branch back to a good starting point:

$ git reset --hard HEAD
$ git checkout master

More information for new contributors

Before you get too into writing patches for Django, there’s a little more information on contributing that you should probably take a look at:

- You should make sure to read Django’s documentation on claiming tickets and submitting patches. It covers Trac etiquette, how to claim tickets for yourself, expected coding style for patches, and many other important details.

- First time contributors should also read Django’s documentation for first time contributors. It has lots of good advice for those of us who are new to helping out with Django.

- After those, if you’re still hungry for more information about contributing, you can always browse through the rest of Django’s documentation on contributing. It contains a ton of useful information and should be your first source for answering any questions you might have.

Finding your first real ticket

Once you’ve looked through some of that information, you’ll be ready to go out and find a ticket of your own to write a patch for. Pay special attention to tickets with the “easy pickings” criterion. These tickets are often much simpler in nature and are great for first time contributors. Once you’re familiar with contributing to Django, you can move on to writing patches for more difficult and complicated tickets.

If you just want to get started already (and nobody would blame you!), try taking a look at the list of easy tickets that need patches and the easy tickets that have patches which need improvement. If you’re familiar with writing tests, you can also look at the list of easy tickets that need tests. Just remember to follow the guidelines about claiming tickets that were mentioned in the link to Django’s documentation on claiming tickets and submitting patches.

What’s next?

After a ticket has a patch, it needs to be reviewed by a second set of eyes. After uploading a patch or submitting a pull request, be sure to update the ticket metadata by setting the flags on the ticket to say “has patch”, “doesn’t need tests”, etc, so others can find it for review. Contributing doesn’t necessarily always mean writing a patch from scratch. Reviewing existing patches is also a very helpful contribution. See Triaging tickets for details.

Using Django

Introductions to all the key parts of Django you’ll need to know:

- How to install Django

- Models and databases

- Handling HTTP requests

- Working with forms

- Templates

- Class-based views

- Migrations

- Managing files

- Testing in Django

- User authentication in Django

- Django’s cache framework

- Conditional View Processing

- Cryptographic signing

- Sending email

- Internationalization and localization

- Logging

- Pagination

- Porting to Python 3

- Security in Django

- Performance and optimization

- Serializing Django objects

- Django settings

- Signals

- System check framework

- External packages

How to install Django

This document will get you up and running with Django.

Install Python

Being a Python Web framework, Django requires Python. See What Python version can I use with Django? for details.

Get the latest version of Python at https://www.python.org/download/ or with your operating system’s package manager.

Django on Jython

If you use Jython (a Python implementation for the Java platform), you’ll need to follow a few additional steps. See Running Django on Jython for details.

Python on Windows

If you are just starting with Django and using Windows, you may find How to install Django on Windows useful.

Install Apache and mod_wsgi

If you just want to experiment with Django, skip ahead to the next section; Django includes a lightweight web server you can use for testing, so you won’t need to set up Apache until you’re ready to deploy Django in production.

If you want to use Django on a production site, use Apache with mod_wsgi. mod_wsgi can operate in one of two modes: an embedded mode and a daemon mode. In embedded mode, mod_wsgi is similar to mod_perl – it embeds Python within Apache and loads Python code into memory when the server starts. Code stays in memory throughout the life of an Apache process, which leads to significant performance gains over other server arrangements. In daemon mode, mod_wsgi spawns an independent daemon process that handles requests. The daemon process can run as a different user than the Web server, possibly leading to improved security, and the daemon process can be restarted without restarting the entire Apache Web server, possibly making refreshing your codebase more seamless. Consult the mod_wsgi documentation to determine which mode is right for your setup. Make sure you have Apache installed, with the mod_wsgi module activated. Django will work with any version of Apache that supports mod_wsgi.

See How to use Django with mod_wsgi for information on how to configure mod_wsgi once you have it installed.

If you can’t use mod_wsgi for some reason, fear not: Django supports many other deployment options. One is uWSGI; it works very well with nginx. Additionally, Django follows the WSGI spec (PEP 3333), which allows it to run on a variety of server platforms.

Get your database running

If you plan to use Django’s database API functionality, you’ll need to make sure a database server is running. Django supports many different database servers and is officially supported with PostgreSQL, MySQL, Oracle and SQLite.

If you are developing a simple project or something you don’t plan to deploy in a production environment, SQLite is generally the simplest option as it doesn’t require running a separate server. However, SQLite has many differences from other databases, so if you are working on something substantial, it’s recommended to develop with the same database as you plan on using in production.

In addition to the officially supported databases, there are backends provided by 3rd parties that allow you to use other databases with Django.

In addition to a database backend, you’ll need to make sure your Python database bindings are installed.

- If you’re using PostgreSQL, you’ll need the psycopg2 package. Refer to the PostgreSQL notes for further details.

- If you’re using MySQL, you’ll need a DB API driver like mysqlclient. See notes for the MySQL backend for details.

- If you’re using SQLite you might want to read the SQLite backend notes.

- If you’re using Oracle, you’ll need a copy of cx_Oracle, but please read the notes for the Oracle backend for details regarding supported versions of both Oracle and cx_Oracle.

- If you’re using an unofficial 3rd party backend, please consult the documentation provided for any additional requirements.

If you plan to use Django’s manage.py migrate command to automatically create database tables for your models (after first installing Django and creating a project), you’ll need to ensure that Django has permission to create and alter tables in the database you’re using; if you plan to manually create the tables, you can simply grant Django SELECT, INSERT, UPDATE and DELETE permissions. After creating a database user with these permissions, you’ll specify the details in your project’s settings file, see DATABASES for details.

If you’re using Django’s testing framework to test database queries, Django will need permission to create a test database.

Remove any old versions of Django

If you are upgrading your installation of Django from a previous version, you will need to uninstall the old Django version before installing the new version.

If you installed Django using pip or easy_install previously, installing with pip or easy_install again will automatically take care of the old version, so you don’t need to do it yourself.

If you previously installed Django using python setup.py install, uninstalling is as simple as deleting the django directory from your Python site-packages. To find the directory you need to remove, you can run the following at your shell prompt (not the interactive Python prompt):

$ python -c "import django; print(django.__path__)"

Install the Django code

Installation instructions are slightly different depending on whether you’re installing a distribution-specific package, downloading the latest official release, or fetching the latest development version.

It’s easy, no matter which way you choose.

Installing an official release with pip

This is the recommended way to install Django.

1. Install pip. The easiest is to use the standalone pip installer. If your distribution already has pip installed, you might need to update it if it’s outdated. If it’s outdated, you’ll know because installation won’t work.

2. Take a look at virtualenv and virtualenvwrapper. These tools provide isolated Python environments, which are more practical than installing packages systemwide. They also allow installing packages without administrator privileges. The contributing tutorial walks through how to create a virtualenv on Python 3.

3. After you’ve created and activated a virtual environment, enter the command pip install Django at the shell prompt.

Installing a distribution-specific package

Check the distribution specific notes to see if your platform/distribution provides official Django packages/installers. Distribution-provided packages will typically allow for automatic installation of dependencies and easy upgrade paths; however, these packages will rarely contain the latest release of Django.

Installing the development version

Tracking Django development

If you decide to use the latest development version of Django, you’ll want to pay close attention to the development timeline, and you’ll want to keep an eye on the release notes for the upcoming release. This will help you stay on top of any new features you might want to use, as well as any changes you’ll need to make to your code when updating your copy of Django. (For stable releases, any necessary changes are documented in the release notes.)

If you’d like to be able to update your Django code occasionally with the latest bug fixes and improvements, follow these instructions:

1. Make sure that you have Git installed and that you can run its commands from a shell. (Enter git help at a shell prompt to test this.)

2. Check out Django’s main development branch like so:

$ git clone git://github.com/django/django.git

This will create a directory django in your current directory.

3. Make sure that the Python interpreter can load Django’s code. The most convenient way to do this is to use virtualenv, virtualenvwrapper, and pip. The contributing tutorial walks through how to create a virtualenv on Python 3.

4. After setting up and activating the virtualenv, run the following command:

$ pip install -e django/

This will make Django’s code importable, and will also make the django-admin utility command available. In other words, you’re all set!

When you want to update your copy of the Django source code, just run the command git pull from within the django directory. When you do this, Git will automatically download any changes.

Models and databases

A model is the single, definitive source of data about your data. It contains the essential fields and behaviors of the data you’re storing. Generally, each model maps to a single database table.

- Models

- Making queries

- Aggregation

- Managers

- Performing raw SQL queries

- Database transactions

- Multiple databases

- Tablespaces

- Database access optimization

- Examples of model relationship API usage

Models

A model is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data you’re storing. Generally, each model maps to a single database table.

The basics:

- Each model is a Python class that subclasses django.db.models.Model.

- Each attribute of the model represents a database field.

- With all of this, Django gives you an automatically-generated database-access API; see Making queries.

Quick example

This example model defines a Person, which has a first_name and last_name:

from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)

first_name and last_name are fields of the model. Each field is specified as a class attribute, and each attribute maps to a database column.

The above Person model would create a database table like this:

CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);

Some technical notes:

- The name of the table, myapp_person, is automatically derived from some model metadata but can be overridden. See Table names for more details.

- An id field is added automatically, but this behavior can be overridden. See Automatic primary key fields.

- The CREATE TABLE SQL in this example is formatted using PostgreSQL syntax, but it’s worth noting Django uses SQL tailored to the database backend specified in your settings file.

Using models

Once you have defined your models, you need to tell Django you’re going to use those models. Do this by editing your settings file and changing the INSTALLED_APPS setting to add the name of the module that contains your models.py.

For example, if the models for your application live in the module myapp.models (the package structure that is created for an application by the manage.py startapp script), INSTALLED_APPS should read, in part:

INSTALLED_APPS = [
#...
'myapp',
#...
]

When you add new apps to INSTALLED_APPS, be sure to run manage.py migrate, optionally making migrations for them first with manage.py makemigrations.

Fields

The most important part of a model – and the only required part of a model – is the list of database fields it defines. Fields are specified by class attributes. Be careful not to choose field names that conflict with the models API like clean, save, or delete.

Example:

from django.db import models

class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)

class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()

Field types

Each field in your model should be an instance of the appropriate Field class. Django uses the field class types to determine a few things:

- The column type, which tells the database what kind of data to store (e.g. INTEGER, VARCHAR, TEXT).

- The default HTML widget to use when rendering a form field (e.g. <input type="text">, <select>).

- The minimal validation requirements, used in Django’s admin and in automatically-generated forms.

Django ships with dozens of built-in field types; you can find the complete list in the model field reference. You can easily write your own fields if Django’s built-in ones don’t do the trick; see Writing custom model fields.

Field options

Each field takes a certain set of field-specific arguments (documented in the model field reference). For example, CharField (and its subclasses) require a max_length argument which specifies the size of the VARCHAR database field used to store the data.

There’s also a set of common arguments available to all field types. All are optional. They’re fully explained in the reference, but here’s a quick summary of the most often-used ones:

null

If True, Django will store empty values as NULL in the database. Default is False.

blank

If True, the field is allowed to be blank. Default is False.

Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.

choices

An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field. If this is given, the default form widget will be a select box instead of the standard text field and will limit choices to the choices given.

A choices list looks like this:

YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
('GR', 'Graduate'),
)

The first element in each tuple is the value that will be stored in the database. The second element will be displayed by the default form widget or in a ModelChoiceField. Given a model instance, the display value for a choices field can be accessed using the get_FOO_display() method. For example:

from django.db import models

class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)

>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'

default

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

help_text

Extra “help” text to be displayed with the form widget. It’s useful for documentation even if your field isn’t used on a form.

primary_key

If True, this field is the primary key for the model.

If you don’t specify primary_key=True for any fields in your model, Django will automatically add an IntegerField to hold the primary key, so you don’t need to set primary_key=True on any of your fields unless you want to override the default primary-key behavior. For more, see Automatic primary key fields.

The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one. For example:

from django.db import models

class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)

>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
['Apple', 'Pear']

unique

If True, this field must be unique throughout the table.

Again, these are just short descriptions of the most common field options. Full details can be found in the common model field option reference.

Automatic primary key fields

By default, Django gives each model the following field:

id = models.AutoField(primary_key=True)

This is an auto-incrementing primary key.

If you’d like to specify a custom primary key, just specify primary_key=True on one of your fields. If Django sees you’ve explicitly set Field.primary_key, it won’t add the automatic id column.

Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

Verbose field names

Each field type, except for ForeignKey, ManyToManyField and OneToOneField, takes an optional first positional argument – a verbose name. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name, converting underscores to spaces.

In this example, the verbose name is "person's first name":

first_name = models.CharField("person's first name", max_length=30)

In this example, the verbose name is "first name":

first_name = models.CharField(max_length=30)

ForeignKey, ManyToManyField and OneToOneField require the first argument to be a model class, so use the verbose_name keyword argument:

poll = models.ForeignKey(
Poll,
on_delete=models.CASCADE,
verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
verbose_name="related place",
)

The convention is not to capitalize the first letter of the verbose_name. Django will automatically capitalize the first letter where it needs to.

Relationships

Clearly, the power of relational databases lies in relating tables to each other. Django offers ways to define the three most common types of database relationships: many-to-one, many-to-many and one-to-one.

Many-to-one relationships

To define a many-to-one relationship, use django.db.models.ForeignKey. You use it just like any other Field type: by including it as a class attribute of your model.

ForeignKey requires a positional argument: the class to which the model is related.

For example, if a Car model has a Manufacturer – that is, a Manufacturer makes multiple cars but each Car only has one Manufacturer – use the following definitions:

from django.db import models

class Manufacturer(models.Model):
# ...
pass

class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# ...

You can also create recursive relationships (an object with a many-to-one relationship to itself) and relationships to models not yet defined; see the model field reference for details.

It’s suggested, but not required, that the name of a ForeignKey field (manufacturer in the example above) be the name of the model, lowercase. You can, of course, call the field whatever you want. For example:

class Car(models.Model):
company_that_makes_it = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
)
# ...

See also

ForeignKey fields accept a number of extra arguments which are explained in the model field reference. These options help define how the relationship should work; all are optional.

For details on accessing backwards-related objects, see the Following relationships backward example.

For sample code, see the Many-to-one relationship model example.

Many-to-many relationships

To define a many-to-many relationship, use ManyToManyField. You use it just like any other Field type: by including it as a class attribute of your model.

ManyToManyField requires a positional argument: the class to which the model is related.

For example, if a Pizza has multiple Topping objects – that is, a Topping can be on multiple pizzas and each Pizza has multiple toppings – here’s how you’d represent that:

from django.db import models

class Topping(models.Model):
# ...
pass

class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)

As with ForeignKey, you can also create recursive relationships (an object with a many-to-many relationship to itself) and relationships to models not yet defined.

It’s suggested, but not required, that the name of a ManyToManyField (toppings in the example above) be a plural describing the set of related model objects.

It doesn’t matter which model has the ManyToManyField, but you should only put it in one of the models – not both.

Generally, ManyToManyField instances should go in the object that’s going to be edited on a form. In the above example, toppings is in Pizza (rather than Topping having a pizzas ManyToManyField ) because it’s more natural to think about a pizza having toppings than a topping being on multiple pizzas. The way it’s set up above, the Pizza form would let users select the toppings.

See also

See the Many-to-many relationship model example for a full example.

ManyToManyField fields also accept a number of extra arguments which are explained in the model field reference. These options help define how the relationship should work; all are optional.

Extra fields on many-to-many relationships

When you’re only dealing with simple many-to-many relationships such as mixing and matching pizzas and toppings, a standard ManyToManyField is all you need. However, sometimes you may need to associate data with the relationship between two models.

For example, consider the case of an application tracking the musical groups which musicians belong to. There is a many-to-many relationship between a person and the groups of which they are a member, so you could use a ManyToManyField to represent this relationship. However, there is a lot of detail about the membership that you might want to collect, such as the date at which the person joined the group.

For these situations, Django allows you to specify the model that will be used to govern the many-to-many relationship. You can then put extra fields on the intermediate model. The intermediate model is associated with the ManyToManyField using the through argument to point to the model that will act as an intermediary. For our musician example, the code would look something like this:

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=128)

def __str__(self):              # __unicode__ on Python 2
return self.name

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')

def __str__(self):              # __unicode__ on Python 2
return self.name

class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)

When you set up the intermediary model, you explicitly specify foreign keys to the models that are involved in the many-to-many relationship. This explicit declaration defines how the two models are related.

There are a few restrictions on the intermediate model:

- Your intermediate model must contain one - and only one - foreign key to the source model (this would be Group in our example), or you must explicitly specify the foreign keys Django should use for the relationship using ManyToManyField.through_fields. If you have more than one foreign key and through_fields is not specified, a validation error will be raised. A similar restriction applies to the foreign key to the target model (this would be Person in our example).

- For a model which has a many-to-many relationship to itself through an intermediary model, two foreign keys to the same model are permitted, but they will be treated as the two (different) sides of the many-to-many relationship. If there are more than two foreign keys though, you must also specify through_fields as above, or a validation error will be raised.

- When defining a many-to-many relationship from a model to itself, using an intermediary model, you must use symmetrical=False (see the model field reference).

Now that you have set up your ManyToManyField to use your intermediary model (Membership, in this case), you’re ready to start creating some many-to-many relationships. You do this by creating instances of the intermediate model:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason="Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]

Unlike normal many-to-many fields, you can’t use add, create, or assignment (i.e., beatles.members = [...]) to create relationships:

# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name="George Harrison")
# AND NEITHER WILL THIS
>>> beatles.members = [john, paul, ringo, george]

Why? You can’t just create a relationship between a Person and a Group - you need to specify all the detail for the relationship required by the Membership model. The simple add, create and assignment calls don’t provide a way to specify this extra detail. As a result, they are disabled for many-to-many relationships that use an intermediate model. The only way to create this type of relationship is to create instances of the intermediate model.

The remove() method is disabled for similar reasons. However, the clear() method can be used to remove all many-to-many relationships for an instance:

>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
[]

Once you have established the many-to-many relationships by creating instances of your intermediate model, you can issue queries. Just as with normal many-to-many relationships, you can query using the attributes of the many-to-many-related model:

# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>]

As you are using an intermediate model, you can also query on its attributes:

# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]

If you need to access a membership’s information you may do so by directly querying the Membership model:

>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

Another way to access the same information is by querying the many-to-many reverse relationship from a Person object:

>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

One-to-one relationships

To define a one-to-one relationship, use OneToOneField. You use it just like any other Field type: by including it as a class attribute of your model.

This is most useful on the primary key of an object when that object “extends” another object in some way.

OneToOneField requires a positional argument: the class to which the model is related.

For example, if you were building a database of “places”, you would build pretty standard stuff such as address, phone number, etc. in the database. Then, if you wanted to build a database of restaurants on top of the places, instead of repeating yourself and replicating those fields in the Restaurant model, you could make Restaurant have a OneToOneField to Place (because a restaurant “is a” place; in fact, to handle this you’d typically use inheritance, which involves an implicit one-to-one relation).

As with ForeignKey, a recursive relationship can be defined and references to as-yet undefined models can be made.

See also

See the One-to-one relationship model example for a full example.

OneToOneField fields also accept an optional parent_link argument.

OneToOneField classes used to automatically become the primary key on a model. This is no longer true (although you can manually pass in the primary_key argument if you like). Thus, it’s now possible to have multiple fields of type OneToOneField on a single model.

Models across files

It’s perfectly OK to relate a model to one from another app. To do this, import the related model at the top of the file where your model is defined. Then, just refer to the other model class wherever needed. For example:

from django.db import models
from geography.models import ZipCode

class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
ZipCode,
on_delete=models.SET_NULL,
blank=True,
null=True,
)

Field name restrictions

Django places only two restrictions on model field names:

1. A field name cannot be a Python reserved word, because that would result in a Python syntax error. For example:

class Example(models.Model):
pass = models.IntegerField() # 'pass' is a reserved word!

2. A field name cannot contain more than one underscore in a row, due to the way Django’s query lookup syntax works. For example:

class Example(models.Model):
foo__bar = models.IntegerField() # 'foo__bar' has two underscores!

These limitations can be worked around, though, because your field name doesn’t necessarily have to match your database column name. See the db_column option.

SQL reserved words, such as join, where or select, are allowed as model field names, because Django escapes all database table names and column names in every underlying SQL query. It uses the quoting syntax of your particular database engine.

Custom field types

If one of the existing model fields cannot be used to fit your purposes, or if you wish to take advantage of some less common database column types, you can create your own field class. Full coverage of creating your own fields is provided in Writing custom model fields.

Meta options

Give your model metadata by using an inner class Meta, like so:

from django.db import models

class Ox(models.Model):
horn_length = models.IntegerField()

class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"

Model metadata is “anything that’s not a field”, such as ordering options (ordering), database table name (db_table), or human-readable singular and plural names (verbose_name and verbose_name_plural). None are required, and adding class Meta to a model is completely optional.

A complete list of all possible Meta options can be found in the model option reference.

Model attributes

objects

The most important attribute of a model is the Manager. It’s the interface through which database query operations are provided to Django models and is used to retrieve the instances from the database. If no custom Manager is defined, the default name is objects. Managers are only accessible via model classes, not the model instances.

Model methods

Define custom methods on a model to add custom “row-level” functionality to your objects. Whereas Manager methods are intended to do “table-wide” things, model methods should act on a particular model instance.

This is a valuable technique for keeping business logic in one place – the model.

For example, this model has a few custom methods:

from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()

def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"

def _get_full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)

The last method in this example is a property.

The model instance reference has a complete list of methods automatically given to each model. You can override most of these – see overriding predefined model methods, below – but there are a couple that you’ll almost always want to define:

__str__() (Python 3)

A Python “magic method” that returns a unicode “representation” of any object. This is what Python and Django will use whenever a model instance needs to be coerced and displayed as a plain string. Most notably, this happens when you display an object in an interactive console or in the admin.

You’ll always want to define this method; the default isn’t very helpful at all.

__unicode__() (Python 2)

Python 2 equivalent of __str__().

get_absolute_url()

This tells Django how to calculate the URL for an object. Django uses this in its admin interface, and any time it needs to figure out a URL for an object.

Any object that has a URL that uniquely identifies it should define this method.

Overriding predefined model methods

There’s another set of model methods that encapsulate a bunch of database behavior that you’ll want to customize. In particular you’ll often want to change the way save() and delete() work.

You’re free to override these methods (and any other model method) to alter behavior.

A classic use-case for overriding the built-in methods is if you want something to happen whenever you save an object. For example (see save() for documentation of the parameters it accepts):

from django.db import models

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()

def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
do_something_else()

You can also prevent saving:

from django.db import models

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()

def save(self, *args, **kwargs):
if self.name == "Yoko Ono's blog":
return # Yoko shall never have her own blog!
else:
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.

It’s important to remember to call the superclass method – that’s that super(Blog, self).save(*args, **kwargs) business – to ensure that the object still gets saved into the database. If you forget to call the superclass method, the default behavior won’t happen and the database won’t get touched.

It’s also important that you pass through the arguments that can be passed to the model method – that’s what the *args, **kwargs bit does. Django will, from time to time, extend the capabilities of built-in model methods, adding new arguments. If you use *args, **kwargs in your method definitions, you are guaranteed that your code will automatically support those arguments when they are added.

Overridden model methods are not called on bulk operations

Note that the delete() method for an object is not necessarily called when deleting objects in bulk using a QuerySet or as a result of a cascading delete. To ensure customized delete logic gets executed, you can use pre_delete and/or post_delete signals.

Unfortunately, there isn’t a workaround when creating or updating objects in bulk, since none of save(), pre_save, and post_save are called.

Executing custom SQL

Another common pattern is writing custom SQL statements in model methods and module-level methods. For more details on using raw SQL, see the documentation on using raw SQL.

Model inheritance

Model inheritance in Django works almost identically to the way normal class inheritance works in Python, but the basics at the beginning of the page should still be followed. That means the base class should subclass django.db.models.Model.

The only decision you have to make is whether you want the parent models to be models in their own right (with their own database tables), or if the parents are just holders of common information that will only be visible through the child models.

There are three styles of inheritance that are possible in Django.

1. Often, you will just want to use the parent class to hold information that you don’t want to have to type out for each child model. This class isn’t going to ever be used in isolation, so Abstract base classes are what you’re after.

2. If you’re subclassing an existing model (perhaps something from another application entirely) and want each model to have its own database table, Multi-table inheritance is the way to go.

3. Finally, if you only want to modify the Python-level behavior of a model, without changing the models fields in any way, you can use Proxy models.

Abstract base classes

Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class. This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class. It is an error to have fields in the abstract base class with the same name as those in the child (and Django will raise an exception).

An example:

from django.db import models

class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()

class Meta:
abstract = True

class Student(CommonInfo):
home_group = models.CharField(max_length=5)

The Student model will have three fields: name, age and home_group. The CommonInfo model cannot be used as a normal Django model, since it is an abstract base class. It does not generate a database table or have a manager, and cannot be instantiated or saved directly.

For many uses, this type of model inheritance will be exactly what you want. It provides a way to factor out common information at the Python level, while still only creating one database table per child model at the database level.

Meta inheritance

When an abstract base class is created, Django makes any Meta inner class you declared in the base class available as an attribute. If a child class does not declare its own Meta class, it will inherit the parent’s Meta. If the child wants to extend the parent’s Meta class, it can subclass it. For example:

from django.db import models

class CommonInfo(models.Model):
# ...
class Meta:
abstract = True
ordering = ['name']

class Student(CommonInfo):
# ...
class Meta(CommonInfo.Meta):
db_table = 'student_info'

Django does make one adjustment to the Meta class of an abstract base class: before installing the Meta attribute, it sets abstract=False. This means that children of abstract base classes don’t automatically become abstract classes themselves. Of course, you can make an abstract base class that inherits from another abstract base class. You just need to remember to explicitly set abstract=True each time.

Some attributes won’t make sense to include in the Meta class of an abstract base class. For example, including db_table would mean that all the child classes (the ones that don’t specify their own Meta) would use the same database table, which is almost certainly not what you want.

Be careful with related_name

If you are using the related_name attribute on a ForeignKey or ManyToManyField, you must always specify a unique reverse name for the field. This would normally cause a problem in abstract base classes, since the fields on this class are included into each of the child classes, with exactly the same values for the attributes (including related_name) each time.

To work around this problem, when you are using related_name in an abstract base class (only), part of the name should contain '%(app_label)s' and '%(class)s'.

- '%(class)s' is replaced by the lower-cased name of the child class that the field is used in.

- '%(app_label)s' is replaced by the lower-cased name of the app the child class is contained within. Each installed application name must be unique and the model class names within each app must also be unique, therefore the resulting name will end up being different.

For example, given an app common/models.py:

from django.db import models

class Base(models.Model):
m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")

class Meta:
abstract = True

class ChildA(Base):
pass

class ChildB(Base):
pass

Along with another app rare/models.py:

from common.models import Base

class ChildB(Base):
pass

The reverse name of the common.ChildA.m2m field will be common_childa_related, while the reverse name of the common.ChildB.m2m field will be common_childb_related, and finally the reverse name of the rare.ChildB.m2m field will be rare_childb_related. It is up to you how you use the '%(class)s' and '%(app_label)s portion to construct your related name, but if you forget to use it, Django will raise errors when you perform system checks (or run migrate).

If you don’t specify a related_name attribute for a field in an abstract base class, the default reverse name will be the name of the child class followed by '_set', just as it normally would be if you’d declared the field directly on the child class. For example, in the above code, if the related_name attribute was omitted, the reverse name for the m2m field would be childa_set in the ChildA case and childb_set for the ChildB field.

Multi-table inheritance

The second type of model inheritance supported by Django is when each model in the hierarchy is a model all by itself. Each model corresponds to its own database table and can be queried and created individually. The inheritance relationship introduces links between the child model and each of its parents (via an automatically-created OneToOneField). For example:

from django.db import models

class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)

class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)

All of the fields of Place will also be available in Restaurant, although the data will reside in a different database table. So these are both possible:

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")

If you have a Place that is also a Restaurant, you can get from the Place object to the Restaurant object by using the lower-case version of the model name:

>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>

However, if p in the above example was not a Restaurant (it had been created directly as a Place object or was the parent of some other class), referring to p.restaurant would raise a Restaurant.DoesNotExist exception.

Meta and multi-table inheritance

In the multi-table inheritance situation, it doesn’t make sense for a child class to inherit from its parent’s Meta class. All the Meta options have already been applied to the parent class and applying them again would normally only lead to contradictory behavior (this is in contrast with the abstract base class case, where the base class doesn’t exist in its own right).

So a child model does not have access to its parent’s Meta class. However, there are a few limited cases where the child inherits behavior from the parent: if the child does not specify an ordering attribute or a get_latest_by attribute, it will inherit these from its parent.

If the parent has an ordering and you don’t want the child to have any natural ordering, you can explicitly disable it:

class ChildModel(ParentModel):
# ...
class Meta:
# Remove parent's ordering effect
ordering = []

Inheritance and reverse relations

Because multi-table inheritance uses an implicit OneToOneField to link the child and the parent, it’s possible to move from the parent down to the child, as in the above example. However, this uses up the name that is the default related_name value for ForeignKey and ManyToManyField relations. If you are putting those types of relations on a subclass of the parent model, you must specify the related_name attribute on each such field. If you forget, Django will raise a validation error.

For example, using the above Place class again, let’s create another subclass with a ManyToManyField:

class Supplier(Place):
customers = models.ManyToManyField(Place)

This results in the error:

Reverse query name for 'Supplier.customers' clashes with reverse query
name for 'Supplier.place_ptr'.

HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.

Adding related_name to the customers field as follows would resolve the error: models.ManyToManyField(Place, related_name='provider').

Specifying the parent link field

As mentioned, Django will automatically create a OneToOneField linking your child class back to any non-abstract parent models. If you want to control the name of the attribute linking back to the parent, you can create your own OneToOneField and set parent_link=True to indicate that your field is the link back to the parent class.

Proxy models

When using multi-table inheritance, a new database table is created for each subclass of a model. This is usually the desired behavior, since the subclass needs a place to store any additional data fields that are not present on the base class. Sometimes, however, you only want to change the Python behavior of a model – perhaps to change the default manager, or add a new method.

This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.

Proxy models are declared like normal models. You tell Django that it’s a proxy model by setting the proxy attribute of the Meta class to True.

For example, suppose you want to add a method to the Person model. You can do it like this:

from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)

class MyPerson(Person):
class Meta:
proxy = True

def do_something(self):
# ...
pass

The MyPerson class operates on the same database table as its parent Person class. In particular, any new instances of Person will also be accessible through MyPerson, and vice-versa:

>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>

You could also use a proxy model to define a different default ordering on a model. You might not always want to order the Person model, but regularly order by the last_name attribute when you use the proxy. This is easy:

class OrderedPerson(Person):
class Meta:
ordering = ["last_name"]
proxy = True

Now normal Person queries will be unordered and OrderedPerson queries will be ordered by last_name.

QuerySets still return the model that was requested

There is no way to have Django return, say, a MyPerson object whenever you query for Person objects. A queryset for Person objects will return those types of objects. The whole point of proxy objects is that code relying on the original Person will use those and your own code can use the extensions you included (that no other code is relying on anyway). It is not a way to replace the Person (or any other) model everywhere with something of your own creation.

Base class restrictions

A proxy model must inherit from exactly one non-abstract model class. You can’t inherit from multiple non-abstract models as the proxy model doesn’t provide any connection between the rows in the different database tables. A proxy model can inherit from any number of abstract model classes, providing they do not define any model fields.

Proxy model managers

If you don’t specify any model managers on a proxy model, it inherits the managers from its model parents. If you define a manager on the proxy model, it will become the default, although any managers defined on the parent classes will still be available.

Continuing our example from above, you could change the default manager used when you query the Person model like this:

from django.db import models

class NewManager(models.Manager):
# ...
pass

class MyPerson(Person):
objects = NewManager()

class Meta:
proxy = True

If you wanted to add a new manager to the Proxy, without replacing the existing default, you can use the techniques described in the custom manager documentation: create a base class containing the new managers and inherit that after the primary base class:

# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
secondary = NewManager()

class Meta:
abstract = True

class MyPerson(Person, ExtraManagers):
class Meta:
proxy = True

You probably won’t need to do this very often, but, when you do, it’s possible.

Differences between proxy inheritance and unmanaged models

Proxy model inheritance might look fairly similar to creating an unmanaged model, using the managed attribute on a model’s Meta class. The two alternatives are not quite the same and it’s worth considering which one you should use.

One difference is that you can (and, in fact, must unless you want an empty model) specify model fields on models with Meta.managed=False. You could, with careful setting of Meta.db_table create an unmanaged model that shadowed an existing model and add Python methods to it. However, that would be very repetitive and fragile as you need to keep both copies synchronized if you make any changes.

The other difference that is more important for proxy models, is how model managers are handled. Proxy models are intended to behave exactly like the model they are proxying for. So they inherit the parent model’s managers, including the default manager. In the normal multi-table model inheritance case, children do not inherit managers from their parents as the custom managers aren’t always appropriate when extra fields are involved. The manager documentation has more details about this latter case.

When these two features were implemented, attempts were made to squash them into a single option. It turned out that interactions with inheritance, in general, and managers, in particular, made the API very complicated and potentially difficult to understand and use. It turned out that two options were needed in any case, so the current separation arose.

So, the general rules are:

1. If you are mirroring an existing model or database table and don’t want all the original database table columns, use Meta.managed=False. That option is normally useful for modeling database views and tables not under the control of Django.

2. If you are wanting to change the Python-only behavior of a model, but keep all the same fields as in the original, use Meta.proxy=True. This sets things up so that the proxy model is an exact copy of the storage structure of the original model when data is saved.

Multiple inheritance

Just as with Python’s subclassing, it’s possible for a Django model to inherit from multiple parent models. Keep in mind that normal Python name resolution rules apply. The first base class that a particular name (e.g. Meta) appears in will be the one that is used; for example, this means that if multiple parents contain a Meta class, only the first one is going to be used, and all others will be ignored.

Generally, you won’t need to inherit from multiple parents. The main use-case where this is useful is for “mix-in” classes: adding a particular extra field or method to every class that inherits the mix-in. Try to keep your inheritance hierarchies as simple and straightforward as possible so that you won’t have to struggle to work out where a particular piece of information is coming from.

Note that inheriting from multiple models that have a common id primary key field will raise an error. To properly use multiple inheritance, you can use an explicit AutoField in the base models:

class Article(models.Model):
article_id = models.AutoField(primary_key=True)
...

class Book(models.Model):
book_id = models.AutoField(primary_key=True)
...

class BookReview(Book, Article):
pass

Or use a common ancestor to hold the AutoField:

class Piece(models.Model):
pass

class Article(Piece):
...

class Book(Piece):
...

class BookReview(Book, Article):
pass

Field name “hiding” is not permitted

In normal Python class inheritance, it is permissible for a child class to override any attribute from the parent class. In Django, this is not permitted for attributes that are Field instances (at least, not at the moment). If a base class has a field called author, you cannot create another model field called author in any class that inherits from that base class.

Overriding fields in a parent model leads to difficulties in areas such as initializing new instances (specifying which field is being initialized in Model.__init__) and serialization. These are features which normal Python class inheritance doesn’t have to deal with in quite the same way, so the difference between Django model inheritance and Python class inheritance isn’t arbitrary.

This restriction only applies to attributes which are Field instances. Normal Python attributes can be overridden if you wish. It also only applies to the name of the attribute as Python sees it: if you are manually specifying the database column name, you can have the same column name appearing in both a child and an ancestor model for multi-table inheritance (they are columns in two different database tables).

Django will raise a FieldError if you override any model field in any ancestor model.

Organizing models in a package

The manage.py startapp command creates an application structure that includes a models.py file. If you have many models, organizing them in separate files may be useful.

To do so, create a models package. Remove models.py and create a myapp/models/ directory with an __init__.py file and the files to store your models. You must import the models in the __init__.py file.

For example, if you had organic.py and synthetic.py in the models directory:

myapp/models/__init__.py

from .organic import Person
from .synthetic import Robot

Explicitly importing each model rather than using from .models import * has the advantages of not cluttering the namespace, making code more readable, and keeping code analysis tools useful.

See also

The Models Reference

Covers all the model related APIs including model fields, related objects, and QuerySet.

Making queries

Once you’ve created your data models, Django automatically gives you a database-abstraction API that lets you create, retrieve, update and delete objects. This document explains how to use this API. Refer to the data model reference for full details of all the various model lookup options.

Throughout this guide (and in the reference), we’ll refer to the following models, which comprise a Weblog application:

from django.db import models

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()

def __str__(self):              # __unicode__ on Python 2
return self.name

class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()

def __str__(self):              # __unicode__ on Python 2
return self.name

class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()

def __str__(self):              # __unicode__ on Python 2
return self.headline

Creating objects

To represent database-table data in Python objects, Django uses an intuitive system: A model class represents a database table, and an instance of that class represents a particular record in the database table.

To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database.

Assuming models live in a file mysite/blog/models.py, here’s an example:

>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

This performs an INSERT SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save().

The save() method has no return value.

See also

save() takes a number of advanced options not described here. See the documentation for save() for complete details.

To create and save an object in a single step, use the create() method.

Saving changes to objects

To save changes to an object that’s already in the database, use save().

Given a Blog instance b5 that has already been saved to the database, this example changes its name and updates its record in the database:

>>> b5.name = 'New name'
>>> b5.save()

This performs an UPDATE SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save().

Saving ForeignKey and ManyToManyField fields

Updating a ForeignKey field works exactly the same way as saving a normal field – simply assign an object of the right type to the field in question. This example updates the blog attribute of an Entry instance entry, assuming appropriate instances of Entry and Blog are already saved to the database (so we can retrieve them below):

>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

Updating a ManyToManyField works a little differently – use the add() method on the field to add a record to the relation. This example adds the Author instance joe to the entry object:

>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)

To add multiple records to a ManyToManyField in one go, include multiple arguments in the call to add(), like this:

>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)

Django will complain if you try to assign or add an object of the wrong type.

Retrieving objects

To retrieve objects from your database, construct a QuerySet via a Manager on your model class.

A QuerySet represents a collection of objects from your database. It can have zero, one or many filters. Filters narrow down the query results based on the given parameters. In SQL terms, a QuerySet equates to a SELECT statement, and a filter is a limiting clause such as WHERE or LIMIT.

You get a QuerySet by using your model’s Manager. Each model has at least one Manager, and it’s called objects by default. Access it directly via the model class, like so:

>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback:
...
AttributeError: "Manager isn't accessible via Blog instances."

Note

Managers are accessible only via model classes, rather than from model instances, to enforce a separation between “table-level” operations and “record-level” operations.

The Manager is the main source of QuerySets for a model. For example, Blog.objects.all() returns a QuerySet that contains all Blog objects in the database.

Retrieving all objects

The simplest way to retrieve objects from a table is to get all of them. To do this, use the all() method on a Manager:

>>> all_entries = Entry.objects.all()

The all() method returns a QuerySet of all the objects in the database.

Retrieving specific objects with filters

The QuerySet returned by all() describes all objects in the database table. Usually, though, you’ll need to select only a subset of the complete set of objects.

To create such a subset, you refine the initial QuerySet, adding filter conditions. The two most common ways to refine a QuerySet are:

filter(**kwargs)

Returns a new QuerySet containing objects that match the given lookup parameters.

exclude(**kwargs)

Returns a new QuerySet containing objects that do not match the given lookup parameters.

The lookup parameters (**kwargs in the above function definitions) should be in the format described in Field lookups below.

For example, to get a QuerySet of blog entries from the year 2006, use filter() like so:

Entry.objects.filter(pub_date__year=2006)

With the default manager class, it is the same as:

Entry.objects.all().filter(pub_date__year=2006)

Chaining filters

The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example:

>>> Entry.objects.filter(
...     headline__startswith='What'
... ).exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(
...     pub_date__gte=datetime(2005, 1, 30)
... )

This takes the initial QuerySet of all entries in the database, adds a filter, then an exclusion, then another filter. The final result is a QuerySet containing all entries with a headline that starts with “What”, that were published between January 30, 2005, and the current day.

Filtered QuerySets are unique

Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused.

Example:

>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())

These three QuerySets are separate. The first is a base QuerySet containing all entries that contain a headline starting with “What”. The second is a subset of the first, with an additional criteria that excludes records whose pub_date is today or in the future. The third is a subset of the first, with an additional criteria that selects only the records whose pub_date is today or in the future. The initial QuerySet (q1) is unaffected by the refinement process.

QuerySets are lazy

QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated. Take a look at this example:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

Though this looks like three database hits, in fact it hits the database only once, at the last line (print(q)). In general, the results of a QuerySet aren’t fetched from the database until you “ask” for them. When you do, the QuerySet is evaluated by accessing the database. For more details on exactly when evaluation takes place, see When QuerySets are evaluated.

Retrieving a single object with get()

filter() will always give you a QuerySet, even if only a single object matches the query - in this case, it will be a QuerySet containing a single element.

If you know there is only one object that matches your query, you can use the get() method on a Manager which returns the object directly:

>>> one_entry = Entry.objects.get(pk=1)

You can use any query expression with get(), just like with filter() - again, see Field lookups below.

Note that there is a difference between using get(), and using filter() with a slice of [0]. If there are no results that match the query, get() will raise a DoesNotExist exception. This exception is an attribute of the model class that the query is being performed on - so in the code above, if there is no Entry object with a primary key of 1, Django will raise Entry.DoesNotExist.

Similarly, Django will complain if more than one item matches the get() query. In this case, it will raise MultipleObjectsReturned, which again is an attribute of the model class itself.

Other QuerySet methods

Most of the time you’ll use all(), get(), filter() and exclude() when you need to look up objects from the database. However, that’s far from all there is; see the QuerySet API Reference for a complete list of all the various QuerySet methods.

Limiting QuerySets

Use a subset of Python’s array-slicing syntax to limit your QuerySet to a certain number of results. This is the equivalent of SQL’s LIMIT and OFFSET clauses.

For example, this returns the first 5 objects (LIMIT 5):

>>> Entry.objects.all()[:5]

This returns the sixth through tenth objects (OFFSET 5 LIMIT 5):

>>> Entry.objects.all()[5:10]

Negative indexing (i.e. Entry.objects.all()[-1]) is not supported.

Generally, slicing a QuerySet returns a new QuerySet – it doesn’t evaluate the query. An exception is if you use the “step” parameter of Python slice syntax. For example, this would actually execute the query in order to return a list of every second object of the first 10:

>>> Entry.objects.all()[:10:2]

To retrieve a single object rather than a list (e.g. SELECT foo FROM bar LIMIT 1), use a simple index instead of a slice. For example, this returns the first Entry in the database, after ordering entries alphabetically by headline:

>>> Entry.objects.order_by('headline')[0]

This is roughly equivalent to:

>>> Entry.objects.order_by('headline')[0:1].get()

Note, however, that the first of these will raise IndexError while the second will raise DoesNotExist if no objects match the given criteria. See get() for more details.

Field lookups

Field lookups are how you specify the meat of an SQL WHERE clause. They’re specified as keyword arguments to the QuerySet methods filter(), exclude() and get().

Basic lookups keyword arguments take the form field__lookuptype=value. (That’s a double-underscore). For example:

>>> Entry.objects.filter(pub_date__lte='2006-01-01')

translates (roughly) into the following SQL:

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

How this is possible

Python has the ability to define functions that accept arbitrary name-value arguments whose names and values are evaluated at runtime. For more information, see Keyword Arguments in the official Python tutorial.

The field specified in a lookup has to be the name of a model field. There’s one exception though, in case of a ForeignKey you can specify the field name suffixed with _id. In this case, the value parameter is expected to contain the raw value of the foreign model’s primary key. For example:

>>> Entry.objects.filter(blog_id=4)

If you pass an invalid keyword argument, a lookup function will raise TypeError.

The database API supports about two dozen lookup types; a complete reference can be found in the field lookup reference. To give you a taste of what’s available, here’s some of the more common lookups you’ll probably use:

exact

An “exact” match. For example:

>>> Entry.objects.get(headline__exact="Cat bites dog")

Would generate SQL along these lines:

SELECT ... WHERE headline = 'Cat bites dog';

If you don’t provide a lookup type – that is, if your keyword argument doesn’t contain a double underscore – the lookup type is assumed to be exact.

For example, the following two statements are equivalent:

>>> Blog.objects.get(id__exact=14)  # Explicit form
>>> Blog.objects.get(id=14)         # __exact is implied

This is for convenience, because exact lookups are the common case.

iexact

A case-insensitive match. So, the query:

>>> Blog.objects.get(name__iexact="beatles blog")

Would match a Blog titled "Beatles Blog", "beatles blog", or even "BeAtlES blOG".

contains

Case-sensitive containment test. For example:

Entry.objects.get(headline__contains='Lennon')

Roughly translates to this SQL:

SELECT ... WHERE headline LIKE '%Lennon%';

Note this will match the headline 'Today Lennon honored' but not 'today lennon honored'.

There’s also a case-insensitive version, icontains.

startswith, endswith

Starts-with and ends-with search, respectively. There are also case-insensitive versions called istartswith and iendswith.

Again, this only scratches the surface. A complete reference can be found in the field lookup reference.

Lookups that span relationships

Django offers a powerful and intuitive way to “follow” relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.

This example retrieves all Entry objects with a Blog whose name is 'Beatles Blog':

>>> Entry.objects.filter(blog__name='Beatles Blog')

This spanning can be as deep as you’d like.

It works backwards, too. To refer to a “reverse” relationship, just use the lowercase name of the model.

This example retrieves all Blog objects which have at least one Entry whose headline contains 'Lennon':

>>> Blog.objects.filter(entry__headline__contains='Lennon')

If you are filtering across multiple relationships and one of the intermediate models doesn’t have a value that meets the filter condition, Django will treat it as if there is an empty (all values are NULL), but valid, object there. All this means is that no error will be raised. For example, in this filter:

Blog.objects.filter(entry__authors__name='Lennon')

(if there was a related Author model), if there was no author associated with an entry, it would be treated as if there was also no name attached, rather than raising an error because of the missing author. Usually this is exactly what you want to have happen. The only case where it might be confusing is if you are using isnull. Thus:

Blog.objects.filter(entry__authors__name__isnull=True)

will return Blog objects that have an empty name on the author and also those which have an empty author on the entry. If you don’t want those latter objects, you could write:

Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)

Spanning multi-valued relationships

When you are filtering an object based on a ManyToManyField or a reverse ForeignKey, there are two different sorts of filter you may be interested in. Consider the Blog/Entry relationship (Blog to Entry is a one-to-many relation). We might be interested in finding blogs that have an entry which has both “Lennon” in the headline and was published in 2008. Or we might want to find blogs that have an entry with “Lennon” in the headline as well as an entry that was published in 2008. Since there are multiple entries associated with a single Blog, both of these queries are possible and make sense in some situations.

The same type of situation arises with a ManyToManyField. For example, if an Entry has a ManyToManyField called tags, we might want to find entries linked to tags called “music” and “bands” or we might want an entry that contains a tag with a name of “music” and a status of “public”.

To handle both of these situations, Django has a consistent way of processing filter() calls. Everything inside a single filter() call is applied simultaneously to filter out items matching all those requirements. Successive filter() calls further restrict the set of objects, but for multi-valued relations, they apply to any object linked to the primary model, not necessarily those objects that were selected by an earlier filter() call.

That may sound a bit confusing, so hopefully an example will clarify. To select all blogs that contain entries with both “Lennon” in the headline and that were published in 2008 (the same entry satisfying both conditions), we would write:

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

To select all blogs that contain an entry with “Lennon” in the headline as well as an entry that was published in 2008, we would write:

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

Suppose there is only one blog that had both entries containing “Lennon” and entries from 2008, but that none of the entries from 2008 contained “Lennon”. The first query would not return any blogs, but the second query would return that one blog.

In the second example, the first filter restricts the queryset to all those blogs linked to entries with “Lennon” in the headline. The second filter restricts the set of blogs further to those that are also linked to entries that were published in 2008. The entries selected by the second filter may or may not be the same as the entries in the first filter. We are filtering the Blog items with each filter statement, not the Entry items.

Note

The behavior of filter() for queries that span multi-value relationships, as described above, is not implemented equivalently for exclude(). Instead, the conditions in a single exclude() call will not necessarily refer to the same item.

For example, the following query would exclude blogs that contain both entries with “Lennon” in the headline and entries published in 2008:

Blog.objects.exclude(
entry__headline__contains='Lennon',
entry__pub_date__year=2008,
)

However, unlike the behavior when using filter(), this will not limit blogs based on entries that satisfy both conditions. In order to do that, i.e. to select all blogs that do not contain entries published with “Lennon” that were published in 2008, you need to make two queries:

Blog.objects.exclude(
entry=Entry.objects.filter(
headline__contains='Lennon',
pub_date__year=2008,
),
)

Filters can reference fields on the model

In the examples given so far, we have constructed filters that compare the value of a model field with a constant. But what if you want to compare the value of a model field with another field on the same model?

Django provides F expressions to allow such comparisons. Instances of F() act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.

For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F() object to reference the pingback count, and use that F() object in the query:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

Django supports the use of addition, subtraction, multiplication, division, modulo, and power arithmetic with F() objects, both with constants and with other F() objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count, we would issue the query:

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

You can also use the double underscore notation to span relationships in an F() object. An F() object with a double underscore will introduce any joins needed to access the related object. For example, to retrieve all the entries where the author’s name is the same as the blog name, we could issue the query:

>>> Entry.objects.filter(authors__name=F('blog__name'))

For date and date/time fields, you can add or subtract a timedelta object. The following would return all entries that were modified more than 3 days after they were published:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

The F() objects support bitwise operations by .bitand() and .bitor(), for example:

>>> F('somefield').bitand(16)

The pk lookup shortcut

For convenience, Django provides a pk lookup shortcut, which stands for “primary key”.

In the example Blog model, the primary key is the id field, so these three statements are equivalent:

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact

The use of pk isn’t limited to __exact queries – any query term can be combined with pk to perform a query on the primary key of a model:

# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1,4,7])

# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)

pk lookups also work across joins. For example, these three statements are equivalent:

>>> Entry.objects.filter(blog__id__exact=3) # Explicit form
>>> Entry.objects.filter(blog__id=3)        # __exact is implied
>>> Entry.objects.filter(blog__pk=3)        # __pk implies __id__exact

Escaping percent signs and underscores in LIKE statements

The field lookups that equate to LIKE SQL statements (iexact, contains, icontains, startswith, istartswith, endswith and iendswith) will automatically escape the two special characters used in LIKE statements – the percent sign and the underscore. (In a LIKE statement, the percent sign signifies a multiple-character wildcard and the underscore signifies a single-character wildcard.)

This means things should work intuitively, so the abstraction doesn’t leak. For example, to retrieve all the entries that contain a percent sign, just use the percent sign as any other character:

>>> Entry.objects.filter(headline__contains='%')

Django takes care of the quoting for you; the resulting SQL will look something like this:

SELECT ... WHERE headline LIKE '%\%%';

Same goes for underscores. Both percentage signs and underscores are handled for you transparently.

Caching and QuerySets

Each QuerySet contains a cache to minimize database access. Understanding how it works will allow you to write the most efficient code.

In a newly created QuerySet, the cache is empty. The first time a QuerySet is evaluated – and, hence, a database query happens – Django saves the query results in the QuerySet’s cache and returns the results that have been explicitly requested (e.g., the next element, if the QuerySet is being iterated over). Subsequent evaluations of the QuerySet reuse the cached results.

Keep this caching behavior in mind, because it may bite you if you don’t use your QuerySets correctly. For example, the following will create two QuerySets, evaluate them, and throw them away:

>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])

That means the same database query will be executed twice, effectively doubling your database load. Also, there’s a possibility the two lists may not include the same database records, because an Entry may have been added or deleted in the split second between the two requests.

To avoid this problem, simply save the QuerySet and reuse it:

>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # Evaluate the query set.
>>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

When QuerySets are not cached

Querysets do not always cache their results. When evaluating only part of the queryset, the cache is checked, but if it is not populated then the items returned by the subsequent query are not cached. Specifically, this means that limiting the queryset using an array slice or an index will not populate the cache.

For example, repeatedly getting a certain index in a queryset object will query the database each time:

>>> queryset = Entry.objects.all()
>>> print queryset[5] # Queries the database
>>> print queryset[5] # Queries the database again

However, if the entire queryset has already been evaluated, the cache will be checked instead:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print queryset[5] # Uses cache
>>> print queryset[5] # Uses cache

Here are some examples of other actions that will result in the entire queryset being evaluated and therefore populate the cache:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)

Note

Simply printing the queryset will not populate the cache. This is because the call to __repr__() only returns a slice of the entire queryset.

Complex lookups with Q objects

Keyword argument queries – in filter(), etc. – are “AND”ed together. If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects.

A Q object (django.db.models.Q) is an object used to encapsulate a collection of keyword arguments. These keyword arguments are specified as in “Field lookups” above.

For example, this Q object encapsulates a single LIKE query:

from django.db.models import Q
Q(question__startswith='What')

Q objects can be combined using the & and | operators. When an operator is used on two Q objects, it yields a new Q object.

For example, this statement yields a single Q object that represents the “OR” of two "question__startswith" queries:

Q(question__startswith='Who') | Q(question__startswith='What')

This is equivalent to the following SQL WHERE clause:

WHERE question LIKE 'Who%' OR question LIKE 'What%'

You can compose statements of arbitrary complexity by combining Q objects with the & and | operators and use parenthetical grouping. Also, Q objects can be negated using the ~ operator, allowing for combined lookups that combine both a normal query and a negated (NOT) query:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

Each lookup function that takes keyword-arguments (e.g. filter(), exclude(), get()) can also be passed one or more Q objects as positional (not-named) arguments. If you provide multiple Q object arguments to a lookup function, the arguments will be “AND”ed together. For example:

Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

... roughly translates into the SQL:

SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

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. For example:

Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who',
)

... would be a valid query, equivalent to the previous example; but:

# INVALID QUERY
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

... would not be valid.

See also

The OR lookups examples in the Django unit tests show some possible uses of Q.

Comparing objects

To compare two model instances, just use the standard Python comparison operator, the double equals sign: ==. Behind the scenes, that compares the primary key values of two models.

Using the Entry example above, the following two statements are equivalent:

>>> some_entry == other_entry
>>> some_entry.id == other_entry.id

If a model’s primary key isn’t called id, no problem. Comparisons will always use the primary key, whatever it’s called. For example, if a model’s primary key field is called name, these two statements are equivalent:

>>> some_obj == other_obj
>>> some_obj.name == other_obj.name

Deleting objects

The delete method, conveniently, is named delete(). This method immediately deletes the object and returns the number of objects deleted and a dictionary with the number of deletions per object type. Example:

>>> e.delete()
(1, {'weblog.Entry': 1})

Changed in Django 1.9:
The return value describing the number of objects deleted was added.

You can also delete objects in bulk. Every QuerySet has a delete() method, which deletes all members of that QuerySet.

For example, this deletes all Entry objects with a pub_date year of 2005:

>>> Entry.objects.filter(pub_date__year=2005).delete()
(5, {'webapp.Entry': 5})

Keep in mind that this will, whenever possible, be executed purely in SQL, and so the delete() methods of individual object instances will not necessarily be called during the process. If you’ve provided a custom delete() method on a model class and want to ensure that it is called, you will need to “manually” delete instances of that model (e.g., by iterating over a QuerySet and calling delete() on each object individually) rather than using the bulk delete() method of a QuerySet.

Changed in Django 1.9:
The return value describing the number of objects deleted was added.

When Django deletes an object, by default it emulates the behavior of the SQL constraint ON DELETE CASCADE – in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it. For example:

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

This cascade behavior is customizable via the on_delete argument to the ForeignKey.

Note that delete() is the only QuerySet method that is not exposed on a Manager itself. This is a safety mechanism to prevent you from accidentally requesting Entry.objects.delete(), and deleting all the entries. If you do want to delete all the objects, then you have to explicitly request a complete query set:

Entry.objects.all().delete()

Copying model instances

Although there is no built-in method for copying model instances, it is possible to easily create new instance with all fields’ values copied. In the simplest case, you can just set pk to None. Using our blog example:

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1

blog.pk = None
blog.save() # blog.pk == 2

Things get more complicated if you use inheritance. Consider a subclass of Blog:

class ThemeBlog(Blog):
theme = models.CharField(max_length=200)

django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
django_blog.save() # django_blog.pk == 3

Due to how inheritance works, you have to set both pk and id to None:

django_blog.pk = None
django_blog.id = None
django_blog.save() # django_blog.pk == 4

This process does not copy related objects. If you want to copy relations, you have to write a little bit more code. In our example, Entry has a many to many field to Author:

entry = Entry.objects.all()[0] # some previous entry
old_authors = entry.authors.all()
entry.pk = None
entry.save()
entry.authors = old_authors # saves new many2many relations

Updating multiple objects at once

Sometimes you want to set a field to a particular value for all the objects in a QuerySet. You can do this with the update() method. For example:

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

You can only set non-relation fields and ForeignKey fields using this method. To update a non-relation field, provide the new value as a constant. To update ForeignKey fields, set the new value to be the new model instance you want to point to. For example:

>>> b = Blog.objects.get(pk=1)

# Change every Entry so that it belongs to this Blog.
>>> Entry.objects.all().update(blog=b)

The update() method is applied instantly and returns the number of rows matched by the query (which may not be equal to the number of rows updated if some rows already have the new value). The only restriction on the QuerySet being updated is that it can only access one database table: the model’s main table. You can filter based on related fields, but you can only update columns in the model’s main table. Example:

>>> b = Blog.objects.get(pk=1)

# Update all the headlines belonging to this Blog.
>>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')

Be aware that the update() method is converted directly to an SQL statement. It is a bulk operation for direct updates. It doesn’t run any save() methods on your models, or emit the pre_save or post_save signals (which are a consequence of calling save()), or honor the auto_now field option. If you want to save every item in a QuerySet and make sure that the save() method is called on each instance, you don’t need any special function to handle that. Just loop over them and call save():

for item in my_queryset:
item.save()

Calls to update can also use F expressions to update one field based on the value of another field in the model. This is especially useful for incrementing counters based upon their current value. For example, to increment the pingback count for every entry in the blog:

>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

However, unlike F() objects in filter and exclude clauses, you can’t introduce joins when you use F() objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F() object, a FieldError will be raised:

# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))

Related objects

When you define a relationship in a model (i.e., a ForeignKey, OneToOneField, or ManyToManyField), instances of that model will have a convenient API to access the related object(s).

Using the models at the top of this page, for example, an Entry object e can get its associated Blog object by accessing the blog attribute: e.blog.

(Behind the scenes, this functionality is implemented by Python descriptors. This shouldn’t really matter to you, but we point it out here for the curious.)

Django also creates API accessors for the “other” side of the relationship – the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().

All examples in this section use the sample Blog, Author and Entry models defined at the top of this page.

One-to-many relationships

Forward

If a model has a ForeignKey, instances of that model will have access to the related (foreign) object via a simple attribute of the model.

Example:

>>> e = Entry.objects.get(id=2)
>>> e.blog # Returns the related Blog object.

You can get and set via a foreign-key attribute. As you may expect, changes to the foreign key aren’t saved to the database until you call save(). Example:

>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()

If a ForeignKey field has null=True set (i.e., it allows NULL values), you can assign None to remove the relation. Example:

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

Forward access to one-to-many relationships is cached the first time the related object is accessed. Subsequent accesses to the foreign key on the same object instance are cached. Example:

>>> e = Entry.objects.get(id=2)
>>> print(e.blog)  # Hits the database to retrieve the associated Blog.
>>> print(e.blog)  # Doesn't hit the database; uses cached version.

Note that the select_related() QuerySet method recursively prepopulates the cache of all one-to-many relationships ahead of time. Example:

>>> e = Entry.objects.select_related().get(id=2)
>>> print(e.blog)  # Doesn't hit the database; uses cached version.
>>> print(e.blog)  # Doesn't hit the database; uses cached version.

Following relationships “backward”

If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased. This Manager returns QuerySets, which can be filtered and manipulated as described in the “Retrieving objects” section above.

Example:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

You can override the FOO_set name by setting the related_name parameter in the ForeignKey definition. For example, if the Entry model was altered to blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries'), the above example code would look like this:

>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # Returns all Entry objects related to Blog.

# b.entries is a Manager that returns QuerySets.
>>> b.entries.filter(headline__contains='Lennon')
>>> b.entries.count()

Using a custom reverse manager

By default the RelatedManager used for reverse relations is a subclass of the default manager for that model. If you would like to specify a different manager for a given query you can use the following syntax:

from django.db import models

class Entry(models.Model):
#...
objects = models.Manager()  # Default Manager
entries = EntryManager()    # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()

If EntryManager performed default filtering in its get_queryset() method, that filtering would apply to the all() call.

Of course, specifying a custom reverse manager also enables you to call its custom methods:

b.entry_set(manager='entries').is_published()

Additional methods to handle related objects

In addition to the QuerySet methods defined in “Retrieving objects” above, the ForeignKey Manager has additional methods used to handle the set of related objects. A synopsis of each is below, and complete details can be found in the related objects reference.

add(obj1, obj2, ...)

Adds the specified model objects to the related object set.

create(**kwargs)

Creates a new object, saves it and puts it in the related object set. Returns the newly created object.

remove(obj1, obj2, ...)

Removes the specified model objects from the related object set.

clear()

Removes all objects from the related object set.

set(objs)

Replace the set of related objects.

To assign the members of a related set in one fell swoop, just assign to it from any iterable object. The iterable can contain object instances, or just a list of primary key values. For example:

b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]

In this example, e1 and e2 can be full Entry instances, or integer primary key values.

If the clear() method is available, any pre-existing objects will be removed from the entry_set before all objects in the iterable (in this case, a list) are added to the set. If the clear() method is not available, all objects in the iterable will be added without removing any existing elements.

Each “reverse” operation described in this section has an immediate effect on the database. Every addition, creation and deletion is immediately and automatically saved to the database.

Many-to-many relationships

Both ends of a many-to-many relationship get automatic API access to the other end. The API works just as a “backward” one-to-many relationship, above.

The only difference is in the attribute naming: The model that defines the ManyToManyField uses the attribute name of that field itself, whereas the “reverse” model uses the lowercased model name of the original model, plus '_set' (just like reverse one-to-many relationships).

An example makes this easier to understand:

e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')

a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

Like ForeignKey, ManyToManyField can specify related_name. In the above example, if the ManyToManyField in Entry had specified related_name='entries', then each Author instance would have an entries attribute instead of entry_set.

One-to-one relationships

One-to-one relationships are very similar to many-to-one relationships. If you define a OneToOneField on your model, instances of that model will have access to the related object via a simple attribute of the model.

For example:

class EntryDetail(models.Model):
entry = models.OneToOneField(Entry, on_delete=models.CASCADE)
details = models.TextField()

ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.

The difference comes in “reverse” queries. The related model in a one-to-one relationship also has access to a Manager object, but that Manager represents a single object, rather than a collection of objects:

e = Entry.objects.get(id=2)
e.entrydetail # returns the related EntryDetail object

If no object has been assigned to this relationship, Django will raise a DoesNotExist exception.

Instances can be assigned to the reverse relationship in the same way as you would assign the forward relationship:

e.entrydetail = ed

How are the backward relationships possible?

Other object-relational mappers require you to define relationships on both sides. The Django developers believe this is a violation of the DRY (Don’t Repeat Yourself) principle, so Django only requires you to define the relationship on one end.

But how is this possible, given that a model class doesn’t know which other model classes are related to it until those other model classes are loaded?

The answer lies in the app registry. When Django starts, it imports each application listed in INSTALLED_APPS, and then the models module inside each application. Whenever a new model class is created, Django adds backward-relationships to any related models. If the related models haven’t been imported yet, Django keeps tracks of the relationships and adds them when the related models eventually are imported.

For this reason, it’s particularly important that all the models you’re using be defined in applications listed in INSTALLED_APPS. Otherwise, backwards relations may not work properly.

Queries over related objects

Queries involving related objects follow the same rules as queries involving normal value fields. When specifying the value for a query to match, you may use either an object instance itself, or the primary key value for the object.

For example, if you have a Blog object b with id=5, the following three queries would be identical:

Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly

Falling back to raw SQL

If you find yourself needing to write an SQL query that is too complex for Django’s database-mapper to handle, you can fall back on writing SQL by hand. Django has a couple of options for writing raw SQL queries; see Performing raw SQL queries.

Finally, it’s important to note that the Django database layer is merely an interface to your database. You can access your database via other tools, programming languages or database frameworks; there’s nothing Django-specific about your database.

Aggregation

The topic guide on Django’s database-abstraction API described the way that you can use Django queries that create, retrieve, update and delete individual objects. However, sometimes you will need to retrieve values that are derived by summarizing or aggregating a collection of objects. This topic guide describes the ways that aggregate values can be generated and returned using Django queries.

Throughout this guide, we’ll refer to the following models. These models are used to track the inventory for a series of online bookstores:

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()

class Publisher(models.Model):
name = models.CharField(max_length=300)
num_awards = models.IntegerField()

class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
pubdate = models.DateField()

class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
registered_users = models.PositiveIntegerField()

Cheat sheet

In a hurry? Here’s how to do common aggregate queries, assuming the models above:

# Total number of books.
>>> Book.objects.count()
2452

# Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count()
73

# Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

# Max price across all books.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')}

# Cost per page
>>> from django.db.models import F, FloatField, Sum
>>> Book.objects.all().aggregate(
...    price_per_page=Sum(F('price')/F('pages'), output_field=FloatField()))
{'price_per_page': 0.4470664529184653}

# All the following queries involve traversing the Book<->Publisher
# foreign key relationship backwards.

# Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
>>> pubs[0].num_books
73

# The top 5 publishers, in order by number of books.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323

Generating aggregates over a QuerySet

Django provides two ways to generate aggregates. The first way is to generate summary values over an entire QuerySet. For example, say you wanted to calculate the average price of all books available for sale. Django’s query syntax provides a means for describing the set of all books:

>>> Book.objects.all()

What we need is a way to calculate summary values over the objects that belong to this QuerySet. This is done by appending an aggregate() clause onto the QuerySet:

>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

The all() is redundant in this example, so this could be simplified to:

>>> Book.objects.aggregate(Avg('price'))
{'price__avg': 34.35}

The argument to the aggregate() clause describes the aggregate value that we want to compute - in this case, the average of the price field on the Book model. A list of the aggregate functions that are available can be found in the QuerySet reference.

aggregate() is a terminal clause for a QuerySet that, when invoked, returns a dictionary of name-value pairs. The name is an identifier for the aggregate value; the value is the computed aggregate. The name is automatically generated from the name of the field and the aggregate function. If you want to manually specify a name for the aggregate value, you can do so by providing that name when you specify the aggregate clause:

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}

If you want to generate more than one aggregate, you just add another argument to the aggregate() clause. So, if we also wanted to know the maximum and minimum price of all books, we would issue the query:

>>> from django.db.models import Avg, Max, Min
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

Generating aggregates for each item in a QuerySet

The second way to generate summary values is to generate an independent summary for each object in a QuerySet. For example, if you are retrieving a list of books, you may want to know how many authors contributed to each book. Each Book has a many-to-many relationship with the Author; we want to summarize this relationship for each book in the QuerySet.

Per-object summaries can be generated using the annotate() clause. When an annotate() clause is specified, each object in the QuerySet will be annotated with the specified values.

The syntax for these annotations is identical to that used for the aggregate() clause. Each argument to annotate() describes an aggregate that is to be calculated. For example, to annotate books with the number of authors:

# Build an annotated queryset
>>> from django.db.models import Count
>>> q = Book.objects.annotate(Count('authors'))
# Interrogate the first object in the queryset
>>> q[0]
<Book: The Definitive Guide to Django>
>>> q[0].authors__count
2
# Interrogate the second object in the queryset
>>> q[1]
<Book: Practical Django Projects>
>>> q[1].authors__count
1

As with aggregate(), the name for the annotation is automatically derived from the name of the aggregate function and the name of the field being aggregated. You can override this default name by providing an alias when you specify the annotation:

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

Unlike aggregate(), annotate() is not a terminal clause. The output of the annotate() clause is a QuerySet; this QuerySet can be modified using any other QuerySet operation, including filter(), order_by(), or even additional calls to annotate().

Combining multiple aggregations

Combining multiple aggregations with annotate() will yield the wrong results because joins are used instead of subqueries:

>>> book = Book.objects.first()
>>> book.authors.count()
2
>>> book.store_set.count()
3
>>> q = Book.objects.annotate(Count('authors'), Count('store'))
>>> q[0].authors__count
6
>>> q[0].store__count
6

For most aggregates, there is no way to avoid this problem, however, the Count aggregate has a distinct parameter that may help:

>>> q = Book.objects.annotate(Count('authors', distinct=True), Count('store', distinct=True))
>>> q[0].authors__count
2
>>> q[0].store__count
3

If in doubt, inspect the SQL query!

In order to understand what happens in your query, consider inspecting the query property of your QuerySet.

Joins and aggregates

So far, we have dealt with aggregates over fields that belong to the model being queried. However, sometimes the value you want to aggregate will belong to a model that is related to the model you are querying.

When specifying the field to be aggregated in an aggregate function, Django will allow you to use the same double underscore notation that is used when referring to related fields in filters. Django will then handle any table joins that are required to retrieve and aggregate the related value.

For example, to find the price range of books offered in each store, you could use the annotation:

>>> from django.db.models import Max, Min
>>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price'))

This tells Django to retrieve the Store model, join (through the many-to-many relationship) with the Book model, and aggregate on the price field of the book model to produce a minimum and maximum value.

The same rules apply to the aggregate() clause. If you wanted to know the lowest and highest price of any book that is available for sale in any of the stores, you could use the aggregate:

>>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price'))

Join chains can be as deep as you require. For example, to extract the age of the youngest author of any book available for sale, you could issue the query:

>>> Store.objects.aggregate(youngest_age=Min('books__authors__age'))

Following relationships backwards

In a way similar to Lookups that span relationships, aggregations and annotations on fields of models or models that are related to the one you are querying can include traversing “reverse” relationships. The lowercase name of related models and double-underscores are used here too.

For example, we can ask for all publishers, annotated with their respective total book stock counters (note how we use 'book' to specify the Publisher -> Book reverse foreign key hop):

>>> from django.db.models import Count, Min, Sum, Avg
>>> Publisher.objects.annotate(Count('book'))

(Every Publisher in the resulting QuerySet will have an extra attribute called book__count.)

We can also ask for the oldest book of any of those managed by every publisher:

>>> Publisher.objects.aggregate(oldest_pubdate=Min('book__pubdate'))

(The resulting dictionary will have a key called 'oldest_pubdate'. If no such alias were specified, it would be the rather long 'book__pubdate__min'.)

This doesn’t apply just to foreign keys. It also works with many-to-many relations. For example, we can ask for every author, annotated with the total number of pages considering all the books the author has (co-)authored (note how we use 'book' to specify the Author -> Book reverse many-to-many hop):

>>> Author.objects.annotate(total_pages=Sum('book__pages'))

(Every Author in the resulting QuerySet will have an extra attribute called total_pages. If no such alias were specified, it would be the rather long book__pages__sum.)

Or ask for the average rating of all the books written by author(s) we have on file:

>>> Author.objects.aggregate(average_rating=Avg('book__rating'))

(The resulting dictionary will have a key called 'average_rating'. If no such alias were specified, it would be the rather long 'book__rating__avg'.)

Aggregations and other QuerySet clauses

filter() and exclude()

Aggregates can also participate in filters. Any filter() (or exclude()) applied to normal model fields will have the effect of constraining the objects that are considered for aggregation.

When used with an annotate() clause, a filter has the effect of constraining the objects for which an annotation is calculated. For example, you can generate an annotated list of all books that have a title starting with “Django” using the query:

>>> from django.db.models import Count, Avg
>>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors'))

When used with an aggregate() clause, a filter has the effect of constraining the objects over which the aggregate is calculated. For example, you can generate the average price of all books with a title that starts with “Django” using the query:

>>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price'))

Filtering on annotations

Annotated values can also be filtered. The alias for the annotation can be used in filter() and exclude() clauses in the same way as any other model field.

For example, to generate a list of books that have more than one author, you can issue the query:

>>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)

This query generates an annotated result set, and then generates a filter based upon that annotation.

Order of annotate() and filter() clauses

When developing a complex query that involves both annotate() and filter() clauses, pay particular attention to the order in which the clauses are applied to the QuerySet.

When an annotate() clause is applied to a query, the annotation is computed over the state of the query up to the point where the annotation is requested. The practical implication of this is that filter() and annotate() are not commutative operations.

Given:

- Publisher A has two books with ratings 4 and 5.

- Publisher B has two books with ratings 1 and 4.

- Publisher C has one book with rating 1.

Here’s an example with the Count aggregate:

>>> a, b = Publisher.objects.annotate(num_books=Count('book', distinct=True)).filter(book__rating__gt=3.0)
>>> a, a.num_books
(<Publisher: A>, 2)
>>> b, b.num_books
(<Publisher: B>, 2)

>>> a, b = Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))
>>> a, a.num_books
(<Publisher: A>, 2)
>>> b, b.num_books
(<Publisher: B>, 1)

Both queries return a list of publishers that have at least one book with a rating exceeding 3.0, hence publisher C is excluded.

In the first query, the annotation precedes the filter, so the filter has no effect on the annotation. distinct=True is required to avoid a query bug.

The second query counts the number of books that have a rating exceeding 3.0 for each publisher. The filter precedes the annotation, so the filter constrains the objects considered when calculating the annotation.

Here’s another example with the Avg aggregate:

>>> a, b = Publisher.objects.annotate(avg_rating=Avg('book__rating')).filter(book__rating__gt=3.0)
>>> a, a.avg_rating
(<Publisher: A>, 4.5)  # (5+4)/2
>>> b, b.avg_rating
(<Publisher: B>, 2.5)  # (1+4)/2

>>> a, b = Publisher.objects.filter(book__rating__gt=3.0).annotate(avg_rating=Avg('book__rating'))
>>> a, a.avg_rating
(<Publisher: A>, 4.5)  # (5+4)/2
>>> b, b.avg_rating
(<Publisher: B>, 4.0)  # 4/1 (book with rating 1 excluded)

The first query asks for the average rating of all a publisher’s books for publisher’s that have at least one book with a rating exceeding 3.0. The second query asks for the average of a publisher’s book’s ratings for only those ratings exceeding 3.0.

It’s difficult to intuit how the ORM will translate complex querysets into SQL queries so when in doubt, inspect the SQL with str(queryset.query) and write plenty of tests.

order_by()

Annotations can be used as a basis for ordering. When you define an order_by() clause, the aggregates you provide can reference any alias defined as part of an annotate() clause in the query.

For example, to order a QuerySet of books by the number of authors that have contributed to the book, you could use the following query:

>>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')

values()

Ordinarily, annotations are generated on a per-object basis - an annotated QuerySet will return one result for each object in the original QuerySet. However, when a values() clause is used to constrain the columns that are returned in the result set, the method for evaluating annotations is slightly different. Instead of returning an annotated result for each result in the original QuerySet, the original results are grouped according to the unique combinations of the fields specified in the values() clause. An annotation is then provided for each unique group; the annotation is computed over all members of the group.

For example, consider an author query that attempts to find out the average rating of books written by each author:

>>> Author.objects.annotate(average_rating=Avg('book__rating'))

This will return one result for each author in the database, annotated with their average book rating.

However, the result will be slightly different if you use a values() clause:

>>> Author.objects.values('name').annotate(average_rating=Avg('book__rating'))

In this example, the authors will be grouped by name, so you will only get an annotated result for each unique author name. This means if you have two authors with the same name, their results will be merged into a single result in the output of the query; the average will be computed as the average over the books written by both authors.

Order of annotate() and values() clauses

As with the filter() clause, the order in which annotate() and values() clauses are applied to a query is significant. If the values() clause precedes the annotate(), the annotation will be computed using the grouping described by the values() clause.

However, if the annotate() clause precedes the values() clause, the annotations will be generated over the entire query set. In this case, the values() clause only constrains the fields that are generated on output.

For example, if we reverse the order of the values() and annotate() clause from our previous example:

>>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating')

This will now yield one unique result for each author; however, only the author’s name and the average_rating annotation will be returned in the output data.

You should also note that average_rating has been explicitly included in the list of values to be returned. This is required because of the ordering of the values() and annotate() clause.

If the values() clause precedes the annotate() clause, any annotations will be automatically added to the result set. However, if the values() clause is applied after the annotate() clause, you need to explicitly include the aggregate column.

Interaction with default ordering or order_by()

Fields that are mentioned in the order_by() part of a queryset (or which are used in the default ordering on a model) are used when selecting the output data, even if they are not otherwise specified in the values() call. These extra fields are used to group “like” results together and they can make otherwise identical result rows appear to be separate. This shows up, particularly, when counting things.

By way of example, suppose you have a model like this:

from django.db import models

class Item(models.Model):
name = models.CharField(max_length=10)
data = models.IntegerField()

class Meta:
ordering = ["name"]

The important part here is the default ordering on the name field. If you want to count how many times each distinct data value appears, you might try this:

# Warning: not quite correct!
Item.objects.values("data").annotate(Count("id"))

...which will group the Item objects by their common data values and then count the number of id values in each group. Except that it won’t quite work. The default ordering by name will also play a part in the grouping, so this query will group by distinct (data, name) pairs, which isn’t what you want. Instead, you should construct this queryset:

Item.objects.values("data").annotate(Count("id")).order_by()

...clearing any ordering in the query. You could also order by, say, data without any harmful effects, since that is already playing a role in the query.

This behavior is the same as that noted in the queryset documentation for distinct() and the general rule is the same: normally you won’t want extra columns playing a part in the result, so clear out the ordering, or at least make sure it’s restricted only to those fields you also select in a values() call.

Note

You might reasonably ask why Django doesn’t remove the extraneous columns for you. The main reason is consistency with distinct() and other places: Django never removes ordering constraints that you have specified (and we can’t change those other methods’ behavior, as that would violate our API stability policy).

Aggregating annotations

You can also generate an aggregate on the result of an annotation. When you define an aggregate() clause, the aggregates you provide can reference any alias defined as part of an annotate() clause in the query.

For example, if you wanted to calculate the average number of authors per book you first annotate the set of books with the author count, then aggregate that author count, referencing the annotation field:

>>> from django.db.models import Count, Avg
>>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors'))
{'num_authors__avg': 1.66}

Managers

class Manager[source]

A Manager is the interface through which database query operations are provided to Django models. At least one Manager exists for every model in a Django application.

The way Manager classes work is documented in Making queries; this document specifically touches on model options that customize Manager behavior.

Manager names

By default, Django adds a Manager with the name objects to every Django model class. However, if you want to use objects as a field name, or if you want to use a name other than objects for the Manager, you can rename it on a per-model basis. To rename the Manager for a given class, define a class attribute of type models.Manager() on that model. For example:

from django.db import models

class Person(models.Model):
#...
people = models.Manager()

Using this example model, Person.objects will generate an AttributeError exception, but Person.people.all() will provide a list of all Person objects.

Custom managers

You can use a custom Manager in a particular model by extending the base Manager class and instantiating your custom Manager in your model.

There are two reasons you might want to customize a Manager: to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.

Adding extra manager methods

Adding extra Manager methods is the preferred way to add “table-level” functionality to your models. (For “row-level” functionality – i.e., functions that act on a single instance of a model object – use Model methods, not custom Manager methods.)

A custom Manager method can return anything you want. It doesn’t have to return a QuerySet.

For example, this custom Manager offers a method with_counts(), which returns a list of all OpinionPoll objects, each with an extra num_responses attribute that is the result of an aggregate query:

from django.db import models

class PollManager(models.Manager):
def with_counts(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
SELECT p.id, p.question, p.poll_date, COUNT(*)
FROM polls_opinionpoll p, polls_response r
WHERE p.id = r.poll_id
GROUP BY p.id, p.question, p.poll_date
ORDER BY p.poll_date DESC""")
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], question=row[1], poll_date=row[2])
p.num_responses = row[3]
result_list.append(p)
return result_list

class OpinionPoll(models.Model):
question = models.CharField(max_length=200)
poll_date = models.DateField()
objects = PollManager()

class Response(models.Model):
poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE)
person_name = models.CharField(max_length=50)
response = models.TextField()

With this example, you’d use OpinionPoll.objects.with_counts() to return that list of OpinionPoll objects with num_responses attributes.

Another thing to note about this example is that Manager methods can access self.model to get the model class to which they’re attached.

Modifying a manager’s initial QuerySet

A Manager’s base QuerySet returns all objects in the system. For example, using this model:

from django.db import models

class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)

...the statement Book.objects.all() will return all books in the database.

You can override a Manager’s base QuerySet by overriding the Manager.get_queryset() method. get_queryset() should return a QuerySet with the properties you require.

For example, the following model has two Managers – one that returns all objects, and one that returns only the books by Roald Dahl:

# First, define the Manager subclass.
class DahlBookManager(models.Manager):
def get_queryset(self):
return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')

# Then hook it into the Book model explicitly.
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)

objects = models.Manager() # The default manager.
dahl_objects = DahlBookManager() # The Dahl-specific manager.

With this sample model, Book.objects.all() will return all books in the database, but Book.dahl_objects.all() will only return the ones written by Roald Dahl.

Of course, because get_queryset() returns a QuerySet object, you can use filter(), exclude() and all the other QuerySet methods on it. So these statements are all legal:

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

This example also pointed out another interesting technique: using multiple managers on the same model. You can attach as many Manager() instances to a model as you’d like. This is an easy way to define common “filters” for your models.

For example:

class AuthorManager(models.Manager):
def get_queryset(self):
return super(AuthorManager, self).get_queryset().filter(role='A')

class EditorManager(models.Manager):
def get_queryset(self):
return super(EditorManager, self).get_queryset().filter(role='E')

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
people = models.Manager()
authors = AuthorManager()
editors = EditorManager()

This example allows you to request Person.authors.all(), Person.editors.all(), and Person.people.all(), yielding predictable results.

Default managers

If you use custom Manager objects, take note that the first Manager Django encounters (in the order in which they’re defined in the model) has a special status. Django interprets the first Manager defined in a class as the “default” Manager, and several parts of Django (including dumpdata) will use that Manager exclusively for that model. As a result, it’s a good idea to be careful in your choice of default manager in order to avoid a situation where overriding get_queryset() results in an inability to retrieve objects you’d like to work with.

Using managers for related object access

By default, Django uses an instance of a “plain” manager class when accessing related objects (i.e. choice.poll), not the default manager on the related object. This is because Django needs to be able to retrieve the related object, even if it would otherwise be filtered out (and hence be inaccessible) by the default manager.

If the normal plain manager class (django.db.models.Manager) is not appropriate for your circumstances, you can force Django to use the same class as the default manager for your model by setting the use_for_related_fields attribute on the manager class. This is documented fully below.

Calling custom QuerySet methods from the manager

While most methods from the standard QuerySet are accessible directly from the Manager, this is only the case for the extra methods defined on a custom QuerySet if you also implement them on the Manager:

class PersonQuerySet(models.QuerySet):
def authors(self):
return self.filter(role='A')

def editors(self):
return self.filter(role='E')

class PersonManager(models.Manager):
def get_queryset(self):
return PersonQuerySet(self.model, using=self._db)

def authors(self):
return self.get_queryset().authors()

def editors(self):
return self.get_queryset().editors()

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
people = PersonManager()

This example allows you to call both authors() and editors() directly from the manager Person.people.

Creating a manager with QuerySet methods

In lieu of the above approach which requires duplicating methods on both the QuerySet and the Manager, QuerySet.as_manager() can be used to create an instance of Manager with a copy of a custom QuerySet’s methods:

class Person(models.Model):
...
people = PersonQuerySet.as_manager()

The Manager instance created by QuerySet.as_manager() will be virtually identical to the PersonManager from the previous example.

Not every QuerySet method makes sense at the Manager level; for instance we intentionally prevent the QuerySet.delete() method from being copied onto the Manager class.

Methods are copied according to the following rules:

- Public methods are copied by default.

- Private methods (starting with an underscore) are not copied by default.

- Methods with a queryset_only attribute set to False are always copied.

- Methods with a queryset_only attribute set to True are never copied.

For example:

class CustomQuerySet(models.QuerySet):
# Available on both Manager and QuerySet.
def public_method(self):
return

# Available only on QuerySet.
def _private_method(self):
return

# Available only on QuerySet.
def opted_out_public_method(self):
return
opted_out_public_method.queryset_only = True

# Available on both Manager and QuerySet.
def _opted_in_private_method(self):
return
_opted_in_private_method.queryset_only = False

from_queryset()

classmethod from_queryset(queryset_class)

For advanced usage you might want both a custom Manager and a custom QuerySet. You can do that by calling Manager.from_queryset() which returns a subclass of your base Manager with a copy of the custom QuerySet methods:

class BaseManager(models.Manager):
def manager_only_method(self):
return

class CustomQuerySet(models.QuerySet):
def manager_and_queryset_method(self):
return

class MyModel(models.Model):
objects = BaseManager.from_queryset(CustomQuerySet)()

You may also store the generated class into a variable:

CustomManager = BaseManager.from_queryset(CustomQuerySet)

class MyModel(models.Model):
objects = CustomManager()

Custom managers and model inheritance

Class inheritance and model managers aren’t quite a perfect match for each other. Managers are often specific to the classes they are defined on and inheriting them in subclasses isn’t necessarily a good idea. Also, because the first manager declared is the default manager, it is important to allow that to be controlled. So here’s how Django handles custom managers and model inheritance:

1. Managers defined on non-abstract base classes are not inherited by child classes. If you want to reuse a manager from a non-abstract base, redeclare it explicitly on the child class. These sorts of managers are likely to be fairly specific to the class they are defined on, so inheriting them can often lead to unexpected results (particularly as far as the default manager goes). Therefore, they aren’t passed onto child classes.

2. Managers from abstract base classes are always inherited by the child class, using Python’s normal name resolution order (names on the child class override all others; then come names on the first parent class, and so on). Abstract base classes are designed to capture information and behavior that is common to their child classes. Defining common managers is an appropriate part of this common information.

3. The default manager on a class is either the first manager declared on the class, if that exists, or the default manager of the first abstract base class in the parent hierarchy, if that exists. If no default manager is explicitly declared, Django’s normal default manager is used.

These rules provide the necessary flexibility if you want to install a collection of custom managers on a group of models, via an abstract base class, but still customize the default manager. For example, suppose you have this base class:

class AbstractBase(models.Model):
# ...
objects = CustomManager()

class Meta:
abstract = True

If you use this directly in a subclass, objects will be the default manager if you declare no managers in the base class:

class ChildA(AbstractBase):
# ...
# This class has CustomManager as the default manager.
pass

If you want to inherit from AbstractBase, but provide a different default manager, you can provide the default manager on the child class:

class ChildB(AbstractBase):
# ...
# An explicit default manager.
default_manager = OtherManager()

Here, default_manager is the default. The objects manager is still available, since it’s inherited. It just isn’t used as the default.

Finally for this example, suppose you want to add extra managers to the child class, but still use the default from AbstractBase. You can’t add the new manager directly in the child class, as that would override the default and you would have to also explicitly include all the managers from the abstract base class. The solution is to put the extra managers in another base class and introduce it into the inheritance hierarchy after the defaults:

class ExtraManager(models.Model):
extra_manager = OtherManager()

class Meta:
abstract = True

class ChildC(AbstractBase, ExtraManager):
# ...
# Default manager is CustomManager, but OtherManager is
# also available via the "extra_manager" attribute.
pass

Note that while you can define a custom manager on the abstract model, you can’t invoke any methods using the abstract model. That is:

ClassA.objects.do_something()

is legal, but:

AbstractBase.objects.do_something()

will raise an exception. This is because managers are intended to encapsulate logic for managing collections of objects. Since you can’t have a collection of abstract objects, it doesn’t make sense to be managing them. If you have functionality that applies to the abstract model, you should put that functionality in a staticmethod or classmethod on the abstract model.

Implementation concerns

Whatever features you add to your custom Manager, it must be possible to make a shallow copy of a Manager instance; i.e., the following code must work:

>>> import copy
>>> manager = MyManager()
>>> my_copy = copy.copy(manager)

Django makes shallow copies of manager objects during certain queries; if your Manager cannot be copied, those queries will fail.

This won’t be an issue for most custom managers. If you are just adding simple methods to your Manager, it is unlikely that you will inadvertently make instances of your Manager uncopyable. However, if you’re overriding __getattr__ or some other private method of your Manager object that controls object state, you should ensure that you don’t affect the ability of your Manager to be copied.

Controlling automatic manager types

This document has already mentioned a couple of places where Django creates a manager class for you: default managers and the “plain” manager used to access related objects. There are other places in the implementation of Django where temporary plain managers are needed. Those automatically created managers will normally be instances of the django.db.models.Manager class.

Throughout this section, we will use the term “automatic manager” to mean a manager that Django creates for you – either as a default manager on a model with no managers, or to use temporarily when accessing related objects.

Sometimes this default class won’t be the right choice. The default manager may not have all the methods you need to work with your data. A custom manager class of your own will allow you to create custom QuerySet objects to give you the information you need.

Django provides a way for custom manager developers to say that their manager class should be used for automatic managers whenever it is the default manager on a model. This is done by setting the use_for_related_fields attribute on the manager class:

class MyManager(models.Manager):
use_for_related_fields = True
# ...

If this attribute is set on the default manager for a model (only the default manager is considered in these situations), Django will use that class whenever it needs to automatically create a manager for the class. Otherwise, it will use django.db.models.Manager.

Historical Note

Given the purpose for which it’s used, the name of this attribute (use_for_related_fields) might seem a little odd. Originally, the attribute only controlled the type of manager used for related field access, which is where the name came from. As it became clear the concept was more broadly useful, the name hasn’t been changed. This is primarily so that existing code will continue to work in future Django versions.

Writing correct managers for use in automatic manager instances

The use_for_related_fields feature is primarily for managers that need to return a custom QuerySet subclass. In providing this functionality in your manager, there are a couple of things to remember.

Do not filter away any results in this type of manager subclass

One reason an automatic manager is used is to access objects that are related to from some other model. In those situations, Django has to be able to see all the objects for the model it is fetching, so that anything which is referred to can be retrieved.

If you override the get_queryset() method and filter out any rows, Django will return incorrect results. Don’t do that. A manager that filters results in get_queryset() is not appropriate for use as an automatic manager.

Set use_for_related_fields when you define the class

The use_for_related_fields attribute must be set on the manager class, not on an instance of the class. The earlier example shows the correct way to set it, whereas the following will not work:

# BAD: Incorrect code
class MyManager(models.Manager):
# ...
pass

# Sets the attribute on an instance of MyManager. Django will
# ignore this setting.
mgr = MyManager()
mgr.use_for_related_fields = True

class MyModel(models.Model):
# ...
objects = mgr

# End of incorrect code.

You also shouldn’t change the attribute on the class object after it has been used in a model, since the attribute’s value is processed when the model class is created and not subsequently reread. Set the attribute on the manager class when it is first defined, as in the initial example of this section and everything will work smoothly.

Performing raw SQL queries

When the model query APIs don’t go far enough, you can fall back to writing raw SQL. Django gives you two ways of performing raw SQL queries: you can use Manager.raw() to perform raw queries and return model instances, or you can avoid the model layer entirely and execute custom SQL directly.

Warning

You should be very careful whenever you write raw SQL. Every time you use it, you should properly escape any parameters that the user can control by using params in order to protect against SQL injection attacks. Please read more about SQL injection protection.

Performing raw queries

The raw() manager method can be used to perform raw SQL queries that return model instances:

Manager.raw(raw_query, params=None, translations=None)

This method takes a raw SQL query, executes it, and returns a django.db.models.query.RawQuerySet instance. This RawQuerySet instance can be iterated over just like a normal QuerySet to provide object instances.

This is best illustrated with an example. Suppose you have the following model:

class Person(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
birth_date = models.DateField(...)

You could then execute custom SQL like so:

>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
...     print(p)
John Smith
Jane Jones

Of course, this example isn’t very exciting – it’s exactly the same as running Person.objects.all(). However, raw() has a bunch of other options that make it very powerful.

Model table names

Where did the name of the Person table come from in that example?

By default, Django figures out a database table name by joining the model’s “app label” – the name you used in manage.py startapp – to the model’s class name, with an underscore between them. In the example we’ve assumed that the Person model lives in an app named myapp, so its table would be myapp_person.

For more details check out the documentation for the db_table option, which also lets you manually set the database table name.

Warning

No checking is done on the SQL statement that is passed in to .raw(). Django expects that the statement will return a set of rows from the database, but does nothing to enforce that. If the query does not return rows, a (possibly cryptic) error will result.

Warning

If you are performing queries on MySQL, note that MySQL’s silent type coercion may cause unexpected results when mixing types. If you query on a string type column, but with an integer value, MySQL will coerce the types of all values in the table to an integer before performing the comparison. For example, if your table contains the values 'abc', 'def' and you query for WHERE mycolumn=0, both rows will match. To prevent this, perform the correct typecasting before using the value in a query.

Warning

While a RawQuerySet instance can be iterated over like a normal QuerySet, RawQuerySet doesn’t implement all methods you can use with QuerySet. For example, __bool__() and __len__() are not defined in RawQuerySet, and thus all RawQuerySet instances are considered True. The reason these methods are not implemented in RawQuerySet is that implementing them without internal caching would be a performance drawback and adding such caching would be backward incompatible.

Mapping query fields to model fields

raw() automatically maps fields in the query to fields on the model.

The order of fields in your query doesn’t matter. In other words, both of the following queries work identically:

>>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')
...
>>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person')
...

Matching is done by name. This means that you can use SQL’s AS clauses to map fields in the query to model fields. So if you had some other table that had Person data in it, you could easily map it into Person instances:

>>> Person.objects.raw('''SELECT first AS first_name,
...                              last AS last_name,
...                              bd AS birth_date,
...                              pk AS id,
...                       FROM some_other_table''')

As long as the names match, the model instances will be created correctly.

Alternatively, you can map fields in the query to model fields using the translations argument to raw(). This is a dictionary mapping names of fields in the query to names of fields on the model. For example, the above query could also be written:

>>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
>>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)

Index lookups

raw() supports indexing, so if you need only the first result you can write:

>>> first_person = Person.objects.raw('SELECT * FROM myapp_person')[0]

However, the indexing and slicing are not performed at the database level. If you have a large number of Person objects in your database, it is more efficient to limit the query at the SQL level:

>>> first_person = Person.objects.raw('SELECT * FROM myapp_person LIMIT 1')[0]

Deferring model fields

Fields may also be left out:

>>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person')

The Person objects returned by this query will be deferred model instances (see defer()). This means that the fields that are omitted from the query will be loaded on demand. For example:

>>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'):
...     print(p.first_name, # This will be retrieved by the original query
...           p.last_name) # This will be retrieved on demand
...
John Smith
Jane Jones

From outward appearances, this looks like the query has retrieved both the first name and last name. However, this example actually issued 3 queries. Only the first names were retrieved by the raw() query – the last names were both retrieved on demand when they were printed.

There is only one field that you can’t leave out - the primary key field. Django uses the primary key to identify model instances, so it must always be included in a raw query. An InvalidQuery exception will be raised if you forget to include the primary key.

Adding annotations

You can also execute queries containing fields that aren’t defined on the model. For example, we could use PostgreSQL’s age() function to get a list of people with their ages calculated by the database:

>>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
>>> for p in people:
...     print("%s is %s." % (p.first_name, p.age))
John is 37.
Jane is 42.
...

Passing parameters into raw()

If you need to perform parameterized queries, you can use the params argument to raw():

>>> lname = 'Doe'
>>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])

params is a list or dictionary of parameters. You’ll use %s placeholders in the query string for a list, or %(key)s placeholders for a dictionary (where key is replaced by a dictionary key, of course), regardless of your database engine. Such placeholders will be replaced with parameters from the params argument.

Note

Dictionary params are not supported with the SQLite backend; with this backend, you must pass parameters as a list.

Warning

Do not use string formatting on raw queries!

It’s tempting to write the above query as:

>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)

Don’t.

Using the params argument completely protects you from SQL injection attacks, a common exploit where attackers inject arbitrary SQL into your database. If you use string interpolation, sooner or later you’ll fall victim to SQL injection. As long as you remember to always use the params argument you’ll be protected.

Executing custom SQL directly

Sometimes even Manager.raw() isn’t quite enough: you might need to perform queries that don’t map cleanly to models, or directly execute UPDATE, INSERT, or DELETE queries.

In these cases, you can always access the database directly, routing around the model layer entirely.

The object django.db.connection represents the default database connection. To use the database connection, call connection.cursor() to get a cursor object. Then, call cursor.execute(sql, [params]) to execute the SQL and cursor.fetchone() or cursor.fetchall() to return the resulting rows.

For example:

from django.db import connection

def my_custom_sql(self):
cursor = connection.cursor()

cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])

cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()

return row

Note that if you want to include literal percent signs in the query, you have to double them in the case you are passing parameters:

cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' AND id = %s", [self.id])

If you are using more than one database, you can use django.db.connections to obtain the connection (and cursor) for a specific database. django.db.connections is a dictionary-like object that allows you to retrieve a specific connection using its alias:

from django.db import connections
cursor = connections['my_db_alias'].cursor()
# Your code here...

By default, the Python DB API will return results without their field names, which means you end up with a list of values, rather than a dict. At a small performance and memory cost, you can return results as a dict by using something like this:

def dictfetchall(cursor):
"Return all rows from a cursor as a dict"
columns = [col[0] for col in cursor.description]
return [
dict(zip(columns, row))
for row in cursor.fetchall()
]

Another option is to use collections.namedtuple() from the Python standard library. A namedtuple is a tuple-like object that has fields accessible by attribute lookup; it’s also indexable and iterable. Results are immutable and accessible by field names or indices, which might be useful:

from collections import namedtuple

def namedtuplefetchall(cursor):
"Return all rows from a cursor as a namedtuple"
desc = cursor.description
nt_result = namedtuple('Result', [col[0] for col in desc])
return [nt_result(*row) for row in cursor.fetchall()]

Here is an example of the difference between the three:

>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
>>> cursor.fetchall()
((54360982, None), (54360880, None))

>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
>>> dictfetchall(cursor)
[{'parent_id': None, 'id': 54360982}, {'parent_id': None, 'id': 54360880}]

>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
>>> results = namedtuplefetchall(cursor)
>>> results
[Result(id=54360982, parent_id=None), Result(id=54360880, parent_id=None)]
>>> results[0].id
54360982
>>> results[0][0]
54360982

Connections and cursors

connection and cursor mostly implement the standard Python DB-API described in PEP 249 — except when it comes to transaction handling.

If you’re not familiar with the Python DB-API, note that the SQL statement in cursor.execute() uses placeholders, "%s", rather than adding parameters directly within the SQL. If you use this technique, the underlying database library will automatically escape your parameters as necessary.

Also note that Django expects the "%s" placeholder, not the "?" placeholder, which is used by the SQLite Python bindings. This is for the sake of consistency and sanity.

Using a cursor as a context manager:

with connection.cursor() as c:
c.execute(...)

is equivalent to:

c = connection.cursor()
try:
c.execute(...)
finally:
c.close()

Database transactions

Django gives you a few ways to control how database transactions are managed.

Managing database transactions

Django’s default transaction behavior

Django’s default behavior is to run in autocommit mode. Each query is immediately committed to the database, unless a transaction is active. See below for details.

Django uses transactions or savepoints automatically to guarantee the integrity of ORM operations that require multiple queries, especially delete() and update() queries.

Django’s TestCase class also wraps each test in a transaction for performance reasons.

Tying transactions to HTTP requests

A common way to handle transactions on the web is to wrap each request in a transaction. Set ATOMIC_REQUESTS to True in the configuration of each database for which you want to enable this behavior.

It works like this. Before calling a view function, Django starts a transaction. If the response is produced without problems, Django commits the transaction. If the view produces an exception, Django rolls back the transaction.

You may perform subtransactions using savepoints in your view code, typically with the atomic() context manager. However, at the end of the view, either all or none of the changes will be committed.

Warning

While the simplicity of this transaction model is appealing, it also makes it inefficient when traffic increases. Opening a transaction for every view has some overhead. The impact on performance depends on the query patterns of your application and on how well your database handles locking.

Per-request transactions and streaming responses

When a view returns a StreamingHttpResponse, reading the contents of the response will often execute code to generate the content. Since the view has already returned, such code runs outside of the transaction.

Generally speaking, it isn’t advisable to write to the database while generating a streaming response, since there’s no sensible way to handle errors after starting to send the response.

In practice, this feature simply wraps every view function in the atomic() decorator described below.

Note that only the execution of your view is enclosed in the transactions. Middleware runs outside of the transaction, and so does the rendering of template responses.

When ATOMIC_REQUESTS is enabled, it’s still possible to prevent views from running in a transaction.

non_atomic_requests(using=None)[source]

This decorator will negate the effect of ATOMIC_REQUESTS for a given view:

from django.db import transaction

@transaction.non_atomic_requests
def my_view(request):
do_stuff()

@transaction.non_atomic_requests(using='other')
def my_other_view(request):
do_stuff_on_the_other_database()

It only works if it’s applied to the view itself.

Controlling transactions explicitly

Django provides a single API to control database transactions.

atomic(using=None, savepoint=True)[source]

Atomicity is the defining property of database transactions. atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database. If there is an exception, the changes are rolled back.

atomic blocks can be nested. In this case, when an inner block completes successfully, its effects can still be rolled back if an exception is raised in the outer block at a later point.

atomic is usable both as a decorator:

from django.db import transaction

@transaction.atomic
def viewfunc(request):
# This code executes inside a transaction.
do_stuff()

and as a context manager:

from django.db import transaction

def viewfunc(request):
# This code executes in autocommit mode (Django's default).
do_stuff()

with transaction.atomic():
# This code executes inside a transaction.
do_more_stuff()

Wrapping atomic in a try/except block allows for natural handling of integrity errors:

from django.db import IntegrityError, transaction

@transaction.atomic
def viewfunc(request):
create_parent()

try:
with transaction.atomic():
generate_relationships()
except IntegrityError:
handle_exception()

add_children()

In this example, even if generate_relationships() causes a database error by breaking an integrity constraint, you can execute queries in add_children(), and the changes from create_parent() are still there. Note that any operations attempted in generate_relationships() will already have been rolled back safely when handle_exception() is called, so the exception handler can also operate on the database if necessary.

Avoid catching exceptions inside atomic!

When exiting an atomic block, Django looks at whether it’s exited normally or with an exception to determine whether to commit or roll back. If you catch and handle exceptions inside an atomic block, you may hide from Django the fact that a problem has happened. This can result in unexpected behavior.

This is mostly a concern for DatabaseError and its subclasses such as IntegrityError. After such an error, the transaction is broken and Django will perform a rollback at the end of the atomic block. If you attempt to run database queries before the rollback happens, Django will raise a TransactionManagementError. You may also encounter this behavior when an ORM-related signal handler raises an exception.

The correct way to catch database errors is around an atomic block as shown above. If necessary, add an extra atomic block for this purpose. This pattern has another advantage: it delimits explicitly which operations will be rolled back if an exception occurs.

If you catch exceptions raised by raw SQL queries, Django’s behavior is unspecified and database-dependent.

In order to guarantee atomicity, atomic disables some APIs. Attempting to commit, roll back, or change the autocommit state of the database connection within an atomic block will raise an exception.

atomic takes a using argument which should be the name of a database. If this argument isn’t provided, Django uses the "default" database.

Under the hood, Django’s transaction management code:

- opens a transaction when entering the outermost atomic block;

- creates a savepoint when entering an inner atomic block;

- releases or rolls back to the savepoint when exiting an inner block;

- commits or rolls back the transaction when exiting the outermost block.

You can disable the creation of savepoints for inner blocks by setting the savepoint argument to False. If an exception occurs, Django will perform the rollback when exiting the first parent block with a savepoint if there is one, and the outermost block otherwise. Atomicity is still guaranteed by the outer transaction. This option should only be used if the overhead of savepoints is noticeable. It has the drawback of breaking the error handling described above.

You may use atomic when autocommit is turned off. It will only use savepoints, even for the outermost block.

Changed in Django 1.8.5:
Previously the outermost atomic block couldn’t be declared with savepoint=False when autocommit was turned off.

Performance considerations

Open transactions have a performance cost for your database server. To minimize this overhead, keep your transactions as short as possible. This is especially important if you’re using atomic() in long-running processes, outside of Django’s request / response cycle.

Autocommit

Why Django uses autocommit

In the SQL standards, each SQL query starts a transaction, unless one is already active. Such transactions must then be explicitly committed or rolled back.

This isn’t always convenient for application developers. To alleviate this problem, most databases provide an autocommit mode. When autocommit is turned on and no transaction is active, each SQL query gets wrapped in its own transaction. In other words, not only does each such query start a transaction, but the transaction also gets automatically committed or rolled back, depending on whether the query succeeded.

PEP 249, the Python Database API Specification v2.0, requires autocommit to be initially turned off. Django overrides this default and turns autocommit on.

To avoid this, you can deactivate the transaction management, but it isn’t recommended.

Deactivating transaction management

You can totally disable Django’s transaction management for a given database by setting AUTOCOMMIT to False in its configuration. If you do this, Django won’t enable autocommit, and won’t perform any commits. You’ll get the regular behavior of the underlying database library.

This requires you to commit explicitly every transaction, even those started by Django or by third-party libraries. Thus, this is best used in situations where you want to run your own transaction-controlling middleware or do something really strange.

Performing actions after commit

New in Django 1.9.

Sometimes you need to perform an action related to the current database transaction, but only if the transaction successfully commits. Examples might include a Celery task, an email notification, or a cache invalidation.

Django provides the on_commit() function to register callback functions that should be executed after a transaction is successfully committed:

on_commit(func, using=None)[source]

Pass any function (that takes no arguments) to on_commit():

from django.db import transaction

def do_something():
pass  # send a mail, invalidate a cache, fire off a Celery task, etc.

transaction.on_commit(do_something)

You can also wrap your function in a lambda:

transaction.on_commit(lambda: some_celery_task.delay('arg1'))

The function you pass in will be called immediately after a hypothetical database write made where on_commit() is called would be successfully committed.

If you call on_commit() while there isn’t an active transaction, the callback will be executed immediately.

If that hypothetical database write is instead rolled back (typically when an unhandled exception is raised in an atomic() block), your function will be discarded and never called.

Savepoints

Savepoints (i.e. nested atomic() blocks) are handled correctly. That is, an on_commit() callable registered after a savepoint (in a nested atomic() block) will be called after the outer transaction is committed, but not if a rollback to that savepoint or any previous savepoint occurred during the transaction:

with transaction.atomic():  # Outer atomic, start a new transaction
transaction.on_commit(foo)

with transaction.atomic():  # Inner atomic block, create a savepoint
transaction.on_commit(bar)

# foo() and then bar() will be called when leaving the outermost block

On the other hand, when a savepoint is rolled back (due to an exception being raised), the inner callable will not be called:

with transaction.atomic():  # Outer atomic, start a new transaction
transaction.on_commit(foo)

try:
with transaction.atomic():  # Inner atomic block, create a savepoint
transaction.on_commit(bar)
raise SomeError()  # Raising an exception - abort the savepoint
except SomeError:
pass

# foo() will be called, but not bar()

Order of execution

On-commit functions for a given transaction are executed in the order they were registered.

Exception handling

If one on-commit function within a given transaction raises an uncaught exception, no later registered functions in that same transaction will run. This is, of course, the same behavior as if you’d executed the functions sequentially yourself without on_commit().

Timing of execution

Your callbacks are executed after a successful commit, so a failure in a callback will not cause the transaction to roll back. They are executed conditionally upon the success of the transaction, but they are not part of the transaction. For the intended use cases (mail notifications, Celery tasks, etc.), this should be fine. If it’s not (if your follow-up action is so critical that its failure should mean the failure of the transaction itself), then you don’t want to use the on_commit() hook. Instead, you may want two-phase commit such as the psycopg Two-Phase Commit protocol support and the optional Two-Phase Commit Extensions in the Python DB-API specification.

Callbacks are not run until autocommit is restored on the connection following the commit (because otherwise any queries done in a callback would open an implicit transaction, preventing the connection from going back into autocommit mode).

When in autocommit mode and outside of an atomic() block, the function will run immediately, not on commit.

On-commit functions only work with autocommit mode and the atomic() (or ATOMIC_REQUESTS) transaction API. Calling on_commit() when autocommit is disabled and you are not within an atomic block will result in an error.

Use in tests

Django’s TestCase class wraps each test in a transaction and rolls back that transaction after each test, in order to provide test isolation. This means that no transaction is ever actually committed, thus your on_commit() callbacks will never be run. If you need to test the results of an on_commit() callback, use a TransactionTestCase instead.

Why no rollback hook?

A rollback hook is harder to implement robustly than a commit hook, since a variety of things can cause an implicit rollback.

For instance, if your database connection is dropped because your process was killed without a chance to shut down gracefully, your rollback hook will never run.

The solution is simple: instead of doing something during the atomic block (transaction) and then undoing it if the transaction fails, use on_commit() to delay doing it in the first place until after the transaction succeeds. It’s a lot easier to undo something you never did in the first place!

Low-level APIs

Warning

Always prefer atomic() if possible at all. It accounts for the idiosyncrasies of each database and prevents invalid operations.

The low level APIs are only useful if you’re implementing your own transaction management.

Autocommit

Django provides a straightforward API in the django.db.transaction module to manage the autocommit state of each database connection.

get_autocommit(using=None)[source]

set_autocommit(autocommit, using=None)[source]

These functions take a using argument which should be the name of a database. If it isn’t provided, Django uses the "default" database.

Autocommit is initially turned on. If you turn it off, it’s your responsibility to restore it.

Once you turn autocommit off, you get the default behavior of your database adapter, and Django won’t help you. Although that behavior is specified in PEP 249, implementations of adapters aren’t always consistent with one another. Review the documentation of the adapter you’re using carefully.

You must ensure that no transaction is active, usually by issuing a commit() or a rollback(), before turning autocommit back on.

Django will refuse to turn autocommit off when an atomic() block is active, because that would break atomicity.

Transactions

A transaction is an atomic set of database queries. Even if your program crashes, the database guarantees that either all the changes will be applied, or none of them.

Django doesn’t provide an API to start a transaction. The expected way to start a transaction is to disable autocommit with set_autocommit().

Once you’re in a transaction, you can choose either to apply the changes you’ve performed until this point with commit(), or to cancel them with rollback(). These functions are defined in django.db.transaction.

commit(using=None)[source]

rollback(using=None)[source]

These functions take a using argument which should be the name of a database. If it isn’t provided, Django uses the "default" database.

Django will refuse to commit or to rollback when an atomic() block is active, because that would break atomicity.

Savepoints

A savepoint is a marker within a transaction that enables you to roll back part of a transaction, rather than the full transaction. Savepoints are available with the SQLite (≥ 3.6.8), PostgreSQL, Oracle and MySQL (when using the InnoDB storage engine) backends. Other backends provide the savepoint functions, but they’re empty operations – they don’t actually do anything.

Savepoints aren’t especially useful if you are using autocommit, the default behavior of Django. However, once you open a transaction with atomic(), you build up a series of database operations awaiting a commit or rollback. If you issue a rollback, the entire transaction is rolled back. Savepoints provide the ability to perform a fine-grained rollback, rather than the full rollback that would be performed by transaction.rollback().

When the atomic() decorator is nested, it creates a savepoint to allow partial commit or rollback. You’re strongly encouraged to use atomic() rather than the functions described below, but they’re still part of the public API, and there’s no plan to deprecate them.

Each of these functions takes a using argument which should be the name of a database for which the behavior applies. If no using argument is provided then the "default" database is used.

Savepoints are controlled by three functions in django.db.transaction:

savepoint(using=None)[source]

Creates a new savepoint. This marks a point in the transaction that is known to be in a “good” state. Returns the savepoint ID (sid).

savepoint_commit(sid, using=None)[source]

Releases savepoint sid. The changes performed since the savepoint was created become part of the transaction.

savepoint_rollback(sid, using=None)[source]

Rolls back the transaction to savepoint sid.

These functions do nothing if savepoints aren’t supported or if the database is in autocommit mode.

In addition, there’s a utility function:

clean_savepoints(using=None)[source]

Resets the counter used to generate unique savepoint IDs.

The following example demonstrates the use of savepoints:

from django.db import transaction

# open a transaction
@transaction.atomic
def viewfunc(request):

a.save()
# transaction now contains a.save()

sid = transaction.savepoint()

b.save()
# transaction now contains a.save() and b.save()

if want_to_keep_b:
transaction.savepoint_commit(sid)
# open transaction still contains a.save() and b.save()
else:
transaction.savepoint_rollback(sid)
# open transaction now contains only a.save()

Savepoints may be used to recover from a database error by performing a partial rollback. If you’re doing this inside an atomic() block, the entire block will still be rolled back, because it doesn’t know you’ve handled the situation at a lower level! To prevent this, you can control the rollback behavior with the following functions.

get_rollback(using=None)[source]

set_rollback(rollback, using=None)[source]

Setting the rollback flag to True forces a rollback when exiting the innermost atomic block. This may be useful to trigger a rollback without raising an exception.

Setting it to False prevents such a rollback. Before doing that, make sure you’ve rolled back the transaction to a known-good savepoint within the current atomic block! Otherwise you’re breaking atomicity and data corruption may occur.

Database-specific notes

Savepoints in SQLite

While SQLite ≥ 3.6.8 supports savepoints, a flaw in the design of the sqlite3 module makes them hardly usable.

When autocommit is enabled, savepoints don’t make sense. When it’s disabled, sqlite3 commits implicitly before savepoint statements. (In fact, it commits before any statement other than SELECT, INSERT, UPDATE, DELETE and REPLACE.) This bug has two consequences:

- The low level APIs for savepoints are only usable inside a transaction ie. inside an atomic() block.

- It’s impossible to use atomic() when autocommit is turned off.

Transactions in MySQL

If you’re using MySQL, your tables may or may not support transactions; it depends on your MySQL version and the table types you’re using. (By “table types,” we mean something like “InnoDB” or “MyISAM”.) MySQL transaction peculiarities are outside the scope of this article, but the MySQL site has information on MySQL transactions.

If your MySQL setup does not support transactions, then Django will always function in autocommit mode: statements will be executed and committed as soon as they’re called. If your MySQL setup does support transactions, Django will handle transactions as explained in this document.

Handling exceptions within PostgreSQL transactions

Note

This section is relevant only if you’re implementing your own transaction management. This problem cannot occur in Django’s default mode and atomic() handles it automatically.

Inside a transaction, when a call to a PostgreSQL cursor raises an exception (typically IntegrityError), all subsequent SQL in the same transaction will fail with the error “current transaction is aborted, queries ignored until end of transaction block”. While simple use of save() is unlikely to raise an exception in PostgreSQL, there are more advanced usage patterns which might, such as saving objects with unique fields, saving using the force_insert/force_update flag, or invoking custom SQL.

There are several ways to recover from this sort of error.

Transaction rollback

The first option is to roll back the entire transaction. For example:

a.save() # Succeeds, but may be undone by transaction rollback
try:
b.save() # Could throw exception
except IntegrityError:
transaction.rollback()
c.save() # Succeeds, but a.save() may have been undone

Calling transaction.rollback() rolls back the entire transaction. Any uncommitted database operations will be lost. In this example, the changes made by a.save() would be lost, even though that operation raised no error itself.

Savepoint rollback

You can use savepoints to control the extent of a rollback. Before performing a database operation that could fail, you can set or update the savepoint; that way, if the operation fails, you can roll back the single offending operation, rather than the entire transaction. For example:

a.save() # Succeeds, and never undone by savepoint rollback
sid = transaction.savepoint()
try:
b.save() # Could throw exception
transaction.savepoint_commit(sid)
except IntegrityError:
transaction.savepoint_rollback(sid)
c.save() # Succeeds, and a.save() is never undone

In this example, a.save() will not be undone in the case where b.save() raises an exception.

Multiple databases

This topic guide describes Django’s support for interacting with multiple databases. Most of the rest of Django’s documentation assumes you are interacting with a single database. If you want to interact with multiple databases, you’ll need to take some additional steps.

Defining your databases

The first step to using more than one database with Django is to tell Django about the database servers you’ll be using. This is done using the DATABASES setting. This setting maps database aliases, which are a way to refer to a specific database throughout Django, to a dictionary of settings for that specific connection. The settings in the inner dictionaries are described fully in the DATABASES documentation.

Databases can have any alias you choose. However, the alias default has special significance. Django uses the database with the alias of default when no other database has been selected.

The following is an example settings.py snippet defining two databases – a default PostgreSQL database and a MySQL database called users:

DATABASES = {
'default': {
'NAME': 'app_data',
'ENGINE': 'django.db.backends.postgresql',
'USER': 'postgres_user',
'PASSWORD': 's3krit'
},
'users': {
'NAME': 'user_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'priv4te'
}
}

If the concept of a default database doesn’t make sense in the context of your project, you need to be careful to always specify the database that you want to use. Django requires that a default database entry be defined, but the parameters dictionary can be left blank if it will not be used. You must setup DATABASE_ROUTERS for all of your apps’ models, including those in any contrib and third-party apps you are using, so that no queries are routed to the default database in order to do this. The following is an example settings.py snippet defining two non-default databases, with the default entry intentionally left empty:

DATABASES = {
'default': {},
'users': {
'NAME': 'user_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'superS3cret'
},
'customers': {
'NAME': 'customer_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_cust',
'PASSWORD': 'veryPriv@ate'
}
}

If you attempt to access a database that you haven’t defined in your DATABASES setting, Django will raise a django.db.utils.ConnectionDoesNotExist exception.

Synchronizing your databases

The migrate management command operates on one database at a time. By default, it operates on the default database, but by providing the --database option, you can tell it to synchronize a different database. So, to synchronize all models onto all databases in our example, you would need to call:

$ ./manage.py migrate
$ ./manage.py migrate --database=users

If you don’t want every application to be synchronized onto a particular database, you can define a database router that implements a policy constraining the availability of particular models.

Using other management commands

The other django-admin commands that interact with the database operate in the same way as migrate – they only ever operate on one database at a time, using --database to control the database used.

Automatic database routing

The easiest way to use multiple databases is to set up a database routing scheme. The default routing scheme ensures that objects remain ‘sticky’ to their original database (i.e., an object retrieved from the foo database will be saved on the same database). The default routing scheme ensures that if a database isn’t specified, all queries fall back to the default database.

You don’t have to do anything to activate the default routing scheme – it is provided ‘out of the box’ on every Django project. However, if you want to implement more interesting database allocation behaviors, you can define and install your own database routers.

Database routers

A database Router is a class that provides up to four methods:

db_for_read(model, **hints)

Suggest the database that should be used for read operations for objects of type model.

If a database operation is able to provide any additional information that might assist in selecting a database, it will be provided in the hints dictionary. Details on valid hints are provided below.

Returns None if there is no suggestion.

db_for_write(model, **hints)

Suggest the database that should be used for writes of objects of type Model.

If a database operation is able to provide any additional information that might assist in selecting a database, it will be provided in the hints dictionary. Details on valid hints are provided below.

Returns None if there is no suggestion.

allow_relation(obj1, obj2, **hints)

Return True if a relation between obj1 and obj2 should be allowed, False if the relation should be prevented, or None if the router has no opinion. This is purely a validation operation, used by foreign key and many to many operations to determine if a relation should be allowed between two objects.

allow_migrate(db, app_label, model_name=None, **hints)

Determine if the migration operation is allowed to run on the database with alias db. Return True if the operation should run, False if it shouldn’t run, or None if the router has no opinion.

The app_label positional argument is the label of the application being migrated.

model_name is set by most migration operations to the value of model._meta.model_name (the lowercased version of the model __name__) of the model being migrated. Its value is None for the RunPython and RunSQL operations unless they provide it using hints.

hints are used by certain operations to communicate additional information to the router.

When model_name is set, hints normally contains the model class under the key 'model'. Note that it may be a historical model, and thus not have any custom attributes, methods, or managers. You should only rely on _meta.

This method can also be used to determine the availability of a model on a given database.

Note that migrations will just silently not perform any operations on a model for which this returns False. This may result in broken foreign keys, extra tables, or missing tables if you change it once you have applied some migrations.

Changed in Django 1.8:
The signature of allow_migrate has changed significantly from previous versions. See the deprecation notes for more details.

A router doesn’t have to provide all these methods – it may omit one or more of them. If one of the methods is omitted, Django will skip that router when performing the relevant check.

Hints

The hints received by the database router can be used to decide which database should receive a given request.

At present, the only hint that will be provided is instance, an object instance that is related to the read or write operation that is underway. This might be the instance that is being saved, or it might be an instance that is being added in a many-to-many relation. In some cases, no instance hint will be provided at all. The router checks for the existence of an instance hint, and determine if that hint should be used to alter routing behavior.

Using routers

Database routers are installed using the DATABASE_ROUTERS setting. This setting defines a list of class names, each specifying a router that should be used by the master router (django.db.router).

The master router is used by Django’s database operations to allocate database usage. Whenever a query needs to know which database to use, it calls the master router, providing a model and a hint (if available). Django then tries each router in turn until a database suggestion can be found. If no suggestion can be found, it tries the current _state.db of the hint instance. If a hint instance wasn’t provided, or the instance doesn’t currently have database state, the master router will allocate the default database.

An example

Example purposes only!

This example is intended as a demonstration of how the router infrastructure can be used to alter database usage. It intentionally ignores some complex issues in order to demonstrate how routers are used.

This example won’t work if any of the models in myapp contain relationships to models outside of the other database. Cross-database relationships introduce referential integrity problems that Django can’t currently handle.

The primary/replica (referred to as master/slave by some databases) configuration described is also flawed – it doesn’t provide any solution for handling replication lag (i.e., query inconsistencies introduced because of the time taken for a write to propagate to the replicas). It also doesn’t consider the interaction of transactions with the database utilization strategy.

So - what does this mean in practice? Let’s consider another sample configuration. This one will have several databases: one for the auth application, and all other apps using a primary/replica setup with two read replicas. Here are the settings specifying these databases:

DATABASES = {
'default': {},
'auth_db': {
'NAME': 'auth_db',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'swordfish',
},
'primary': {
'NAME': 'primary',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'spam',
},
'replica1': {
'NAME': 'replica1',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'eggs',
},
'replica2': {
'NAME': 'replica2',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'bacon',
},
}

Now we’ll need to handle routing. First we want a router that knows to send queries for the auth app to auth_db:

class AuthRouter(object):
"""
A router to control all database operations on models in the
auth application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.app_label == 'auth':
return 'auth_db'
return None

def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'auth':
return 'auth_db'
return None

def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth app is involved.
"""
if obj1._meta.app_label == 'auth' or \
obj2._meta.app_label == 'auth':
return True
return None

def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth app only appears in the 'auth_db'
database.
"""
if app_label == 'auth':
return db == 'auth_db'
return None

And we also want a router that sends all other apps to the primary/replica configuration, and randomly chooses a replica to read from:

import random

class PrimaryReplicaRouter(object):
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen replica.
"""
return random.choice(['replica1', 'replica2'])

def db_for_write(self, model, **hints):
"""
Writes always go to primary.
"""
return 'primary'

def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the primary/replica pool.
"""
db_list = ('primary', 'replica1', 'replica2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None

def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
return True

Finally, in the settings file, we add the following (substituting path.to. with the actual Python path to the module(s) where the routers are defined):

DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']

The order in which routers are processed is significant. Routers will be queried in the order the are listed in the DATABASE_ROUTERS setting . In this example, the AuthRouter is processed before the PrimaryReplicaRouter, and as a result, decisions concerning the models in auth are processed before any other decision is made. If the DATABASE_ROUTERS setting listed the two routers in the other order, PrimaryReplicaRouter.allow_migrate() would be processed first. The catch-all nature of the PrimaryReplicaRouter implementation would mean that all models would be available on all databases.

With this setup installed, lets run some Django code:

>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username='fred')
>>> fred.first_name = 'Frederick'

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

>>> # These retrieval will be randomly allocated to a replica database
>>> dna = Person.objects.get(name='Douglas Adams')

>>> # A new object has no database allocation when created
>>> mh = Book(title='Mostly Harmless')

>>> # This assignment will consult the router, and set mh onto
>>> # the same database as the author object
>>> mh.author = dna

>>> # This save will force the 'mh' instance onto the primary database...
>>> mh.save()

>>> # ... but if we re-retrieve the object, it will come back on a replica
>>> mh = Book.objects.get(title='Mostly Harmless')

Manually selecting a database

Django also provides an API that allows you to maintain complete control over database usage in your code. A manually specified database allocation will take priority over a database allocated by a router.

Manually selecting a database for a QuerySet

You can select the database for a QuerySet at any point in the QuerySet “chain.” Just call using() on the QuerySet to get another QuerySet that uses the specified database.

using() takes a single argument: the alias of the database on which you want to run the query. For example:

>>> # This will run on the 'default' database.
>>> Author.objects.all()

>>> # So will this.
>>> Author.objects.using('default').all()

>>> # This will run on the 'other' database.
>>> Author.objects.using('other').all()

Selecting a database for save()

Use the using keyword to Model.save() to specify to which database the data should be saved.

For example, to save an object to the legacy_users database, you’d use this:

>>> my_object.save(using='legacy_users')

If you don’t specify using, the save() method will save into the default database allocated by the routers.

Moving an object from one database to another

If you’ve saved an instance to one database, it might be tempting to use save(using=...) as a way to migrate the instance to a new database. However, if you don’t take appropriate steps, this could have some unexpected consequences.

Consider the following example:

>>> p = Person(name='Fred')
>>> p.save(using='first')  # (statement 1)
>>> p.save(using='second') # (statement 2)

In statement 1, a new Person object is saved to the first database. At this time, p doesn’t have a primary key, so Django issues an SQL INSERT statement. This creates a primary key, and Django assigns that primary key to p.

When the save occurs in statement 2, p already has a primary key value, and Django will attempt to use that primary key on the new database. If the primary key value isn’t in use in the second database, then you won’t have any problems – the object will be copied to the new database.

However, if the primary key of p is already in use on the second database, the existing object in the second database will be overridden when p is saved.

You can avoid this in two ways. First, you can clear the primary key of the instance. If an object has no primary key, Django will treat it as a new object, avoiding any loss of data on the second database:

>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.pk = None # Clear the primary key.
>>> p.save(using='second') # Write a completely new object.

The second option is to use the force_insert option to save() to ensure that Django does an SQL INSERT:

>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.save(using='second', force_insert=True)

This will ensure that the person named Fred will have the same primary key on both databases. If that primary key is already in use when you try to save onto the second database, an error will be raised.

Selecting a database to delete from

By default, a call to delete an existing object will be executed on the same database that was used to retrieve the object in the first place:

>>> u = User.objects.using('legacy_users').get(username='fred')
>>> u.delete() # will delete from the `legacy_users` database

To specify the database from which a model will be deleted, pass a using keyword argument to the Model.delete() method. This argument works just like the using keyword argument to save().

For example, if you’re migrating a user from the legacy_users database to the new_users database, you might use these commands:

>>> user_obj.save(using='new_users')
>>> user_obj.delete(using='legacy_users')

Using managers with multiple databases

Use the db_manager() method on managers to give managers access to a non-default database.

For example, say you have a custom manager method that touches the database – User.objects.create_user(). Because create_user() is a manager method, not a QuerySet method, you can’t do User.objects.using('new_users').create_user(). (The create_user() method is only available on User.objects, the manager, not on QuerySet objects derived from the manager.) The solution is to use db_manager(), like this:

User.objects.db_manager('new_users').create_user(...)

db_manager() returns a copy of the manager bound to the database you specify.

Using get_queryset() with multiple databases

If you’re overriding get_queryset() on your manager, be sure to either call the method on the parent (using super()) or do the appropriate handling of the _db attribute on the manager (a string containing the name of the database to use).

For example, if you want to return a custom QuerySet class from the get_queryset method, you could do this:

class MyManager(models.Manager):
def get_queryset(self):
qs = CustomQuerySet(self.model)
if self._db is not None:
qs = qs.using(self._db)
return qs

Exposing multiple databases in Django’s admin interface

Django’s admin doesn’t have any explicit support for multiple databases. If you want to provide an admin interface for a model on a database other than that specified by your router chain, you’ll need to write custom ModelAdmin classes that will direct the admin to use a specific database for content.

ModelAdmin objects have five methods that require customization for multiple-database support:

class MultiDBModelAdmin(admin.ModelAdmin):
# A handy constant for the name of the alternate database.
using = 'other'

def save_model(self, request, obj, form, change):
# Tell Django to save objects to the 'other' database.
obj.save(using=self.using)

def delete_model(self, request, obj):
# Tell Django to delete objects from the 'other' database
obj.delete(using=self.using)

def get_queryset(self, request):
# Tell Django to look for objects on the 'other' database.
return super(MultiDBModelAdmin, self).get_queryset(request).using(self.using)

def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
# Tell Django to populate ForeignKey widgets using a query
# on the 'other' database.
return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)

def formfield_for_manytomany(self, db_field, request=None, **kwargs):
# Tell Django to populate ManyToMany widgets using a query
# on the 'other' database.
return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)

The implementation provided here implements a multi-database strategy where all objects of a given type are stored on a specific database (e.g., all User objects are in the other database). If your usage of multiple databases is more complex, your ModelAdmin will need to reflect that strategy.

Inlines can be handled in a similar fashion. They require three customized methods:

class MultiDBTabularInline(admin.TabularInline):
using = 'other'

def get_queryset(self, request):
# Tell Django to look for inline objects on the 'other' database.
return super(MultiDBTabularInline, self).get_queryset(request).using(self.using)

def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
# Tell Django to populate ForeignKey widgets using a query
# on the 'other' database.
return super(MultiDBTabularInline, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)

def formfield_for_manytomany(self, db_field, request=None, **kwargs):
# Tell Django to populate ManyToMany widgets using a query
# on the 'other' database.
return super(MultiDBTabularInline, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)

Once you’ve written your model admin definitions, they can be registered with any Admin instance:

from django.contrib import admin

# Specialize the multi-db admin objects for use with specific models.
class BookInline(MultiDBTabularInline):
model = Book

class PublisherAdmin(MultiDBModelAdmin):
inlines = [BookInline]

admin.site.register(Author, MultiDBModelAdmin)
admin.site.register(Publisher, PublisherAdmin)

othersite = admin.AdminSite('othersite')
othersite.register(Publisher, MultiDBModelAdmin)

This example sets up two admin sites. On the first site, the Author and Publisher objects are exposed; Publisher objects have an tabular inline showing books published by that publisher. The second site exposes just publishers, without the inlines.

Using raw cursors with multiple databases

If you are using more than one database you can use django.db.connections to obtain the connection (and cursor) for a specific database. django.db.connections is a dictionary-like object that allows you to retrieve a specific connection using its alias:

from django.db import connections
cursor = connections['my_db_alias'].cursor()

Limitations of multiple databases

Cross-database relations

Django doesn’t currently provide any support for foreign key or many-to-many relationships spanning multiple databases. If you have used a router to partition models to different databases, any foreign key and many-to-many relationships defined by those models must be internal to a single database.

This is because of referential integrity. In order to maintain a relationship between two objects, Django needs to know that the primary key of the related object is valid. If the primary key is stored on a separate database, it’s not possible to easily evaluate the validity of a primary key.

If you’re using Postgres, Oracle, or MySQL with InnoDB, this is enforced at the database integrity level – database level key constraints prevent the creation of relations that can’t be validated.

However, if you’re using SQLite or MySQL with MyISAM tables, there is no enforced referential integrity; as a result, you may be able to ‘fake’ cross database foreign keys. However, this configuration is not officially supported by Django.

Behavior of contrib apps

Several contrib apps include models, and some apps depend on others. Since cross-database relationships are impossible, this creates some restrictions on how you can split these models across databases:

- each one of contenttypes.ContentType, sessions.Session and sites.Site can be stored in any database, given a suitable router.

- auth models — User, Group and Permission — are linked together and linked to ContentType, so they must be stored in the same database as ContentType.

- admin depends on auth, so their models must be in the same database as auth.

- flatpages and redirects depend on sites, so their models must be in the same database as sites.

In addition, some objects are automatically created just after migrate creates a table to hold them in a database:

- a default Site,

- a ContentType for each model (including those not stored in that database),

- three Permission for each model (including those not stored in that database).

For common setups with multiple databases, it isn’t useful to have these objects in more than one database. Common setups include primary/replica and connecting to external databases. Therefore, it’s recommended to write a database router that allows synchronizing these three models to only one database. Use the same approach for contrib and third-party apps that don’t need their tables in multiple databases.

Warning

If you’re synchronizing content types to more than one database, be aware that their primary keys may not match across databases. This may result in data corruption or data loss.

Tablespaces

A common paradigm for optimizing performance in database systems is the use of tablespaces to organize disk layout.

Warning

Django does not create the tablespaces for you. Please refer to your database engine’s documentation for details on creating and managing tablespaces.

Declaring tablespaces for tables

A tablespace can be specified for the table generated by a model by supplying the db_tablespace option inside the model’s class Meta. This option also affects tables automatically created for ManyToManyFields in the model.

You can use the DEFAULT_TABLESPACE setting to specify a default value for db_tablespace. This is useful for setting a tablespace for the built-in Django apps and other applications whose code you cannot control.

Declaring tablespaces for indexes

You can pass the db_tablespace option to a Field constructor to specify an alternate tablespace for the Field’s column index. If no index would be created for the column, the option is ignored.

You can use the DEFAULT_INDEX_TABLESPACE setting to specify a default value for db_tablespace.

If db_tablespace isn’t specified and you didn’t set DEFAULT_INDEX_TABLESPACE, the index is created in the same tablespace as the tables.

An example

class TablespaceExample(models.Model):
name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes")
data = models.CharField(max_length=255, db_index=True)
edges = models.ManyToManyField(to="self", db_tablespace="indexes")

class Meta:
db_tablespace = "tables"

In this example, the tables generated by the TablespaceExample model (i.e. the model table and the many-to-many table) would be stored in the tables tablespace. The index for the name field and the indexes on the many-to-many table would be stored in the indexes tablespace. The data field would also generate an index, but no tablespace for it is specified, so it would be stored in the model tablespace tables by default.

Database support

PostgreSQL and Oracle support tablespaces. SQLite and MySQL don’t.

When you use a backend that lacks support for tablespaces, Django ignores all tablespace-related options.

Database access optimization

Django’s database layer provides various ways to help developers get the most out of their databases. This document gathers together links to the relevant documentation, and adds various tips, organized under a number of headings that outline the steps to take when attempting to optimize your database usage.

Profile first

As general programming practice, this goes without saying. Find out what queries you are doing and what they are costing you. You may also want to use an external project like django-debug-toolbar, or a tool that monitors your database directly.

Remember that you may be optimizing for speed or memory or both, depending on your requirements. Sometimes optimizing for one will be detrimental to the other, but sometimes they will help each other. Also, work that is done by the database process might not have the same cost (to you) as the same amount of work done in your Python process. It is up to you to decide what your priorities are, where the balance must lie, and profile all of these as required since this will depend on your application and server.

With everything that follows, remember to profile after every change to ensure that the change is a benefit, and a big enough benefit given the decrease in readability of your code. All of the suggestions below come with the caveat that in your circumstances the general principle might not apply, or might even be reversed.

Use standard DB optimization techniques

...including:

- Indexes. This is a number one priority, after you have determined from profiling what indexes should be added. Use Field.db_index or Meta.index_together to add these from Django. Consider adding indexes to fields that you frequently query using filter(), exclude(), order_by(), etc. as indexes may help to speed up lookups. Note that determining the best indexes is a complex database-dependent topic that will depend on your particular application. The overhead of maintaining an index may outweigh any gains in query speed.

- Appropriate use of field types.

We will assume you have done the obvious things above. The rest of this document focuses on how to use Django in such a way that you are not doing unnecessary work. This document also does not address other optimization techniques that apply to all expensive operations, such as general purpose caching.

Understand QuerySets

Understanding QuerySets is vital to getting good performance with simple code. In particular:

Understand QuerySet evaluation

To avoid performance problems, it is important to understand:

- that QuerySets are lazy.

- when they are evaluated.

- how the data is held in memory.

Understand cached attributes

As well as caching of the whole QuerySet, there is caching of the result of attributes on ORM objects. In general, attributes that are not callable will be cached. For example, assuming the example Weblog models:

>>> entry = Entry.objects.get(id=1)
>>> entry.blog   # Blog object is retrieved at this point
>>> entry.blog   # cached version, no DB access

But in general, callable attributes cause DB lookups every time:

>>> entry = Entry.objects.get(id=1)
>>> entry.authors.all()   # query performed
>>> entry.authors.all()   # query performed again

Be careful when reading template code - the template system does not allow use of parentheses, but will call callables automatically, hiding the above distinction.

Be careful with your own custom properties - it is up to you to implement caching when required, for example using the cached_property decorator.

Use the with template tag

To make use of the caching behavior of QuerySet, you may need to use the with template tag.

Use iterator()

When you have a lot of objects, the caching behavior of the QuerySet can cause a large amount of memory to be used. In this case, iterator() may help.

Do database work in the database rather than in Python

For instance:

- At the most basic level, use filter and exclude to do filtering in the database.

- Use F expressions to filter based on other fields within the same model.

- Use annotate to do aggregation in the database.

If these aren’t enough to generate the SQL you need:

Use RawSQL

A less portable but more powerful method is the RawSQL expression, which allows some SQL to be explicitly added to the query. If that still isn’t powerful enough:

Use raw SQL

Write your own custom SQL to retrieve data or populate models. Use django.db.connection.queries to find out what Django is writing for you and start from there.

Retrieve individual objects using a unique, indexed column

There are two reasons to use a column with unique or db_index when using get() to retrieve individual objects. First, the query will be quicker because of the underlying database index. Also, the query could run much slower if multiple objects match the lookup; having a unique constraint on the column guarantees this will never happen.

So using the example Weblog models:

>>> entry = Entry.objects.get(id=10)

will be quicker than:

>>> entry = Entry.objects.get(headline="News Item Title")

because id is indexed by the database and is guaranteed to be unique.

Doing the following is potentially quite slow:

>>> entry = Entry.objects.get(headline__startswith="News")

First of all, headline is not indexed, which will make the underlying database fetch slower.

Second, the lookup doesn’t guarantee that only one object will be returned. If the query matches more than one object, it will retrieve and transfer all of them from the database. This penalty could be substantial if hundreds or thousands of records are returned. The penalty will be compounded if the database lives on a separate server, where network overhead and latency also play a factor.

Retrieve everything at once if you know you will need it

Hitting the database multiple times for different parts of a single ‘set’ of data that you will need all parts of is, in general, less efficient than retrieving it all in one query. This is particularly important if you have a query that is executed in a loop, and could therefore end up doing many database queries, when only one was needed. So:

Use QuerySet.select_related() and prefetch_related()

Understand select_related() and prefetch_related() thoroughly, and use them:

- in view code,

- and in managers and default managers where appropriate. Be aware when your manager is and is not used; sometimes this is tricky so don’t make assumptions.

Don’t retrieve things you don’t need

Use QuerySet.values() and values_list()

When you just want a dict or list of values, and don’t need ORM model objects, make appropriate usage of values(). These can be useful for replacing model objects in template code - as long as the dicts you supply have the same attributes as those used in the template, you are fine.

Use QuerySet.defer() and only()

Use defer() and only() if there are database columns you know that you won’t need (or won’t need in most cases) to avoid loading them. Note that if you do use them, the ORM will have to go and get them in a separate query, making this a pessimization if you use it inappropriately.

Also, be aware that there is some (small extra) overhead incurred inside Django when constructing a model with deferred fields. Don’t be too aggressive in deferring fields without profiling as the database has to read most of the non-text, non-VARCHAR data from the disk for a single row in the results, even if it ends up only using a few columns. The defer() and only() methods are most useful when you can avoid loading a lot of text data or for fields that might take a lot of processing to convert back to Python. As always, profile first, then optimize.

Use QuerySet.count()

...if you only want the count, rather than doing len(queryset).

Use QuerySet.exists()

...if you only want to find out if at least one result exists, rather than if queryset.

But:

Don’t overuse count() and exists()

If you are going to need other data from the QuerySet, just evaluate it.

For example, assuming an Email model that has a body attribute and a many-to-many relation to User, the following template code is optimal:

{% if display_inbox %}
{% with emails=user.emails.all %}
{% if emails %}
<p>You have {{ emails|length }} email(s)</p>
{% for email in emails %}
<p>{{ email.body }}</p>
{% endfor %}
{% else %}
<p>No messages today.</p>
{% endif %}
{% endwith %}
{% endif %}

It is optimal because:

1. Since QuerySets are lazy, this does no database queries if ‘display_inbox’ is False.

2. Use of with means that we store user.emails.all in a variable for later use, allowing its cache to be re-used.

3. The line {% if emails %} causes QuerySet.__bool__() to be called, which causes the user.emails.all() query to be run on the database, and at the least the first line to be turned into an ORM object. If there aren’t any results, it will return False, otherwise True.

4. The use of {{ emails|length }} calls QuerySet.__len__(), filling out the rest of the cache without doing another query.

5. The for loop iterates over the already filled cache.

In total, this code does either one or zero database queries. The only deliberate optimization performed is the use of the with tag. Using QuerySet.exists() or QuerySet.count() at any point would cause additional queries.

Use QuerySet.update() and delete()

Rather than retrieve a load of objects, set some values, and save them individual, use a bulk SQL UPDATE statement, via QuerySet.update(). Similarly, do bulk deletes where possible.

Note, however, that these bulk update methods cannot call the save() or delete() methods of individual instances, which means that any custom behavior you have added for these methods will not be executed, including anything driven from the normal database object signals.

Use foreign key values directly

If you only need a foreign key value, use the foreign key value that is already on the object you’ve got, rather than getting the whole related object and taking its primary key. i.e. do:

entry.blog_id

instead of:

entry.blog.id

Don’t order results if you don’t care

Ordering is not free; each field to order by is an operation the database must perform. If a model has a default ordering (Meta.ordering) and you don’t need it, remove it on a QuerySet by calling order_by() with no parameters.

Adding an index to your database may help to improve ordering performance.

Insert in bulk

When creating objects, where possible, use the bulk_create() method to reduce the number of SQL queries. For example:

Entry.objects.bulk_create([
Entry(headline="Python 3.0 Released"),
Entry(headline="Python 3.1 Planned")
])

...is preferable to:

Entry.objects.create(headline="Python 3.0 Released")
Entry.objects.create(headline="Python 3.1 Planned")

Note that there are a number of caveats to this method, so make sure it’s appropriate for your use case.

This also applies to ManyToManyFields, so doing:

my_band.members.add(me, my_friend)

...is preferable to:

my_band.members.add(me)
my_band.members.add(my_friend)

...where Bands and Artists have a many-to-many relationship.

Examples of model relationship API usage

- Many-to-many relationships

- Many-to-one relationships

- One-to-one relationships

Many-to-many relationships

To define a many-to-many relationship, use ManyToManyField.

In this example, an Article can be published in multiple Publication objects, and a Publication has multiple Article objects:

from django.db import models

class Publication(models.Model):
title = models.CharField(max_length=30)

def __str__(self):              # __unicode__ on Python 2
return self.title

class Meta:
ordering = ('title',)

class Article(models.Model):
headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication)

def __str__(self):              # __unicode__ on Python 2
return self.headline

class Meta:
ordering = ('headline',)

What follows are examples of operations that can be performed using the Python API facilities. Note that if you are using an intermediate model for a many-to-many relationship, some of the related manager’s methods are disabled, so some of these examples won’t work with such models.

Create a couple of Publications:

>>> p1 = Publication(title='The Python Journal')
>>> p1.save()
>>> p2 = Publication(title='Science News')
>>> p2.save()
>>> p3 = Publication(title='Science Weekly')
>>> p3.save()

Create an Article:

>>> a1 = Article(headline='Django lets you build Web apps easily')

You can’t associate it with a Publication until it’s been saved:

>>> a1.publications.add(p1)
Traceback (most recent call last):
...
ValueError: 'Article' instance needs to have a primary key value before a many-to-many relationship can be used.

Save it!

>>> a1.save()

Associate the Article with a Publication:

>>> a1.publications.add(p1)

Create another Article, and set it to appear in both Publications:

>>> a2 = Article(headline='NASA uses Python')
>>> a2.save()
>>> a2.publications.add(p1, p2)
>>> a2.publications.add(p3)

Adding a second time is OK:

>>> a2.publications.add(p3)

Adding an object of the wrong type raises TypeError:

>>> a2.publications.add(a1)
Traceback (most recent call last):
...
TypeError: 'Publication' instance expected

Create and add a Publication to an Article in one step using create():

>>> new_publication = a2.publications.create(title='Highlights for Children')

Article objects have access to their related Publication objects:

>>> a1.publications.all()
[<Publication: The Python Journal>]
>>> a2.publications.all()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]

Publication objects have access to their related Article objects:

>>> p2.article_set.all()
[<Article: NASA uses Python>]
>>> p1.article_set.all()
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Publication.objects.get(id=4).article_set.all()
[<Article: NASA uses Python>]

Many-to-many relationships can be queried using lookups across relationships:

>>> Article.objects.filter(publications__id=1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications__pk=1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications=1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications=p1)
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications__title__startswith="Science")
[<Article: NASA uses Python>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications__title__startswith="Science").distinct()
[<Article: NASA uses Python>]

The count() function respects distinct() as well:

>>> Article.objects.filter(publications__title__startswith="Science").count()
2

>>> Article.objects.filter(publications__title__startswith="Science").distinct().count()
1

>>> Article.objects.filter(publications__in=[1,2]).distinct()
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications__in=[p1,p2]).distinct()
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]

Reverse m2m queries are supported (i.e., starting at the table that doesn’t have a ManyToManyField):

>>> Publication.objects.filter(id=1)
[<Publication: The Python Journal>]
>>> Publication.objects.filter(pk=1)
[<Publication: The Python Journal>]

>>> Publication.objects.filter(article__headline__startswith="NASA")
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]

>>> Publication.objects.filter(article__id=1)
[<Publication: The Python Journal>]
>>> Publication.objects.filter(article__pk=1)
[<Publication: The Python Journal>]
>>> Publication.objects.filter(article=1)
[<Publication: The Python Journal>]
>>> Publication.objects.filter(article=a1)
[<Publication: The Python Journal>]

>>> Publication.objects.filter(article__in=[1,2]).distinct()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
>>> Publication.objects.filter(article__in=[a1,a2]).distinct()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]

Excluding a related item works as you would expect, too (although the SQL involved is a little complex):

>>> Article.objects.exclude(publications=p2)
[<Article: Django lets you build Web apps easily>]

If we delete a Publication, its Articles won’t be able to access it:

>>> p1.delete()
>>> Publication.objects.all()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]
>>> a1 = Article.objects.get(pk=1)
>>> a1.publications.all()
[]

If we delete an Article, its Publications won’t be able to access it:

>>> a2.delete()
>>> Article.objects.all()
[<Article: Django lets you build Web apps easily>]
>>> p2.article_set.all()
[]

Adding via the ‘other’ end of an m2m:

>>> a4 = Article(headline='NASA finds intelligent life on Earth')
>>> a4.save()
>>> p2.article_set.add(a4)
>>> p2.article_set.all()
[<Article: NASA finds intelligent life on Earth>]
>>> a4.publications.all()
[<Publication: Science News>]

Adding via the other end using keywords:

>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
>>> p2.article_set.all()
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
>>> a5 = p2.article_set.all()[1]
>>> a5.publications.all()
[<Publication: Science News>]

Removing Publication from an Article:

>>> a4.publications.remove(p2)
>>> p2.article_set.all()
[<Article: Oxygen-free diet works wonders>]
>>> a4.publications.all()
[]

And from the other end:

>>> p2.article_set.remove(a5)
>>> p2.article_set.all()
[]
>>> a5.publications.all()
[]

Relation sets can be assigned. Assignment clears any existing set members:

>>> a4.publications.all()
[<Publication: Science News>]
>>> a4.publications = [p3]
>>> a4.publications.all()
[<Publication: Science Weekly>]

Relation sets can be cleared:

>>> p2.article_set.clear()
>>> p2.article_set.all()
[]

And you can clear from the other end:

>>> p2.article_set.add(a4, a5)
>>> p2.article_set.all()
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
>>> a4.publications.all()
[<Publication: Science News>, <Publication: Science Weekly>]
>>> a4.publications.clear()
>>> a4.publications.all()
[]
>>> p2.article_set.all()
[<Article: Oxygen-free diet works wonders>]

Recreate the Article and Publication we have deleted:

>>> p1 = Publication(title='The Python Journal')
>>> p1.save()
>>> a2 = Article(headline='NASA uses Python')
>>> a2.save()
>>> a2.publications.add(p1, p2, p3)

Bulk delete some Publications - references to deleted publications should go:

>>> Publication.objects.filter(title__startswith='Science').delete()
>>> Publication.objects.all()
[<Publication: Highlights for Children>, <Publication: The Python Journal>]
>>> Article.objects.all()
[<Article: Django lets you build Web apps easily>, <Article: NASA finds intelligent life on Earth>, <Article: NASA uses Python>, <Article: Oxygen-free diet works wonders>]
>>> a2.publications.all()
[<Publication: The Python Journal>]

Bulk delete some articles - references to deleted objects should go:

>>> q = Article.objects.filter(headline__startswith='Django')
>>> print(q)
[<Article: Django lets you build Web apps easily>]
>>> q.delete()

After the delete(), the QuerySet cache needs to be cleared, and the referenced objects should be gone:

>>> print(q)
[]
>>> p1.article_set.all()
[<Article: NASA uses Python>]

An alternate to calling clear() is to assign the empty set:

>>> p1.article_set = []
>>> p1.article_set.all()
[]

>>> a2.publications = [p1, new_publication]
>>> a2.publications.all()
[<Publication: Highlights for Children>, <Publication: The Python Journal>]
>>> a2.publications = []
>>> a2.publications.all()
[]

Many-to-one relationships

To define a many-to-one relationship, use ForeignKey:

from django.db import models

class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()

def __str__(self):              # __unicode__ on Python 2
return "%s %s" % (self.first_name, self.last_name)

class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

def __str__(self):              # __unicode__ on Python 2
return self.headline

class Meta:
ordering = ('headline',)

What follows are examples of operations that can be performed using the Python API facilities.

Create a few Reporters:

>>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r.save()

>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
>>> r2.save()

Create an Article:

>>> from datetime import date
>>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
>>> a.save()

>>> a.reporter.id
1

>>> a.reporter
<Reporter: John Smith>

Note that you must save an object before it can be assigned to a foreign key relationship. For example, creating an Article with unsaved Reporter raises ValueError:

>>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> Article.objects.create(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3)
Traceback (most recent call last):
...
ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'.

Changed in Django 1.8.4:
Previously, saving an object with unsaved related objects did not raise an error and could result in silent data loss. In 1.8-1.8.3, unsaved model instances couldn’t be assigned to related fields, but this restriction was removed to allow easier usage of in-memory models.

Article objects have access to their related Reporter objects:

>>> r = a.reporter

On Python 2, these are strings of type str instead of unicode strings because that’s what was used in the creation of this reporter (and we haven’t refreshed the data from the database, which always returns unicode strings):

>>> r.first_name, r.last_name
('John', 'Smith')

Create an Article via the Reporter object:

>>> new_article = r.article_set.create(headline="John's second story", pub_date=date(2005, 7, 29))
>>> new_article
<Article: John's second story>
>>> new_article.reporter
<Reporter: John Smith>
>>> new_article.reporter.id
1

Create a new article, and add it to the article set:

>>> new_article2 = Article(headline="Paul's story", pub_date=date(2006, 1, 17))
>>> r.article_set.add(new_article2)
>>> new_article2.reporter
<Reporter: John Smith>
>>> new_article2.reporter.id
1
>>> r.article_set.all()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]

Add the same article to a different article set - check that it moves:

>>> r2.article_set.add(new_article2)
>>> new_article2.reporter.id
2
>>> new_article2.reporter
<Reporter: Paul Jones>

Adding an object of the wrong type raises TypeError:

>>> r.article_set.add(r2)
Traceback (most recent call last):
...
TypeError: 'Article' instance expected

>>> r.article_set.all()
[<Article: John's second story>, <Article: This is a test>]
>>> r2.article_set.all()
[<Article: Paul's story>]

>>> r.article_set.count()
2

>>> r2.article_set.count()
1

Note that in the last example the article has moved from John to Paul.

Related managers support field lookups as well. The API automatically follows relationships as far as you need. Use double underscores to separate relationships. This works as many levels deep as you want. There’s no limit. For example:

>>> r.article_set.filter(headline__startswith='This')
[<Article: This is a test>]

# Find all Articles for any Reporter whose first name is "John".
>>> Article.objects.filter(reporter__first_name='John')
[<Article: John's second story>, <Article: This is a test>]

Exact match is implied here:

>>> Article.objects.filter(reporter__first_name='John')
[<Article: John's second story>, <Article: This is a test>]

Query twice over the related field. This translates to an AND condition in the WHERE clause:

>>> Article.objects.filter(reporter__first_name='John', reporter__last_name='Smith')
[<Article: John's second story>, <Article: This is a test>]

For the related lookup you can supply a primary key value or pass the related object explicitly:

>>> Article.objects.filter(reporter__pk=1)
[<Article: John's second story>, <Article: This is a test>]
>>> Article.objects.filter(reporter=1)
[<Article: John's second story>, <Article: This is a test>]
>>> Article.objects.filter(reporter=r)
[<Article: John's second story>, <Article: This is a test>]

>>> Article.objects.filter(reporter__in=[1,2]).distinct()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
>>> Article.objects.filter(reporter__in=[r,r2]).distinct()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]

You can also use a queryset instead of a literal list of instances:

>>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinct()
[<Article: John's second story>, <Article: This is a test>]

Querying in the opposite direction:

>>> Reporter.objects.filter(article__pk=1)
[<Reporter: John Smith>]
>>> Reporter.objects.filter(article=1)
[<Reporter: John Smith>]
>>> Reporter.objects.filter(article=a)
[<Reporter: John Smith>]

>>> Reporter.objects.filter(article__headline__startswith='This')
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
>>> Reporter.objects.filter(article__headline__startswith='This').distinct()
[<Reporter: John Smith>]

Counting in the opposite direction works in conjunction with distinct():

>>> Reporter.objects.filter(article__headline__startswith='This').count()
3
>>> Reporter.objects.filter(article__headline__startswith='This').distinct().count()
1

Queries can go round in circles:

>>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
[<Reporter: John Smith>]
>>> Reporter.objects.filter(article__reporter=r).distinct()
[<Reporter: John Smith>]

If you delete a reporter, his articles will be deleted (assuming that the ForeignKey was defined with django.db.models.ForeignKey.on_delete set to CASCADE, which is the default):

>>> Article.objects.all()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
>>> Reporter.objects.order_by('first_name')
[<Reporter: John Smith>, <Reporter: Paul Jones>]
>>> r2.delete()
>>> Article.objects.all()
[<Article: John's second story>, <Article: This is a test>]
>>> Reporter.objects.order_by('first_name')
[<Reporter: John Smith>]

You can delete using a JOIN in the query:

>>> Reporter.objects.filter(article__headline__startswith='This').delete()
>>> Reporter.objects.all()
[]
>>> Article.objects.all()
[]

One-to-one relationships

To define a one-to-one relationship, use OneToOneField.

In this example, a Place optionally can be a Restaurant:

from django.db import models

class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)

def __str__(self):              # __unicode__ on Python 2
return "%s the place" % self.name

class Restaurant(models.Model):
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
primary_key=True,
)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)

def __str__(self):              # __unicode__ on Python 2
return "%s the restaurant" % self.place.name

class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
name = models.CharField(max_length=50)

def __str__(self):              # __unicode__ on Python 2
return "%s the waiter at %s" % (self.name, self.restaurant)

What follows are examples of operations that can be performed using the Python API facilities.

Create a couple of Places:

>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
>>> p1.save()
>>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
>>> p2.save()

Create a Restaurant. Pass the ID of the “parent” object as this object’s ID:

>>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
>>> r.save()

A Restaurant can access its place:

>>> r.place
<Place: Demon Dogs the place>

A Place can access its restaurant, if available:

>>> p1.restaurant
<Restaurant: Demon Dogs the restaurant>

p2 doesn’t have an associated restaurant:

>>> from django.core.exceptions import ObjectDoesNotExist
>>> try:
>>>     p2.restaurant
>>> except ObjectDoesNotExist:
>>>     print("There is no restaurant here.")
There is no restaurant here.

You can also use hasattr to avoid the need for exception catching:

>>> hasattr(p2, 'restaurant')
False

Set the place using assignment notation. Because place is the primary key on Restaurant, the save will create a new restaurant:

>>> r.place = p2
>>> r.save()
>>> p2.restaurant
<Restaurant: Ace Hardware the restaurant>
>>> r.place
<Place: Ace Hardware the place>

Set the place back again, using assignment in the reverse direction:

>>> p1.restaurant = r
>>> p1.restaurant
<Restaurant: Demon Dogs the restaurant>

Note that you must save an object before it can be assigned to a one-to-one relationship. For example, creating a Restaurant with unsaved Place raises ValueError:

>>> p3 = Place(name='Demon Dogs', address='944 W. Fullerton')
>>> Restaurant.objects.create(place=p3, serves_hot_dogs=True, serves_pizza=False)
Traceback (most recent call last):
...
ValueError: save() prohibited to prevent data loss due to unsaved related object 'place'.

Changed in Django 1.8.4:
Previously, saving an object with unsaved related objects did not raise an error and could result in silent data loss. In 1.8-1.8.3, unsaved model instances couldn’t be assigned to related fields, but this restriction was removed to allow easier usage of in-memory models.

Restaurant.objects.all() just returns the Restaurants, not the Places. Note that there are two restaurants - Ace Hardware the Restaurant was created in the call to r.place = p2:

>>> Restaurant.objects.all()
[<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]

Place.objects.all() returns all Places, regardless of whether they have Restaurants:

>>> Place.objects.order_by('name')
[<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]

You can query the models using lookups across relationships:

>>> Restaurant.objects.get(place=p1)
<Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.get(place__pk=1)
<Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.filter(place__name__startswith="Demon")
[<Restaurant: Demon Dogs the restaurant>]
>>> Restaurant.objects.exclude(place__address__contains="Ashland")
[<Restaurant: Demon Dogs the restaurant>]

This of course works in reverse:

>>> Place.objects.get(pk=1)
<Place: Demon Dogs the place>
>>> Place.objects.get(restaurant__place=p1)
<Place: Demon Dogs the place>
>>> Place.objects.get(restaurant=r)
<Place: Demon Dogs the place>
>>> Place.objects.get(restaurant__place__name__startswith="Demon")
<Place: Demon Dogs the place>

Add a Waiter to the Restaurant:

>>> w = r.waiter_set.create(name='Joe')
>>> w
<Waiter: Joe the waiter at Demon Dogs the restaurant>

Query the waiters:

>>> Waiter.objects.filter(restaurant__place=p1)
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
>>> Waiter.objects.filter(restaurant__place__name__startswith="Demon")
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]

Handling HTTP requests

Information on handling HTTP requests in Django:

- URL dispatcher

- Writing views

- View decorators

- File Uploads

- Django shortcut functions

- Generic views

- Middleware

- How to use sessions

URL dispatcher

A clean, elegant URL scheme is an important detail in a high-quality Web application. Django lets you design URLs however you want, with no framework limitations.

There’s no .php or .cgi required, and certainly none of that 0,2097,1-1-1928,00 nonsense.

See Cool URIs don’t change, by World Wide Web creator Tim Berners-Lee, for excellent arguments on why URLs should be clean and usable.

Overview

To design URLs for an app, you create a Python module informally called a URLconf (URL configuration). This module is pure Python code and is a simple mapping between URL patterns (simple regular expressions) to Python functions (your views).

This mapping can be as short or as long as needed. It can reference other mappings. And, because it’s pure Python code, it can be constructed dynamically.

Django also provides a way to translate URLs according to the active language. See the internationalization documentation for more information.

How Django processes a request

When a user requests a page from your Django-powered site, this is the algorithm the system follows to determine which Python code to execute:

1. Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has a urlconf attribute (set by middleware request processing), its value will be used in place of the ROOT_URLCONF setting.

2. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list of django.conf.urls.url() instances.

3. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.

4. Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function (or a class-based view). The view gets passed the following arguments:

- An instance of HttpRequest.

- If the matched regular expression returned no named groups, then the matches from the regular expression are provided as positional arguments.

- The keyword arguments are made up of any named groups matched by the regular expression, overridden by any arguments specified in the optional kwargs argument to django.conf.urls.url().

5. If no regex matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.

Example

Here’s a sample URLconf:

from django.conf.urls import url

from . import views

urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

Notes:

- To capture a value from the URL, just put parenthesis around it.

- There’s no need to add a leading slash, because every URL has that. For example, it’s ^articles, not ^/articles.

- The 'r' in front of each regular expression string is optional but recommended. It tells Python that a string is “raw” – that nothing in the string should be escaped. See Dive Into Python’s explanation.

Example requests:

- A request to /articles/2005/03/ would match the third entry in the list. Django would call the function views.month_archive(request, '2005', '03').

- /articles/2005/3/ would not match any URL patterns, because the third entry in the list requires two digits for the month.

- /articles/2003/ would match the first pattern in the list, not the second one, because the patterns are tested in order, and the first one is the first test to pass. Feel free to exploit the ordering to insert special cases like this. Here, Django would call the function views.special_case_2003(request)

- /articles/2003 would not match any of these patterns, because each pattern requires that the URL end with a slash.

- /articles/2003/03/03/ would match the final pattern. Django would call the function views.article_detail(request, '2003', '03', '03').

Named groups

The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it’s possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.

In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.

Here’s the above example URLconf, rewritten to use named groups:

from django.conf.urls import url

from . import views

urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

This accomplishes exactly the same thing as the previous example, with one subtle difference: The captured values are passed to view functions as keyword arguments rather than positional arguments. For example:

- A request to /articles/2005/03/ would call the function views.month_archive(request, year='2005', month='03'), instead of views.month_archive(request, '2005', '03').

- A request to /articles/2003/03/03/ would call the function views.article_detail(request, year='2003', month='03', day='03').

In practice, this means your URLconfs are slightly more explicit and less prone to argument-order bugs – and you can reorder the arguments in your views’ function definitions. Of course, these benefits come at the cost of brevity; some developers find the named-group syntax ugly and too verbose.

The matching/grouping algorithm

Here’s the algorithm the URLconf parser follows, with respect to named groups vs. non-named groups in a regular expression:

1. If there are any named arguments, it will use those, ignoring non-named arguments.

2. Otherwise, it will pass all non-named arguments as positional arguments.

In both cases, any extra keyword arguments that have been given as per Passing extra options to view functions (below) will also be passed to the view.

What the URLconf searches against

The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.

For example, in a request to https://www.example.com/myapp/, the URLconf will look for myapp/.

In a request to https://www.example.com/myapp/?page=3, the URLconf will look for myapp/.

The URLconf doesn’t look at the request method. In other words, all request methods – POST, GET, HEAD, etc. – will be routed to the same function for the same URL.

Captured arguments are always strings

Each captured argument is sent to the view as a plain Python string, regardless of what sort of match the regular expression makes. For example, in this URLconf line:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

...the year argument passed to views.year_archive() will be a string,

not an integer, even though the [0-9]{4} will only match integer strings.

Specifying defaults for view arguments

A convenient trick is to specify default parameters for your views’ arguments. Here’s an example URLconf and view:

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# View (in blog/views.py)
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.
...

In the above example, both URL patterns point to the same view – views.page – but the first pattern doesn’t capture anything from the URL. If the first pattern matches, the page() function will use its default argument for num, "1". If the second pattern matches, page() will use whatever num value was captured by the regex.

Performance

Each regular expression in a urlpatterns is compiled the first time it’s accessed. This makes the system blazingly fast.

Syntax of the urlpatterns variable

urlpatterns should be a Python list of url() instances.

Error handling

When Django can’t find a regex matching the requested URL, or when an exception is raised, Django will invoke an error-handling view.

The views to use for these cases are specified by four variables. Their default values should suffice for most projects, but further customization is possible by overriding their default values.

See the documentation on customizing error views for the full details.

Such values can be set in your root URLconf. Setting these variables in any other URLconf will have no effect.

Values must be callables, or strings representing the full Python import path to the view that should be called to handle the error condition at hand.

The variables are:

- handler400 – See django.conf.urls.handler400.

- handler403 – See django.conf.urls.handler403.

- handler404 – See django.conf.urls.handler404.

- handler500 – See django.conf.urls.handler500.

Including other URLconfs

At any point, your urlpatterns can “include” other URLconf modules. This essentially “roots” a set of URLs below other ones.

For example, here’s an excerpt of the URLconf for the Django website itself. It includes a number of other URLconfs:

from django.conf.urls import include, url

urlpatterns = [
# ... snip ...
url(r'^community/', include('django_website.aggregator.urls')),
url(r'^contact/', include('django_website.contact.urls')),
# ... snip ...
]

Note that the regular expressions in this example don’t have a $ (end-of-string match character) but do include a trailing slash. Whenever Django encounters include() (django.conf.urls.include()), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

Another possibility is to include additional URL patterns by using a list of url() instances. For example, consider this URLconf:

from django.conf.urls import include, url

from apps.main import views as main_views
from credit import views as credit_views

extra_patterns = [
url(r'^reports/$', credit_views.report),
url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
url(r'^charge/$', credit_views.charge),
]

urlpatterns = [
url(r'^$', main_views.homepage),
url(r'^help/', include('apps.help.urls')),
url(r'^credit/', include(extra_patterns)),
]

In this example, the /credit/reports/ URL will be handled by the credit_views.report() Django view.

This can be used to remove redundancy from URLconfs where a single pattern prefix is used repeatedly. For example, consider this URLconf:

from django.conf.urls import url
from . import views

urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]

We can improve this by stating the common path prefix only once and grouping the suffixes that differ:

from django.conf.urls import include, url
from . import views

urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
url(r'^history/$', views.history),
url(r'^edit/$', views.edit),
url(r'^discuss/$', views.discuss),
url(r'^permissions/$', views.permissions),
])),
]

Captured parameters

An included URLconf receives any captured parameters from parent URLconfs, so the following example is valid:

# In settings/urls/main.py
from django.conf.urls import include, url

urlpatterns = [
url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
]

# In foo/urls/blog.py
from django.conf.urls import url
from . import views

urlpatterns = [
url(r'^$', views.blog.index),
url(r'^archive/$', views.blog.archive),
]

In the above example, the captured "username" variable is passed to the included URLconf, as expected.

Nested arguments

Regular expressions allow nested arguments, and Django will resolve them and pass them to the view. When reversing, Django will try to fill in all outer captured arguments, ignoring any nested captured arguments. Consider the following URL patterns which optionally take a page argument:

from django.conf.urls import url

urlpatterns = [
url(r'blog/(page-(\d+)/)?$', blog_articles),                  # bad
url(r'comments/(?:page-(?P<page_number>\d+)/)?$', comments),  # good
]

Both patterns use nested arguments and will resolve: for example, blog/page-2/ will result in a match to blog_articles with two positional arguments: page-2/ and 2. The second pattern for comments will match comments/page-2/ with keyword argument page_number set to 2. The outer argument in this case is a non-capturing argument (?:...).

The blog_articles view needs the outermost captured argument to be reversed, page-2/ or no arguments in this case, while comments can be reversed with either no arguments or a value for page_number.

Nested captured arguments create a strong coupling between the view arguments and the URL as illustrated by blog_articles: the view receives part of the URL (page-2/) instead of only the value the view is interested in. This coupling is even more pronounced when reversing, since to reverse the view we need to pass the piece of URL instead of the page number.

As a rule of thumb, only capture the values the view needs to work with and use non-capturing arguments when the regular expression needs an argument but the view ignores it.

Passing extra options to view functions

URLconfs have a hook that lets you pass extra arguments to your view functions, as a Python dictionary.

The django.conf.urls.url() function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.

For example:

from django.conf.urls import url
from . import views

urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

In this example, for a request to /blog/2005/, Django will call views.year_archive(request, year='2005', foo='bar').

This technique is used in the syndication framework to pass metadata and options to views.

Dealing with conflicts

It’s possible to have a URL pattern which captures named keyword arguments, and also passes arguments with the same names in its dictionary of extra arguments. When this happens, the arguments in the dictionary will be used instead of the arguments captured in the URL.

Passing extra options to include()

Similarly, you can pass extra options to include(). When you pass extra options to include(), each line in the included URLconf will be passed the extra options.

For example, these two URLconf sets are functionally identical:

Set one:

# main.py
from django.conf.urls import include, url

urlpatterns = [
url(r'^blog/', include('inner'), {'blogid': 3}),
]

# inner.py
from django.conf.urls import url
from mysite import views

urlpatterns = [
url(r'^archive/$', views.archive),
url(r'^about/$', views.about),
]

Set two:

# main.py
from django.conf.urls import include, url
from mysite import views

urlpatterns = [
url(r'^blog/', include('inner')),
]

# inner.py
from django.conf.urls import url

urlpatterns = [
url(r'^archive/$', views.archive, {'blogid': 3}),
url(r'^about/$', views.about, {'blogid': 3}),
]

Note that extra options will always be passed to every line in the included URLconf, regardless of whether the line’s view actually accepts those options as valid. For this reason, this technique is only useful if you’re certain that every view in the included URLconf accepts the extra options you’re passing.

Reverse resolution of URLs

A common need when working on a Django project is the possibility to obtain URLs in their final forms either for embedding in generated content (views and assets URLs, URLs shown to the user, etc.) or for handling of the navigation flow on the server side (redirections, etc.)

It is strongly desirable to avoid hard-coding these URLs (a laborious, non-scalable and error-prone strategy). Equally dangerous is devising ad-hoc mechanisms to generate URLs that are parallel to the design described by the URLconf, which can result in the production of URLs that become stale over time.

In other words, what’s needed is a DRY mechanism. Among other advantages it would allow evolution of the URL design without having to go over all the project source code to search and replace outdated URLs.

The primary piece of information we have available to get a URL is an identification (e.g. the name) of the view in charge of handling it. Other pieces of information that necessarily must participate in the lookup of the right URL are the types (positional, keyword) and values of the view arguments.

Django provides a solution such that the URL mapper is the only repository of the URL design. You feed it with your URLconf and then it can be used in both directions:

- Starting with a URL requested by the user/browser, it calls the right Django view providing any arguments it might need with their values as extracted from the URL.

- Starting with the identification of the corresponding Django view plus the values of arguments that would be passed to it, obtain the associated URL.

The first one is the usage we’ve been discussing in the previous sections. The second one is what is known as reverse resolution of URLs, reverse URL matching, reverse URL lookup, or simply URL reversing.

Django provides tools for performing URL reversing that match the different layers where URLs are needed:

- In templates: Using the url template tag.

- In Python code: Using the django.core.urlresolvers.reverse() function.

- In higher level code related to handling of URLs of Django model instances: The get_absolute_url() method.

Examples

Consider again this URLconf entry:

from django.conf.urls import url

from . import views

urlpatterns = [
#...
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]

According to this design, the URL for the archive corresponding to year nnnn is /articles/nnnn/.

You can obtain these in template code by using:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

Or in Python code:

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

If, for some reason, it was decided that the URLs where content for yearly article archives are published at should be changed then you would only need to change the entry in the URLconf.

In some scenarios where views are of a generic nature, a many-to-one relationship might exist between URLs and views. For these cases the view name isn’t a good enough identifier for it when comes the time of reversing URLs. Read the next section to know about the solution Django provides for this.

Naming URL patterns

In order to perform URL reversing, you’ll need to use named URL patterns as done in the examples above. The string used for the URL name can contain any characters you like. You are not restricted to valid Python names.

When you name your URL patterns, make sure you use names that are unlikely to clash with any other application’s choice of names. If you call your URL pattern comment, and another application does the same thing, there’s no guarantee which URL will be inserted into your template when you use this name.

Putting a prefix on your URL names, perhaps derived from the application name, will decrease the chances of collision. We recommend something like myapp-comment instead of comment.

URL namespaces

Introduction

URL namespaces allow you to uniquely reverse named URL patterns even if different applications use the same URL names. It’s a good practice for third-party apps to always use namespaced URLs (as we did in the tutorial). Similarly, it also allows you to reverse URLs if multiple instances of an application are deployed. In other words, since multiple instances of a single application will share named URLs, namespaces provide a way to tell these named URLs apart.

Django applications that make proper use of URL namespacing can be deployed more than once for a particular site. For example django.contrib.admin has an AdminSite class which allows you to easily deploy more than one instance of the admin. In a later example, we’ll discuss the idea of deploying the polls application from the tutorial in two different locations so we can serve the same functionality to two different audiences (authors and publishers).

A URL namespace comes in two parts, both of which are strings:

application namespace

This describes the name of the application that is being deployed. Every instance of a single application will have the same application namespace. For example, Django’s admin application has the somewhat predictable application namespace of 'admin'.

instance namespace

This identifies a specific instance of an application. Instance namespaces should be unique across your entire project. However, an instance namespace can be the same as the application namespace. This is used to specify a default instance of an application. For example, the default Django admin instance has an instance namespace of 'admin'.

Namespaced URLs are specified using the ':' operator. For example, the main index page of the admin application is referenced using 'admin:index'. This indicates a namespace of 'admin', and a named URL of 'index'.

Namespaces can also be nested. The named URL 'sports:polls:index' would look for a pattern named 'index' in the namespace 'polls' that is itself defined within the top-level namespace 'sports'.

Reversing namespaced URLs

When given a namespaced URL (e.g. 'polls:index') to resolve, Django splits the fully qualified name into parts and then tries the following lookup:

1. First, Django looks for a matching application namespace (in this example, 'polls'). This will yield a list of instances of that application.

2. If there is a current application defined, Django finds and returns the URL resolver for that instance. The current application can be specified with the current_app argument to the reverse() function.

The url template tag uses the namespace of the currently resolved view as the current application in a RequestContext. You can override this default by setting the current application on the request.current_app attribute.

Changed in Django 1.8:
In previous versions of Django, you had to set the current_app attribute on any Context or RequestContext that is used to render a template.

Changed in Django 1.9:
Previously, the url template tag did not use the namespace of the currently resolved view and you had to set the current_app attribute on the request.

3. If there is no current application. Django looks for a default application instance. The default application instance is the instance that has an instance namespace matching the application namespace (in this example, an instance of polls called 'polls').

4. If there is no default application instance, Django will pick the last deployed instance of the application, whatever its instance name may be.

5. If the provided namespace doesn’t match an application namespace in step 1, Django will attempt a direct lookup of the namespace as an instance namespace.

If there are nested namespaces, these steps are repeated for each part of the namespace until only the view name is unresolved. The view name will then be resolved into a URL in the namespace that has been found.

Example

To show this resolution strategy in action, consider an example of two instances of the polls application from the tutorial: one called 'author-polls' and one called 'publisher-polls'. Assume we have enhanced that application so that it takes the instance namespace into consideration when creating and displaying polls.

urls.py

from django.conf.urls import include, url

urlpatterns = [
url(r'^author-polls/', include('polls.urls', namespace='author-polls')),
url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]

polls/urls.py

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
...
]

Using this setup, the following lookups are possible:

- If one of the instances is current - say, if we were rendering the detail page in the instance 'author-polls' - 'polls:index' will resolve to the index page of the 'author-polls' instance; i.e. both of the following will result in "/author-polls/".

In the method of a class-based view:

reverse('polls:index', current_app=self.request.resolver_match.namespace)

and in the template:

{% url 'polls:index' %}

- If there is no current instance - say, if we were rendering a page somewhere else on the site - 'polls:index' will resolve to the last registered instance of polls. Since there is no default instance (instance namespace of 'polls'), the last instance of polls that is registered will be used. This would be 'publisher-polls' since it’s declared last in the urlpatterns.

- 'author-polls:index' will always resolve to the index page of the instance 'author-polls' (and likewise for 'publisher-polls') .

If there were also a default instance - i.e., an instance named 'polls' - the only change from above would be in the case where there is no current instance (the second item in the list above). In this case 'polls:index' would resolve to the index page of the default instance instead of the instance declared last in urlpatterns.

URL namespaces and included URLconfs

Application namespaces of included URLconfs can be specified in two ways.

Firstly, you can set an app_name attribute in the included URLconf module, at the same level as the urlpatterns attribute. You have to pass the actual module, or a string reference to the module, to include(), not the list of urlpatterns itself.

polls/urls.py

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
...
]

urls.py

from django.conf.urls import include, url

urlpatterns = [
url(r'^polls/', include('polls.urls')),
]

The URLs defined in polls.urls will have an application namespace polls.

Secondly, you can include an object that contains embedded namespace data. If you include() a list of url() instances, the URLs contained in that object will be added to the global namespace. However, you can also include() a 2-tuple containing:

(<list of url() instances>, <application namespace>)

For example:

from django.conf.urls import include, url

from . import views

polls_patterns = ([
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
], 'polls')

urlpatterns = [
url(r'^polls/', include(polls_patterns)),
]

This will include the nominated URL patterns into the given application namespace.

The instance namespace can be specified using the namespace argument to include(). If the instance namespace is not specified, it will default to the included URLconf’s application namespace. This means it will also be the default instance for that namespace.

Changed in Django 1.9:
In previous versions, you had to specify both the application namespace and the instance namespace in a single place, either by passing them as parameters to include() or by including a 3-tuple containing (<list of url() instances>, <application namespace>, <instance namespace>).

Writing views

A view function, or view for short, is simply a Python function that takes a Web request and returns a Web response. This response can be the HTML contents of a Web page, or a redirect, or a 404 error, or an XML document, or an image . . . or anything, really. The view itself contains whatever arbitrary logic is necessary to return that response. This code can live anywhere you want, as long as it’s on your Python path. There’s no other requirement–no “magic,” so to speak. For the sake of putting the code somewhere, the convention is to put views in a file called views.py, placed in your project or application directory.

A simple view

Here’s a view that returns the current date and time, as an HTML document:

from django.http import HttpResponse
import datetime

def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)

Let’s step through this code one line at a time:

- First, we import the class HttpResponse from the django.http module, along with Python’s datetime library.

- Next, we define a function called current_datetime. This is the view function. Each view function takes an HttpRequest object as its first parameter, which is typically named request.

Note that the name of the view function doesn’t matter; it doesn’t have to be named in a certain way in order for Django to recognize it. We’re calling it current_datetime here, because that name clearly indicates what it does.

- The view returns an HttpResponse object that contains the generated response. Each view function is responsible for returning an HttpResponse object. (There are exceptions, but we’ll get to those later.)

Django’s Time Zone

Django includes a TIME_ZONE setting that defaults to America/Chicago. This probably isn’t where you live, so you might want to change it in your settings file.

Mapping URLs to views

So, to recap, this view function returns an HTML page that includes the current date and time. To display this view at a particular URL, you’ll need to create a URLconf; see URL dispatcher for instructions.

Returning errors

Returning HTTP error codes in Django is easy. There are subclasses of HttpResponse for a number of common HTTP status codes other than 200 (which means “OK”). You can find the full list of available subclasses in the request/response documentation. Just return an instance of one of those subclasses instead of a normal HttpResponse in order to signify an error. For example:

from django.http import HttpResponse, HttpResponseNotFound

def my_view(request):
# ...
if foo:
return HttpResponseNotFound('<h1>Page not found</h1>')
else:
return HttpResponse('<h1>Page was found</h1>')

There isn’t a specialized subclass for every possible HTTP response code, since many of them aren’t going to be that common. However, as documented in the HttpResponse documentation, you can also pass the HTTP status code into the constructor for HttpResponse to create a return class for any status code you like. For example:

from django.http import HttpResponse

def my_view(request):
# ...

# Return a "created" (201) response code.
return HttpResponse(status=201)

Because 404 errors are by far the most common HTTP error, there’s an easier way to handle those errors.

The Http404 exception

class django.http.Http404

When you return an error such as HttpResponseNotFound, you’re responsible for defining the HTML of the resulting error page:

return HttpResponseNotFound('<h1>Page not found</h1>')

For convenience, and because it’s a good idea to have a consistent 404 error page across your site, Django provides an Http404 exception. If you raise Http404 at any point in a view function, Django will catch it and return the standard error page for your application, along with an HTTP error code 404.

Example usage:

from django.http import Http404
from django.shortcuts import render
from polls.models import Poll

def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404("Poll does not exist")
return render(request, 'polls/detail.html', {'poll': p})

In order to show customized HTML when Django returns a 404, you can create an HTML template named 404.html and place it in the top level of your template tree. This template will then be served when DEBUG is set to False.

When DEBUG is True, you can provide a message to Http404 and it will appear in the standard 404 debug template. Use these messages for debugging purposes; they generally aren’t suitable for use in a production 404 template.

Customizing error views

The default error views in Django should suffice for most Web applications, but can easily be overridden if you need any custom behavior. Simply specify the handlers as seen below in your URLconf (setting them anywhere else will have no effect).

The page_not_found() view is overridden by handler404:

handler404 = 'mysite.views.my_custom_page_not_found_view'

The server_error() view is overridden by handler500:

handler500 = 'mysite.views.my_custom_error_view'

The permission_denied() view is overridden by handler403:

handler403 = 'mysite.views.my_custom_permission_denied_view'

The bad_request() view is overridden by handler400:

handler400 = 'mysite.views.my_custom_bad_request_view'

View decorators

Django provides several decorators that can be applied to views to support various HTTP features.

Allowed HTTP methods

The decorators in django.views.decorators.http can be used to restrict access to views based on the request method. These decorators will return a django.http.HttpResponseNotAllowed if the conditions are not met.

require_http_methods(request_method_list)[source]

Decorator to require that a view only accepts particular request methods. Usage:

from django.views.decorators.http import require_http_methods

@require_http_methods(["GET", "POST"])
def my_view(request):
# I can assume now that only GET or POST requests make it this far
# ...
pass

Note that request methods should be in uppercase.

require_GET()

Decorator to require that a view only accepts the GET method.

require_POST()

Decorator to require that a view only accepts the POST method.

require_safe()

Decorator to require that a view only accepts the GET and HEAD methods. These methods are commonly considered “safe” because they should not have the significance of taking an action other than retrieving the requested resource.

Note

Django will automatically strip the content of responses to HEAD requests while leaving the headers unchanged, so you may handle HEAD requests exactly like GET requests in your views. Since some software, such as link checkers, rely on HEAD requests, you might prefer using require_safe instead of require_GET.

Conditional view processing

The following decorators in django.views.decorators.http can be used to control caching behavior on particular views.

condition(etag_func=None, last_modified_func=None)[source]

etag(etag_func)[source]

last_modified(last_modified_func)[source]

These decorators can be used to generate ETag and Last-Modified headers; see conditional view processing.

GZip compression

The decorators in django.views.decorators.gzip control content compression on a per-view basis.

gzip_page()

This decorator compresses content if the browser allows gzip compression. It sets the Vary header accordingly, so that caches will base their storage on the Accept-Encoding header.

Vary headers

The decorators in django.views.decorators.vary can be used to control caching based on specific request headers.

vary_on_cookie(func)[source]

vary_on_headers(*headers)[source]

The Vary header defines which request headers a cache mechanism should take into account when building its cache key.

See using vary headers.

Caching

The decorators in django.views.decorators.cache control server and client-side caching.

never_cache(view_func)[source]

This decorator adds a Cache-Control: max-age=0, no-cache, no-store, must-revalidate header to a response to indicate that a page should never be cached.

Changed in Django 1.9:
Before Django 1.9, Cache-Control: max-age=0 was sent. This didn’t reliably prevent caching in all browsers.

File Uploads

When Django handles a file upload, the file data ends up placed in request.FILES (for more on the request object see the documentation for request and response objects). This document explains how files are stored on disk and in memory, and how to customize the default behavior.

Warning

There are security risks if you are accepting uploaded content from untrusted users! See the security guide’s topic on User-uploaded content for mitigation details.

Basic file uploads

Consider a simple form containing a FileField:

forms.py

from django import forms

class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()

A view handling this form will receive the file data in request.FILES, which is a dictionary containing a key for each FileField (or ImageField, or other FileField subclass) in the form. So the data from the above form would be accessible as request.FILES['file'].

Note that request.FILES will only contain data if the request method was POST and the <form> that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.

Most of the time, you’ll simply pass the file data from request into the form as described in Binding uploaded files to a form. This would look something like:

views.py

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm

# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file

def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})

Notice that we have to pass request.FILES into the form’s constructor; this is how file data gets bound into a form.

Here’s a common way you might handle an uploaded file:

def handle_uploaded_file(f):
with open('some/file/name.txt', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)

Looping over UploadedFile.chunks() instead of using read() ensures that large files don’t overwhelm your system’s memory.

There are a few other methods and attributes available on UploadedFile objects; see UploadedFile for a complete reference.

Handling uploaded files with a model

If you’re saving a file on a Model with a FileField, using a ModelForm makes this process much easier. The file object will be saved to the location specified by the upload_to argument of the corresponding FileField when calling form.save():

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField

def upload_file(request):
if request.method == 'POST':
form = ModelFormWithFileField(request.POST, request.FILES)
if form.is_valid():
# file is saved
form.save()
return HttpResponseRedirect('/success/url/')
else:
form = ModelFormWithFileField()
return render(request, 'upload.html', {'form': form})

If you are constructing an object manually, you can simply assign the file object from request.FILES to the file field in the model:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField

def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
instance = ModelWithFileField(file_field=request.FILES['file'])
instance.save()
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})

Uploading multiple files

If you want to upload multiple files using one form field, set the multiple HTML attribute of field’s widget:

forms.py

from django import forms

class FileFieldForm(forms.Form):
file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

Then override the post method of your FormView subclass to handle multiple file uploads:

views.py

from django.views.generic.edit import FormView
from .forms import FileFieldForm

class FileFieldView(FormView):
form_class = FileFieldForm
template_name = 'upload.html'  # Replace with your template.
success_url = '...'  # Replace with your URL or reverse().

def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('file_field')
if form.is_valid():
for f in files:
...  # Do something with each file.
return self.form_valid(form)
else:
return self.form_invalid(form)

Upload Handlers

When a user uploads a file, Django passes off the file data to an upload handler – a small class that handles file data as it gets uploaded. Upload handlers are initially defined in the FILE_UPLOAD_HANDLERS setting, which defaults to:

["django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler"]

Together MemoryFileUploadHandler and TemporaryFileUploadHandler provide Django’s default file upload behavior of reading small files into memory and large ones onto disk.

You can write custom handlers that customize how Django handles files. You could, for example, use custom handlers to enforce user-level quotas, compress data on the fly, render progress bars, and even send data to another storage location directly without storing it locally. See Writing custom upload handlers for details on how you can customize or completely replace upload behavior.

Where uploaded data is stored

Before you save uploaded files, the data needs to be stored somewhere.

By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold the entire contents of the upload in memory. This means that saving the file involves only a read from memory and a write to disk and thus is very fast.

However, if an uploaded file is too large, Django will write the uploaded file to a temporary file stored in your system’s temporary directory. On a Unix-like platform this means you can expect Django to generate a file called something like /tmp/tmpzfp6I6.upload. If an upload is large enough, you can watch this file grow in size as Django streams the data onto disk.

These specifics – 2.5 megabytes; /tmp; etc. – are simply “reasonable defaults” which can be customized as described in the next section.

Changing upload handler behavior

There are a few settings which control Django’s file upload behavior. See File Upload Settings for details.

Modifying upload handlers on the fly

Sometimes particular views require different upload behavior. In these cases, you can override upload handlers on a per-request basis by modifying request.upload_handlers. By default, this list will contain the upload handlers given by FILE_UPLOAD_HANDLERS, but you can modify the list as you would any other list.

For instance, suppose you’ve written a ProgressBarUploadHandler that provides feedback on upload progress to some sort of AJAX widget. You’d add this handler to your upload handlers like this:

request.upload_handlers.insert(0, ProgressBarUploadHandler(request))

You’d probably want to use list.insert() in this case (instead of append()) because a progress bar handler would need to run before any other handlers. Remember, the upload handlers are processed in order.

If you want to replace the upload handlers completely, you can just assign a new list:

request.upload_handlers = [ProgressBarUploadHandler(request)]

Note

You can only modify upload handlers before accessing request.POST or request.FILES – it doesn’t make sense to change upload handlers after upload handling has already started. If you try to modify request.upload_handlers after reading from request.POST or request.FILES Django will throw an error.

Thus, you should always modify uploading handlers as early in your view as possible.

Also, request.POST is accessed by CsrfViewMiddleware which is enabled by default. This means you will need to use csrf_exempt() on your view to allow you to change the upload handlers. You will then need to use csrf_protect() on the function that actually processes the request. Note that this means that the handlers may start receiving the file upload before the CSRF checks have been done. Example code:

from django.views.decorators.csrf import csrf_exempt, csrf_protect

@csrf_exempt
def upload_file_view(request):
request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
return _upload_file_view(request)

@csrf_protect
def _upload_file_view(request):
... # Process request

Django shortcut functions

The package django.shortcuts collects helper functions and classes that “span” multiple levels of MVC. In other words, these functions/classes introduce controlled coupling for convenience’s sake.

render()

render(request, template_name, context=None, context_instance=_context_instance_undefined, content_type=None, status=None, current_app=_current_app_undefined, dirs=_dirs_undefined, using=None)[source]

Combines a given template with a given context dictionary and returns an HttpResponse object with that rendered text.

Django does not provide a shortcut function which returns a TemplateResponse because the constructor of TemplateResponse offers the same level of convenience as render().

Required arguments

request

The request object used to generate this response.

template_name

The full name of a template to use or sequence of template names. If a sequence is given, the first template that exists will be used. See the template loading documentation for more information on how templates are found.

Optional arguments

context

A dictionary of values to add to the template context. By default, this is an empty dictionary. If a value in the dictionary is callable, the view will call it just before rendering the template.

Changed in Django 1.8:
The context argument used to be called dictionary. That name is deprecated in Django 1.8 and will be removed in Django 1.10.

context_instance

The context instance to render the template with. By default, the template will be rendered with a RequestContext instance (filled with values from request and context).

Deprecated since version 1.8: The context_instance argument is deprecated. Simply use context.

content_type

The MIME type to use for the resulting document. Defaults to the value of the DEFAULT_CONTENT_TYPE setting.

status

The status code for the response. Defaults to 200.

current_app

A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

Deprecated since version 1.8: The current_app argument is deprecated. Instead you should set request.current_app.

using

The NAME of a template engine to use for loading the template.

Changed in Django 1.8:
The using parameter was added.

Deprecated since version 1.8: The dirs parameter was deprecated.

Example

The following example renders the template myapp/index.html with the MIME type application/xhtml+xml:

from django.shortcuts import render

def my_view(request):
# View code here...
return render(request, 'myapp/index.html', {
'foo': 'bar',
}, content_type='application/xhtml+xml')

This example is equivalent to:

from django.http import HttpResponse
from django.template import loader

def my_view(request):
# View code here...
t = loader.get_template('myapp/index.html')
c = {'foo': 'bar'}
return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')

render_to_response()

render_to_response(template_name, context=None, context_instance=_context_instance_undefined, content_type=None, status=None, dirs=_dirs_undefined, using=None)[source]

This function preceded the introduction of render() and works similarly except that it doesn’t make the request available in the response. It’s not recommended and is likely to be deprecated in the future.

Required arguments

template_name

The full name of a template to use or sequence of template names. If a sequence is given, the first template that exists will be used. See the template loading documentation for more information on how templates are found.

Optional arguments

context

A dictionary of values to add to the template context. By default, this is an empty dictionary. If a value in the dictionary is callable, the view will call it just before rendering the template.

Changed in Django 1.8:
The context argument used to be called dictionary. That name is deprecated in Django 1.8 and will be removed in Django 1.10.

context_instance

The context instance to render the template with. By default, the template will be rendered with a Context instance (filled with values from context). If you need to use context processors, render the template with a RequestContext instance instead. Your code might look something like this:

return render_to_response('my_template.html',
my_context,
context_instance=RequestContext(request))

Deprecated since version 1.8: The context_instance argument is deprecated. Use the render() function instead which always makes RequestContext available.

content_type

The MIME type to use for the resulting document. Defaults to the value of the DEFAULT_CONTENT_TYPE setting.

status

The status code for the response. Defaults to 200.

using

The NAME of a template engine to use for loading the template.

Changed in Django 1.8:
The status and using parameters were added.

Deprecated since version 1.8: The dirs parameter was deprecated.

redirect()

redirect(to, permanent=False, *args, **kwargs)[source]

Returns an HttpResponseRedirect to the appropriate URL for the arguments passed.

The arguments could be:

- A model: the model’s get_absolute_url() function will be called.

- A view name, possibly with arguments: urlresolvers.reverse will be used to reverse-resolve the name.

- An absolute or relative URL, which will be used as-is for the redirect location.

By default issues a temporary redirect; pass permanent=True to issue a permanent redirect.

Examples

You can use the redirect() function in a number of ways.

1. By passing some object; that object’s get_absolute_url() method will be called to figure out the redirect URL:

from django.shortcuts import redirect

def my_view(request):
...
object = MyModel.objects.get(...)
return redirect(object)

2. By passing the name of a view and optionally some positional or keyword arguments; the URL will be reverse resolved using the reverse() method:

def my_view(request):
...
return redirect('some-view-name', foo='bar')

3. By passing a hardcoded URL to redirect to:

def my_view(request):
...
return redirect('/some/url/')

This also works with full URLs:

def my_view(request):
...
return redirect('https://example.com/')

By default, redirect() returns a temporary redirect. All of the above forms accept a permanent argument; if set to True a permanent redirect will be returned:

def my_view(request):
...
object = MyModel.objects.get(...)
return redirect(object, permanent=True)

get_object_or_404()

get_object_or_404(klass, *args, **kwargs)[source]

Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.

Required arguments

klass

A Model class, a Manager, or a QuerySet instance from which to get the object.

**kwargs

Lookup parameters, which should be in the format accepted by get() and filter().

Example

The following example gets the object with the primary key of 1 from MyModel:

from django.shortcuts import get_object_or_404

def my_view(request):
my_object = get_object_or_404(MyModel, pk=1)

This example is equivalent to:

from django.http import Http404

def my_view(request):
try:
my_object = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")

The most common use case is to pass a Model, as shown above. However, you can also pass a QuerySet instance:

queryset = Book.objects.filter(title__startswith='M')
get_object_or_404(queryset, pk=1)

The above example is a bit contrived since it’s equivalent to doing:

get_object_or_404(Book, title__startswith='M', pk=1)

but it can be useful if you are passed the queryset variable from somewhere else.

Finally, you can also use a Manager. This is useful for example if you have a custom manager:

get_object_or_404(Book.dahl_objects, title='Matilda')

You can also use related managers:

author = Author.objects.get(name='Roald Dahl')
get_object_or_404(author.book_set, title='Matilda')

Note: As with get(), a MultipleObjectsReturned exception will be raised if more than one object is found.

get_list_or_404()

get_list_or_404(klass, *args, **kwargs)[source]

Returns the result of filter() on a given model manager cast to a list, raising Http404 if the resulting list is empty.

Required arguments

klass

A Model, Manager or QuerySet instance from which to get the list.

**kwargs

Lookup parameters, which should be in the format accepted by get() and filter().

Example

The following example gets all published objects from MyModel:

from django.shortcuts import get_list_or_404

def my_view(request):
my_objects = get_list_or_404(MyModel, published=True)

This example is equivalent to:

from django.http import Http404

def my_view(request):
my_objects = list(MyModel.objects.filter(published=True))
if not my_objects:
raise Http404("No MyModel matches the given query.")

Generic views

See Built-in class-based views API.

Middleware

Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.

Each middleware component is responsible for doing some specific function. For example, Django includes a middleware component, AuthenticationMiddleware, that associates users with requests using sessions.

This document explains how middleware works, how you activate middleware, and how to write your own middleware. Django ships with some built-in middleware you can use right out of the box. They’re documented in the built-in middleware reference.

Activating middleware

To activate a middleware component, add it to the MIDDLEWARE_CLASSES list in your Django settings.

In MIDDLEWARE_CLASSES, each middleware component is represented by a string: the full Python path to the middleware’s class name. For example, here’s the default value created by django-admin startproject:

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',
]

A Django installation doesn’t require any middleware — MIDDLEWARE_CLASSES can be empty, if you’d like — but it’s strongly suggested that you at least use CommonMiddleware.

The order in MIDDLEWARE_CLASSES matters because a middleware can depend on other middleware. For instance, AuthenticationMiddleware stores the authenticated user in the session; therefore, it must run after SessionMiddleware. See Middleware ordering for some common hints about ordering of Django middleware classes.

Hooks and application order

During the request phase, before calling the view, Django applies middleware in the order it’s defined in MIDDLEWARE_CLASSES, top-down. Two hooks are available:

- process_request()

- process_view()

During the response phase, after calling the view, middleware are applied in reverse order, from the bottom up. Three hooks are available:

- process_exception() (only if the view raised an exception)

- process_template_response() (only for template responses)

- process_response()

If you prefer, you can also think of it like an onion: each middleware class is a “layer” that wraps the view.

The behavior of each hook is described below.

Writing your own middleware

Writing your own middleware is easy. Each middleware component is a single Python class that defines one or more of the following methods:

process_request()

process_request(request)

request is an HttpRequest object.

process_request() is called on each request, before Django decides which view to execute.

It should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other process_request() middleware, then, process_view() middleware, and finally, the appropriate view. If it returns an HttpResponse object, Django won’t bother calling any other request, view or exception middleware, or the appropriate view; it’ll apply response middleware to that HttpResponse, and return the result.

process_view()

process_view(request, view_func, view_args, view_kwargs)

request is an HttpRequest object. view_func is the Python function that Django is about to use. (It’s the actual function object, not the name of the function as a string.) view_args is a list of positional arguments that will be passed to the view, and view_kwargs is a dictionary of keyword arguments that will be passed to the view. Neither view_args nor view_kwargs include the first view argument (request).

process_view() is called just before Django calls the view.

It should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other process_view() middleware and, then, the appropriate view. If it returns an HttpResponse object, Django won’t bother calling any other view or exception middleware, or the appropriate view; it’ll apply response middleware to that HttpResponse, and return the result.

Note

Accessing request.POST inside middleware from process_request or process_view will prevent any view running after the middleware from being able to modify the upload handlers for the request, and should normally be avoided.

The CsrfViewMiddleware class can be considered an exception, as it provides the csrf_exempt() and csrf_protect() decorators which allow views to explicitly control at what point the CSRF validation should occur.

process_template_response()

process_template_response(request, response)

request is an HttpRequest object. response is the TemplateResponse object (or equivalent) returned by a Django view or by a middleware.

process_template_response() is called just after the view has finished executing, if the response instance has a render() method, indicating that it is a TemplateResponse or equivalent.

It must return a response object that implements a render method. It could alter the given response by changing response.template_name and response.context_data, or it could create and return a brand-new TemplateResponse or equivalent.

You don’t need to explicitly render responses – responses will be automatically rendered once all template response middleware has been called.

Middleware are run in reverse order during the response phase, which includes process_template_response().

process_response()

process_response(request, response)

request is an HttpRequest object. response is the HttpResponse or StreamingHttpResponse object returned by a Django view or by a middleware.

process_response() is called on all responses before they’re returned to the browser.

It must return an HttpResponse or StreamingHttpResponse object. It could alter the given response, or it could create and return a brand-new HttpResponse or StreamingHttpResponse.

Unlike the process_request() and process_view() methods, the process_response() method is always called, even if the process_request() and process_view() methods of the same middleware class were skipped (because an earlier middleware method returned an HttpResponse). In particular, this means that your process_response() method cannot rely on setup done in process_request().

Finally, remember that during the response phase, middleware are applied in reverse order, from the bottom up. This means classes defined at the end of MIDDLEWARE_CLASSES will be run first.

Dealing with streaming responses

Unlike HttpResponse, StreamingHttpResponse does not have a content attribute. As a result, middleware can no longer assume that all responses will have a content attribute. If they need access to the content, they must test for streaming responses and adjust their behavior accordingly:

if response.streaming:
response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
response.content = alter_content(response.content)

Note

streaming_content should be assumed to be too large to hold in memory. Response middleware may wrap it in a new generator, but must not consume it. Wrapping is typically implemented as follows:

def wrap_streaming_content(content):
for chunk in content:
yield alter_content(chunk)

process_exception()

process_exception(request, exception)

request is an HttpRequest object. exception is an Exception object raised by the view function.

Django calls process_exception() when a view raises an exception. process_exception() should return either None or an HttpResponse object. If it returns an HttpResponse object, the template response and response middleware will be applied, and the resulting response returned to the browser. Otherwise, default exception handling kicks in.

Again, middleware are run in reverse order during the response phase, which includes process_exception. If an exception middleware returns a response, the middleware classes above that middleware will not be called at all.

__init__()

Most middleware classes won’t need an initializer since middleware classes are essentially placeholders for the process_* methods. If you do need some global state you may use __init__ to set up. However, keep in mind a couple of caveats:

- Django initializes your middleware without any arguments, so you can’t define __init__ as requiring any arguments.

- Unlike the process_* methods which get called once per request, __init__ gets called only once, when the Web server responds to the first request.

Marking middleware as unused

It’s sometimes useful to determine at run-time whether a piece of middleware should be used. In these cases, your middleware’s __init__ method may raise django.core.exceptions.MiddlewareNotUsed. Django will then remove that piece of middleware from the middleware process and a debug message will be logged to the django.request logger when DEBUG is set to True.

Changed in Django 1.8:
Previously, MiddlewareNotUsed exceptions weren’t logged.

Guidelines

- Middleware classes don’t have to subclass anything.

- The middleware class can live anywhere on your Python path. All Django cares about is that the MIDDLEWARE_CLASSES setting includes the path to it.

- Feel free to look at Django’s available middleware for examples.

- If you write a middleware component that you think would be useful to other people, contribute to the community! Let us know, and we’ll consider adding it to Django.

How to use sessions

Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies. Cookies contain a session ID – not the data itself (unless you’re using the cookie based backend).

Enabling sessions

Sessions are implemented via a piece of middleware.

To enable session functionality, do the following:

- Edit the MIDDLEWARE_CLASSES setting and make sure it contains 'django.contrib.sessions.middleware.SessionMiddleware'. The default settings.py created by django-admin startproject has SessionMiddleware activated.

If you don’t want to use sessions, you might as well remove the SessionMiddleware line from MIDDLEWARE_CLASSES and 'django.contrib.sessions' from your INSTALLED_APPS. It’ll save you a small bit of overhead.

Configuring the session engine

By default, Django stores sessions in your database (using the model django.contrib.sessions.models.Session). Though this is convenient, in some setups it’s faster to store session data elsewhere, so Django can be configured to store session data on your filesystem or in your cache.

Using database-backed sessions

If you want to use a database-backed session, you need to add 'django.contrib.sessions' to your INSTALLED_APPS setting.

Once you have configured your installation, run manage.py migrate to install the single database table that stores session data.

Using cached sessions

For better performance, you may want to use a cache-based session backend.

To store session data using Django’s cache system, you’ll first need to make sure you’ve configured your cache; see the cache documentation for details.

Warning

You should only use cache-based sessions if you’re using the Memcached cache backend. The local-memory cache backend doesn’t retain data long enough to be a good choice, and it’ll be faster to use file or database sessions directly instead of sending everything through the file or database cache backends. Additionally, the local-memory cache backend is NOT multi-process safe, therefore probably not a good choice for production environments.

If you have multiple caches defined in CACHES, Django will use the default cache. To use another cache, set SESSION_CACHE_ALIAS to the name of that cache.

Once your cache is configured, you’ve got two choices for how to store data in the cache:

- Set SESSION_ENGINE to "django.contrib.sessions.backends.cache" for a simple caching session store. Session data will be stored directly in your cache. However, session data may not be persistent: cached data can be evicted if the cache fills up or if the cache server is restarted.

- For persistent, cached data, set SESSION_ENGINE to "django.contrib.sessions.backends.cached_db". This uses a write-through cache – every write to the cache will also be written to the database. Session reads only use the database if the data is not already in the cache.

Both session stores are quite fast, but the simple cache is faster because it disregards persistence. In most cases, the cached_db backend will be fast enough, but if you need that last bit of performance, and are willing to let session data be expunged from time to time, the cache backend is for you.

If you use the cached_db session backend, you also need to follow the configuration instructions for the using database-backed sessions.

Using file-based sessions

To use file-based sessions, set the SESSION_ENGINE setting to "django.contrib.sessions.backends.file".

You might also want to set the SESSION_FILE_PATH setting (which defaults to output from tempfile.gettempdir(), most likely /tmp) to control where Django stores session files. Be sure to check that your Web server has permissions to read and write to this location.

Using cookie-based sessions

To use cookies-based sessions, set the SESSION_ENGINE setting to "django.contrib.sessions.backends.signed_cookies". The session data will be stored using Django’s tools for cryptographic signing and the SECRET_KEY setting.

Note

It’s recommended to leave the SESSION_COOKIE_HTTPONLY setting on True to prevent access to the stored data from JavaScript.

Warning

If the SECRET_KEY is not kept secret and you are using the PickleSerializer, this can lead to arbitrary remote code execution.

An attacker in possession of the SECRET_KEY can not only generate falsified session data, which your site will trust, but also remotely execute arbitrary code, as the data is serialized using pickle.

If you use cookie-based sessions, pay extra care that your secret key is always kept completely secret, for any system which might be remotely accessible.

The session data is signed but not encrypted

When using the cookies backend the session data can be read by the client.

A MAC (Message Authentication Code) is used to protect the data against changes by the client, so that the session data will be invalidated when being tampered with. The same invalidation happens if the client storing the cookie (e.g. your user’s browser) can’t store all of the session cookie and drops data. Even though Django compresses the data, it’s still entirely possible to exceed the common limit of 4096 bytes per cookie.

No freshness guarantee

Note also that while the MAC can guarantee the authenticity of the data (that it was generated by your site, and not someone else), and the integrity of the data (that it is all there and correct), it cannot guarantee freshness i.e. that you are being sent back the last thing you sent to the client. This means that for some uses of session data, the cookie backend might open you up to replay attacks. Unlike other session backends which keep a server-side record of each session and invalidate it when a user logs out, cookie-based sessions are not invalidated when a user logs out. Thus if an attacker steals a user’s cookie, they can use that cookie to login as that user even if the user logs out. Cookies will only be detected as ‘stale’ if they are older than your SESSION_COOKIE_AGE.

Performance

Finally, the size of a cookie can have an impact on the speed of your site.

Using sessions in views

When SessionMiddleware is activated, each HttpRequest object – the first argument to any Django view function – will have a session attribute, which is a dictionary-like object.

You can read it and write to request.session at any point in your view. You can edit it multiple times.

class backends.base.SessionBase

This is the base class for all session objects. It has the following standard dictionary methods:

__getitem__(key)

Example: fav_color = request.session['fav_color']

__setitem__(key, value)

Example: request.session['fav_color'] = 'blue'

__delitem__(key)

Example: del request.session['fav_color']. This raises KeyError if the given key isn’t already in the session.

__contains__(key)

Example: 'fav_color' in request.session

get(key, default=None)

Example: fav_color = request.session.get('fav_color', 'red')

pop(key, default=__not_given)

Example: fav_color = request.session.pop('fav_color', 'blue')

keys()

items()

setdefault()

clear()

It also has these methods:

flush()

Deletes the current session data from the session and deletes the session cookie. This is used if you want to ensure that the previous session data can’t be accessed again from the user’s browser (for example, the django.contrib.auth.logout() function calls it).

Changed in Django 1.8:
Deletion of the session cookie is a behavior new in Django 1.8. Previously, the behavior was to regenerate the session key value that was sent back to the user in the cookie.

set_test_cookie()

Sets a test cookie to determine whether the user’s browser supports cookies. Due to the way cookies work, you won’t be able to test this until the user’s next page request. See Setting test cookies below for more information.

test_cookie_worked()

Returns either True or False, depending on whether the user’s browser accepted the test cookie. Due to the way cookies work, you’ll have to call set_test_cookie() on a previous, separate page request. See Setting test cookies below for more information.

delete_test_cookie()

Deletes the test cookie. Use this to clean up after yourself.

set_expiry(value)

Sets the expiration time for the session. You can pass a number of different values:

- If value is an integer, the session will expire after that many seconds of inactivity. For example, calling request.session.set_expiry(300) would make the session expire in 5 minutes.

- If value is a datetime or timedelta object, the session will expire at that specific date/time. Note that datetime and timedelta values are only serializable if you are using the PickleSerializer.

- If value is 0, the user’s session cookie will expire when the user’s Web browser is closed.

- If value is None, the session reverts to using the global session expiry policy.

Reading a session is not considered activity for expiration purposes. Session expiration is computed from the last time the session was modified.

get_expiry_age()

Returns the number of seconds until this session expires. For sessions with no custom expiration (or those set to expire at browser close), this will equal SESSION_COOKIE_AGE.

This function accepts two optional keyword arguments:

- modification: last modification of the session, as a datetime object. Defaults to the current time.

- expiry: expiry information for the session, as a datetime object, an int (in seconds), or None. Defaults to the value stored in the session by set_expiry(), if there is one, or None.

get_expiry_date()

Returns the date this session will expire. For sessions with no custom expiration (or those set to expire at browser close), this will equal the date SESSION_COOKIE_AGE seconds from now.

This function accepts the same keyword arguments as get_expiry_age().

get_expire_at_browser_close()

Returns either True or False, depending on whether the user’s session cookie will expire when the user’s Web browser is closed.

clear_expired()

Removes expired sessions from the session store. This class method is called by clearsessions.

cycle_key()

Creates a new session key while retaining the current session data. django.contrib.auth.login() calls this method to mitigate against session fixation.

Session serialization

By default, Django serializes session data using JSON. You can use the SESSION_SERIALIZER setting to customize the session serialization format. Even with the caveats described in Write your own serializer, we highly recommend sticking with JSON serialization especially if you are using the cookie backend.

For example, here’s an attack scenario if you use pickle to serialize session data. If you’re using the signed cookie session backend and SECRET_KEY is known by an attacker (there isn’t an inherent vulnerability in Django that would cause it to leak), the attacker could insert a string into their session which, when unpickled, executes arbitrary code on the server. The technique for doing so is simple and easily available on the internet. Although the cookie session storage signs the cookie-stored data to prevent tampering, a SECRET_KEY leak immediately escalates to a remote code execution vulnerability.

Bundled serializers

class serializers.JSONSerializer

A wrapper around the JSON serializer from django.core.signing. Can only serialize basic data types.

In addition, as JSON supports only string keys, note that using non-string keys in request.session won’t work as expected:

>>> # initial assignment
>>> request.session[0] = 'bar'
>>> # subsequent requests following serialization & deserialization
>>> # of session data
>>> request.session[0]  # KeyError
>>> request.session['0']
'bar'

Similarly, data that can’t be encoded in JSON, such as non-UTF8 bytes like '\xd9' (which raises UnicodeDecodeError), can’t be stored.

See the Write your own serializer section for more details on limitations of JSON serialization.

class serializers.PickleSerializer

Supports arbitrary Python objects, but, as described above, can lead to a remote code execution vulnerability if SECRET_KEY becomes known by an attacker.

Write your own serializer

Note that unlike PickleSerializer, the JSONSerializer cannot handle arbitrary Python data types. As is often the case, there is a trade-off between convenience and security. If you wish to store more advanced data types including datetime and Decimal in JSON backed sessions, you will need to write a custom serializer (or convert such values to a JSON serializable object before storing them in request.session). While serializing these values is fairly straightforward (django.core.serializers.json.DateTimeAwareJSONEncoder may be helpful), writing a decoder that can reliably get back the same thing that you put in is more fragile. For example, you run the risk of returning a datetime that was actually a string that just happened to be in the same format chosen for datetimes).

Your serializer class must implement two methods, dumps(self, obj) and loads(self, data), to serialize and deserialize the dictionary of session data, respectively.

Session object guidelines

- Use normal Python strings as dictionary keys on request.session. This is more of a convention than a hard-and-fast rule.

- Session dictionary keys that begin with an underscore are reserved for internal use by Django.

- Don’t override request.session with a new object, and don’t access or set its attributes. Use it like a Python dictionary.

Examples

This simplistic view sets a has_commented variable to True after a user posts a comment. It doesn’t let a user post a comment more than once:

def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')

This simplistic view logs in a “member” of the site:

def login(request):
m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponse("You're logged in.")
else:
return HttpResponse("Your username and password didn't match.")

...And this one logs a member out, according to login() above:

def logout(request):
try:
del request.session['member_id']
except KeyError:
pass
return HttpResponse("You're logged out.")

The standard django.contrib.auth.logout() function actually does a bit more than this to prevent inadvertent data leakage. It calls the flush() method of request.session. We are using this example as a demonstration of how to work with session objects, not as a full logout() implementation.

Setting test cookies

As a convenience, Django provides an easy way to test whether the user’s browser accepts cookies. Just call the set_test_cookie() method of request.session in a view, and call test_cookie_worked() in a subsequent view – not in the same view call.

This awkward split between set_test_cookie() and test_cookie_worked() is necessary due to the way cookies work. When you set a cookie, you can’t actually tell whether a browser accepted it until the browser’s next request.

It’s good practice to use delete_test_cookie() to clean up after yourself. Do this after you’ve verified that the test cookie worked.

Here’s a typical usage example:

from django.http import HttpResponse
from django.shortcuts import render

def login(request):
if request.method == 'POST':
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse("You're logged in.")
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
return render(request, 'foo/login_form.html')

Using sessions out of views

Note

The examples in this section import the SessionStore object directly from the django.contrib.sessions.backends.db backend. In your own code, you should consider importing SessionStore from the session engine designated by SESSION_ENGINE, as below:

>>> from importlib import import_module
>>> from django.conf import settings
>>> SessionStore = import_module(settings.SESSION_ENGINE).SessionStore

An API is available to manipulate session data outside of a view:

>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore()
>>> # stored as seconds since epoch since datetimes are not serializable in JSON.
>>> s['last_login'] = 1376587691
>>> s.create()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login']
1376587691

SessionStore.create() is designed to create a new session (i.e. one not loaded from the session store and with session_key=None). save() is designed to save an existing session (i.e. one loaded from the session store). Calling save() on a new session may also work but has a small chance of generating a session_key that collides with an existing one. create() calls save() and loops until an unused session_key is generated.

If you’re using the django.contrib.sessions.backends.db backend, each session is just a normal Django model. The Session model is defined in django/contrib/sessions/models.py. Because it’s a normal model, you can access sessions using the normal Django database API:

>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)

Note that you’ll need to call get_decoded() to get the session dictionary. This is necessary because the dictionary is stored in an encoded format:

>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}

When sessions are saved

By default, Django only saves to the session database when the session has been modified – that is if any of its dictionary values have been assigned or deleted:

# Session is modified.
request.session['foo'] = 'bar'

# Session is modified.
del request.session['foo']

# Session is modified.
request.session['foo'] = {}

# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
request.session['foo']['bar'] = 'baz'

In the last case of the above example, we can tell the session object explicitly that it has been modified by setting the modified attribute on the session object:

request.session.modified = True

To change this default behavior, set the SESSION_SAVE_EVERY_REQUEST setting to True. When set to True, Django will save the session to the database on every single request.

Note that the session cookie is only sent when a session has been created or modified. If SESSION_SAVE_EVERY_REQUEST is True, the session cookie will be sent on every request.

Similarly, the expires part of a session cookie is updated each time the session cookie is sent.

The session is not saved if the response’s status code is 500.

Browser-length sessions vs. persistent sessions

You can control whether the session framework uses browser-length sessions vs. persistent sessions with the SESSION_EXPIRE_AT_BROWSER_CLOSE setting.

By default, SESSION_EXPIRE_AT_BROWSER_CLOSE is set to False, which means session cookies will be stored in users’ browsers for as long as SESSION_COOKIE_AGE. Use this if you don’t want people to have to log in every time they open a browser.

If SESSION_EXPIRE_AT_BROWSER_CLOSE is set to True, Django will use browser-length cookies – cookies that expire as soon as the user closes their browser. Use this if you want people to have to log in every time they open a browser.

This setting is a global default and can be overwritten at a per-session level by explicitly calling the set_expiry() method of request.session as described above in using sessions in views.

Note

Some browsers (Chrome, for example) provide settings that allow users to continue browsing sessions after closing and re-opening the browser. In some cases, this can interfere with the SESSION_EXPIRE_AT_BROWSER_CLOSE setting and prevent sessions from expiring on browser close. Please be aware of this while testing Django applications which have the SESSION_EXPIRE_AT_BROWSER_CLOSE setting enabled.

Clearing the session store

As users create new sessions on your website, session data can accumulate in your session store. If you’re using the database backend, the django_session database table will grow. If you’re using the file backend, your temporary directory will contain an increasing number of files.

To understand this problem, consider what happens with the database backend. When a user logs in, Django adds a row to the django_session database table. Django updates this row each time the session data changes. If the user logs out manually, Django deletes the row. But if the user does not log out, the row never gets deleted. A similar process happens with the file backend.

Django does not provide automatic purging of expired sessions. Therefore, it’s your job to purge expired sessions on a regular basis. Django provides a clean-up management command for this purpose: clearsessions. It’s recommended to call this command on a regular basis, for example as a daily cron job.

Note that the cache backend isn’t vulnerable to this problem, because caches automatically delete stale data. Neither is the cookie backend, because the session data is stored by the users’ browsers.

Settings

A few Django settings give you control over session behavior:

- SESSION_CACHE_ALIAS

- SESSION_COOKIE_AGE

- SESSION_COOKIE_DOMAIN

- SESSION_COOKIE_HTTPONLY

- SESSION_COOKIE_NAME

- SESSION_COOKIE_PATH

- SESSION_COOKIE_SECURE

- SESSION_ENGINE

- SESSION_EXPIRE_AT_BROWSER_CLOSE

- SESSION_FILE_PATH

- SESSION_SAVE_EVERY_REQUEST

- SESSION_SERIALIZER

Session security

Subdomains within a site are able to set cookies on the client for the whole domain. This makes session fixation possible if cookies are permitted from subdomains not controlled by trusted users.

For example, an attacker could log into good.example.com and get a valid session for their account. If the attacker has control over bad.example.com, they can use it to send their session key to you since a subdomain is permitted to set cookies on *.example.com. When you visit good.example.com, you’ll be logged in as the attacker and might inadvertently enter your sensitive personal data (e.g. credit card info) into the attackers account.

Another possible attack would be if good.example.com sets its SESSION_COOKIE_DOMAIN to ".example.com" which would cause session cookies from that site to be sent to bad.example.com.

Technical details

- The session dictionary accepts any json serializable value when using JSONSerializer or any picklable Python object when using PickleSerializer. See the pickle module for more information.

- Session data is stored in a database table named django_session .

- Django only sends a cookie if it needs to. If you don’t set any session data, it won’t send a session cookie.

The SessionStore object

When working with sessions internally, Django uses a session store object from the corresponding session engine. By convention, the session store object class is named SessionStore and is located in the module designated by SESSION_ENGINE.

All SessionStore classes available in Django inherit from SessionBase and implement data manipulation methods, namely:

- exists()

- create()

- save()

- delete()

- load()

- clear_expired()

In order to build a custom session engine or to customize an existing one, you may create a new class inheriting from SessionBase or any other existing SessionStore class.

Extending most of the session engines is quite straightforward, but doing so with database-backed session engines generally requires some extra effort (see the next section for details).

Extending database-backed session engines

New in Django 1.9.

Creating a custom database-backed session engine built upon those included in Django (namely db and cached_db) may be done by inheriting AbstractBaseSession and either SessionStore class.

AbstractBaseSession and BaseSessionManager are importable from django.contrib.sessions.base_session so that they can be imported without including django.contrib.sessions in INSTALLED_APPS.

class base_session.AbstractBaseSession

New in Django 1.9.

The abstract base session model.

session_key

Primary key. The field itself may contain up to 40 characters. The current implementation generates a 32-character string (a random sequence of digits and lowercase ASCII letters).

session_data

A string containing an encoded and serialized session dictionary.

expire_date

A datetime designating when the session expires.

Expired sessions are not available to a user, however, they may still be stored in the database until the clearsessions management command is run.

classmethod get_session_store_class()

Returns a session store class to be used with this session model.

get_decoded()

Returns decoded session data.

Decoding is performed by the session store class.

You can also customize the model manager by subclassing BaseSessionManager:

class base_session.BaseSessionManager

New in Django 1.9.

encode(session_dict)

Returns the given session dictionary serialized and encoded as a string.

Encoding is performed by the session store class tied to a model class.

save(session_key, session_dict, expire_date)

Saves session data for a provided session key, or deletes the session in case the data is empty.

Customization of SessionStore classes is achieved by overriding methods and properties described below:

class backends.db.SessionStore

Implements database-backed session store.

classmethod get_model_class()

New in Django 1.9.

Override this method to return a custom session model if you need one.

create_model_instance(data)

New in Django 1.9.

Returns a new instance of the session model object, which represents the current session state.

Overriding this method provides the ability to modify session model data before it’s saved to database.

class backends.cached_db.SessionStore

Implements cached database-backed session store.

cache_key_prefix

New in Django 1.9.

A prefix added to a session key to build a cache key string.

Example

The example below shows a custom database-backed session engine that includes an additional database column to store an account ID (thus providing an option to query the database for all active sessions for an account):

from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models

class CustomSession(AbstractBaseSession):
account_id = models.IntegerField(null=True, db_index=True)

@classmethod
def get_session_store_class(cls):
return SessionStore

class SessionStore(DBStore):
@classmethod
def get_model_class(cls):
return CustomSession

def create_model_instance(self, data):
obj = super(SessionStore, self).create_model_instance(data)
try:
account_id = int(data.get('_auth_user_id'))
except (ValueError, TypeError):
account_id = None
obj.account_id = account_id
return obj

If you are migrating from the Django’s built-in cached_db session store to a custom one based on cached_db, you should override the cache key prefix in order to prevent a namespace clash:

class SessionStore(CachedDBStore):
cache_key_prefix = 'mysessions.custom_cached_db_backend'

# ...

Session IDs in URLs

The Django sessions framework is entirely, and solely, cookie-based. It does not fall back to putting session IDs in URLs as a last resort, as PHP does. This is an intentional design decision. Not only does that behavior make URLs ugly, it makes your site vulnerable to session-ID theft via the “Referer” header.

Working with forms

About this document

This document provides an introduction to the basics of web forms and how they are handled in Django. For a more detailed look at specific areas of the forms API, see The Forms API, Form fields, and Form and field validation.

Unless you’re planning to build websites and applications that do nothing but publish content, and don’t accept input from your visitors, you’re going to need to understand and use forms.

Django provides a range of tools and libraries to help you build forms to accept input from site visitors, and then process and respond to the input.

HTML forms

In HTML, a form is a collection of elements inside <form>...</form> that allow a visitor to do things like enter text, select options, manipulate objects or controls, and so on, and then send that information back to the server.

Some of these form interface elements - text input or checkboxes - are fairly simple and are built into HTML itself. Others are much more complex; an interface that pops up a date picker or allows you to move a slider or manipulate controls will typically use JavaScript and CSS as well as HTML form <input> elements to achieve these effects.

As well as its <input> elements, a form must specify two things:

- where: the URL to which the data corresponding to the user’s input should be returned

- how: the HTTP method the data should be returned by

As an example, the login form for the Django admin contains several <input> elements: one of type="text" for the username, one of type="password" for the password, and one of type="submit" for the “Log in” button. It also contains some hidden text fields that the user doesn’t see, which Django uses to determine what to do next.

It also tells the browser that the form data should be sent to the URL specified in the <form>’s action attribute - /admin/ - and that it should be sent using the HTTP mechanism specified by the method attribute - post.

When the <input type="submit" value="Log in"> element is triggered, the data is returned to /admin/.

GET and POST

GET and POST are the only HTTP methods to use when dealing with forms.

Django’s login form is returned using the POST method, in which the browser bundles up the form data, encodes it for transmission, sends it to the server, and then receives back its response.

GET, by contrast, bundles the submitted data into a string, and uses this to compose a URL. The URL contains the address where the data must be sent, as well as the data keys and values. You can see this in action if you do a search in the Django documentation, which will produce a URL of the form https://docs.djangoproject.com/search/?q=forms&release=1.

GET and POST are typically used for different purposes.

Any request that could be used to change the state of the system - for example, a request that makes changes in the database - should use POST. GET should be used only for requests that do not affect the state of the system.

GET would also be unsuitable for a password form, because the password would appear in the URL, and thus, also in browser history and server logs, all in plain text. Neither would it be suitable for large quantities of data, or for binary data, such as an image. A Web application that uses GET requests for admin forms is a security risk: it can be easy for an attacker to mimic a form’s request to gain access to sensitive parts of the system. POST, coupled with other protections like Django’s CSRF protection offers more control over access.

On the other hand, GET is suitable for things like a web search form, because the URLs that represent a GET request can easily be bookmarked, shared, or resubmitted.

Django’s role in forms

Handling forms is a complex business. Consider Django’s admin, where numerous items of data of several different types may need to be prepared for display in a form, rendered as HTML, edited using a convenient interface, returned to the server, validated and cleaned up, and then saved or passed on for further processing.

Django’s form functionality can simplify and automate vast portions of this work, and can also do it more securely than most programmers would be able to do in code they wrote themselves.

Django handles three distinct parts of the work involved in forms:

- preparing and restructuring data to make it ready for rendering

- creating HTML forms for the data

- receiving and processing submitted forms and data from the client

It is possible to write code that does all of this manually, but Django can take care of it all for you.

Forms in Django

We’ve described HTML forms briefly, but an HTML <form> is just one part of the machinery required.

In the context of a Web application, ‘form’ might refer to that HTML <form>, or to the Django Form that produces it, or to the structured data returned when it is submitted, or to the end-to-end working collection of these parts.

The Django Form class

At the heart of this system of components is Django’s Form class. In much the same way that a Django model describes the logical structure of an object, its behavior, and the way its parts are represented to us, a Form class describes a form and determines how it works and appears.

In a similar way that a model class’s fields map to database fields, a form class’s fields map to HTML form <input> elements. (A ModelForm maps a model class’s fields to HTML form <input> elements via a Form; this is what the Django admin is based upon.)

A form’s fields are themselves classes; they manage form data and perform validation when a form is submitted. A DateField and a FileField handle very different kinds of data and have to do different things with it.

A form field is represented to a user in the browser as an HTML “widget” - a piece of user interface machinery. Each field type has an appropriate default Widget class, but these can be overridden as required.

Instantiating, processing, and rendering forms

When rendering an object in Django, we generally:

1. get hold of it in the view (fetch it from the database, for example)

2. pass it to the template context

3. expand it to HTML markup using template variables

Rendering a form in a template involves nearly the same work as rendering any other kind of object, but there are some key differences.

In the case of a model instance that contained no data, it would rarely if ever be useful to do anything with it in a template. On the other hand, it makes perfect sense to render an unpopulated form - that’s what we do when we want the user to populate it.

So when we handle a model instance in a view, we typically retrieve it from the database. When we’re dealing with a form we typically instantiate it in the view.

When we instantiate a form, we can opt to leave it empty or pre-populate it, for example with:

- data from a saved model instance (as in the case of admin forms for editing)

- data that we have collated from other sources

- data received from a previous HTML form submission

The last of these cases is the most interesting, because it’s what makes it possible for users not just to read a website, but to send information back to it too.

Building a form

The work that needs to be done

Suppose you want to create a simple form on your website, in order to obtain the user’s name. You’d need something like this in your template:

<form action="/your-name/" method="post">
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>

This tells the browser to return the form data to the URL /your-name/, using the POST method. It will display a text field, labeled “Your name:”, and a button marked “OK”. If the template context contains a current_name variable, that will be used to pre-fill the your_name field.

You’ll need a view that renders the template containing the HTML form, and that can supply the current_name field as appropriate.

When the form is submitted, the POST request which is sent to the server will contain the form data.

Now you’ll also need a view corresponding to that /your-name/ URL which will find the appropriate key/value pairs in the request, and then process them.

This is a very simple form. In practice, a form might contain dozens or hundreds of fields, many of which might need to be pre-populated, and we might expect the user to work through the edit-submit cycle several times before concluding the operation.

We might require some validation to occur in the browser, even before the form is submitted; we might want to use much more complex fields, that allow the user to do things like pick dates from a calendar and so on.

At this point it’s much easier to get Django to do most of this work for us.

Building a form in Django

The Form class

We already know what we want our HTML form to look like. Our starting point for it in Django is this:

forms.py

from django import forms

class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)

This defines a Form class with a single field (your_name). We’ve applied a human-friendly label to the field, which will appear in the <label> when it’s rendered (although in this case, the label we specified is actually the same one that would be generated automatically if we had omitted it).

The field’s maximum allowable length is defined by max_length. This does two things. It puts a maxlength="100" on the HTML <input> (so the browser should prevent the user from entering more than that number of characters in the first place). It also means that when Django receives the form back from the browser, it will validate the length of the data.

A Form instance has an is_valid() method, which runs validation routines for all its fields. When this method is called, if all fields contain valid data, it will:

- return True

- place the form’s data in its cleaned_data attribute.

The whole form, when rendered for the first time, will look like:

<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">

Note that it does not include the <form> tags, or a submit button. We’ll have to provide those ourselves in the template.

The view

Form data sent back to a Django website is processed by a view, generally the same view which published the form. This allows us to reuse some of the same logic.

To handle the form we need to instantiate it in the view for the URL where we want it to be published:

views.py

from django.shortcuts import render
from django.http import HttpResponseRedirect

from .forms import NameForm

def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')

# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()

return render(request, 'name.html', {'form': form})

If we arrive at this view with a GET request, it will create an empty form instance and place it in the template context to be rendered. This is what we can expect to happen the first time we visit the URL.

If the form is submitted using a POST request, the view will once again create a form instance and populate it with data from the request: form = NameForm(request.POST) This is called “binding data to the form” (it is now a bound form).

We call the form’s is_valid() method; if it’s not True, we go back to the template with the form. This time the form is no longer empty (unbound) so the HTML form will be populated with the data previously submitted, where it can be edited and corrected as required.

If is_valid() is True, we’ll now be able to find all the validated form data in its cleaned_data attribute. We can use this data to update the database or do other processing before sending an HTTP redirect to the browser telling it where to go next.

The template

We don’t need to do much in our name.html template. The simplest example is:

<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>

All the form’s fields and their attributes will be unpacked into HTML markup from that {{ form }} by Django’s template language.

Forms and Cross Site Request Forgery protection

Django ships with an easy-to-use protection against Cross Site Request Forgeries. When submitting a form via POST with CSRF protection enabled you must use the csrf_token template tag as in the preceding example. However, since CSRF protection is not directly tied to forms in templates, this tag is omitted from the following examples in this document.

HTML5 input types and browser validation

If your form includes a URLField, an EmailField or any integer field type, Django will use the url, email and number HTML5 input types. By default, browsers may apply their own validation on these fields, which may be stricter than Django’s validation. If you would like to disable this behavior, set the novalidate attribute on the form tag, or specify a different widget on the field, like TextInput.

We now have a working web form, described by a Django Form, processed by a view, and rendered as an HTML <form>.

That’s all you need to get started, but the forms framework puts a lot more at your fingertips. Once you understand the basics of the process described above, you should be prepared to understand other features of the forms system and ready to learn a bit more about the underlying machinery.

More about Django Form classes

All form classes are created as subclasses of django.forms.Form, including the ModelForm, which you encounter in Django’s admin.

Models and Forms

In fact if your form is going to be used to directly add or edit a Django model, a ModelForm can save you a great deal of time, effort, and code, because it will build a form, along with the appropriate fields and their attributes, from a Model class.

Bound and unbound form instances

The distinction between Bound and unbound forms is important:

- An unbound form has no data associated with it. When rendered to the user, it will be empty or will contain default values.

- A bound form has submitted data, and hence can be used to tell if that data is valid. If an invalid bound form is rendered, it can include inline error messages telling the user what data to correct.

The form’s is_bound attribute will tell you whether a form has data bound to it or not.

More on fields

Consider a more useful form than our minimal example above, which we could use to implement “contact me” functionality on a personal website:

forms.py

from django import forms

class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)

Our earlier form used a single field, your_name, a CharField. In this case, our form has four fields: subject, message, sender and cc_myself. CharField, EmailField and BooleanField are just three of the available field types; a full list can be found in Form fields.

Widgets

Each form field has a corresponding Widget class, which in turn corresponds to an HTML form widget such as <input type="text">.

In most cases, the field will have a sensible default widget. For example, by default, a CharField will have a TextInput widget, that produces an <input type="text"> in the HTML. If you needed <textarea> instead, you’d specify the appropriate widget when defining your form field, as we have done for the message field.

Field data

Whatever the data submitted with a form, once it has been successfully validated by calling is_valid() (and is_valid() has returned True), the validated form data will be in the form.cleaned_data dictionary. This data will have been nicely converted into Python types for you.

Note

You can still access the unvalidated data directly from request.POST at this point, but the validated data is better.

In the contact form example above, cc_myself will be a boolean value. Likewise, fields such as IntegerField and FloatField convert values to a Python int and float respectively.

Here’s how the form data could be processed in the view that handles this form:

views.py

from django.core.mail import send_mail

if form.is_valid():
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']

recipients = ['info@example.com']
if cc_myself:
recipients.append(sender)

send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/')

Tip

For more on sending email from Django, see Sending email.

Some field types need some extra handling. For example, files that are uploaded using a form need to be handled differently (they can be retrieved from request.FILES, rather than request.POST). For details of how to handle file uploads with your form, see Binding uploaded files to a form.

Working with form templates

All you need to do to get your form into a template is to place the form instance into the template context. So if your form is called form in the context, {{ form }} will render its <label> and <input> elements appropriately.

Form rendering options

Additional form template furniture

Don’t forget that a form’s output does not include the surrounding <form> tags, or the form’s submit control. You will have to provide these yourself.

There are other output options though for the <label>/<input> pairs:

- {{ form.as_table }} will render them as table cells wrapped in <tr> tags

- {{ form.as_p }} will render them wrapped in <p> tags

- {{ form.as_ul }} will render them wrapped in <li> tags

Note that you’ll have to provide the surrounding <table> or <ul> elements yourself.

Here’s the output of {{ form.as_p }} for our ContactForm instance:

<p><label for="id_subject">Subject:</label>
<input id="id_subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="id_message">Message:</label>
<textarea name="message" id="id_message"></textarea></p>
<p><label for="id_sender">Sender:</label>
<input type="email" name="sender" id="id_sender" /></p>
<p><label for="id_cc_myself">Cc myself:</label>
<input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>

Note that each form field has an ID attribute set to id_<field-name>, which is referenced by the accompanying label tag. This is important in ensuring that forms are accessible to assistive technology such as screen reader software. You can also customize the way in which labels and ids are generated.

See Outputting forms as HTML for more on this.

Rendering fields manually

We don’t have to let Django unpack the form’s fields; we can do it manually if we like (allowing us to reorder the fields, for example). Each field is available as an attribute of the form using {{ form.name_of_field }}, and in a Django template, will be rendered appropriately. For example:

{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="{{ form.sender.id_for_label }}">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
{{ form.cc_myself }}
</div>

Complete <label> elements can also be generated using the label_tag(). For example:

<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>

Rendering form error messages

Of course, the price of this flexibility is more work. Until now we haven’t had to worry about how to display form errors, because that’s taken care of for us. In this example we have had to make sure we take care of any errors for each field and any errors for the form as a whole. Note {{ form.non_field_errors }} at the top of the form and the template lookup for errors on each field.

Using {{ form.name_of_field.errors }} displays a list of form errors, rendered as an unordered list. This might look like:

<ul class="errorlist">
<li>Sender is required.</li>
</ul>

The list has a CSS class of errorlist to allow you to style its appearance. If you wish to further customize the display of errors you can do so by looping over them:

{% if form.subject.errors %}
<ol>
{% for error in form.subject.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}

Non-field errors (and/or hidden field errors that are rendered at the top of the form when using helpers like form.as_p()) will be rendered with an additional class of nonfield to help distinguish them from field-specific errors. For example, {{ form.non_field_errors }} would look like:

<ul class="errorlist nonfield">
<li>Generic validation error</li>
</ul>

Changed in Django 1.8:
The nonfield class as described in the example above was added.

See The Forms API for more on errors, styling, and working with form attributes in templates.

Looping over the form’s fields

If you’re using the same HTML for each of your form fields, you can reduce duplicate code by looping through each field in turn using a {% for %} loop:

{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}

Useful attributes on {{ field }} include:

{{ field.label }}

The label of the field, e.g. Email address.

{{ field.label_tag }}

The field’s label wrapped in the appropriate HTML <label> tag. This includes the form’s label_suffix. For example, the default label_suffix is a colon:

<label for="id_email">Email address:</label>

{{ field.id_for_label }}

The ID that will be used for this field (id_email in the example above). If you are constructing the label manually, you may want to use this in lieu of label_tag. It’s also useful, for example, if you have some inline JavaScript and want to avoid hardcoding the field’s ID.

{{ field.value }}

The value of the field. e.g someone@example.com.

{{ field.html_name }}

The name of the field that will be used in the input element’s name field. This takes the form prefix into account, if it has been set.

{{ field.help_text }}

Any help text that has been associated with the field.

{{ field.errors }}

Outputs a <ul class="errorlist"> containing any validation errors corresponding to this field. You can customize the presentation of the errors with a {% for error in field.errors %} loop. In this case, each object in the loop is a simple string containing the error message.

{{ field.is_hidden }}

This attribute is True if the form field is a hidden field and False otherwise. It’s not particularly useful as a template variable, but could be useful in conditional tests such as:

{% if field.is_hidden %}
{# Do something special #}
{% endif %}

{{ field.field }}

The Field instance from the form class that this BoundField wraps. You can use it to access Field attributes, e.g. {{ char_field.field.max_length }}.

See also

For a complete list of attributes and methods, see BoundField.

Looping over hidden and visible fields

If you’re manually laying out a form in a template, as opposed to relying on Django’s default form layout, you might want to treat <input type="hidden"> fields differently from non-hidden fields. For example, because hidden fields don’t display anything, putting error messages “next to” the field could cause confusion for your users – so errors for those fields should be handled differently.

Django provides two methods on a form that allow you to loop over the hidden and visible fields independently: hidden_fields() and visible_fields(). Here’s a modification of an earlier example that uses these two methods:

{# Include the hidden fields #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}

This example does not handle any errors in the hidden fields. Usually, an error in a hidden field is a sign of form tampering, since normal form interaction won’t alter them. However, you could easily insert some error displays for those form errors, as well.

Reusable form templates

If your site uses the same rendering logic for forms in multiple places, you can reduce duplication by saving the form’s loop in a standalone template and using the include tag to reuse it in other templates:

# In your form template:
{% include "form_snippet.html" %}

# In form_snippet.html:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}

If the form object passed to a template has a different name within the context, you can alias it using the with argument of the include tag:

{% include "form_snippet.html" with form=comment_form %}

If you find yourself doing this often, you might consider creating a custom inclusion tag.

Further topics

This covers the basics, but forms can do a whole lot more:

- Formsets

- Using initial data with a formset

- Limiting the maximum number of forms

- Formset validation

- Validating the number of forms in a formset

- Dealing with ordering and deletion of forms

- Adding additional fields to a formset

- Passing custom parameters to formset forms

- Using a formset in views and templates

- Creating forms from models

- ModelForm

- Model formsets

- Inline formsets

- Form Assets (the Media class)

- Assets as a static definition

- Media as a dynamic property

- Paths in asset definitions

- Media objects

- Media on Forms

See also

The Forms Reference

Covers the full API reference, including form fields, form widgets, and form and field validation.

Formsets

class BaseFormSet[source]

A formset is a layer of abstraction to work with multiple forms on the same page. It can be best compared to a data grid. Let’s say you have the following form:

>>> from django import forms
>>> class ArticleForm(forms.Form):
...     title = forms.CharField()
...     pub_date = forms.DateField()

You might want to allow the user to create several articles at once. To create a formset out of an ArticleForm you would do:

>>> from django.forms import formset_factory
>>> ArticleFormSet = formset_factory(ArticleForm)

You now have created a formset named ArticleFormSet. The formset gives you the ability to iterate over the forms in the formset and display them as you would with a regular form:

>>> formset = ArticleFormSet()
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>

As you can see it only displayed one empty form. The number of empty forms that is displayed is controlled by the extra parameter. By default, formset_factory() defines one extra form; the following example will display two blank forms:

>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)

Iterating over the formset will render the forms in the order they were created. You can change this order by providing an alternate implementation for the __iter__() method.

Formsets can also be indexed into, which returns the corresponding form. If you override __iter__, you will need to also override __getitem__ to have matching behavior.

Using initial data with a formset

Initial data is what drives the main usability of a formset. As shown above you can define the number of extra forms. What this means is that you are telling the formset how many additional forms to show in addition to the number of forms it generates from the initial data. Let’s take a look at an example:

>>> import datetime
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
>>> formset = ArticleFormSet(initial=[
...     {'title': 'Django is now open source',
...      'pub_date': datetime.date.today(),}
... ])

>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>

There are now a total of three forms showing above. One for the initial data that was passed in and two extra forms. Also note that we are passing in a list of dictionaries as the initial data.

See also

Creating formsets from models with model formsets.

Limiting the maximum number of forms

The max_num parameter to formset_factory() gives you the ability to limit the number of forms the formset will display:

>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
>>> formset = ArticleFormSet()
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>

If the value of max_num is greater than the number of existing items in the initial data, up to extra additional blank forms will be added to the formset, so long as the total number of forms does not exceed max_num. For example, if extra=2 and max_num=2 and the formset is initialized with one initial item, a form for the initial item and one blank form will be displayed.

If the number of items in the initial data exceeds max_num, all initial data forms will be displayed regardless of the value of max_num and no extra forms will be displayed. For example, if extra=3 and max_num=1 and the formset is initialized with two initial items, two forms with the initial data will be displayed.

A max_num value of None (the default) puts a high limit on the number of forms displayed (1000). In practice this is equivalent to no limit.

By default, max_num only affects how many forms are displayed and does not affect validation. If validate_max=True is passed to the formset_factory(), then max_num will affect validation. See Validating the number of forms in a formset.

Formset validation

Validation with a formset is almost identical to a regular Form. There is an is_valid method on the formset to provide a convenient way to validate all forms in the formset:

>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm)
>>> data = {
...     'form-TOTAL_FORMS': '1',
...     'form-INITIAL_FORMS': '0',
...     'form-MAX_NUM_FORMS': '',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
True

We passed in no data to the formset which is resulting in a valid form. The formset is smart enough to ignore extra forms that were not changed. If we provide an invalid article:

>>> data = {
...     'form-TOTAL_FORMS': '2',
...     'form-INITIAL_FORMS': '0',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': 'Test',
...     'form-0-pub_date': '1904-06-16',
...     'form-1-title': 'Test',
...     'form-1-pub_date': '', # <-- this date is missing but required
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
False
>>> formset.errors
[{}, {'pub_date': ['This field is required.']}]

As we can see, formset.errors is a list whose entries correspond to the forms in the formset. Validation was performed for each of the two forms, and the expected error message appears for the second item.

BaseFormSet.total_error_count()[source]

To check how many errors there are in the formset, we can use the total_error_count method:

>>> # Using the previous example
>>> formset.errors
[{}, {'pub_date': ['This field is required.']}]
>>> len(formset.errors)
2
>>> formset.total_error_count()
1

We can also check if form data differs from the initial data (i.e. the form was sent without any data):

>>> data = {
...     'form-TOTAL_FORMS': '1',
...     'form-INITIAL_FORMS': '0',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': '',
...     'form-0-pub_date': '',
... }
>>> formset = ArticleFormSet(data)
>>> formset.has_changed()
False

Understanding the ManagementForm

You may have noticed the additional data (form-TOTAL_FORMS, form-INITIAL_FORMS and form-MAX_NUM_FORMS) that was required in the formset’s data above. This data is required for the ManagementForm. This form is used by the formset to manage the collection of forms contained in the formset. If you don’t provide this management data, an exception will be raised:

>>> data = {
...     'form-0-title': 'Test',
...     'form-0-pub_date': '',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
Traceback (most recent call last):
...
django.forms.utils.ValidationError: ['ManagementForm data is missing or has been tampered with']

It is used to keep track of how many form instances are being displayed. If you are adding new forms via JavaScript, you should increment the count fields in this form as well. On the other hand, if you are using JavaScript to allow deletion of existing objects, then you need to ensure the ones being removed are properly marked for deletion by including form-#-DELETE in the POST data. It is expected that all forms are present in the POST data regardless.

The management form is available as an attribute of the formset itself. When rendering a formset in a template, you can include all the management data by rendering {{ my_formset.management_form }} (substituting the name of your formset as appropriate).

total_form_count and initial_form_count

BaseFormSet has a couple of methods that are closely related to the ManagementForm, total_form_count and initial_form_count.

total_form_count returns the total number of forms in this formset. initial_form_count returns the number of forms in the formset that were pre-filled, and is also used to determine how many forms are required. You will probably never need to override either of these methods, so please be sure you understand what they do before doing so.

empty_form

BaseFormSet provides an additional attribute empty_form which returns a form instance with a prefix of __prefix__ for easier use in dynamic forms with JavaScript.

Custom formset validation

A formset has a clean method similar to the one on a Form class. This is where you define your own validation that works at the formset level:

>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm

>>> class BaseArticleFormSet(BaseFormSet):
...     def clean(self):
...         """Checks that no two articles have the same title."""
...         if any(self.errors):
...             # Don't bother validating the formset unless each form is valid on its own
...             return
...         titles = []
...         for form in self.forms:
...             title = form.cleaned_data['title']
...             if title in titles:
...                 raise forms.ValidationError("Articles in a set must have distinct titles.")
...             titles.append(title)

>>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet)
>>> data = {
...     'form-TOTAL_FORMS': '2',
...     'form-INITIAL_FORMS': '0',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': 'Test',
...     'form-0-pub_date': '1904-06-16',
...     'form-1-title': 'Test',
...     'form-1-pub_date': '1912-06-23',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
False
>>> formset.errors
[{}, {}]
>>> formset.non_form_errors()
['Articles in a set must have distinct titles.']

The formset clean method is called after all the Form.clean methods have been called. The errors will be found using the non_form_errors() method on the formset.

Validating the number of forms in a formset

Django provides a couple ways to validate the minimum or maximum number of submitted forms. Applications which need more customizable validation of the number of forms should use custom formset validation.

validate_max

If validate_max=True is passed to formset_factory(), validation will also check that the number of forms in the data set, minus those marked for deletion, is less than or equal to max_num.

>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, max_num=1, validate_max=True)
>>> data = {
...     'form-TOTAL_FORMS': '2',
...     'form-INITIAL_FORMS': '0',
...     'form-MIN_NUM_FORMS': '',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': 'Test',
...     'form-0-pub_date': '1904-06-16',
...     'form-1-title': 'Test 2',
...     'form-1-pub_date': '1912-06-23',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
False
>>> formset.errors
[{}, {}]
>>> formset.non_form_errors()
['Please submit 1 or fewer forms.']

validate_max=True validates against max_num strictly even if max_num was exceeded because the amount of initial data supplied was excessive.

Note

Regardless of validate_max, if the number of forms in a data set exceeds max_num by more than 1000, then the form will fail to validate as if validate_max were set, and additionally only the first 1000 forms above max_num will be validated. The remainder will be truncated entirely. This is to protect against memory exhaustion attacks using forged POST requests.

validate_min

If validate_min=True is passed to formset_factory(), validation will also check that the number of forms in the data set, minus those marked for deletion, is greater than or equal to min_num.

>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, min_num=3, validate_min=True)
>>> data = {
...     'form-TOTAL_FORMS': '2',
...     'form-INITIAL_FORMS': '0',
...     'form-MIN_NUM_FORMS': '',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': 'Test',
...     'form-0-pub_date': '1904-06-16',
...     'form-1-title': 'Test 2',
...     'form-1-pub_date': '1912-06-23',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
False
>>> formset.errors
[{}, {}]
>>> formset.non_form_errors()
['Please submit 3 or more forms.']

Dealing with ordering and deletion of forms

The formset_factory() provides two optional parameters can_order and can_delete to help with ordering of forms in formsets and deletion of forms from a formset.

can_order

BaseFormSet.can_order

Default: False

Lets you create a formset with the ability to order:

>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, can_order=True)
>>> formset = ArticleFormSet(initial=[
...     {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
...     {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
... ])
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr>
<tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="number" name="form-0-ORDER" value="1" id="id_form-0-ORDER" /></td></tr>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr>
<tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="number" name="form-1-ORDER" value="2" id="id_form-1-ORDER" /></td></tr>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>
<tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="number" name="form-2-ORDER" id="id_form-2-ORDER" /></td></tr>

This adds an additional field to each form. This new field is named ORDER and is an forms.IntegerField. For the forms that came from the initial data it automatically assigned them a numeric value. Let’s look at what will happen when the user changes these values:

>>> data = {
...     'form-TOTAL_FORMS': '3',
...     'form-INITIAL_FORMS': '2',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': 'Article #1',
...     'form-0-pub_date': '2008-05-10',
...     'form-0-ORDER': '2',
...     'form-1-title': 'Article #2',
...     'form-1-pub_date': '2008-05-11',
...     'form-1-ORDER': '1',
...     'form-2-title': 'Article #3',
...     'form-2-pub_date': '2008-05-01',
...     'form-2-ORDER': '0',
... }

>>> formset = ArticleFormSet(data, initial=[
...     {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
...     {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
... ])
>>> formset.is_valid()
True
>>> for form in formset.ordered_forms:
...     print(form.cleaned_data)
{'pub_date': datetime.date(2008, 5, 1), 'ORDER': 0, 'title': 'Article #3'}
{'pub_date': datetime.date(2008, 5, 11), 'ORDER': 1, 'title': 'Article #2'}
{'pub_date': datetime.date(2008, 5, 10), 'ORDER': 2, 'title': 'Article #1'}

can_delete

BaseFormSet.can_delete

Default: False

Lets you create a formset with the ability to select forms for deletion:

>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, can_delete=True)
>>> formset = ArticleFormSet(initial=[
...     {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
...     {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
... ])
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr>
<tr><th><label for="id_form-0-DELETE">Delete:</label></th><td><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE" /></td></tr>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr>
<tr><th><label for="id_form-1-DELETE">Delete:</label></th><td><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE" /></td></tr>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>
<tr><th><label for="id_form-2-DELETE">Delete:</label></th><td><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE" /></td></tr>

Similar to can_order this adds a new field to each form named DELETE and is a forms.BooleanField. When data comes through marking any of the delete fields you can access them with deleted_forms:

>>> data = {
...     'form-TOTAL_FORMS': '3',
...     'form-INITIAL_FORMS': '2',
...     'form-MAX_NUM_FORMS': '',
...     'form-0-title': 'Article #1',
...     'form-0-pub_date': '2008-05-10',
...     'form-0-DELETE': 'on',
...     'form-1-title': 'Article #2',
...     'form-1-pub_date': '2008-05-11',
...     'form-1-DELETE': '',
...     'form-2-title': '',
...     'form-2-pub_date': '',
...     'form-2-DELETE': '',
... }

>>> formset = ArticleFormSet(data, initial=[
...     {'title': 'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
...     {'title': 'Article #2', 'pub_date': datetime.date(2008, 5, 11)},
... ])
>>> [form.cleaned_data for form in formset.deleted_forms]
[{'DELETE': True, 'pub_date': datetime.date(2008, 5, 10), 'title': 'Article #1'}]

If you are using a ModelFormSet, model instances for deleted forms will be deleted when you call formset.save().

If you call formset.save(commit=False), objects will not be deleted automatically. You’ll need to call delete() on each of the formset.deleted_objects to actually delete them:

>>> instances = formset.save(commit=False)
>>> for obj in formset.deleted_objects:
...     obj.delete()

On the other hand, if you are using a plain FormSet, it’s up to you to handle formset.deleted_forms, perhaps in your formset’s save() method, as there’s no general notion of what it means to delete a form.

Adding additional fields to a formset

If you need to add additional fields to the formset this can be easily accomplished. The formset base class provides an add_fields method. You can simply override this method to add your own fields or even redefine the default fields/attributes of the order and deletion fields:

>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> class BaseArticleFormSet(BaseFormSet):
...     def add_fields(self, form, index):
...         super(BaseArticleFormSet, self).add_fields(form, index)
...         form.fields["my_field"] = forms.CharField()

>>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet)
>>> formset = ArticleFormSet()
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>
<tr><th><label for="id_form-0-my_field">My field:</label></th><td><input type="text" name="form-0-my_field" id="id_form-0-my_field" /></td></tr>

Passing custom parameters to formset forms

Sometimes your form class takes custom parameters, like MyArticleForm. You can pass this parameter when instantiating the formset:

>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm

>>> class MyArticleForm(ArticleForm):
...     def __init__(self, *args, **kwargs):
...         self.user = kwargs.pop('user')
...         super(MyArticleForm, self).__init__(*args, **kwargs)

>>> ArticleFormSet = formset_factory(MyArticleForm)
>>> formset = ArticleFormSet(form_kwargs={'user': request.user})

The form_kwargs may also depend on the specific form instance. The formset base class provides a get_form_kwargs method. The method takes a single argument - the index of the form in the formset. The index is None for the empty_form:

>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory

>>> class BaseArticleFormSet(BaseFormSet):
...     def get_form_kwargs(self, index):
...         kwargs = super(BaseArticleFormSet, self).get_form_kwargs(index)
...         kwargs['custom_kwarg'] = index
...         return kwargs

New in Django 1.9:
The form_kwargs argument was added.

Using a formset in views and templates

Using a formset inside a view is as easy as using a regular Form class. The only thing you will want to be aware of is making sure to use the management form inside the template. Let’s look at a sample view:

from django.forms import formset_factory
from django.shortcuts import render
from myapp.forms import ArticleForm

def manage_articles(request):
ArticleFormSet = formset_factory(ArticleForm)
if request.method == 'POST':
formset = ArticleFormSet(request.POST, request.FILES)
if formset.is_valid():
# do something with the formset.cleaned_data
pass
else:
formset = ArticleFormSet()
return render(request, 'manage_articles.html', {'formset': formset})

The manage_articles.html template might look like this:

<form method="post" action="">
{{ formset.management_form }}
<table>
{% for form in formset %}
{{ form }}
{% endfor %}
</table>
</form>

However there’s a slight shortcut for the above by letting the formset itself deal with the management form:

<form method="post" action="">
<table>
{{ formset }}
</table>
</form>

The above ends up calling the as_table method on the formset class.

Manually rendered can_delete and can_order

If you manually render fields in the template, you can render can_delete parameter with {{ form.DELETE }}:

<form method="post" action="">
{{ formset.management_form }}
{% for form in formset %}
<ul>
<li>{{ form.title }}</li>
<li>{{ form.pub_date }}</li>
{% if formset.can_delete %}
<li>{{ form.DELETE }}</li>
{% endif %}
</ul>
{% endfor %}
</form>

Similarly, if the formset has the ability to order (can_order=True), it is possible to render it with {{ form.ORDER }}.

Using more than one formset in a view

You are able to use more than one formset in a view if you like. Formsets borrow much of its behavior from forms. With that said you are able to use prefix to prefix formset form field names with a given value to allow more than one formset to be sent to a view without name clashing. Lets take a look at how this might be accomplished:

from django.forms import formset_factory
from django.shortcuts import render
from myapp.forms import ArticleForm, BookForm

def manage_articles(request):
ArticleFormSet = formset_factory(ArticleForm)
BookFormSet = formset_factory(BookForm)
if request.method == 'POST':
article_formset = ArticleFormSet(request.POST, request.FILES, prefix='articles')
book_formset = BookFormSet(request.POST, request.FILES, prefix='books')
if article_formset.is_valid() and book_formset.is_valid():
# do something with the cleaned_data on the formsets.
pass
else:
article_formset = ArticleFormSet(prefix='articles')
book_formset = BookFormSet(prefix='books')
return render(request, 'manage_articles.html', {
'article_formset': article_formset,
'book_formset': book_formset,
})

You would then render the formsets as normal. It is important to point out that you need to pass prefix on both the POST and non-POST cases so that it is rendered and processed correctly.

Creating forms from models

ModelForm

class ModelForm[source]

If you’re building a database-driven app, chances are you’ll have forms that map closely to Django models. For instance, you might have a BlogComment model, and you want to create a form that lets people submit comments. In this case, it would be redundant to define the field types in your form, because you’ve already defined the fields in your model.

For this reason, Django provides a helper class that lets you create a Form class from a Django model.

For example:

>>> from django.forms import ModelForm
>>> from myapp.models import Article

# Create the form class.
>>> class ArticleForm(ModelForm):
...     class Meta:
...         model = Article
...         fields = ['pub_date', 'headline', 'content', 'reporter']

# Creating a form to add an article.
>>> form = ArticleForm()

# Creating a form to change an existing article.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)

Field types

The generated Form class will have a form field for every model field specified, in the order specified in the fields attribute.

Each model field has a corresponding default form field. For example, a CharField on a model is represented as a CharField on a form. A model ManyToManyField is represented as a MultipleChoiceField. Here is the full list of conversions:

Model field

Form field

AutoField

Not represented in the form

BigIntegerField

IntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807.

BooleanField

BooleanField

CharField

CharField with max_length set to the model field’s max_length

CommaSeparatedIntegerField

CharField

DateField

DateField

DateTimeField

DateTimeField

DecimalField

DecimalField

EmailField

EmailField

FileField

FileField

FilePathField

FilePathField

FloatField

FloatField

ForeignKey

ModelChoiceField (see below)

ImageField

ImageField

IntegerField

IntegerField

IPAddressField

IPAddressField

GenericIPAddressField

GenericIPAddressField

ManyToManyField

ModelMultipleChoiceField (see below)

NullBooleanField

NullBooleanField

PositiveIntegerField

IntegerField

PositiveSmallIntegerField

IntegerField

SlugField

SlugField

SmallIntegerField

IntegerField

TextField

CharField with widget=forms.Textarea

TimeField

TimeField

URLField

URLField

As you might expect, the ForeignKey and ManyToManyField model field types are special cases:

- ForeignKey is represented by django.forms.ModelChoiceField, which is a ChoiceField whose choices are a model QuerySet.

- ManyToManyField is represented by django.forms.ModelMultipleChoiceField, which is a MultipleChoiceField whose choices are a model QuerySet.

In addition, each generated form field has attributes set as follows:

- If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True.

- The form field’s label is set to the verbose_name of the model field, with the first character capitalized.

- The form field’s help_text is set to the help_text of the model field.

- If the model field has choices set, then the form field’s widget will be set to Select, with choices coming from the model field’s choices. The choices will normally include the blank choice which is selected by default. If the field is required, this forces the user to make a selection. The blank choice will not be included if the model field has blank=False and an explicit default value (the default value will be initially selected instead).

Finally, note that you can override the form field used for a given model field. See Overriding the default fields below.

A full example

Consider this set of models:

from django.db import models
from django.forms import ModelForm

TITLE_CHOICES = (
('MR', 'Mr.'),
('MRS', 'Mrs.'),
('MS', 'Ms.'),
)

class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
birth_date = models.DateField(blank=True, null=True)

def __str__(self):              # __unicode__ on Python 2
return self.name

class Book(models.Model):
name = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)

class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date']

class BookForm(ModelForm):
class Meta:
model = Book
fields = ['name', 'authors']

With these models, the ModelForm subclasses above would be roughly equivalent to this (the only difference being the save() method, which we’ll discuss in a moment.):

from django import forms

class AuthorForm(forms.Form):
name = forms.CharField(max_length=100)
title = forms.CharField(
max_length=3,
widget=forms.Select(choices=TITLE_CHOICES),
)
birth_date = forms.DateField(required=False)

class BookForm(forms.Form):
name = forms.CharField(max_length=100)
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

Validation on a ModelForm

There are two main steps involved in validating a ModelForm:

1. Validating the form

2. Validating the model instance

Just like normal form validation, model form validation is triggered implicitly when calling is_valid() or accessing the errors attribute and explicitly when calling full_clean(), although you will typically not use the latter method in practice.

Model validation (Model.full_clean()) is triggered from within the form validation step, right after the form’s clean() method is called.

Warning

The cleaning process modifies the model instance passed to the ModelForm constructor in various ways. For instance, any date fields on the model are converted into actual date objects. Failed validation may leave the underlying model instance in an inconsistent state and therefore it’s not recommended to reuse it.

Overriding the clean() method

You can override the clean() method on a model form to provide additional validation in the same way you can on a normal form.

A model form instance attached to a model object will contain an instance attribute that gives its methods access to that specific model instance.

Warning

The ModelForm.clean() method sets a flag that makes the model validation step validate the uniqueness of model fields that are marked as unique, unique_together or unique_for_date|month|year.

If you would like to override the clean() method and maintain this validation, you must call the parent class’s clean() method.

Interaction with model validation

As part of the validation process, ModelForm will call the clean() method of each field on your model that has a corresponding field on your form. If you have excluded any model fields, validation will not be run on those fields. See the form validation documentation for more on how field cleaning and validation work.

The model’s clean() method will be called before any uniqueness checks are made. See Validating objects for more information on the model’s clean() hook.

Considerations regarding model’s error_messages

Error messages defined at the form field level or at the form Meta level always take precedence over the error messages defined at the model field level.

Error messages defined on model fields are only used when the ValidationError is raised during the model validation step and no corresponding error messages are defined at the form level.

You can override the error messages from NON_FIELD_ERRORS raised by model validation by adding the NON_FIELD_ERRORS key to the error_messages dictionary of the ModelForm’s inner Meta class:

from django.forms import ModelForm
from django.core.exceptions import NON_FIELD_ERRORS

class ArticleForm(ModelForm):
class Meta:
error_messages = {
NON_FIELD_ERRORS: {
'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
}
}

The save() method

Every ModelForm also has a save() method. This method creates and saves a database object from the data bound to the form. A subclass of ModelForm can accept an existing model instance as the keyword argument instance; if this is supplied, save() will update that instance. If it’s not supplied, save() will create a new instance of the specified model:

>>> from myapp.models import Article
>>> from myapp.forms import ArticleForm

# Create a form instance from POST data.
>>> f = ArticleForm(request.POST)

# Save a new Article object from the form's data.
>>> new_article = f.save()

# Create a form to edit an existing Article, but use
# POST data to populate the form.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()

Note that if the form hasn’t been validated, calling save() will do so by checking form.errors. A ValueError will be raised if the data in the form doesn’t validate – i.e., if form.errors evaluates to True.

This save() method accepts an optional commit keyword argument, which accepts either True or False. If you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database. In this case, it’s up to you to call save() on the resulting model instance. This is useful if you want to do custom processing on the object before saving it, or if you want to use one of the specialized model saving options. commit is True by default.

Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.

To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data. For example:

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()

Calling save_m2m() is only required if you use save(commit=False). When you use a simple save() on a form, all data – including many-to-many data – is saved without the need for any additional method calls. For example:

# Create a form instance with POST data.
>>> a = Author()
>>> f = AuthorForm(request.POST, instance=a)

# Create and save the new author instance. There's no need to do anything else.
>>> new_author = f.save()

Other than the save() and save_m2m() methods, a ModelForm works exactly the same way as any other forms form. For example, the is_valid() method is used to check for validity, the is_multipart() method is used to determine whether a form requires multipart file upload (and hence whether request.FILES must be passed to the form), etc. See Binding uploaded files to a form for more information.

Selecting the fields to use

It is strongly recommended that you explicitly set all fields that should be edited in the form using the fields attribute. Failure to do so can easily lead to security problems when a form unexpectedly allows a user to set certain fields, especially when new fields are added to a model. Depending on how the form is rendered, the problem may not even be visible on the web page.

The alternative approach would be to include all fields automatically, or blacklist only some. This fundamental approach is known to be much less secure and has led to serious exploits on major websites (e.g. GitHub).

There are, however, two shortcuts available for cases where you can guarantee these security concerns do not apply to you:

1. Set the fields attribute to the special value '__all__' to indicate that all fields in the model should be used. For example:

from django.forms import ModelForm

class AuthorForm(ModelForm):
class Meta:
model = Author
fields = '__all__'

2. Set the exclude attribute of the ModelForm’s inner Meta class to a list of fields to be excluded from the form.

For example:

class PartialAuthorForm(ModelForm):
class Meta:
model = Author
exclude = ['title']

Since the Author model has the 3 fields name, title and birth_date, this will result in the fields name and birth_date being present on the form.

If either of these are used, the order the fields appear in the form will be the order the fields are defined in the model, with ManyToManyField instances appearing last.

In addition, Django applies the following rule: if you set editable=False on the model field, any form created from the model via ModelForm will not include that field.

Changed in Django 1.8:
In older versions, omitting both fields and exclude resulted in a form with all the model’s fields. Doing this now raises an ImproperlyConfigured exception.

Note

Any fields not included in a form by the above logic will not be set by the form’s save() method. Also, if you manually add the excluded fields back to the form, they will not be initialized from the model instance.

Django will prevent any attempt to save an incomplete model, so if the model does not allow the missing fields to be empty, and does not provide a default value for the missing fields, any attempt to save() a ModelForm with missing fields will fail. To avoid this failure, you must instantiate your model with initial values for the missing, but required fields:

author = Author(title='Mr')
form = PartialAuthorForm(request.POST, instance=author)
form.save()

Alternatively, you can use save(commit=False) and manually set any extra required fields:

form = PartialAuthorForm(request.POST)
author = form.save(commit=False)
author.title = 'Mr'
author.save()

See the section on saving forms for more details on using save(commit=False).

Overriding the default fields

The default field types, as described in the Field types table above, are sensible defaults. If you have a DateField in your model, chances are you’d want that to be represented as a DateField in your form. But ModelForm gives you the flexibility of changing the form field for a given model.

To specify a custom widget for a field, use the widgets attribute of the inner Meta class. This should be a dictionary mapping field names to widget classes or instances.

For example, if you want the CharField for the name attribute of Author to be represented by a <textarea> instead of its default <input type="text">, you can override the field’s widget:

from django.forms import ModelForm, Textarea
from myapp.models import Author

class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
widgets = {
'name': Textarea(attrs={'cols': 80, 'rows': 20}),
}

The widgets dictionary accepts either widget instances (e.g., Textarea(...)) or classes (e.g., Textarea).

Similarly, you can specify the labels, help_texts and error_messages attributes of the inner Meta class if you want to further customize a field.

For example if you wanted to customize the wording of all user facing strings for the name field:

from django.utils.translation import ugettext_lazy as _

class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
labels = {
'name': _('Writer'),
}
help_texts = {
'name': _('Some useful help text.'),
}
error_messages = {
'name': {
'max_length': _("This writer's name is too long."),
},
}

You can also specify field_classes to customize the type of fields instantiated by the form.

For example, if you wanted to use MySlugFormField for the slug field, you could do the following:

from django.forms import ModelForm
from myapp.models import Article

class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
field_classes = {
'slug': MySlugFormField,
}

Finally, if you want complete control over of a field – including its type, validators, required, etc. – you can do this by declaratively specifying fields like you would in a regular Form.

If you want to specify a field’s validators, you can do so by defining the field declaratively and setting its validators parameter:

from django.forms import ModelForm, CharField
from myapp.models import Article

class ArticleForm(ModelForm):
slug = CharField(validators=[validate_slug])

class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']

New in Django 1.9:
The Meta.field_classes attribute was added.

Note

When you explicitly instantiate a form field like this, it is important to understand how ModelForm and regular Form are related.

ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.

Fields defined declaratively are left as-is, therefore any customizations made to Meta attributes such as widgets, labels, help_texts, or error_messages are ignored; these only apply to fields that are generated automatically.

Similarly, fields defined declaratively do not draw their attributes like max_length or required from the corresponding model. If you want to maintain the behavior specified in the model, you must set the relevant arguments explicitly when declaring the form field.

For example, if the Article model looks like this:

class Article(models.Model):
headline = models.CharField(
max_length=200,
null=True,
blank=True,
help_text='Use puns liberally',
)
content = models.TextField()

and you want to do some custom validation for headline, while keeping the blank and help_text values as specified, you might define ArticleForm like this:

class ArticleForm(ModelForm):
headline = MyFormField(
max_length=200,
required=False,
help_text='Use puns liberally',
)

class Meta:
model = Article
fields = ['headline', 'content']

You must ensure that the type of the form field can be used to set the contents of the corresponding model field. When they are not compatible, you will get a ValueError as no implicit conversion takes place.

See the form field documentation for more information on fields and their arguments.

Enabling localization of fields

By default, the fields in a ModelForm will not localize their data. To enable localization for fields, you can use the localized_fields attribute on the Meta class.

>>> from django.forms import ModelForm
>>> from myapp.models import Author
>>> class AuthorForm(ModelForm):
...     class Meta:
...         model = Author
...         localized_fields = ('birth_date',)

If localized_fields is set to the special value '__all__', all fields will be localized.

Form inheritance

As with basic forms, you can extend and reuse ModelForms by inheriting them. This is useful if you need to declare extra fields or extra methods on a parent class for use in a number of forms derived from models. For example, using the previous ArticleForm class:

>>> class EnhancedArticleForm(ArticleForm):
...     def clean_pub_date(self):
...         ...

This creates a form that behaves identically to ArticleForm, except there’s some extra validation and cleaning for the pub_date field.

You can also subclass the parent’s Meta inner class if you want to change the Meta.fields or Meta.exclude lists:

>>> class RestrictedArticleForm(EnhancedArticleForm):
...     class Meta(ArticleForm.Meta):
...         exclude = ('body',)

This adds the extra method from the EnhancedArticleForm and modifies the original ArticleForm.Meta to remove one field.

There are a couple of things to note, however.

- Normal Python name resolution rules apply. If you have multiple base classes that declare a Meta inner class, only the first one will be used. This means the child’s Meta, if it exists, otherwise the Meta of the first parent, etc.

- It’s possible to inherit from both Form and ModelForm simultaneously, however, you must ensure that ModelForm appears first in the MRO. This is because these classes rely on different metaclasses and a class can only have one metaclass.

- It’s possible to declaratively remove a Field inherited from a parent class by setting the name to be None on the subclass.

You can only use this technique to opt out from a field defined declaratively by a parent class; it won’t prevent the ModelForm metaclass from generating a default field. To opt-out from default fields, see Selecting the fields to use.

Providing initial values

As with regular forms, it’s possible to specify initial data for forms by specifying an initial parameter when instantiating the form. Initial values provided this way will override both initial values from the form field and values from an attached model instance. For example:

>>> article = Article.objects.get(pk=1)
>>> article.headline
'My headline'
>>> form = ArticleForm(initial={'headline': 'Initial headline'}, instance=article)
>>> form['headline'].value()
'Initial headline'

ModelForm factory function

You can create forms from a given model using the standalone function modelform_factory(), instead of using a class definition. This may be more convenient if you do not have many customizations to make:

>>> from django.forms import modelform_factory
>>> from myapp.models import Book
>>> BookForm = modelform_factory(Book, fields=("author", "title"))

This can also be used to make simple modifications to existing forms, for example by specifying the widgets to be used for a given field:

>>> from django.forms import Textarea
>>> Form = modelform_factory(Book, form=BookForm,
...                          widgets={"title": Textarea()})

The fields to include can be specified using the fields and exclude keyword arguments, or the corresponding attributes on the ModelForm inner Meta class. Please see the ModelForm Selecting the fields to use documentation.

... or enable localization for specific fields:

>>> Form = modelform_factory(Author, form=AuthorForm, localized_fields=("birth_date",))

Model formsets

class models.BaseModelFormSet

Like regular formsets, Django provides a couple of enhanced formset classes that make it easy to work with Django models. Let’s reuse the Author model from above:

>>> from django.forms import modelformset_factory
>>> from myapp.models import Author
>>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))

Using fields restricts the formset to use only the given fields. Alternatively, you can take an “opt-out” approach, specifying which fields to exclude:

>>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))

Changed in Django 1.8:
In older versions, omitting both fields and exclude resulted in a formset with all the model’s fields. Doing this now raises an ImproperlyConfigured exception.

This will create a formset that is capable of working with the data associated with the Author model. It works just like a regular formset:

>>> formset = AuthorFormSet()
>>> print(formset)
<input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" />
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr>
<tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title">
<option value="" selected="selected">---------</option>
<option value="MR">Mr.</option>
<option value="MRS">Mrs.</option>
<option value="MS">Ms.</option>
</select><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr>

Note

modelformset_factory() uses formset_factory() to generate formsets. This means that a model formset is just an extension of a basic formset that knows how to interact with a particular model.

Changing the queryset

By default, when you create a formset from a model, the formset will use a queryset that includes all objects in the model (e.g., Author.objects.all()). You can override this behavior by using the queryset argument:

>>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))

Alternatively, you can create a subclass that sets self.queryset in __init__:

from django.forms import BaseModelFormSet
from myapp.models import Author

class BaseAuthorFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super(BaseAuthorFormSet, self).__init__(*args, **kwargs)
self.queryset = Author.objects.filter(name__startswith='O')

Then, pass your BaseAuthorFormSet class to the factory function:

>>> AuthorFormSet = modelformset_factory(
...     Author, fields=('name', 'title'), formset=BaseAuthorFormSet)

If you want to return a formset that doesn’t include any pre-existing instances of the model, you can specify an empty QuerySet:

>>> AuthorFormSet(queryset=Author.objects.none())

Changing the form

By default, when you use modelformset_factory, a model form will be created using modelform_factory(). Often, it can be useful to specify a custom model form. For example, you can create a custom model form that has custom validation:

class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ('name', 'title')

def clean_name(self):
# custom validation for the name field
...

Then, pass your model form to the factory function:

AuthorFormSet = modelformset_factory(Author, form=AuthorForm)

It is not always necessary to define a custom model form. The modelformset_factory function has several arguments which are passed through to modelform_factory, which are described below.

Specifying widgets to use in the form with widgets

Using the widgets parameter, you can specify a dictionary of values to customize the ModelForm’s widget class for a particular field. This works the same way as the widgets dictionary on the inner Meta class of a ModelForm works:

>>> AuthorFormSet = modelformset_factory(
...     Author, fields=('name', 'title'),
...     widgets={'name': Textarea(attrs={'cols': 80, 'rows': 20})})

Enabling localization for fields with localized_fields

Using the localized_fields parameter, you can enable localization for fields in the form.

>>> AuthorFormSet = modelformset_factory(
...     Author, fields=('name', 'title', 'birth_date'),
...     localized_fields=('birth_date',))

If localized_fields is set to the special value '__all__', all fields will be localized.

Providing initial values

As with regular formsets, it’s possible to specify initial data for forms in the formset by specifying an initial parameter when instantiating the model formset class returned by modelformset_factory(). However, with model formsets, the initial values only apply to extra forms, those that aren’t attached to an existing model instance. If the extra forms with initial data aren’t changed by the user, they won’t be validated or saved.

Saving objects in the formset

As with a ModelForm, you can save the data as a model object. This is done with the formset’s save() method:

# Create a formset instance with POST data.
>>> formset = AuthorFormSet(request.POST)

# Assuming all is valid, save the data.
>>> instances = formset.save()

The save() method returns the instances that have been saved to the database. If a given instance’s data didn’t change in the bound data, the instance won’t be saved to the database and won’t be included in the return value (instances, in the above example).

When fields are missing from the form (for example because they have been excluded), these fields will not be set by the save() method. You can find more information about this restriction, which also holds for regular ModelForms, in Selecting the fields to use.

Pass commit=False to return the unsaved model instances:

# don't save to the database
>>> instances = formset.save(commit=False)
>>> for instance in instances:
...     # do something with instance
...     instance.save()

This gives you the ability to attach data to the instances before saving them to the database. If your formset contains a ManyToManyField, you’ll also need to call formset.save_m2m() to ensure the many-to-many relationships are saved properly.

After calling save(), your model formset will have three new attributes containing the formset’s changes:

models.BaseModelFormSet.changed_objects

models.BaseModelFormSet.deleted_objects

models.BaseModelFormSet.new_objects

Limiting the number of editable objects

As with regular formsets, you can use the max_num and extra parameters to modelformset_factory() to limit the number of extra forms displayed.

max_num does not prevent existing objects from being displayed:

>>> Author.objects.order_by('name')
[<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]

>>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=1)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> [x.name for x in formset.get_queryset()]
['Charles Baudelaire', 'Paul Verlaine', 'Walt Whitman']

Also, extra=0 doesn’t prevent creation of new model instances as you can add additional forms with JavaScript or just send additional POST data. Formsets don’t yet provide functionality for an “edit only” view that prevents creation of new instances.

If the value of max_num is greater than the number of existing related objects, up to extra additional blank forms will be added to the formset, so long as the total number of forms does not exceed max_num:

>>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=4, extra=2)
>>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
>>> for form in formset:
...     print(form.as_table())
<tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr>
<tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr>
<tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr>
<tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr>

A max_num value of None (the default) puts a high limit on the number of forms displayed (1000). In practice this is equivalent to no limit.

Using a model formset in a view

Model formsets are very similar to formsets. Let’s say we want to present a formset to edit Author model instances:

from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Author

def manage_authors(request):
AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
if request.method == 'POST':
formset = AuthorFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
# do something.
else:
formset = AuthorFormSet()
return render(request, 'manage_authors.html', {'formset': formset})

As you can see, the view logic of a model formset isn’t drastically different than that of a “normal” formset. The only difference is that we call formset.save() to save the data into the database. (This was described above, in Saving objects in the formset.)

Overriding clean() on a ModelFormSet

Just like with ModelForms, by default the clean() method of a ModelFormSet will validate that none of the items in the formset violate the unique constraints on your model (either unique, unique_together or unique_for_date|month|year). If you want to override the clean() method on a ModelFormSet and maintain this validation, you must call the parent class’s clean method:

from django.forms import BaseModelFormSet

class MyModelFormSet(BaseModelFormSet):
def clean(self):
super(MyModelFormSet, self).clean()
# example custom validation across forms in the formset
for form in self.forms:
# your custom formset validation
...

Also note that by the time you reach this step, individual model instances have already been created for each Form. Modifying a value in form.cleaned_data is not sufficient to affect the saved value. If you wish to modify a value in ModelFormSet.clean() you must modify form.instance:

from django.forms import BaseModelFormSet

class MyModelFormSet(BaseModelFormSet):
def clean(self):
super(MyModelFormSet, self).clean()

for form in self.forms:
name = form.cleaned_data['name'].upper()
form.cleaned_data['name'] = name
# update the instance value.
form.instance.name = name

Using a custom queryset

As stated earlier, you can override the default queryset used by the model formset:

from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Author

def manage_authors(request):
AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
if request.method == "POST":
formset = AuthorFormSet(
request.POST, request.FILES,
queryset=Author.objects.filter(name__startswith='O'),
)
if formset.is_valid():
formset.save()
# Do something.
else:
formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
return render(request, 'manage_authors.html', {'formset': formset})

Note that we pass the queryset argument in both the POST and GET cases in this example.

Using the formset in the template

There are three ways to render a formset in a Django template.

First, you can let the formset do most of the work:

<form method="post" action="">
{{ formset }}
</form>

Second, you can manually render the formset, but let the form deal with itself:

<form method="post" action="">
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
</form>

When you manually render the forms yourself, be sure to render the management form as shown above. See the management form documentation.

Third, you can manually render each field:

<form method="post" action="">
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{{ field.label_tag }} {{ field }}
{% endfor %}
{% endfor %}
</form>

If you opt to use this third method and you don’t iterate over the fields with a {% for %} loop, you’ll need to render the primary key field. For example, if you were rendering the name and age fields of a model:

<form method="post" action="">
{{ formset.management_form }}
{% for form in formset %}
{{ form.id }}
<ul>
<li>{{ form.name }}</li>
<li>{{ form.age }}</li>
</ul>
{% endfor %}
</form>

Notice how we need to explicitly render {{ form.id }}. This ensures that the model formset, in the POST case, will work correctly. (This example assumes a primary key named id. If you’ve explicitly defined your own primary key that isn’t called id, make sure it gets rendered.)

Inline formsets

class models.BaseInlineFormSet

Inline formsets is a small abstraction layer on top of model formsets. These simplify the case of working with related objects via a foreign key. Suppose you have these two models:

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)

class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)

If you want to create a formset that allows you to edit books belonging to a particular author, you could do this:

>>> from django.forms import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',))
>>> author = Author.objects.get(name='Mike Royko')
>>> formset = BookFormSet(instance=author)

Note

inlineformset_factory() uses modelformset_factory() and marks can_delete=True.

See also

Manually rendered can_delete and can_order.

Overriding methods on an InlineFormSet

When overriding methods on InlineFormSet, you should subclass BaseInlineFormSet rather than BaseModelFormSet.

For example, if you want to override clean():

from django.forms import BaseInlineFormSet

class CustomInlineFormSet(BaseInlineFormSet):
def clean(self):
super(CustomInlineFormSet, self).clean()
# example custom validation across forms in the formset
for form in self.forms:
# your custom formset validation
...

See also Overriding clean() on a ModelFormSet.

Then when you create your inline formset, pass in the optional argument formset:

>>> from django.forms import inlineformset_factory
>>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',),
...     formset=CustomInlineFormSet)
>>> author = Author.objects.get(name='Mike Royko')
>>> formset = BookFormSet(instance=author)

More than one foreign key to the same model

If your model contains more than one foreign key to the same model, you’ll need to resolve the ambiguity manually using fk_name. For example, consider the following model:

class Friendship(models.Model):
from_friend = models.ForeignKey(
Friend,
on_delete=models.CASCADE,
related_name='from_friends',
)
to_friend = models.ForeignKey(
Friend,
on_delete=models.CASCADE,
related_name='friends',
)
length_in_months = models.IntegerField()

To resolve this, you can use fk_name to inlineformset_factory():

>>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name='from_friend',
...     fields=('to_friend', 'length_in_months'))

Using an inline formset in a view

You may want to provide a view that allows a user to edit the related objects of a model. Here’s how you can do that:

def manage_books(request, author_id):
author = Author.objects.get(pk=author_id)
BookInlineFormSet = inlineformset_factory(Author, Book, fields=('title',))
if request.method == "POST":
formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
if formset.is_valid():
formset.save()
# Do something. Should generally end with a redirect. For example:
return HttpResponseRedirect(author.get_absolute_url())
else:
formset = BookInlineFormSet(instance=author)
return render(request, 'manage_books.html', {'formset': formset})

Notice how we pass instance in both the POST and GET cases.

Specifying widgets to use in the inline form

inlineformset_factory uses modelformset_factory and passes most of its arguments to modelformset_factory. This means you can use the widgets parameter in much the same way as passing it to modelformset_factory. See Specifying widgets to use in the form with widgets above.

Form Assets (the Media class)

Rendering an attractive and easy-to-use Web form requires more than just HTML - it also requires CSS stylesheets, and if you want to use fancy “Web2.0” widgets, you may also need to include some JavaScript on each page. The exact combination of CSS and JavaScript that is required for any given page will depend upon the widgets that are in use on that page.

This is where asset definitions come in. Django allows you to associate different files – like stylesheets and scripts – with the forms and widgets that require those assets. For example, if you want to use a calendar to render DateFields, you can define a custom Calendar widget. This widget can then be associated with the CSS and JavaScript that is required to render the calendar. When the Calendar widget is used on a form, Django is able to identify the CSS and JavaScript files that are required, and provide the list of file names in a form suitable for easy inclusion on your Web page.

Assets and Django Admin

The Django Admin application defines a number of customized widgets for calendars, filtered selections, and so on. These widgets define asset requirements, and the Django Admin uses the custom widgets in place of the Django defaults. The Admin templates will only include those files that are required to render the widgets on any given page.

If you like the widgets that the Django Admin application uses, feel free to use them in your own application! They’re all stored in django.contrib.admin.widgets.

Which JavaScript toolkit?

Many JavaScript toolkits exist, and many of them include widgets (such as calendar widgets) that can be used to enhance your application. Django has deliberately avoided blessing any one JavaScript toolkit. Each toolkit has its own relative strengths and weaknesses - use whichever toolkit suits your requirements. Django is able to integrate with any JavaScript toolkit.

Assets as a static definition

The easiest way to define assets is as a static definition. Using this method, the declaration is an inner Media class. The properties of the inner class define the requirements.

Here’s a simple example:

from django import forms

class CalendarWidget(forms.TextInput):
class Media:
css = {
'all': ('pretty.css',)
}
js = ('animations.js', 'actions.js')

This code defines a CalendarWidget, which will be based on TextInput. Every time the CalendarWidget is used on a form, that form will be directed to include the CSS file pretty.css, and the JavaScript files animations.js and actions.js.

This static definition is converted at runtime into a widget property named media. The list of assets for a CalendarWidget instance can be retrieved through this property:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>

Here’s a list of all possible Media options. There are no required options.

css

A dictionary describing the CSS files required for various forms of output media.

The values in the dictionary should be a tuple/list of file names. See the section on paths for details of how to specify paths to these files.

The keys in the dictionary are the output media types. These are the same types accepted by CSS files in media declarations: ‘all’, ‘aural’, ‘braille’, ‘embossed’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’ and ‘tv’. If you need to have different stylesheets for different media types, provide a list of CSS files for each output medium. The following example would provide two CSS options – one for the screen, and one for print:

class Media:
css = {
'screen': ('pretty.css',),
'print': ('newspaper.css',)
}

If a group of CSS files are appropriate for multiple output media types, the dictionary key can be a comma separated list of output media types. In the following example, TV’s and projectors will have the same media requirements:

class Media:
css = {
'screen': ('pretty.css',),
'tv,projector': ('lo_res.css',),
'print': ('newspaper.css',)
}

If this last CSS definition were to be rendered, it would become the following HTML:

<link href="http://static.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
<link href="http://static.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
<link href="http://static.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />

js

A tuple describing the required JavaScript files. See the section on paths for details of how to specify paths to these files.

extend

A boolean defining inheritance behavior for Media declarations.

By default, any object using a static Media definition will inherit all the assets associated with the parent widget. This occurs regardless of how the parent defines its own requirements. For example, if we were to extend our basic Calendar widget from the example above:

>>> class FancyCalendarWidget(CalendarWidget):
...     class Media:
...         css = {
...             'all': ('fancy.css',)
...         }
...         js = ('whizbang.js',)

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<link href="http://static.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

The FancyCalendar widget inherits all the assets from its parent widget. If you don’t want Media to be inherited in this way, add an extend=False declaration to the Media declaration:

>>> class FancyCalendarWidget(CalendarWidget):
...     class Media:
...         extend = False
...         css = {
...             'all': ('fancy.css',)
...         }
...         js = ('whizbang.js',)

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

If you require even more control over inheritance, define your assets using a dynamic property. Dynamic properties give you complete control over which files are inherited, and which are not.

Media as a dynamic property

If you need to perform some more sophisticated manipulation of asset requirements, you can define the media property directly. This is done by defining a widget property that returns an instance of forms.Media. The constructor for forms.Media accepts css and js keyword arguments in the same format as that used in a static media definition.

For example, the static definition for our Calendar Widget could also be defined in a dynamic fashion:

class CalendarWidget(forms.TextInput):
def _media(self):
return forms.Media(css={'all': ('pretty.css',)},
js=('animations.js', 'actions.js'))
media = property(_media)

See the section on Media objects for more details on how to construct return values for dynamic media properties.

Paths in asset definitions

Paths used to specify assets can be either relative or absolute. If a path starts with /, http:// or https://, it will be interpreted as an absolute path, and left as-is. All other paths will be prepended with the value of the appropriate prefix.

As part of the introduction of the staticfiles app two new settings were added to refer to “static files” (images, CSS, JavaScript, etc.) that are needed to render a complete web page: STATIC_URL and STATIC_ROOT.

To find the appropriate prefix to use, Django will check if the STATIC_URL setting is not None and automatically fall back to using MEDIA_URL. For example, if the MEDIA_URL for your site was 'http://uploads.example.com/' and STATIC_URL was None:

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         css = {
...             'all': ('/css/pretty.css',),
...         }
...         js = ('animations.js', 'http://othersite.com/actions.js')

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://uploads.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>

But if STATIC_URL is 'http://static.example.com/':

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>

Media objects

When you interrogate the media attribute of a widget or form, the value that is returned is a forms.Media object. As we have already seen, the string representation of a Media object is the HTML required to include the relevant files in the <head> block of your HTML page.

However, Media objects have some other interesting properties.

Subsets of assets

If you only want files of a particular type, you can use the subscript operator to filter out a medium of interest. For example:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>

>>> print(w.media['css'])
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />

When you use the subscript operator, the value that is returned is a new Media object – but one that only contains the media of interest.

Combining Media objects

Media objects can also be added together. When two Media objects are added, the resulting Media object contains the union of the assets specified by both:

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         css = {
...             'all': ('pretty.css',)
...         }
...         js = ('animations.js', 'actions.js')

>>> class OtherWidget(forms.TextInput):
...     class Media:
...         js = ('whizbang.js',)

>>> w1 = CalendarWidget()
>>> w2 = OtherWidget()
>>> print(w1.media + w2.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

Media on Forms

Widgets aren’t the only objects that can have media definitions – forms can also define media. The rules for media definitions on forms are the same as the rules for widgets: declarations can be static or dynamic; path and inheritance rules for those declarations are exactly the same.

Regardless of whether you define a media declaration, all Form objects have a media property. The default value for this property is the result of adding the media definitions for all widgets that are part of the form:

>>> from django import forms
>>> class ContactForm(forms.Form):
...     date = DateField(widget=CalendarWidget)
...     name = CharField(max_length=40, widget=OtherWidget)

>>> f = ContactForm()
>>> f.media
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

If you want to associate additional assets with a form – for example, CSS for form layout – simply add a Media declaration to the form:

>>> class ContactForm(forms.Form):
...     date = DateField(widget=CalendarWidget)
...     name = CharField(max_length=40, widget=OtherWidget)
...
...     class Media:
...         css = {
...             'all': ('layout.css',)
...         }

>>> f = ContactForm()
>>> f.media
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<link href="http://static.example.com/layout.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

Templates

Being a web framework, Django needs a convenient way to generate HTML dynamically. The most common approach relies on templates. A template contains the static parts of the desired HTML output as well as some special syntax describing how dynamic content will be inserted. For a hands-on example of creating HTML pages with templates, see Tutorial 3.

A Django project can be configured with one or several template engines (or even zero if you don’t use templates). Django ships built-in backends for its own template system, creatively called the Django template language (DTL), and for the popular alternative Jinja2. Backends for other template languages may be available from third-parties.

Django defines a standard API for loading and rendering templates regardless of the backend. Loading consists of finding the template for a given identifier and preprocessing it, usually compiling it to an in-memory representation. Rendering means interpolating the template with context data and returning the resulting string.

The Django template language is Django’s own template system. Until Django 1.8 it was the only built-in option available. It’s a good template library even though it’s fairly opinionated and sports a few idiosyncrasies. If you don’t have a pressing reason to choose another backend, you should use the DTL, especially if you’re writing a pluggable application and you intend to distribute templates. Django’s contrib apps that include templates, like django.contrib.admin, use the DTL.

For historical reasons, both the generic support for template engines and the implementation of the Django template language live in the django.template namespace.

Support for template engines

New in Django 1.8:
Support for multiple template engines and the TEMPLATES setting were added in Django 1.8.

Configuration

Templates engines are configured with the TEMPLATES setting. It’s a list of configurations, one for each engine. The default value is empty. The settings.py generated by the startproject command defines a more useful value:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
# ... some options here ...
},
},
]

BACKEND is a dotted Python path to a template engine class implementing Django’s template backend API. The built-in backends are django.template.backends.django.DjangoTemplates and django.template.backends.jinja2.Jinja2.

Since most engines load templates from files, the top-level configuration for each engine contains two common settings:

- DIRS defines a list of directories where the engine should look for template source files, in search order.

- APP_DIRS tells whether the engine should look for templates inside installed applications. Each backend defines a conventional name for the subdirectory inside applications where its templates should be stored.

While uncommon, it’s possible to configure several instances of the same backend with different options. In that case you should define a unique NAME for each engine.

OPTIONS contains backend-specific settings.

Usage

The django.template.loader module defines two functions to load templates.

get_template(template_name, dirs=_dirs_undefined, using=None)[source]

This function loads the template with the given name and returns a Template object.

The exact type of the return value depends on the backend that loaded the template. Each backend has its own Template class.

get_template() tries each template engine in order until one succeeds. If the template cannot be found, it raises TemplateDoesNotExist. If the template is found but contains invalid syntax, it raises TemplateSyntaxError.

How templates are searched and loaded depends on each engine’s backend and configuration.

If you want to restrict the search to a particular template engine, pass the engine’s NAME in the using argument.

Deprecated since version 1.8: The dirs parameter was deprecated.

Changed in Django 1.8:
The using parameter was added.

Changed in Django 1.8:
get_template() returns a backend-dependent Template instead of a django.template.Template.

select_template(template_name_list, dirs=_dirs_undefined, using=None)[source]

select_template() is just like get_template(), except it takes a list of template names. It tries each name in order and returns the first template that exists.

Deprecated since version 1.8: The dirs parameter was deprecated.

Changed in Django 1.8:
The using parameter was added.

Changed in Django 1.8:
select_template() returns a backend-dependent Template instead of a django.template.Template.

If loading a template fails, the following two exceptions, defined in django.template, may be raised:

exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)[source]

This exception is raised when a template cannot be found. It accepts the following optional arguments for populating the template postmortem on the debug page:

backend

The template backend instance from which the exception originated.

tried

A list of sources that were tried when finding the template. This is formatted as a list of tuples containing (origin, status), where origin is an origin-like object and status is a string with the reason the template wasn’t found.

chain

A list of intermediate TemplateDoesNotExist exceptions raised when trying to load a template. This is used by functions, such as get_template(), that try to load a given template from multiple engines.

New in Django 1.9:
The backend, tried, and chain arguments were added.

exception TemplateSyntaxError(msg)[source]

This exception is raised when a template was found but contains errors.

Template objects returned by get_template() and select_template() must provide a render() method with the following signature:

Template.render(context=None, request=None)

Renders this template with a given context.

If context is provided, it must be a dict. If it isn’t provided, the engine will render the template with an empty context.

If request is provided, it must be an HttpRequest. Then the engine must make it, as well as the CSRF token, available in the template. How this is achieved is up to each backend.

Here’s an example of the search algorithm. For this example the TEMPLATES setting is:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
'/home/html/example.com',
'/home/html/default',
],
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
'/home/html/jinja2',
],
},
]

If you call get_template('story_detail.html'), here are the files Django will look for, in order:

- /home/html/example.com/story_detail.html ('django' engine)

- /home/html/default/story_detail.html ('django' engine)

- /home/html/jinja2/story_detail.html ('jinja2' engine)

If you call select_template(['story_253_detail.html', 'story_detail.html']), here’s what Django will look for:

- /home/html/example.com/story_253_detail.html ('django' engine)

- /home/html/default/story_253_detail.html ('django' engine)

- /home/html/jinja2/story_253_detail.html ('jinja2' engine)

- /home/html/example.com/story_detail.html ('django' engine)

- /home/html/default/story_detail.html ('django' engine)

- /home/html/jinja2/story_detail.html ('jinja2' engine)

When Django finds a template that exists, it stops looking.

Tip

You can use select_template() for flexible template loading. For example, if you’ve written a news story and want some stories to have custom templates, use something like select_template(['story_%s_detail.html' % story.id, 'story_detail.html']). That’ll allow you to use a custom template for an individual story, with a fallback template for stories that don’t have custom templates.

It’s possible – and preferable – to organize templates in subdirectories inside each directory containing templates. The convention is to make a subdirectory for each Django app, with subdirectories within those subdirectories as needed.

Do this for your own sanity. Storing all templates in the root level of a single directory gets messy.

To load a template that’s within a subdirectory, just use a slash, like so:

get_template('news/story_detail.html')

Using the same TEMPLATES option as above, this will attempt to load the following templates:

- /home/html/example.com/news/story_detail.html ('django' engine)

- /home/html/default/news/story_detail.html ('django' engine)

- /home/html/jinja2/news/story_detail.html ('jinja2' engine)

In addition, to cut down on the repetitive nature of loading and rendering templates, Django provides a shortcut function which automates the process.

render_to_string(template_name, context=None, context_instance=_context_instance_undefined, request=None, using=None)[source]

render_to_string() loads a template like get_template() and calls its render() method immediately. It takes the following arguments.

template_name

The name of the template to load and render. If it’s a list of template names, Django uses select_template() instead of get_template() to find the template.

context

A dict to be used as the template’s context for rendering.

Changed in Django 1.8:
The context argument used to be called dictionary. That name is deprecated in Django 1.8 and will be removed in Django 1.10.

context is now optional. An empty context will be used if it isn’t provided.

context_instance

An instance of Context or a subclass (e.g., an instance of RequestContext) to use as the template’s context.

Deprecated since version 1.8: The context_instance argument is deprecated. Use context and if needed request.

request

An optional HttpRequest that will be available during the template’s rendering process.

New in Django 1.8:
The request argument was added.

Usage example:

from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})

See also the render() shortcut which calls render_to_string() and feeds the result into an HttpResponse suitable for returning from a view.

Finally, you can use configured engines directly:

engines

Template engines are available in django.template.engines:

from django.template import engines

django_engine = engines['django']
template = django_engine.from_string("Hello {{ name }}!")

The lookup key — 'django' in this example — is the engine’s NAME.

Built-in backends

class DjangoTemplates[source]

Set BACKEND to 'django.template.backends.django.DjangoTemplates' to configure a Django template engine.

When APP_DIRS is True, DjangoTemplates engines look for templates in the templates subdirectory of installed applications. This generic name was kept for backwards-compatibility.

DjangoTemplates engines accept the following OPTIONS:

- 'allowed_include_roots': a list of strings representing allowed prefixes for the {% ssi %} template tag. This is a security measure, so that template authors can’t access files that they shouldn’t be accessing.

For example, if 'allowed_include_roots' is ['/home/html', '/var/www'], then {% ssi /home/html/foo.txt %} would work, but {% ssi /etc/passwd %} wouldn’t.

It defaults to an empty list.

Deprecated since version 1.8: allowed_include_roots is deprecated because the {% ssi %} tag is deprecated.

- 'context_processors': a list of dotted Python paths to callables that are used to populate the context when a template is rendered with a request. These callables take a request object as their argument and return a dict of items to be merged into the context.

It defaults to an empty list.

See RequestContext for more information.

- 'debug': a boolean that turns on/off template debug mode. If it is True, the fancy error page will display a detailed report for any exception raised during template rendering. This report contains the relevant snippet of the template with the appropriate line highlighted.

It defaults to the value of the DEBUG setting.

- 'loaders': a list of dotted Python paths to template loader classes. Each Loader class knows how to import templates from a particular source. Optionally, a tuple can be used instead of a string. The first item in the tuple should be the Loader class name, and subsequent items are passed to the Loader during initialization.

The default depends on the values of DIRS and APP_DIRS.

See Loader types for details.

- 'string_if_invalid': the output, as a string, that the template system should use for invalid (e.g. misspelled) variables.

It defaults to an empty string.

See How invalid variables are handled for details.

- 'file_charset': the charset used to read template files on disk.

It defaults to the value of FILE_CHARSET.

- 'libraries': A dictionary of labels and dotted Python paths of template tag modules to register with the template engine. This can be used to add new libraries or provide alternate labels for existing ones. For example:

OPTIONS={
'libraries': {
'myapp_tags': 'path.to.myapp.tags',
'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
},
}

Libraries can be loaded by passing the corresponding dictionary key to the {% load %} tag.

- 'builtins': A list of dotted Python paths of template tag modules to add to built-ins. For example:

OPTIONS={
'builtins': ['myapp.builtins'],
}

Tags and filters from built-in libraries can be used without first calling the {% load %} tag.

New in Django 1.9:
The libraries and builtins arguments were added.

class Jinja2[source]

Requires Jinja2 to be installed:

$ pip install Jinja2

Set BACKEND to 'django.template.backends.jinja2.Jinja2' to configure a Jinja2 engine.

When APP_DIRS is True, Jinja2 engines look for templates in the jinja2 subdirectory of installed applications.

The most important entry in OPTIONS is 'environment'. It’s a dotted Python path to a callable returning a Jinja2 environment. It defaults to 'jinja2.Environment'. Django invokes that callable and passes other options as keyword arguments. Furthermore, Django adds defaults that differ from Jinja2’s for a few options:

- 'autoescape': True

- 'loader': a loader configured for DIRS and APP_DIRS

- 'auto_reload': settings.DEBUG

- 'undefined': DebugUndefined if settings.DEBUG else Undefined

The default configuration is purposefully kept to a minimum. If a template is rendered with a request (e.g. when using render()), the Jinja2 backend adds the globals request, csrf_input, and csrf_token to the context. Apart from that, this backend doesn’t create a Django-flavored environment. It doesn’t know about Django context processors, filters, and tags. In order to use Django-specific APIs, you must configure them into the environment.

For example, you can create myproject/jinja2.py with this content:

from __future__ import absolute_import  # Python 2 only

from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.urlresolvers import reverse

from jinja2 import Environment

def environment(**options):
env = Environment(**options)
env.globals.update({
'static': staticfiles_storage.url,
'url': reverse,
})
return env

and set the 'environment' option to 'myproject.jinja2.environment'.

Then you could use the following constructs in Jinja2 templates:

<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">

<a href="{{ url('admin:index') }}">Administration</a>

The concepts of tags and filters exist both in the Django template language and in Jinja2 but they’re used differently. Since Jinja2 supports passing arguments to callables in templates, many features that require a template tag or filter in Django templates can be achieved simply by calling a function in Jinja2 templates, as shown in the example above. Jinja2’s global namespace removes the need for template context processors. The Django template language doesn’t have an equivalent of Jinja2 tests.

Custom backends

Here’s how to implement a custom template backend in order to use another template system. A template backend is a class that inherits django.template.backends.base.BaseEngine. It must implement get_template() and optionally from_string(). Here’s an example for a fictional foobar template library:

from django.template import TemplateDoesNotExist, TemplateSyntaxError
from django.template.backends.base import BaseEngine
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy

import foobar

class FooBar(BaseEngine):

# Name of the subdirectory containing the templates for this engine
# inside an installed application.
app_dirname = 'foobar'

def __init__(self, params):
params = params.copy()
options = params.pop('OPTIONS').copy()
super(FooBar, self).__init__(params)

self.engine = foobar.Engine(**options)

def from_string(self, template_code):
try:
return Template(self.engine.from_string(template_code))
except foobar.TemplateCompilationFailed as exc:
raise TemplateSyntaxError(exc.args)

def get_template(self, template_name):
try:
return Template(self.engine.get_template(template_name))
except foobar.TemplateNotFound as exc:
raise TemplateDoesNotExist(exc.args, backend=self)
except foobar.TemplateCompilationFailed as exc:
raise TemplateSyntaxError(exc.args)

class Template(object):

def __init__(self, template):
self.template = template

def render(self, context=None, request=None):
if context is None:
context = {}
if request is not None:
context['request'] = request
context['csrf_input'] = csrf_input_lazy(request)
context['csrf_token'] = csrf_token_lazy(request)
return self.template.render(context)

See DEP 182 for more information.

Debug integration for custom engines

New in Django 1.9:
Debug page integration for non-Django template engines was added.

The Django debug page has hooks to provide detailed information when a template error arises. Custom template engines can use these hooks to enhance the traceback information that appears to users. The following hooks are available:

Template postmortem

The postmortem appears when TemplateDoesNotExist is raised. It lists the template engines and loaders that were used when trying to find a given template. For example, if two Django engines are configured, the postmortem will appear like:

Custom engines can populate the postmortem by passing the backend and tried arguments when raising TemplateDoesNotExist. Backends that use the postmortem should specify an origin on the template object.

Contextual line information

If an error happens during template parsing or rendering, Django can display the line the error happened on. For example:

Custom engines can populate this information by setting a template_debug attribute on exceptions raised during parsing and rendering. This attribute is a dict with the following values:

- 'name': The name of the template in which the exception occurred.

- 'message': The exception message.

- 'source_lines': The lines before, after, and including the line the exception occurred on. This is for context, so it shouldn’t contain more than 20 lines or so.

- 'line': The line number on which the exception occurred.

- 'before': The content on the error line before the token that raised the error.

- 'during': The token that raised the error.

- 'after': The content on the error line after the token that raised the error.

- 'total': The number of lines in source_lines.

- 'top': The line number where source_lines starts.

- 'bottom': The line number where source_lines ends.

Given the above template error, template_debug would look like:

{
'name': '/path/to/template.html',
'message': "Invalid block tag: 'syntax'",
'source_lines': [
(1, 'some\n'),
(2, 'lines\n'),
(3, 'before\n'),
(4, 'Hello {% syntax error %} {{ world }}\n'),
(5, 'some\n'),
(6, 'lines\n'),
(7, 'after\n'),
(8, ''),
],
'line': 4,
'before': 'Hello ',
'during': '{% syntax error %}',
'after': ' {{ world }}\n',
'total': 9,
'bottom': 9,
'top': 1,
}

Origin API and 3rd-party integration

Django templates have an Origin object available through the template.origin attribute. This enables debug information to be displayed in the template postmortem, as well as in 3rd-party libraries, like the Django Debug Toolbar.

Custom engines can provide their own template.origin information by creating an object that specifies the following attributes:

- 'name': The full path to the template.

- 'template_name': The relative path to the template as passed into the the template loading methods.

- 'loader_name': An optional string identifying the function or class used to load the template, e.g. django.template.loaders.filesystem.Loader.

The Django template language

Syntax

About this section

This is an overview of the Django template language’s syntax. For details see the language syntax reference.

A Django template is simply a text document or a Python string marked-up using the Django template language. Some constructs are recognized and interpreted by the template engine. The main ones are variables and tags.

A template is rendered with a context. Rendering replaces variables with their values, which are looked up in the context, and executes tags. Everything else is output as is.

The syntax of the Django template language involves four constructs.

Variables

A variable outputs a value from the context, which is a dict-like object mapping keys to values.

Variables are surrounded by {{ and }} like this:

My first name is {{ first_name }}. My last name is {{ last_name }}.

With a context of {'first_name': 'John', 'last_name': 'Doe'}, this template renders to:

My first name is John. My last name is Doe.

Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation:

{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}

If a variable resolves to a callable, the template system will call it with no arguments and use its result instead of the callable.

Tags

Tags provide arbitrary logic in the rendering process.

This definition is deliberately vague. For example, a tag can output content, serve as a control structure e.g. an “if” statement or a “for” loop, grab content from a database, or even enable access to other template tags.

Tags are surrounded by {% and %} like this:

{% csrf_token %}

Most tags accept arguments:

{% cycle 'odd' 'even' %}

Some tags require beginning and ending tags:

{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

A reference of built-in tags is available as well as instructions for writing custom tags.

Filters

Filters transform the values of variables and tag arguments.

They look like this:

{{ django|title }}

With a context of {'django': 'the web framework for perfectionists with deadlines'}, this template renders to:

The Web Framework For Perfectionists With Deadlines

Some filters take an argument:

{{ my_date|date:"Y-m-d" }}

A reference of built-in filters is available as well as instructions for writing custom filters.

Comments

Comments look like this:

{# this won't be rendered #}

A {% comment %} tag provides multi-line comments.

Components

About this section

This is an overview of the Django template language’s APIs. For details see the API reference.

Engine

django.template.Engine encapsulates an instance of the Django template system. The main reason for instantiating an Engine directly is to use the Django template language outside of a Django project.

django.template.backends.django.DjangoTemplates is a thin wrapper adapting django.template.Engine to Django’s template backend API.

Template

django.template.Template represents a compiled template. Templates are obtained with Engine.get_template() or Engine.from_string()

Likewise django.template.backends.django.Template is a thin wrapper adapting django.template.Template to the common template API.

Context

django.template.Context holds some metadata in addition to the context data. It is passed to Template.render() for rendering a template.

django.template.RequestContext is a subclass of Context that stores the current HttpRequest and runs template context processors.

The common API doesn’t have an equivalent concept. Context data is passed in a plain dict and the current HttpRequest is passed separately if needed.

Loaders

Template loaders are responsible for locating templates, loading them, and returning Template objects.

Django provides several built-in template loaders and supports custom template loaders.

Context processors

Context processors are functions that receive the current HttpRequest as an argument and return a dict of data to be added to the rendering context.

Their main use is to add common data shared by all templates to the context without repeating code in every view.

Django provides many built-in context processors. Implementing a custom context processor is as simple as defining a function.

Class-based views

A view is a callable which takes a request and returns a response. This can be more than just a function, and Django provides an example of some classes which can be used as views. These allow you to structure your views and reuse code by harnessing inheritance and mixins. There are also some generic views for simple tasks which we’ll get to later, but you may want to design your own structure of reusable views which suits your use case. For full details, see the class-based views reference documentation.

- Introduction to class-based views

- Built-in class-based generic views

- Form handling with class-based views

- Using mixins with class-based views

Basic examples

Django provides base view classes which will suit a wide range of applications. All views inherit from the View class, which handles linking the view in to the URLs, HTTP method dispatching and other simple features. RedirectView is for a simple HTTP redirect, and TemplateView extends the base class to make it also render a template.

Simple usage in your URLconf

The simplest way to use generic views is to create them directly in your URLconf. If you’re only changing a few simple attributes on a class-based view, you can simply pass them into the as_view() method call itself:

from django.conf.urls import url
from django.views.generic import TemplateView

urlpatterns = [
url(r'^about/$', TemplateView.as_view(template_name="about.html")),
]

Any arguments passed to as_view() will override attributes set on the class. In this example, we set template_name on the TemplateView. A similar overriding pattern can be used for the url attribute on RedirectView.

Subclassing generic views

The second, more powerful way to use generic views is to inherit from an existing view and override attributes (such as the template_name) or methods (such as get_context_data) in your subclass to provide new values or methods. Consider, for example, a view that just displays one template, about.html. Django has a generic view to do this - TemplateView - so we can just subclass it, and override the template name:

# some_app/views.py
from django.views.generic import TemplateView

class AboutView(TemplateView):
template_name = "about.html"

Then we just need to add this new view into our URLconf. TemplateView is a class, not a function, so we point the URL to the as_view() class method instead, which provides a function-like entry to class-based views:

# urls.py
from django.conf.urls import url
from some_app.views import AboutView

urlpatterns = [
url(r'^about/$', AboutView.as_view()),
]

For more information on how to use the built in generic views, consult the next topic on generic class-based views.

Supporting other HTTP methods

Suppose somebody wants to access our book library over HTTP using the views as an API. The API client would connect every now and then and download book data for the books published since last visit. But if no new books appeared since then, it is a waste of CPU time and bandwidth to fetch the books from the database, render a full response and send it to the client. It might be preferable to ask the API when the most recent book was published.

We map the URL to book list view in the URLconf:

from django.conf.urls import url
from books.views import BookListView

urlpatterns = [
url(r'^books/$', BookListView.as_view()),
]

And the view:

from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book

class BookListView(ListView):
model = Book

def head(self, *args, **kwargs):
last_book = self.get_queryset().latest('publication_date')
response = HttpResponse('')
# RFC 1123 date format
response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
return response

If the view is accessed from a GET request, a plain-and-simple object list is returned in the response (using book_list.html template). But if the client issues a HEAD request, the response has an empty body and the Last-Modified header indicates when the most recent book was published. Based on this information, the client may or may not download the full object list.

Introduction to class-based views

Class-based views provide an alternative way to implement views as Python objects instead of functions. They do not replace function-based views, but have certain differences and advantages when compared to function-based views:

- Organization of code related to specific HTTP methods (GET, POST, etc.) can be addressed by separate methods instead of conditional branching.

- Object oriented techniques such as mixins (multiple inheritance) can be used to factor code into reusable components.

The relationship and history of generic views, class-based views, and class-based generic views

In the beginning there was only the view function contract, Django passed your function an HttpRequest and expected back an HttpResponse. This was the extent of what Django provided.

Early on it was recognized that there were common idioms and patterns found in view development. Function-based generic views were introduced to abstract these patterns and ease view development for the common cases.

The problem with function-based generic views is that while they covered the simple cases well, there was no way to extend or customize them beyond some simple configuration options, limiting their usefulness in many real-world applications.

Class-based generic views were created with the same objective as function-based generic views, to make view development easier. However, the way the solution is implemented, through the use of mixins, provides a toolkit that results in class-based generic views being more extensible and flexible than their function-based counterparts.

If you have tried function based generic views in the past and found them lacking, you should not think of class-based generic views as simply a class-based equivalent, but rather as a fresh approach to solving the original problems that generic views were meant to solve.

The toolkit of base classes and mixins that Django uses to build class-based generic views are built for maximum flexibility, and as such have many hooks in the form of default method implementations and attributes that you are unlikely to be concerned with in the simplest use cases. For example, instead of limiting you to a class-based attribute for form_class, the implementation uses a get_form method, which calls a get_form_class method, which in its default implementation just returns the form_class attribute of the class. This gives you several options for specifying what form to use, from a simple attribute, to a fully dynamic, callable hook. These options seem to add hollow complexity for simple situations, but without them, more advanced designs would be limited.

Using class-based views

At its core, a class-based view allows you to respond to different HTTP request methods with different class instance methods, instead of with conditionally branching code inside a single view function.

So where the code to handle HTTP GET in a view function would look something like:

from django.http import HttpResponse

def my_view(request):
if request.method == 'GET':
# <view logic>
return HttpResponse('result')

In a class-based view, this would become:

from django.http import HttpResponse
from django.views.generic import View

class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')

Because Django’s URL resolver expects to send the request and associated arguments to a callable function, not a class, class-based views have an as_view() class method which serves as the callable entry point to your class. The as_view entry point creates an instance of your class and calls its dispatch() method. dispatch looks at the request to determine whether it is a GET, POST, etc, and relays the request to a matching method if one is defined, or raises HttpResponseNotAllowed if not:

# urls.py
from django.conf.urls import url
from myapp.views import MyView

urlpatterns = [
url(r'^about/$', MyView.as_view()),
]

It is worth noting that what your method returns is identical to what you return from a function-based view, namely some form of HttpResponse. This means that http shortcuts or TemplateResponse objects are valid to use inside a class-based view.

While a minimal class-based view does not require any class attributes to perform its job, class attributes are useful in many class-based designs, and there are two ways to configure or set class attributes.

The first is the standard Python way of subclassing and overriding attributes and methods in the subclass. So that if your parent class had an attribute greeting like this:

from django.http import HttpResponse
from django.views.generic import View

class GreetingView(View):
greeting = "Good Day"

def get(self, request):
return HttpResponse(self.greeting)

You can override that in a subclass:

class MorningGreetingView(GreetingView):
greeting = "Morning to ya"

Another option is to configure class attributes as keyword arguments to the as_view() call in the URLconf:

urlpatterns = [
url(r'^about/$', GreetingView.as_view(greeting="G'day")),
]

Note

While your class is instantiated for each request dispatched to it, class attributes set through the as_view() entry point are configured only once at the time your URLs are imported.

Using mixins

Mixins are a form of multiple inheritance where behaviors and attributes of multiple parent classes can be combined.

For example, in the generic class-based views there is a mixin called TemplateResponseMixin whose primary purpose is to define the method render_to_response(). When combined with the behavior of the View base class, the result is a TemplateView class that will dispatch requests to the appropriate matching methods (a behavior defined in the View base class), and that has a render_to_response() method that uses a template_name attribute to return a TemplateResponse object (a behavior defined in the TemplateResponseMixin).

Mixins are an excellent way of reusing code across multiple classes, but they come with some cost. The more your code is scattered among mixins, the harder it will be to read a child class and know what exactly it is doing, and the harder it will be to know which methods from which mixins to override if you are subclassing something that has a deep inheritance tree.

Note also that you can only inherit from one generic view - that is, only one parent class may inherit from View and the rest (if any) should be mixins. Trying to inherit from more than one class that inherits from View - for example, trying to use a form at the top of a list and combining ProcessFormView and ListView - won’t work as expected.

Handling forms with class-based views

A basic function-based view that handles forms may look something like this:

from django.http import HttpResponseRedirect
from django.shortcuts import render

from .forms import MyForm

def myview(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
else:
form = MyForm(initial={'key': 'value'})

return render(request, 'form_template.html', {'form': form})

A similar class-based view might look like:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views.generic import View

from .forms import MyForm

class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'

def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})

def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')

return render(request, self.template_name, {'form': form})

This is a very simple case, but you can see that you would then have the option of customizing this view by overriding any of the class attributes, e.g. form_class, via URLconf configuration, or subclassing and overriding one or more of the methods (or both!).

Decorating class-based views

The extension of class-based views isn’t limited to using mixins. You can also use decorators. Since class-based views aren’t functions, decorating them works differently depending on if you’re using as_view() or creating a subclass.

Decorating in URLconf

The simplest way of decorating class-based views is to decorate the result of the as_view() method. The easiest place to do this is in the URLconf where you deploy your view:

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = [
url(r'^about/$', login_required(TemplateView.as_view(template_name="secret.html"))),
url(r'^vote/$', permission_required('polls.can_vote')(VoteView.as_view())),
]

This approach applies the decorator on a per-instance basis. If you want every instance of a view to be decorated, you need to take a different approach.

Decorating the class

To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class.

A method on a class isn’t quite the same as a standalone function, so you can’t just apply a function decorator to the method – you need to transform it into a method decorator first. The method_decorator decorator transforms a function decorator into a method decorator so that it can be used on an instance method. For example:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
template_name = 'secret.html'

@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProtectedView, self).dispatch(*args, **kwargs)

Or, more succinctly, you can decorate the class instead and pass the name of the method to be decorated as the keyword argument name:

@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'

If you have a set of common decorators used in several places, you can define a list or tuple of decorators and use this instead of invoking method_decorator() multiple times. These two classes are equivalent:

decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'

@method_decorator(never_cache, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'

The decorators will process a request in the order they are passed to the decorator. In the example, never_cache() will process the request before login_required().

Changed in Django 1.9:
The ability to use method_decorator() on a class and the ability for it to accept a list or tuple of decorators were added.

In this example, every instance of ProtectedView will have login protection.

Note

method_decorator passes *args and **kwargs as parameters to the decorated method on the class. If your method does not accept a compatible set of parameters it will raise a TypeError exception.

Built-in class-based generic views

Writing Web applications can be monotonous, because we repeat certain patterns again and again. Django tries to take away some of that monotony at the model and template layers, but Web developers also experience this boredom at the view level.

Django’s generic views were developed to ease that pain. They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to write too much code.

We can recognize certain common tasks, like displaying a list of objects, and write code that displays a list of any object. Then the model in question can be passed as an extra argument to the URLconf.

Django ships with generic views to do the following:

- Display list and detail pages for a single object. If we were creating an application to manage conferences then a TalkListView and a RegisteredUserListView would be examples of list views. A single talk page is an example of what we call a “detail” view.

- Present date-based objects in year/month/day archive pages, associated detail, and “latest” pages.

- Allow users to create, update, and delete objects – with or without authorization.

Taken together, these views provide easy interfaces to perform the most common tasks developers encounter.

Extending generic views

There’s no question that using generic views can speed up development substantially. In most projects, however, there comes a moment when the generic views no longer suffice. Indeed, the most common question asked by new Django developers is how to make generic views handle a wider array of situations.

This is one of the reasons generic views were redesigned for the 1.3 release - previously, they were just view functions with a bewildering array of options; now, rather than passing in a large amount of configuration in the URLconf, the recommended way to extend generic views is to subclass them, and override their attributes or methods.

That said, generic views will have a limit. If you find you’re struggling to implement your view as a subclass of a generic view, then you may find it more effective to write just the code you need, using your own class-based or functional views.

More examples of generic views are available in some third party applications, or you could write your own as needed.

Generic views of objects

TemplateView certainly is useful, but Django’s generic views really shine when it comes to presenting views of your database content. Because it’s such a common task, Django comes with a handful of built-in generic views that make generating list and detail views of objects incredibly easy.

Let’s start by looking at some examples of showing a list of objects or an individual object.

We’ll be using these models:

# models.py
from django.db import models

class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()

class Meta:
ordering = ["-name"]

def __str__(self):              # __unicode__ on Python 2
return self.name

class Author(models.Model):
salutation = models.CharField(max_length=10)
name = models.CharField(max_length=200)
email = models.EmailField()
headshot = models.ImageField(upload_to='author_headshots')

def __str__(self):              # __unicode__ on Python 2
return self.name

class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField('Author')
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
publication_date = models.DateField()

Now we need to define a view:

# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherList(ListView):
model = Publisher

Finally hook that view into your urls:

# urls.py
from django.conf.urls import url
from books.views import PublisherList

urlpatterns = [
url(r'^publishers/$', PublisherList.as_view()),
]

That’s all the Python code we need to write. We still need to write a template, however. We could explicitly tell the view which template to use by adding a template_name attribute to the view, but in the absence of an explicit template Django will infer one from the object’s name. In this case, the inferred template will be "books/publisher_list.html" – the “books” part comes from the name of the app that defines the model, while the “publisher” bit is just the lowercased version of the model’s name.

Note

Thus, when (for example) the APP_DIRS option of a DjangoTemplates backend is set to True in TEMPLATES, a template location could be: /path/to/project/books/templates/books/publisher_list.html

This template will be rendered against a context containing a variable called object_list that contains all the publisher objects. A very simple template might look like the following:

{% extends "base.html" %}

{% block content %}
<h2>Publishers</h2>
<ul>
{% for publisher in object_list %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
{% endblock %}

That’s really all there is to it. All the cool features of generic views come from changing the attributes set on the generic view. The generic views reference documents all the generic views and their options in detail; the rest of this document will consider some of the common ways you might customize and extend generic views.

Making “friendly” template contexts

You might have noticed that our sample publisher list template stores all the publishers in a variable named object_list. While this works just fine, it isn’t all that “friendly” to template authors: they have to “just know” that they’re dealing with publishers here.

Well, if you’re dealing with a model object, this is already done for you. When you are dealing with an object or queryset, Django is able to populate the context using the lower cased version of the model class’ name. This is provided in addition to the default object_list entry, but contains exactly the same data, i.e. publisher_list.

If this still isn’t a good match, you can manually set the name of the context variable. The context_object_name attribute on a generic view specifies the context variable to use:

# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherList(ListView):
model = Publisher
context_object_name = 'my_favorite_publishers'

Providing a useful context_object_name is always a good idea. Your coworkers who design templates will thank you.

Adding extra context

Often you simply need to present some extra information beyond that provided by the generic view. For example, think of showing a list of all the books on each publisher detail page. The DetailView generic view provides the publisher to the context, but how do we get additional information in that template?

The answer is to subclass DetailView and provide your own implementation of the get_context_data method. The default implementation simply adds the object being displayed to the template, but you can override it to send more:

from django.views.generic import DetailView
from books.models import Publisher, Book

class PublisherDetail(DetailView):

model = Publisher

def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(PublisherDetail, self).get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['book_list'] = Book.objects.all()
return context

Note

Generally, get_context_data will merge the context data of all parent classes with those of the current class. To preserve this behavior in your own classes where you want to alter the context, you should be sure to call get_context_data on the super class. When no two classes try to define the same key, this will give the expected results. However if any class attempts to override a key after parent classes have set it (after the call to super), any children of that class will also need to explicitly set it after super if they want to be sure to override all parents. If you’re having trouble, review the method resolution order of your view.

Another consideration is that the context data from class-based generic views will override data provided by context processors; see get_context_data() for an example.

Viewing subsets of objects

Now let’s take a closer look at the model argument we’ve been using all along. The model argument, which specifies the database model that the view will operate upon, is available on all the generic views that operate on a single object or a collection of objects. However, the model argument is not the only way to specify the objects that the view will operate upon – you can also specify the list of objects using the queryset argument:

from django.views.generic import DetailView
from books.models import Publisher

class PublisherDetail(DetailView):

context_object_name = 'publisher'
queryset = Publisher.objects.all()

Specifying model = Publisher is really just shorthand for saying queryset = Publisher.objects.all(). However, by using queryset to define a filtered list of objects you can be more specific about the objects that will be visible in the view (see Making queries for more information about QuerySet objects, and see the class-based views reference for the complete details).

To pick a simple example, we might want to order a list of books by publication date, with the most recent first:

from django.views.generic import ListView
from books.models import Book

class BookList(ListView):
queryset = Book.objects.order_by('-publication_date')
context_object_name = 'book_list'

That’s a pretty simple example, but it illustrates the idea nicely. Of course, you’ll usually want to do more than just reorder objects. If you want to present a list of books by a particular publisher, you can use the same technique:

from django.views.generic import ListView
from books.models import Book

class AcmeBookList(ListView):

context_object_name = 'book_list'
queryset = Book.objects.filter(publisher__name='ACME Publishing')
template_name = 'books/acme_list.html'

Notice that along with a filtered queryset, we’re also using a custom template name. If we didn’t, the generic view would use the same template as the “vanilla” object list, which might not be what we want.

Also notice that this isn’t a very elegant way of doing publisher-specific books. If we want to add another publisher page, we’d need another handful of lines in the URLconf, and more than a few publishers would get unreasonable. We’ll deal with this problem in the next section.

Note

If you get a 404 when requesting /books/acme/, check to ensure you actually have a Publisher with the name ‘ACME Publishing’. Generic views have an allow_empty parameter for this case. See the class-based-views reference for more details.

Dynamic filtering

Another common need is to filter down the objects given in a list page by some key in the URL. Earlier we hard-coded the publisher’s name in the URLconf, but what if we wanted to write a view that displayed all the books by some arbitrary publisher?

Handily, the ListView has a get_queryset() method we can override. Previously, it has just been returning the value of the queryset attribute, but now we can add more logic.

The key part to making this work is that when class-based views are called, various useful things are stored on self; as well as the request (self.request) this includes the positional (self.args) and name-based (self.kwargs) arguments captured according to the URLconf.

Here, we have a URLconf with a single captured group:

# urls.py
from django.conf.urls import url
from books.views import PublisherBookList

urlpatterns = [
url(r'^books/([\w-]+)/$', PublisherBookList.as_view()),
]

Next, we’ll write the PublisherBookList view itself:

# views.py
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher

class PublisherBookList(ListView):

template_name = 'books/books_by_publisher.html'

def get_queryset(self):
self.publisher = get_object_or_404(Publisher, name=self.args[0])
return Book.objects.filter(publisher=self.publisher)

As you can see, it’s quite easy to add more logic to the queryset selection; if we wanted, we could use self.request.user to filter using the current user, or other more complex logic.

We can also add the publisher into the context at the same time, so we can use it in the template:

# ...

def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(PublisherBookList, self).get_context_data(**kwargs)
# Add in the publisher
context['publisher'] = self.publisher
return context

Performing extra work

The last common pattern we’ll look at involves doing some extra work before or after calling the generic view.

Imagine we had a last_accessed field on our Author model that we were using to keep track of the last time anybody looked at that author:

# models.py
from django.db import models

class Author(models.Model):
salutation = models.CharField(max_length=10)
name = models.CharField(max_length=200)
email = models.EmailField()
headshot = models.ImageField(upload_to='author_headshots')
last_accessed = models.DateTimeField()

The generic DetailView class, of course, wouldn’t know anything about this field, but once again we could easily write a custom view to keep that field updated.

First, we’d need to add an author detail bit in the URLconf to point to a custom view:

from django.conf.urls import url
from books.views import AuthorDetailView

urlpatterns = [
#...
url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetailView.as_view(), name='author-detail'),
]

Then we’d write our new view – get_object is the method that retrieves the object – so we simply override it and wrap the call:

from django.views.generic import DetailView
from django.utils import timezone
from books.models import Author

class AuthorDetailView(DetailView):

queryset = Author.objects.all()

def get_object(self):
# Call the superclass
object = super(AuthorDetailView, self).get_object()
# Record the last accessed date
object.last_accessed = timezone.now()
object.save()
# Return the object
return object

Note

The URLconf here uses the named group pk - this name is the default name that DetailView uses to find the value of the primary key used to filter the queryset.

If you want to call the group something else, you can set pk_url_kwarg on the view. More details can be found in the reference for DetailView

Form handling with class-based views

Form processing generally has 3 paths:

- Initial GET (blank or prepopulated form)

- POST with invalid data (typically redisplay form with errors)

- POST with valid data (process the data and typically redirect)

Implementing this yourself often results in a lot of repeated boilerplate code (see Using a form in a view). To help avoid this, Django provides a collection of generic class-based views for form processing.

Basic forms

Given a simple contact form:

forms.py

from django import forms

class ContactForm(forms.Form):
name = forms.CharField()
message = forms.CharField(widget=forms.Textarea)

def send_email(self):
# send email using the self.cleaned_data dictionary
pass

The view can be constructed using a FormView:

views.py

from myapp.forms import ContactForm
from django.views.generic.edit import FormView

class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = '/thanks/'

def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form.send_email()
return super(ContactView, self).form_valid(form)

Notes:

- FormView inherits TemplateResponseMixin so template_name can be used here.

- The default implementation for form_valid() simply redirects to the success_url.

Model forms

Generic views really shine when working with models. These generic views will automatically create a ModelForm, so long as they can work out which model class to use:

- If the model attribute is given, that model class will be used.

- If get_object() returns an object, the class of that object will be used.

- If a queryset is given, the model for that queryset will be used.

Model form views provide a form_valid() implementation that saves the model automatically. You can override this if you have any special requirements; see below for examples.

You don’t even need to provide a success_url for CreateView or UpdateView - they will use get_absolute_url() on the model object if available.

If you want to use a custom ModelForm (for instance to add extra validation) simply set form_class on your view.

Note

When specifying a custom form class, you must still specify the model, even though the form_class may be a ModelForm.

First we need to add get_absolute_url() to our Author class:

models.py

from django.core.urlresolvers import reverse
from django.db import models

class Author(models.Model):
name = models.CharField(max_length=200)

def get_absolute_url(self):
return reverse('author-detail', kwargs={'pk': self.pk})

Then we can use CreateView and friends to do the actual work. Notice how we’re just configuring the generic class-based views here; we don’t have to write any logic ourselves:

views.py

from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author

class AuthorCreate(CreateView):
model = Author
fields = ['name']

class AuthorUpdate(UpdateView):
model = Author
fields = ['name']

class AuthorDelete(DeleteView):
model = Author
success_url = reverse_lazy('author-list')

Note

We have to use reverse_lazy() here, not just reverse as the urls are not loaded when the file is imported.

The fields attribute works the same way as the fields attribute on the inner Meta class on ModelForm. Unless you define the form class in another way, the attribute is required and the view will raise an ImproperlyConfigured exception if it’s not.

If you specify both the fields and form_class attributes, an ImproperlyConfigured exception will be raised.

Changed in Django 1.8:
Omitting the fields attribute was previously allowed and resulted in a form with all of the model’s fields.

Changed in Django 1.8:
Previously if both fields and form_class were specified, fields was silently ignored.

Finally, we hook these new views into the URLconf:

urls.py

from django.conf.urls import url
from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete

urlpatterns = [
# ...
url(r'author/add/$', AuthorCreate.as_view(), name='author-add'),
url(r'author/(?P<pk>[0-9]+)/$', AuthorUpdate.as_view(), name='author-update'),
url(r'author/(?P<pk>[0-9]+)/delete/$', AuthorDelete.as_view(), name='author-delete'),
]

Note

These views inherit SingleObjectTemplateResponseMixin which uses template_name_suffix to construct the template_name based on the model.

In this example:

- CreateView and UpdateView use myapp/author_form.html

- DeleteView uses myapp/author_confirm_delete.html

If you wish to have separate templates for CreateView and UpdateView, you can set either template_name or template_name_suffix on your view class.

Models and request.user

To track the user that created an object using a CreateView, you can use a custom ModelForm to do this. First, add the foreign key relation to the model:

models.py

from django.contrib.auth.models import User
from django.db import models

class Author(models.Model):
name = models.CharField(max_length=200)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)

# ...

In the view, ensure that you don’t include created_by in the list of fields to edit, and override form_valid() to add the user:

views.py

from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(CreateView):
model = Author
fields = ['name']

def form_valid(self, form):
form.instance.created_by = self.request.user
return super(AuthorCreate, self).form_valid(form)

Note that you’ll need to decorate this view using login_required(), or alternatively handle unauthorized users in the form_valid().

AJAX example

Here is a simple example showing how you might go about implementing a form that works for AJAX requests as well as ‘normal’ form POSTs:

from django.http import JsonResponse
from django.views.generic.edit import CreateView
from myapp.models import Author

class AjaxableResponseMixin(object):
"""
Mixin to add AJAX support to a form.
Must be used with an object-based FormView (e.g. CreateView)
"""
def form_invalid(self, form):
response = super(AjaxableResponseMixin, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response

def form_valid(self, form):
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
response = super(AjaxableResponseMixin, self).form_valid(form)
if self.request.is_ajax():
data = {
'pk': self.object.pk,
}
return JsonResponse(data)
else:
return response

class AuthorCreate(AjaxableResponseMixin, CreateView):
model = Author
fields = ['name']

Using mixins with class-based views

Caution

This is an advanced topic. A working knowledge of Django’s class-based views is advised before exploring these techniques.

Django’s built-in class-based views provide a lot of functionality, but some of it you may want to use separately. For instance, you may want to write a view that renders a template to make the HTTP response, but you can’t use TemplateView; perhaps you need to render a template only on POST, with GET doing something else entirely. While you could use TemplateResponse directly, this will likely result in duplicate code.

For this reason, Django also provides a number of mixins that provide more discrete functionality. Template rendering, for instance, is encapsulated in the TemplateResponseMixin. The Django reference documentation contains full documentation of all the mixins.

Context and template responses

Two central mixins are provided that help in providing a consistent interface to working with templates in class-based views.

TemplateResponseMixin

Every built in view which returns a TemplateResponse will call the render_to_response() method that TemplateResponseMixin provides. Most of the time this will be called for you (for instance, it is called by the get() method implemented by both TemplateView and DetailView); similarly, it’s unlikely that you’ll need to override it, although if you want your response to return something not rendered via a Django template then you’ll want to do it. For an example of this, see the JSONResponseMixin example.

render_to_response() itself calls get_template_names(), which by default will just look up template_name on the class-based view; two other mixins (SingleObjectTemplateResponseMixin and MultipleObjectTemplateResponseMixin) override this to provide more flexible defaults when dealing with actual objects.

ContextMixin

Every built in view which needs context data, such as for rendering a template (including TemplateResponseMixin above), should call get_context_data() passing any data they want to ensure is in there as keyword arguments. get_context_data() returns a dictionary; in ContextMixin it simply returns its keyword arguments, but it is common to override this to add more members to the dictionary.

Building up Django’s generic class-based views

Let’s look at how two of Django’s generic class-based views are built out of mixins providing discrete functionality. We’ll consider DetailView, which renders a “detail” view of an object, and ListView, which will render a list of objects, typically from a queryset, and optionally paginate them. This will introduce us to four mixins which between them provide useful functionality when working with either a single Django object, or multiple objects.

There are also mixins involved in the generic edit views (FormView, and the model-specific views CreateView, UpdateView and DeleteView), and in the date-based generic views. These are covered in the mixin reference documentation.

DetailView: working with a single Django object

To show the detail of an object, we basically need to do two things: we need to look up the object and then we need to make a TemplateResponse with a suitable template, and that object as context.

To get the object, DetailView relies on SingleObjectMixin, which provides a get_object() method that figures out the object based on the URL of the request (it looks for pk and slug keyword arguments as declared in the URLConf, and looks the object up either from the model attribute on the view, or the queryset attribute if that’s provided). SingleObjectMixin also overrides get_context_data(), which is used across all Django’s built in class-based views to supply context data for template renders.

To then make a TemplateResponse, DetailView uses SingleObjectTemplateResponseMixin, which extends TemplateResponseMixin, overriding get_template_names() as discussed above. It actually provides a fairly sophisticated set of options, but the main one that most people are going to use is <app_label>/<model_name>_detail.html. The _detail part can be changed by setting template_name_suffix on a subclass to something else. (For instance, the generic edit views use _form for create and update views, and _confirm_delete for delete views.)

ListView: working with many Django objects

Lists of objects follow roughly the same pattern: we need a (possibly paginated) list of objects, typically a QuerySet, and then we need to make a TemplateResponse with a suitable template using that list of objects.

To get the objects, ListView uses MultipleObjectMixin, which provides both get_queryset() and paginate_queryset(). Unlike with SingleObjectMixin, there’s no need to key off parts of the URL to figure out the queryset to work with, so the default just uses the queryset or model attribute on the view class. A common reason to override get_queryset() here would be to dynamically vary the objects, such as depending on the current user or to exclude posts in the future for a blog.

MultipleObjectMixin also overrides get_context_data() to include appropriate context variables for pagination (providing dummies if pagination is disabled). It relies on object_list being passed in as a keyword argument, which ListView arranges for it.

To make a TemplateResponse, ListView then uses MultipleObjectTemplateResponseMixin; as with SingleObjectTemplateResponseMixin above, this overrides get_template_names() to provide a range of options, with the most commonly-used being <app_label>/<model_name>_list.html, with the _list part again being taken from the template_name_suffix attribute. (The date based generic views use suffixes such as _archive, _archive_year and so on to use different templates for the various specialized date-based list views.)

Using Django’s class-based view mixins

Now we’ve seen how Django’s generic class-based views use the provided mixins, let’s look at other ways we can combine them. Of course we’re still going to be combining them with either built-in class-based views, or other generic class-based views, but there are a range of rarer problems you can solve than are provided for by Django out of the box.

Warning

Not all mixins can be used together, and not all generic class based views can be used with all other mixins. Here we present a few examples that do work; if you want to bring together other functionality then you’ll have to consider interactions between attributes and methods that overlap between the different classes you’re using, and how method resolution order will affect which versions of the methods will be called in what order.

The reference documentation for Django’s class-based views and class-based view mixins will help you in understanding which attributes and methods are likely to cause conflict between different classes and mixins.

If in doubt, it’s often better to back off and base your work on View or TemplateView, perhaps with SingleObjectMixin and MultipleObjectMixin. Although you will probably end up writing more code, it is more likely to be clearly understandable to someone else coming to it later, and with fewer interactions to worry about you will save yourself some thinking. (Of course, you can always dip into Django’s implementation of the generic class-based views for inspiration on how to tackle problems.)

Using SingleObjectMixin with View

If we want to write a simple class-based view that responds only to POST, we’ll subclass View and write a post() method in the subclass. However if we want our processing to work on a particular object, identified from the URL, we’ll want the functionality provided by SingleObjectMixin.

We’ll demonstrate this with the Author model we used in the generic class-based views introduction.

views.py

from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from books.models import Author

class RecordInterest(SingleObjectMixin, View):
"""Records the current user's interest in an author."""
model = Author

def post(self, request, *args, **kwargs):
if not request.user.is_authenticated():
return HttpResponseForbidden()

# Look up the author we're interested in.
self.object = self.get_object()
# Actually record interest somehow here!

return HttpResponseRedirect(reverse('author-detail', kwargs={'pk': self.object.pk}))

In practice you’d probably want to record the interest in a key-value store rather than in a relational database, so we’ve left that bit out. The only bit of the view that needs to worry about using SingleObjectMixin is where we want to look up the author we’re interested in, which it just does with a simple call to self.get_object(). Everything else is taken care of for us by the mixin.

We can hook this into our URLs easily enough:

urls.py

from django.conf.urls import url
from books.views import RecordInterest

urlpatterns = [
#...
url(r'^author/(?P<pk>[0-9]+)/interest/$', RecordInterest.as_view(), name='author-interest'),
]

Note the pk named group, which get_object() uses to look up the Author instance. You could also use a slug, or any of the other features of SingleObjectMixin.

Using SingleObjectMixin with ListView

ListView provides built-in pagination, but you might want to paginate a list of objects that are all linked (by a foreign key) to another object. In our publishing example, you might want to paginate through all the books by a particular publisher.

One way to do this is to combine ListView with SingleObjectMixin, so that the queryset for the paginated list of books can hang off the publisher found as the single object. In order to do this, we need to have two different querysets:

Book queryset for use by ListView

Since we have access to the Publisher whose books we want to list, we simply override get_queryset() and use the Publisher’s reverse foreign key manager.

Publisher queryset for use in get_object()

We’ll rely on the default implementation of get_object() to fetch the correct Publisher object. However, we need to explicitly pass a queryset argument because otherwise the default implementation of get_object() would call get_queryset() which we have overridden to return Book objects instead of Publisher ones.

Note

We have to think carefully about get_context_data(). Since both SingleObjectMixin and ListView will put things in the context data under the value of context_object_name if it’s set, we’ll instead explicitly ensure the Publisher is in the context data. ListView will add in the suitable page_obj and paginator for us providing we remember to call super().

Now we can write a new PublisherDetail:

from django.views.generic import ListView
from django.views.generic.detail import SingleObjectMixin
from books.models import Publisher

class PublisherDetail(SingleObjectMixin, ListView):
paginate_by = 2
template_name = "books/publisher_detail.html"

def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=Publisher.objects.all())
return super(PublisherDetail, self).get(request, *args, **kwargs)

def get_context_data(self, **kwargs):
context = super(PublisherDetail, self).get_context_data(**kwargs)
context['publisher'] = self.object
return context

def get_queryset(self):
return self.object.book_set.all()

Notice how we set self.object within get() so we can use it again later in get_context_data() and get_queryset(). If you don’t set template_name, the template will default to the normal ListView choice, which in this case would be "books/book_list.html" because it’s a list of books; ListView knows nothing about SingleObjectMixin, so it doesn’t have any clue this view is anything to do with a Publisher.

The paginate_by is deliberately small in the example so you don’t have to create lots of books to see the pagination working! Here’s the template you’d want to use:

{% extends "base.html" %}

{% block content %}
<h2>Publisher {{ publisher.name }}</h2>

<ol>
{% for book in page_obj %}
<li>{{ book.title }}</li>
{% endfor %}
</ol>

<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}

<span class="current">
Page {{ page_obj.number }} of {{ paginator.num_pages }}.
</span>

{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endblock %}

Avoid anything more complex

Generally you can use TemplateResponseMixin and SingleObjectMixin when you need their functionality. As shown above, with a bit of care you can even combine SingleObjectMixin with ListView. However things get increasingly complex as you try to do so, and a good rule of thumb is:

Hint

Each of your views should use only mixins or views from one of the groups of generic class-based views: detail, list, editing and date. For example it’s fine to combine TemplateView (built in view) with MultipleObjectMixin (generic list), but you’re likely to have problems combining SingleObjectMixin (generic detail) with MultipleObjectMixin (generic list).

To show what happens when you try to get more sophisticated, we show an example that sacrifices readability and maintainability when there is a simpler solution. First, let’s look at a naive attempt to combine DetailView with FormMixin to enable us to POST a Django Form to the same URL as we’re displaying an object using DetailView.

Using FormMixin with DetailView

Think back to our earlier example of using View and SingleObjectMixin together. We were recording a user’s interest in a particular author; say now that we want to let them leave a message saying why they like them. Again, let’s assume we’re not going to store this in a relational database but instead in something more esoteric that we won’t worry about here.

At this point it’s natural to reach for a Form to encapsulate the information sent from the user’s browser to Django. Say also that we’re heavily invested in REST, so we want to use the same URL for displaying the author as for capturing the message from the user. Let’s rewrite our AuthorDetailView to do that.

We’ll keep the GET handling from DetailView, although we’ll have to add a Form into the context data so we can render it in the template. We’ll also want to pull in form processing from FormMixin, and write a bit of code so that on POST the form gets called appropriately.

Note

We use FormMixin and implement post() ourselves rather than try to mix DetailView with FormView (which provides a suitable post() already) because both of the views implement get(), and things would get much more confusing.

Our new AuthorDetail looks like this:

# CAUTION: you almost certainly do not want to do this.
# It is provided as part of a discussion of problems you can
# run into when combining different generic class-based view
# functionality that is not designed to be used together.

from django import forms
from django.http import HttpResponseForbidden
from django.core.urlresolvers import reverse
from django.views.generic import DetailView
from django.views.generic.edit import FormMixin
from books.models import Author

class AuthorInterestForm(forms.Form):
message = forms.CharField()

class AuthorDetail(FormMixin, DetailView):
model = Author
form_class = AuthorInterestForm

def get_success_url(self):
return reverse('author-detail', kwargs={'pk': self.object.pk})

def get_context_data(self, **kwargs):
context = super(AuthorDetail, self).get_context_data(**kwargs)
context['form'] = self.get_form()
return context

def post(self, request, *args, **kwargs):
if not request.user.is_authenticated():
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)

def form_valid(self, form):
# Here, we would record the user's interest using the message
# passed in form.cleaned_data['message']
return super(AuthorDetail, self).form_valid(form)

get_success_url() is just providing somewhere to redirect to, which gets used in the default implementation of form_valid(). We have to provide our own post() as noted earlier, and override get_context_data() to make the Form available in the context data.

A better solution

It should be obvious that the number of subtle interactions between FormMixin and DetailView is already testing our ability to manage things. It’s unlikely you’d want to write this kind of class yourself.

In this case, it would be fairly easy to just write the post() method yourself, keeping DetailView as the only generic functionality, although writing Form handling code involves a lot of duplication.

Alternatively, it would still be easier than the above approach to have a separate view for processing the form, which could use FormView distinct from DetailView without concerns.

An alternative better solution

What we’re really trying to do here is to use two different class based views from the same URL. So why not do just that? We have a very clear division here: GET requests should get the DetailView (with the Form added to the context data), and POST requests should get the FormView. Let’s set up those views first.

The AuthorDisplay view is almost the same as when we first introduced AuthorDetail; we have to write our own get_context_data() to make the AuthorInterestForm available to the template. We’ll skip the get_object() override from before for clarity:

from django.views.generic import DetailView
from django import forms
from books.models import Author

class AuthorInterestForm(forms.Form):
message = forms.CharField()

class AuthorDisplay(DetailView):
model = Author

def get_context_data(self, **kwargs):
context = super(AuthorDisplay, self).get_context_data(**kwargs)
context['form'] = AuthorInterestForm()
return context

Then the AuthorInterest is a simple FormView, but we have to bring in SingleObjectMixin so we can find the author we’re talking about, and we have to remember to set template_name to ensure that form errors will render the same template as AuthorDisplay is using on GET:

from django.core.urlresolvers import reverse
from django.http import HttpResponseForbidden
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin

class AuthorInterest(SingleObjectMixin, FormView):
template_name = 'books/author_detail.html'
form_class = AuthorInterestForm
model = Author

def post(self, request, *args, **kwargs):
if not request.user.is_authenticated():
return HttpResponseForbidden()
self.object = self.get_object()
return super(AuthorInterest, self).post(request, *args, **kwargs)

def get_success_url(self):
return reverse('author-detail', kwargs={'pk': self.object.pk})

Finally we bring this together in a new AuthorDetail view. We already know that calling as_view() on a class-based view gives us something that behaves exactly like a function based view, so we can do that at the point we choose between the two subviews.

You can of course pass through keyword arguments to as_view() in the same way you would in your URLconf, such as if you wanted the AuthorInterest behavior to also appear at another URL but using a different template:

from django.views.generic import View

class AuthorDetail(View):

def get(self, request, *args, **kwargs):
view = AuthorDisplay.as_view()
return view(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
view = AuthorInterest.as_view()
return view(request, *args, **kwargs)

This approach can also be used with any other generic class-based views or your own class-based views inheriting directly from View or TemplateView, as it keeps the different views as separate as possible.

More than just HTML

Where class-based views shine is when you want to do the same thing many times. Suppose you’re writing an API, and every view should return JSON instead of rendered HTML.

We can create a mixin class to use in all of our views, handling the conversion to JSON once.

For example, a simple JSON mixin might look something like this:

from django.http import JsonResponse

class JSONResponseMixin(object):
"""
A mixin that can be used to render a JSON response.
"""
def render_to_json_response(self, context, **response_kwargs):
"""
Returns a JSON response, transforming 'context' to make the payload.
"""
return JsonResponse(
self.get_data(context),
**response_kwargs
)

def get_data(self, context):
"""
Returns an object that will be serialized as JSON by json.dumps().
"""
# Note: This is *EXTREMELY* naive; in reality, you'll need
# to do much more complex handling to ensure that arbitrary
# objects -- such as Django model instances or querysets
# -- can be serialized as JSON.
return context

Note

Check out the Serializing Django objects documentation for more information on how to correctly transform Django models and querysets into JSON.

This mixin provides a render_to_json_response() method with the same signature as render_to_response(). To use it, we simply need to mix it into a TemplateView for example, and override render_to_response() to call render_to_json_response() instead:

from django.views.generic import TemplateView

class JSONView(JSONResponseMixin, TemplateView):
def render_to_response(self, context, **response_kwargs):
return self.render_to_json_response(context, **response_kwargs)

Equally we could use our mixin with one of the generic views. We can make our own version of DetailView by mixing JSONResponseMixin with the django.views.generic.detail.BaseDetailView – (the DetailView before template rendering behavior has been mixed in):

from django.views.generic.detail import BaseDetailView

class JSONDetailView(JSONResponseMixin, BaseDetailView):
def render_to_response(self, context, **response_kwargs):
return self.render_to_json_response(context, **response_kwargs)

This view can then be deployed in the same way as any other DetailView, with exactly the same behavior – except for the format of the response.

If you want to be really adventurous, you could even mix a DetailView subclass that is able to return both HTML and JSON content, depending on some property of the HTTP request, such as a query argument or a HTTP header. Just mix in both the JSONResponseMixin and a SingleObjectTemplateResponseMixin, and override the implementation of render_to_response() to defer to the appropriate rendering method depending on the type of response that the user requested:

from django.views.generic.detail import SingleObjectTemplateResponseMixin

class HybridDetailView(JSONResponseMixin, SingleObjectTemplateResponseMixin, BaseDetailView):
def render_to_response(self, context):
# Look for a 'format=json' GET argument
if self.request.GET.get('format') == 'json':
return self.render_to_json_response(context)
else:
return super(HybridDetailView, self).render_to_response(context)

Because of the way that Python resolves method overloading, the call to super(HybridDetailView, self).render_to_response(context) ends up calling the render_to_response() implementation of TemplateResponseMixin.

Migrations

Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema. They’re designed to be mostly automatic, but you’ll need to know when to make migrations, when to run them, and the common problems you might run into.

The Commands

There are several commands which you will use to interact with migrations and Django’s handling of database schema:

- migrate, which is responsible for applying migrations, as well as unapplying and listing their status.

- makemigrations, which is responsible for creating new migrations based on the changes you have made to your models.

- sqlmigrate, which displays the SQL statements for a migration.

- showmigrations, which lists a project’s migrations.

You should think of migrations as a version control system for your database schema. makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.

The migration files for each app live in a “migrations” directory inside of that app, and are designed to be committed to, and distributed as part of, its codebase. You should be making them once on your development machine and then running the same migrations on your colleagues’ machines, your staging machines, and eventually your production machines.

Note

It is possible to override the name of the package which contains the migrations on a per-app basis by modifying the MIGRATION_MODULES setting.

Migrations will run the same way on the same dataset and produce consistent results, meaning that what you see in development and staging is, under the same circumstances, exactly what will happen in production.

Django will make migrations for any change to your models or fields - even options that don’t affect the database - as the only way it can reconstruct a field correctly is to have all the changes in the history, and you might need those options in some data migrations later on (for example, if you’ve set custom validators).

Backend Support

Migrations are supported on all backends that Django ships with, as well as any third-party backends if they have programmed in support for schema alteration (done via the SchemaEditor class).

However, some databases are more capable than others when it comes to schema migrations; some of the caveats are covered below.

PostgreSQL

PostgreSQL is the most capable of all the databases here in terms of schema support; the only caveat is that adding columns with default values will cause a full rewrite of the table, for a time proportional to its size.

For this reason, it’s recommended you always create new columns with null=True, as this way they will be added immediately.

MySQL

MySQL lacks support for transactions around schema alteration operations, meaning that if a migration fails to apply you will have to manually unpick the changes in order to try again (it’s impossible to roll back to an earlier point).

In addition, MySQL will fully rewrite tables for almost every schema operation and generally takes a time proportional to the number of rows in the table to add or remove columns. On slower hardware this can be worse than a minute per million rows - adding a few columns to a table with just a few million rows could lock your site up for over ten minutes.

Finally, MySQL has reasonably small limits on name lengths for columns, tables and indexes, as well as a limit on the combined size of all columns an index covers. This means that indexes that are possible on other backends will fail to be created under MySQL.

SQLite

SQLite has very little built-in schema alteration support, and so Django attempts to emulate it by:

- Creating a new table with the new schema

- Copying the data across

- Dropping the old table

- Renaming the new table to match the original name

This process generally works well, but it can be slow and occasionally buggy. It is not recommended that you run and migrate SQLite in a production environment unless you are very aware of the risks and its limitations; the support Django ships with is designed to allow developers to use SQLite on their local machines to develop less complex Django projects without the need for a full database.

Workflow

Working with migrations is simple. Make changes to your models - say, add a field and remove a model - and then run makemigrations:

$ python manage.py makemigrations
Migrations for 'books':
0003_auto.py:
- Alter field author on book

Your models will be scanned and compared to the versions currently contained in your migration files, and then a new set of migrations will be written out. Make sure to read the output to see what makemigrations thinks you have changed - it’s not perfect, and for complex changes it might not be detecting what you expect.

Once you have your new migration files, you should apply them to your database to make sure they work as expected:

$ python manage.py migrate
Operations to perform:
Apply all migrations: books
Running migrations:
Rendering model states... DONE
Applying books.0003_auto... OK

Once the migration is applied, commit the migration and the models change to your version control system as a single commit - that way, when other developers (or your production servers) check out the code, they’ll get both the changes to your models and the accompanying migration at the same time.

New in Django 1.8.

If you want to give the migration(s) a meaningful name instead of a generated one, you can use the makemigrations --name option:

$ python manage.py makemigrations --name changed_my_model your_app_label

Version control

Because migrations are stored in version control, you’ll occasionally come across situations where you and another developer have both committed a migration to the same app at the same time, resulting in two migrations with the same number.

Don’t worry - the numbers are just there for developers’ reference, Django just cares that each migration has a different name. Migrations specify which other migrations they depend on - including earlier migrations in the same app - in the file, so it’s possible to detect when there’s two new migrations for the same app that aren’t ordered.

When this happens, Django will prompt you and give you some options. If it thinks it’s safe enough, it will offer to automatically linearize the two migrations for you. If not, you’ll have to go in and modify the migrations yourself - don’t worry, this isn’t difficult, and is explained more in Migration files below.

Dependencies

While migrations are per-app, the tables and relationships implied by your models are too complex to be created for just one app at a time. When you make a migration that requires something else to run - for example, you add a ForeignKey in your books app to your authors app - the resulting migration will contain a dependency on a migration in authors.

This means that when you run the migrations, the authors migration runs first and creates the table the ForeignKey references, and then the migration that makes the ForeignKey column runs afterwards and creates the constraint. If this didn’t happen, the migration would try to create the ForeignKey column without the table it’s referencing existing and your database would throw an error.

This dependency behavior affects most migration operations where you restrict to a single app. Restricting to a single app (either in makemigrations or migrate) is a best-efforts promise, and not a guarantee; any other apps that need to be used to get dependencies correct will be.

Migration files

Migrations are stored as an on-disk format, referred to here as “migration files”. These files are actually just normal Python files with an agreed-upon object layout, written in a declarative style.

A basic migration file looks like this:

from django.db import migrations, models

class Migration(migrations.Migration):

dependencies = [("migrations", "0001_initial")]

operations = [
migrations.DeleteModel("Tribble"),
migrations.AddField("Author", "rating", models.IntegerField(default=0)),
]

What Django looks for when it loads a migration file (as a Python module) is a subclass of django.db.migrations.Migration called Migration. It then inspects this object for four attributes, only two of which are used most of the time:

- dependencies, a list of migrations this one depends on.

- operations, a list of Operation classes that define what this migration does.

The operations are the key; they are a set of declarative instructions which tell Django what schema changes need to be made. Django scans them and builds an in-memory representation of all of the schema changes to all apps, and uses this to generate the SQL which makes the schema changes.

That in-memory structure is also used to work out what the differences are between your models and the current state of your migrations; Django runs through all the changes, in order, on an in-memory set of models to come up with the state of your models last time you ran makemigrations. It then uses these models to compare against the ones in your models.py files to work out what you have changed.

You should rarely, if ever, need to edit migration files by hand, but it’s entirely possible to write them manually if you need to. Some of the more complex operations are not autodetectable and are only available via a hand-written migration, so don’t be scared about editing them if you have to.

Custom fields

You can’t modify the number of positional arguments in an already migrated custom field without raising a TypeError. The old migration will call the modified __init__ method with the old signature. So if you need a new argument, please create a keyword argument and add something like assert 'argument_name' in kwargs in the constructor.

Model managers

New in Django 1.8.

You can optionally serialize managers into migrations and have them available in RunPython operations. This is done by defining a use_in_migrations attribute on the manager class:

class MyManager(models.Manager):
use_in_migrations = True

class MyModel(models.Model):
objects = MyManager()

If you are using the from_queryset() function to dynamically generate a manager class, you need to inherit from the generated class to make it importable:

class MyManager(MyBaseManager.from_queryset(CustomQuerySet)):
use_in_migrations = True

class MyModel(models.Model):
objects = MyManager()

Please refer to the notes about Historical models in migrations to see the implications that come along.

Initial migrations

Migration.initial

New in Django 1.9.

The “initial migrations” for an app are the migrations that create the first version of that app’s tables. Usually an app will have just one initial migration, but in some cases of complex model interdependencies it may have two or more.

Initial migrations are marked with an initial = True class attribute on the migration class. If an initial class attribute isn’t found, a migration will be considered “initial” if it is the first migration in the app (i.e. if it has no dependencies on any other migration in the same app).

When the migrate --fake-initial option is used, these initial migrations are treated specially. For an initial migration that creates one or more tables (CreateModel operation), Django checks that all of those tables already exist in the database and fake-applies the migration if so. Similarly, for an initial migration that adds one or more fields (AddField operation), Django checks that all of the respective columns already exist in the database and fake-applies the migration if so. Without --fake-initial, initial migrations are treated no differently from any other migration.

Adding migrations to apps

Adding migrations to new apps is straightforward - they come preconfigured to accept migrations, and so just run makemigrations once you’ve made some changes.

If your app already has models and database tables, and doesn’t have migrations yet (for example, you created it against a previous Django version), you’ll need to convert it to use migrations; this is a simple process:

$ python manage.py makemigrations your_app_label

This will make a new initial migration for your app. Now, run python manage.py migrate --fake-initial, and Django will detect that you have an initial migration and that the tables it wants to create already exist, and will mark the migration as already applied. (Without the migrate --fake-initial flag, the command would error out because the tables it wants to create already exist.)

Note that this only works given two things:

- You have not changed your models since you made their tables. For migrations to work, you must make the initial migration first and then make changes, as Django compares changes against migration files, not the database.

- You have not manually edited your database - Django won’t be able to detect that your database doesn’t match your models, you’ll just get errors when migrations try to modify those tables.

Changed in Django 1.8:
The --fake-initial flag to migrate was added. Previously, Django would always automatically fake-apply initial migrations if it detected that the tables exist.

Historical models

When you run migrations, Django is working from historical versions of your models stored in the migration files. If you write Python code using the RunPython operation, or if you have allow_migrate methods on your database routers, you will be exposed to these versions of your models.

Because it’s impossible to serialize arbitrary Python code, these historical models will not have any custom methods that you have defined. They will, however, have the same fields, relationships, managers (limited to those with use_in_migrations = True) and Meta options (also versioned, so they may be different from your current ones).

Warning

This means that you will NOT have custom save() methods called on objects when you access them in migrations, and you will NOT have any custom constructors or instance methods. Plan appropriately!

References to functions in field options such as upload_to and limit_choices_to and model manager declarations with managers having use_in_migrations = True are serialized in migrations, so the functions and classes will need to be kept around for as long as there is a migration referencing them. Any custom model fields will also need to be kept, since these are imported directly by migrations.

In addition, the base classes of the model are just stored as pointers, so you must always keep base classes around for as long as there is a migration that contains a reference to them. On the plus side, methods and managers from these base classes inherit normally, so if you absolutely need access to these you can opt to move them into a superclass.

Considerations when removing model fields

New in Django 1.8.

Similar to the “references to historical functions” considerations described in the previous section, removing custom model fields from your project or third-party app will cause a problem if they are referenced in old migrations.

To help with this situation, Django provides some model field attributes to assist with model field deprecation using the system checks framework.

Add the system_check_deprecated_details attribute to your model field similar to the following:

class IPAddressField(Field):
system_check_deprecated_details = {
'msg': (
'IPAddressField has been deprecated. Support for it (except '
'in historical migrations) will be removed in Django 1.9.'
),
'hint': 'Use GenericIPAddressField instead.',  # optional
'id': 'fields.W900',  # pick a unique ID for your field.
}

After a deprecation period of your choosing (two or three feature releases for fields in Django itself), change the system_check_deprecated_details attribute to system_check_removed_details and update the dictionary similar to:

class IPAddressField(Field):
system_check_removed_details = {
'msg': (
'IPAddressField has been removed except for support in '
'historical migrations.'
),
'hint': 'Use GenericIPAddressField instead.',
'id': 'fields.E900',  # pick a unique ID for your field.
}

You should keep the field’s methods that are required for it to operate in database migrations such as __init__(), deconstruct(), and get_internal_type(). Keep this stub field for as long as any migrations which reference the field exist. For example, after squashing migrations and removing the old ones, you should be able to remove the field completely.

Data Migrations

As well as changing the database schema, you can also use migrations to change the data in the database itself, in conjunction with the schema if you want.

Migrations that alter data are usually called “data migrations”; they’re best written as separate migrations, sitting alongside your schema migrations.

Django can’t automatically generate data migrations for you, as it does with schema migrations, but it’s not very hard to write them. Migration files in Django are made up of Operations, and the main operation you use for data migrations is RunPython.

To start, make an empty migration file you can work from (Django will put the file in the right place, suggest a name, and add dependencies for you):

python manage.py makemigrations --empty yourappname

Then, open up the file; it should look something like this:

# -*- coding: utf-8 -*-
# Generated by Django A.B on YYYY-MM-DD HH:MM
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):
initial = True

dependencies = [
('yourappname', '0001_initial'),
]

operations = [
]

Now, all you need to do is create a new function and have RunPython use it. RunPython expects a callable as its argument which takes two arguments - the first is an app registry that has the historical versions of all your models loaded into it to match where in your history the migration sits, and the second is a SchemaEditor, which you can use to manually effect database schema changes (but beware, doing this can confuse the migration autodetector!)

Let’s write a simple migration that populates our new name field with the combined values of first_name and last_name (we’ve come to our senses and realized that not everyone has first and last names). All we need to do is use the historical model and iterate over the rows:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def combine_names(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
Person = apps.get_model("yourappname", "Person")
for person in Person.objects.all():
person.name = "%s %s" % (person.first_name, person.last_name)
person.save()

class Migration(migrations.Migration):
initial = True

dependencies = [
('yourappname', '0001_initial'),
]

operations = [
migrations.RunPython(combine_names),
]

Once that’s done, we can just run python manage.py migrate as normal and the data migration will run in place alongside other migrations.

You can pass a second callable to RunPython to run whatever logic you want executed when migrating backwards. If this callable is omitted, migrating backwards will raise an exception.

Accessing models from other apps

When writing a RunPython function that uses models from apps other than the one in which the migration is located, the migration’s dependencies attribute should include the latest migration of each app that is involved, otherwise you may get an error similar to: LookupError: No installed app with label 'myappname' when you try to retrieve the model in the RunPython function using apps.get_model().

In the following example, we have a migration in app1 which needs to use models in app2. We aren’t concerned with the details of move_m1 other than the fact it will need to access models from both apps. Therefore we’ve added a dependency that specifies the last migration of app2:

class Migration(migrations.Migration):

dependencies = [
('app1', '0001_initial'),
# added dependency to enable using models from app2 in move_m1
('app2', '0004_foobar'),
]

operations = [
migrations.RunPython(move_m1),
]

More advanced migrations

If you’re interested in the more advanced migration operations, or want to be able to write your own, see the migration operations reference and the “how-to” on writing migrations.

Squashing migrations

You are encouraged to make migrations freely and not worry about how many you have; the migration code is optimized to deal with hundreds at a time without much slowdown. However, eventually you will want to move back from having several hundred migrations to just a few, and that’s where squashing comes in.

Squashing is the act of reducing an existing set of many migrations down to one (or sometimes a few) migrations which still represent the same changes.

Django does this by taking all of your existing migrations, extracting their Operations and putting them all in sequence, and then running an optimizer over them to try and reduce the length of the list - for example, it knows that CreateModel and DeleteModel cancel each other out, and it knows that AddField can be rolled into CreateModel.

Once the operation sequence has been reduced as much as possible - the amount possible depends on how closely intertwined your models are and if you have any RunSQL or RunPython operations (which can’t be optimized through) - Django will then write it back out into a new set of migration files.

These files are marked to say they replace the previously-squashed migrations, so they can coexist with the old migration files, and Django will intelligently switch between them depending where you are in the history. If you’re still part-way through the set of migrations that you squashed, it will keep using them until it hits the end and then switch to the squashed history, while new installs will just use the new squashed migration and skip all the old ones.

This enables you to squash and not mess up systems currently in production that aren’t fully up-to-date yet. The recommended process is to squash, keeping the old files, commit and release, wait until all systems are upgraded with the new release (or if you’re a third-party project, just ensure your users upgrade releases in order without skipping any), and then remove the old files, commit and do a second release.

The command that backs all this is squashmigrations - just pass it the app label and migration name you want to squash up to, and it’ll get to work:

$ ./manage.py squashmigrations myapp 0004
Will squash the following migrations:
- 0001_initial
- 0002_some_change
- 0003_another_change
- 0004_undo_something
Do you wish to proceed? [yN] y
Optimizing...
Optimized from 12 operations to 7 operations.
Created new squashed migration /home/andrew/Programs/DjangoTest/test/migrations/0001_squashed_0004_undo_somthing.py
You should commit this migration but leave the old ones in place;
the new migration will be used for new installs. Once you are sure
all instances of the codebase have applied the migrations you squashed,
you can delete them.

Note that model interdependencies in Django can get very complex, and squashing may result in migrations that do not run; either mis-optimized (in which case you can try again with --no-optimize, though you should also report an issue), or with a CircularDependencyError, in which case you can manually resolve it.

To manually resolve a CircularDependencyError, break out one of the ForeignKeys in the circular dependency loop into a separate migration, and move the dependency on the other app with it. If you’re unsure, see how makemigrations deals with the problem when asked to create brand new migrations from your models. In a future release of Django, squashmigrations will be updated to attempt to resolve these errors itself.

Once you’ve squashed your migration, you should then commit it alongside the migrations it replaces and distribute this change to all running instances of your application, making sure that they run migrate to store the change in their database.

You must then transition the squashed migration to a normal migration by:

- Deleting all the migration files it replaces.

- Updating all migrations that depend on the deleted migrations to depend on the squashed migration instead.

- Removing the replaces attribute in the Migration class of the squashed migration (this is how Django tells that it is a squashed migration).

Note

Once you’ve squashed a migration, you should not then re-squash that squashed migration until you have fully transitioned it to a normal migration.

Serializing values

Migrations are just Python files containing the old definitions of your models - thus, to write them, Django must take the current state of your models and serialize them out into a file.

While Django can serialize most things, there are some things that we just can’t serialize out into a valid Python representation - there’s no Python standard for how a value can be turned back into code (repr() only works for basic values, and doesn’t specify import paths).

Django can serialize the following:

- int, long, float, bool, str, unicode, bytes, None

- list, set, tuple, dict

- datetime.date, datetime.time, and datetime.datetime instances (include those that are timezone-aware)

- decimal.Decimal instances

- functools.partial instances which have serializable func, args, and keywords values.

- LazyObject instances which wrap a serializable value.

- Any Django field

- Any function or method reference (e.g. datetime.datetime.today) (must be in module’s top-level scope)

- Any class reference (must be in module’s top-level scope)

- Anything with a custom deconstruct() method (see below)

Changed in Django 1.9:
Serialization support for functools.partial and LazyObject instances was added.

Django can serialize the following on Python 3 only:

- Unbound methods used from within the class body (see below)

Django cannot serialize:

- Nested classes

- Arbitrary class instances (e.g. MyClass(4.3, 5.7))

- Lambdas

Due to the fact __qualname__ was only introduced in Python 3, Django can only serialize the following pattern (an unbound method used within the class body) on Python 3, and will fail to serialize a reference to it on Python 2:

class MyModel(models.Model):

def upload_to(self):
return "something dynamic"

my_file = models.FileField(upload_to=upload_to)

If you are using Python 2, we recommend you move your methods for upload_to and similar arguments that accept callables (e.g. default) to live in the main module body, rather than the class body.

Adding a deconstruct() method

You can let Django serialize your own custom class instances by giving the class a deconstruct() method. It takes no arguments, and should return a tuple of three things (path, args, kwargs):

- path should be the Python path to the class, with the class name included as the last part (for example, myapp.custom_things.MyClass). If your class is not available at the top level of a module it is not serializable.

- args should be a list of positional arguments to pass to your class’ __init__ method. Everything in this list should itself be serializable.

- kwargs should be a dict of keyword arguments to pass to your class’ __init__ method. Every value should itself be serializable.

Note

This return value is different from the deconstruct() method for custom fields which returns a tuple of four items.

Django will write out the value as an instantiation of your class with the given arguments, similar to the way it writes out references to Django fields.

To prevent a new migration from being created each time makemigrations is run, you should also add a __eq__() method to the decorated class. This function will be called by Django’s migration framework to detect changes between states.

As long as all of the arguments to your class’ constructor are themselves serializable, you can use the @deconstructible class decorator from django.utils.deconstruct to add the deconstruct() method:

from django.utils.deconstruct import deconstructible

@deconstructible
class MyCustomClass(object):

def __init__(self, foo=1):
self.foo = foo
...

def __eq__(self, other):
return self.foo == other.foo

The decorator adds logic to capture and preserve the arguments on their way into your constructor, and then returns those arguments exactly when deconstruct() is called.

Supporting Python 2 and 3

In order to generate migrations that support both Python 2 and 3, all string literals used in your models and fields (e.g. verbose_name, related_name, etc.), must be consistently either bytestrings or text (unicode) strings in both Python 2 and 3 (rather than bytes in Python 2 and text in Python 3, the default situation for unmarked string literals.) Otherwise running makemigrations under Python 3 will generate spurious new migrations to convert all these string attributes to text.

The easiest way to achieve this is to follow the advice in Django’s Python 3 porting guide and make sure that all your modules begin with from __future__ import unicode_literals, so that all unmarked string literals are always unicode, regardless of Python version. When you add this to an app with existing migrations generated on Python 2, your next run of makemigrations on Python 3 will likely generate many changes as it converts all the bytestring attributes to text strings; this is normal and should only happen once.

Supporting multiple Django versions

If you are the maintainer of a third-party app with models, you may need to ship migrations that support multiple Django versions. In this case, you should always run makemigrations with the lowest Django version you wish to support.

The migrations system will maintain backwards-compatibility according to the same policy as the rest of Django, so migration files generated on Django X.Y should run unchanged on Django X.Y+1. The migrations system does not promise forwards-compatibility, however. New features may be added, and migration files generated with newer versions of Django may not work on older versions.

Upgrading from South

If you already have pre-existing migrations created with South, then the upgrade process to use django.db.migrations is quite simple:

- Ensure all installs are fully up-to-date with their migrations.

- Remove 'south' from INSTALLED_APPS.

- Delete all your (numbered) migration files, but not the directory or __init__.py - make sure you remove the .pyc files too.

- Run python manage.py makemigrations. Django should see the empty migration directories and make new initial migrations in the new format.

- Run python manage.py migrate --fake-initial. Django will see that the tables for the initial migrations already exist and mark them as applied without running them. (Django won’t check that the table schema match your models, just that the right table names exist).

Changed in Django 1.8:
The migrate --fake-initial flag was added. Previously, initial migrations were always automatically fake-applied if existing tables were detected.

Libraries/Third-party Apps

If you are a library or app maintainer, and wish to support both South migrations (for Django 1.6 and below) and Django migrations (for 1.7 and above) you should keep two parallel migration sets in your app, one in each format.

To aid in this, South 1.0 will automatically look for South-format migrations in a south_migrations directory first, before looking in migrations, meaning that users’ projects will transparently use the correct set as long as you put your South migrations in the south_migrations directory and your Django migrations in the migrations directory.

More information is available in the South 1.0 release notes.

See also

The Migrations Operations Reference

Covers the schema operations API, special operations, and writing your own operations.

The Writing Migrations “how-to”

Explains how to structure and write database migrations for different scenarios you might encounter.

Managing files

This document describes Django’s file access APIs for files such as those uploaded by a user. The lower level APIs are general enough that you could use them for other purposes. If you want to handle “static files” (JS, CSS, etc.), see Managing static files (e.g. images, JavaScript, CSS).

By default, Django stores files locally, using the MEDIA_ROOT and MEDIA_URL settings. The examples below assume that you’re using these defaults.

However, Django provides ways to write custom file storage systems that allow you to completely customize where and how Django stores files. The second half of this document describes how these storage systems work.

Using files in models

When you use a FileField or ImageField, Django provides a set of APIs you can use to deal with that file.

Consider the following model, using an ImageField to store a photo:

from django.db import models

class Car(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=5, decimal_places=2)
photo = models.ImageField(upload_to='cars')

Any Car instance will have a photo attribute that you can use to get at the details of the attached photo:

>>> car = Car.objects.get(name="57 Chevy")
>>> car.photo
<ImageFieldFile: chevy.jpg>
>>> car.photo.name
'cars/chevy.jpg'
>>> car.photo.path
'/media/cars/chevy.jpg'
>>> car.photo.url
'http://media.example.com/cars/chevy.jpg'

This object – car.photo in the example – is a File object, which means it has all the methods and attributes described below.

Note

The file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.

For example, you can change the file name by setting the file’s name to a path relative to the file storage’s location (MEDIA_ROOT if you are using the default FileSystemStorage):

>>> import os
>>> from django.conf import settings
>>> initial_path = car.photo.path
>>> car.photo.name = 'cars/chevy_ii.jpg'
>>> new_path = settings.MEDIA_ROOT + car.photo.name
>>> # Move the file on the filesystem
>>> os.rename(initial_path, new_path)
>>> car.save()
>>> car.photo.path
'/media/cars/chevy_ii.jpg'
>>> car.photo.path == new_path
True

The File object

Internally, Django uses a django.core.files.File instance any time it needs to represent a file.

Most of the time you’ll simply use a File that Django’s given you (i.e. a file attached to a model as above, or perhaps an uploaded file).

If you need to construct a File yourself, the easiest way is to create one using a Python built-in file object:

>>> from django.core.files import File

# Create a Python file object using open()
>>> f = open('/path/to/hello.world', 'w')
>>> myfile = File(f)

Now you can use any of the documented attributes and methods of the File class.

Be aware that files created in this way are not automatically closed. The following approach may be used to close files automatically:

>>> from django.core.files import File

# Create a Python file object using open() and the with statement
>>> with open('/path/to/hello.world', 'w') as f:
...     myfile = File(f)
...     myfile.write('Hello World')
...
>>> myfile.closed
True
>>> f.closed
True

Closing files is especially important when accessing file fields in a loop over a large number of objects. If files are not manually closed after accessing them, the risk of running out of file descriptors may arise. This may lead to the following error:

IOError: [Errno 24] Too many open files

File storage

Behind the scenes, Django delegates decisions about how and where to store files to a file storage system. This is the object that actually understands things like file systems, opening and reading files, etc.

Django’s default file storage is given by the DEFAULT_FILE_STORAGE setting; if you don’t explicitly provide a storage system, this is the one that will be used.

See below for details of the built-in default file storage system, and see Writing a custom storage system for information on writing your own file storage system.

Storage objects

Though most of the time you’ll want to use a File object (which delegates to the proper storage for that file), you can use file storage systems directly. You can create an instance of some custom file storage class, or – often more useful – you can use the global default storage system:

>>> from django.core.files.storage import default_storage
>>> from django.core.files.base import ContentFile

>>> path = default_storage.save('/path/to/file', ContentFile('new content'))
>>> path
'/path/to/file'

>>> default_storage.size(path)
11
>>> default_storage.open(path).read()
'new content'

>>> default_storage.delete(path)
>>> default_storage.exists(path)
False

See File storage API for the file storage API.

The built-in filesystem storage class

Django ships with a django.core.files.storage.FileSystemStorage class which implements basic local filesystem file storage.

For example, the following code will store uploaded files under /media/photos regardless of what your MEDIA_ROOT setting is:

from django.db import models
from django.core.files.storage import FileSystemStorage

fs = FileSystemStorage(location='/media/photos')

class Car(models.Model):
...
photo = models.ImageField(storage=fs)

Custom storage systems work the same way: you can pass them in as the storage argument to a FileField.

Testing in Django

Automated testing is an extremely useful bug-killing tool for the modern Web developer. You can use a collection of tests – a test suite – to solve, or avoid, a number of problems:

- When you’re writing new code, you can use tests to validate your code works as expected.

- When you’re refactoring or modifying old code, you can use tests to ensure your changes haven’t affected your application’s behavior unexpectedly.

Testing a Web application is a complex task, because a Web application is made of several layers of logic – from HTTP-level request handling, to form validation and processing, to template rendering. With Django’s test-execution framework and assorted utilities, you can simulate requests, insert test data, inspect your application’s output and generally verify your code is doing what it should be doing.

The best part is, it’s really easy.

The preferred way to write tests in Django is using the unittest module built in to the Python standard library. This is covered in detail in the Writing and running tests document.

You can also use any other Python test framework; Django provides an API and tools for that kind of integration. They are described in the Using different testing frameworks section of Advanced testing topics.

- Writing and running tests

- Testing tools

- Advanced testing topics

Writing and running tests

See also

The testing tutorial, the testing tools reference, and the advanced testing topics.

This document is split into two primary sections. First, we explain how to write tests with Django. Then, we explain how to run them.

Writing tests

Django’s unit tests use a Python standard library module: unittest. This module defines tests using a class-based approach.

Here is an example which subclasses from django.test.TestCase, which is a subclass of unittest.TestCase that runs each test inside a transaction to provide isolation:

from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
def setUp(self):
Animal.objects.create(name="lion", sound="roar")
Animal.objects.create(name="cat", sound="meow")

def test_animals_can_speak(self):
"""Animals that can speak are correctly identified"""
lion = Animal.objects.get(name="lion")
cat = Animal.objects.get(name="cat")
self.assertEqual(lion.speak(), 'The lion says "roar"')
self.assertEqual(cat.speak(), 'The cat says "meow"')

When you run your tests, the default behavior of the test utility is to find all the test cases (that is, subclasses of unittest.TestCase) in any file whose name begins with test, automatically build a test suite out of those test cases, and run that suite.

For more details about unittest, see the Python documentation.

Where should the tests live?

The default startapp template creates a tests.py file in the new application. This might be fine if you only have a few tests, but as your test suite grows you’ll likely want to restructure it into a tests package so you can split your tests into different submodules such as test_models.py, test_views.py, test_forms.py, etc. Feel free to pick whatever organizational scheme you like.

See also Using the Django test runner to test reusable applications.

Warning

If your tests rely on database access such as creating or querying models, be sure to create your test classes as subclasses of django.test.TestCase rather than unittest.TestCase.

Using unittest.TestCase avoids the cost of running each test in a transaction and flushing the database, but if your tests interact with the database their behavior will vary based on the order that the test runner executes them. This can lead to unit tests that pass when run in isolation but fail when run in a suite.

Running tests

Once you’ve written tests, run them using the test command of your project’s manage.py utility:

$ ./manage.py test

Test discovery is based on the unittest module’s built-in test discovery. By default, this will discover tests in any file named “test*.py” under the current working directory.

You can specify particular tests to run by supplying any number of “test labels” to ./manage.py test. Each test label can be a full Python dotted path to a package, module, TestCase subclass, or test method. For instance:

# Run all the tests in the animals.tests module
$ ./manage.py test animals.tests

# Run all the tests found within the 'animals' package
$ ./manage.py test animals

# Run just one test case
$ ./manage.py test animals.tests.AnimalTestCase

# Run just one test method
$ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak

You can also provide a path to a directory to discover tests below that directory:

$ ./manage.py test animals/

You can specify a custom filename pattern match using the -p (or --pattern) option, if your test files are named differently from the test*.py pattern:

$ ./manage.py test --pattern="tests_*.py"

If you press Ctrl-C while the tests are running, the test runner will wait for the currently running test to complete and then exit gracefully. During a graceful exit the test runner will output details of any test failures, report on how many tests were run and how many errors and failures were encountered, and destroy any test databases as usual. Thus pressing Ctrl-C can be very useful if you forget to pass the --failfast option, notice that some tests are unexpectedly failing and want to get details on the failures without waiting for the full test run to complete.

If you do not want to wait for the currently running test to finish, you can press Ctrl-C a second time and the test run will halt immediately, but not gracefully. No details of the tests run before the interruption will be reported, and any test databases created by the run will not be destroyed.

Test with warnings enabled

It’s a good idea to run your tests with Python warnings enabled: python -Wall manage.py test. The -Wall flag tells Python to display deprecation warnings. Django, like many other Python libraries, uses these warnings to flag when features are going away. It also might flag areas in your code that aren’t strictly wrong but could benefit from a better implementation.

The test database

Tests that require a database (namely, model tests) will not use your “real” (production) database. Separate, blank databases are created for the tests.

Regardless of whether the tests pass or fail, the test databases are destroyed when all the tests have been executed.

New in Django 1.8:
You can prevent the test databases from being destroyed by using the test --keepdb flag. This preserves the test database between runs. If the database does not exist, it will first be created. Any migrations will also be applied in order to keep it up to date.

The default test database names are created by prepending test_ to the value of each NAME in DATABASES. When using SQLite, the tests will use an in-memory database by default (i.e., the database will be created in memory, bypassing the filesystem entirely!). The TEST dictionary in DATABASES offers a number of settings to configure your test database. For example, if you want to use a different database name, specify NAME in the TEST dictionary for any given database in DATABASES.

On PostgreSQL, USER will also need read access to the built-in postgres database.

Aside from using a separate database, the test runner will otherwise use all of the same database settings you have in your settings file: ENGINE, USER, HOST, etc. The test database is created by the user specified by USER, so you’ll need to make sure that the given user account has sufficient privileges to create a new database on the system.

For fine-grained control over the character encoding of your test database, use the CHARSET TEST option. If you’re using MySQL, you can also use the COLLATION option to control the particular collation used by the test database. See the settings documentation for details of these and other advanced settings.

If using an SQLite in-memory database with Python 3.4+ and SQLite 3.7.13+, shared cache will be enabled, so you can write tests with ability to share the database between threads.

New in Django 1.8:
The ability to use SQLite with a shared cache as described above was added.

Finding data from your production database when running tests?

If your code attempts to access the database when its modules are compiled, this will occur before the test database is set up, with potentially unexpected results. For example, if you have a database query in module-level code and a real database exists, production data could pollute your tests. It is a bad idea to have such import-time database queries in your code anyway - rewrite your code so that it doesn’t do this.

This also applies to customized implementations of ready().

See also

The advanced multi-db testing topics.

Order in which tests are executed

In order to guarantee that all TestCase code starts with a clean database, the Django test runner reorders tests in the following way:

- All TestCase subclasses are run first.

- Then, all other Django-based tests (test cases based on SimpleTestCase, including TransactionTestCase) are run with no particular ordering guaranteed nor enforced among them.

- Then any other unittest.TestCase tests (including doctests) that may alter the database without restoring it to its original state are run.

Note

The new ordering of tests may reveal unexpected dependencies on test case ordering. This is the case with doctests that relied on state left in the database by a given TransactionTestCase test, they must be updated to be able to run independently.

New in Django 1.8:
You may reverse the execution order inside groups by passing the test --reverse option. This can help ensure your tests are independent from each other.

Rollback emulation

Any initial data loaded in migrations will only be available in TestCase tests and not in TransactionTestCase tests, and additionally only on backends where transactions are supported (the most important exception being MyISAM). This is also true for tests which rely on TransactionTestCase such as LiveServerTestCase and StaticLiveServerTestCase.

Django can reload that data for you on a per-testcase basis by setting the serialized_rollback option to True in the body of the TestCase or TransactionTestCase, but note that this will slow down that test suite by approximately 3x.

Third-party apps or those developing against MyISAM will need to set this; in general, however, you should be developing your own projects against a transactional database and be using TestCase for most tests, and thus not need this setting.

The initial serialization is usually very quick, but if you wish to exclude some apps from this process (and speed up test runs slightly), you may add those apps to TEST_NON_SERIALIZED_APPS.

Changed in Django 1.9.

To prevent serialized data from being loaded twice, setting serialized_rollback=True disables the post_migrate signal when flushing the test database.

Other test conditions

Regardless of the value of the DEBUG setting in your configuration file, all Django tests run with DEBUG=False. This is to ensure that the observed output of your code matches what will be seen in a production setting.

Caches are not cleared after each test, and running “manage.py test fooapp” can insert data from the tests into the cache of a live system if you run your tests in production because, unlike databases, a separate “test cache” is not used. This behavior may change in the future.

Understanding the test output

When you run your tests, you’ll see a number of messages as the test runner prepares itself. You can control the level of detail of these messages with the verbosity option on the command line:

Creating test database...
Creating table myapp_animal
Creating table myapp_mineral

This tells you that the test runner is creating a test database, as described in the previous section.

Once the test database has been created, Django will run your tests. If everything goes well, you’ll see something like this:

----------------------------------------------------------------------
Ran 22 tests in 0.221s

OK

If there are test failures, however, you’ll see full details about which tests failed:

======================================================================
FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_poll
self.assertEqual(future_poll.was_published_recently(), False)
AssertionError: True != False

----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (failures=1)

A full explanation of this error output is beyond the scope of this document, but it’s pretty intuitive. You can consult the documentation of Python’s unittest library for details.

Note that the return code for the test-runner script is 1 for any number of failed and erroneous tests. If all the tests pass, the return code is 0. This feature is useful if you’re using the test-runner script in a shell script and need to test for success or failure at that level.

Speeding up the tests

Running tests in parallel

As long as your tests are properly isolated, you can run them in parallel to gain a speed up on multi-core hardware. See test --parallel.

Password hashing

The default password hasher is rather slow by design. If you’re authenticating many users in your tests, you may want to use a custom settings file and set the PASSWORD_HASHERS setting to a faster hashing algorithm:

PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]

Don’t forget to also include in PASSWORD_HASHERS any hashing algorithm used in fixtures, if any.

Testing tools

Django provides a small set of tools that come in handy when writing tests.

The test client

The test client is a Python class that acts as a dummy Web browser, allowing you to test your views and interact with your Django-powered application programmatically.

Some of the things you can do with the test client are:

- Simulate GET and POST requests on a URL and observe the response – everything from low-level HTTP (result headers and status codes) to page content.

- See the chain of redirects (if any) and check the URL and status code at each step.

- Test that a given request is rendered by a given Django template, with a template context that contains certain values.

Note that the test client is not intended to be a replacement for Selenium or other “in-browser” frameworks. Django’s test client has a different focus. In short:

- Use Django’s test client to establish that the correct template is being rendered and that the template is passed the correct context data.

- Use in-browser frameworks like Selenium to test rendered HTML and the behavior of Web pages, namely JavaScript functionality. Django also provides special support for those frameworks; see the section on LiveServerTestCase for more details.

A comprehensive test suite should use a combination of both test types.

Overview and a quick example

To use the test client, instantiate django.test.Client and retrieve Web pages:

>>> from django.test import Client
>>> c = Client()
>>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
>>> response.status_code
200
>>> response = c.get('/customer/details/')
>>> response.content
b'<!DOCTYPE html...'

As this example suggests, you can instantiate Client from within a session of the Python interactive interpreter.

Note a few important things about how the test client works:

- The test client does not require the Web server to be running. In fact, it will run just fine with no Web server running at all! That’s because it avoids the overhead of HTTP and deals directly with the Django framework. This helps make the unit tests run quickly.

- When retrieving pages, remember to specify the path of the URL, not the whole domain. For example, this is correct:

>>> c.get('/login/')

This is incorrect:

>>> c.get('https://www.example.com/login/')

The test client is not capable of retrieving Web pages that are not powered by your Django project. If you need to retrieve other Web pages, use a Python standard library module such as urllib.

- To resolve URLs, the test client uses whatever URLconf is pointed-to by your ROOT_URLCONF setting.

- Although the above example would work in the Python interactive interpreter, some of the test client’s functionality, notably the template-related functionality, is only available while tests are running.

The reason for this is that Django’s test runner performs a bit of black magic in order to determine which template was loaded by a given view. This black magic (essentially a patching of Django’s template system in memory) only happens during test running.

- By default, the test client will disable any CSRF checks performed by your site.

If, for some reason, you want the test client to perform CSRF checks, you can create an instance of the test client that enforces CSRF checks. To do this, pass in the enforce_csrf_checks argument when you construct your client:

>>> from django.test import Client
>>> csrf_client = Client(enforce_csrf_checks=True)

Making requests

Use the django.test.Client class to make requests.

class Client(enforce_csrf_checks=False, **defaults)[source]

It requires no arguments at time of construction. However, you can use keywords arguments to specify some default headers. For example, this will send a User-Agent HTTP header in each request:

>>> c = Client(HTTP_USER_AGENT='Mozilla/5.0')

The values from the extra keywords arguments passed to get(), post(), etc. have precedence over the defaults passed to the class constructor.

The enforce_csrf_checks argument can be used to test CSRF protection (see above).

Once you have a Client instance, you can call any of the following methods:

get(path, data=None, follow=False, secure=False, **extra)[source]

Makes a GET request on the provided path and returns a Response object, which is documented below.

The key-value pairs in the data dictionary are used to create a GET data payload. For example:

>>> c = Client()
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7})

...will result in the evaluation of a GET request equivalent to:

/customers/details/?name=fred&age=7

The extra keyword arguments parameter can be used to specify headers to be sent in the request. For example:

>>> c = Client()
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7},
...       HTTP_X_REQUESTED_WITH='XMLHttpRequest')

...will send the HTTP header HTTP_X_REQUESTED_WITH to the details view, which is a good way to test code paths that use the django.http.HttpRequest.is_ajax() method.

CGI specification

The headers sent via **extra should follow CGI specification. For example, emulating a different “Host” header as sent in the HTTP request from the browser to the server should be passed as HTTP_HOST.

If you already have the GET arguments in URL-encoded form, you can use that encoding instead of using the data argument. For example, the previous GET request could also be posed as:

>>> c = Client()
>>> c.get('/customers/details/?name=fred&age=7')

If you provide a URL with both an encoded GET data and a data argument, the data argument will take precedence.

If you set follow to True the client will follow any redirects and a redirect_chain attribute will be set in the response object containing tuples of the intermediate urls and status codes.

If you had a URL /redirect_me/ that redirected to /next/, that redirected to /final/, this is what you’d see:

>>> response = c.get('/redirect_me/', follow=True)
>>> response.redirect_chain
[('http://testserver/next/', 302), ('http://testserver/final/', 302)]

If you set secure to True the client will emulate an HTTPS request.

post(path, data=None, content_type=MULTIPART_CONTENT, follow=False, secure=False, **extra)[source]

Makes a POST request on the provided path and returns a Response object, which is documented below.

The key-value pairs in the data dictionary are used to submit POST data. For example:

>>> c = Client()
>>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})

...will result in the evaluation of a POST request to this URL:

/login/

...with this POST data:

name=fred&passwd=secret

If you provide content_type (e.g. text/xml for an XML payload), the contents of data will be sent as-is in the POST request, using content_type in the HTTP Content-Type header.

If you don’t provide a value for content_type, the values in data will be transmitted with a content type of multipart/form-data. In this case, the key-value pairs in data will be encoded as a multipart message and used to create the POST data payload.

To submit multiple values for a given key – for example, to specify the selections for a <select multiple> – provide the values as a list or tuple for the required key. For example, this value of data would submit three selected values for the field named choices:

{'choices': ('a', 'b', 'd')}

Submitting files is a special case. To POST a file, you need only provide the file field name as a key, and a file handle to the file you wish to upload as a value. For example:

>>> c = Client()
>>> with open('wishlist.doc') as fp:
...     c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})

(The name attachment here is not relevant; use whatever name your file-processing code expects.)

You may also provide any file-like object (e.g., StringIO or BytesIO) as a file handle.

New in Django 1.8:
The ability to use a file-like object was added.

Note that if you wish to use the same file handle for multiple post() calls then you will need to manually reset the file pointer between posts. The easiest way to do this is to manually close the file after it has been provided to post(), as demonstrated above.

You should also ensure that the file is opened in a way that allows the data to be read. If your file contains binary data such as an image, this means you will need to open the file in rb (read binary) mode.

The extra argument acts the same as for Client.get().

If the URL you request with a POST contains encoded parameters, these parameters will be made available in the request.GET data. For example, if you were to make the request:

>>> c.post('/login/?visitor=true', {'name': 'fred', 'passwd': 'secret'})

... the view handling this request could interrogate request.POST to retrieve the username and password, and could interrogate request.GET to determine if the user was a visitor.

If you set follow to True the client will follow any redirects and a redirect_chain attribute will be set in the response object containing tuples of the intermediate urls and status codes.

If you set secure to True the client will emulate an HTTPS request.

head(path, data=None, follow=False, secure=False, **extra)[source]

Makes a HEAD request on the provided path and returns a Response object. This method works just like Client.get(), including the follow, secure and extra arguments, except it does not return a message body.

options(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)[source]

Makes an OPTIONS request on the provided path and returns a Response object. Useful for testing RESTful interfaces.

When data is provided, it is used as the request body, and a Content-Type header is set to content_type.

The follow, secure and extra arguments act the same as for Client.get().

put(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)[source]

Makes a PUT request on the provided path and returns a Response object. Useful for testing RESTful interfaces.

When data is provided, it is used as the request body, and a Content-Type header is set to content_type.

The follow, secure and extra arguments act the same as for Client.get().

patch(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)[source]

Makes a PATCH request on the provided path and returns a Response object. Useful for testing RESTful interfaces.

The follow, secure and extra arguments act the same as for Client.get().

delete(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra)[source]

Makes a DELETE request on the provided path and returns a Response object. Useful for testing RESTful interfaces.

When data is provided, it is used as the request body, and a Content-Type header is set to content_type.

The follow, secure and extra arguments act the same as for Client.get().

trace(path, follow=False, secure=False, **extra)[source]

New in Django 1.8.

Makes a TRACE request on the provided path and returns a Response object. Useful for simulating diagnostic probes.

Unlike the other request methods, data is not provided as a keyword parameter in order to comply with RFC 7231#section-4.3.8, which mandates that TRACE requests must not have a body.

The follow, secure, and extra arguments act the same as for Client.get().

login(**credentials)[source]

If your site uses Django’s authentication system and you deal with logging in users, you can use the test client’s login() method to simulate the effect of a user logging into the site.

Inactive users (is_active=False) are not permitted to login as this method is meant to be equivalent to the login() view which uses AuthenticationForm and therefore defaults to rejecting users who are inactive.

After you call this method, the test client will have all the cookies and session data required to pass any login-based tests that may form part of a view.

The format of the credentials argument depends on which authentication backend you’re using (which is configured by your AUTHENTICATION_BACKENDS setting). If you’re using the standard authentication backend provided by Django (ModelBackend), credentials should be the user’s username and password, provided as keyword arguments:

>>> c = Client()
>>> c.login(username='fred', password='secret')

# Now you can access a view that's only available to logged-in users.

If you’re using a different authentication backend, this method may require different credentials. It requires whichever credentials are required by your backend’s authenticate() method.

login() returns True if it the credentials were accepted and login was successful.

Finally, you’ll need to remember to create user accounts before you can use this method. As we explained above, the test runner is executed using a test database, which contains no users by default. As a result, user accounts that are valid on your production site will not work under test conditions. You’ll need to create users as part of the test suite – either manually (using the Django model API) or with a test fixture. Remember that if you want your test user to have a password, you can’t set the user’s password by setting the password attribute directly – you must use the set_password() function to store a correctly hashed password. Alternatively, you can use the create_user() helper method to create a new user with a correctly hashed password.

force_login(user, backend=None)[source]

New in Django 1.9.

If your site uses Django’s authentication system, you can use the force_login() method to simulate the effect of a user logging into the site. Use this method instead of login() when a test requires a user be logged in and the details of how a user logged in aren’t important.

Unlike login(), this method skips the authentication and verification steps: inactive users (is_active=False) are permitted to login and the user’s credentials don’t need to be provided.

The user will have its backend attribute set to the value of the backend argument (which should be a dotted Python path string), or to settings.AUTHENTICATION_BACKENDS[0] if a value isn’t provided. The authenticate() function called by login() normally annotates the user like this.

This method is faster than login() since the expensive password hashing algorithms are bypassed. Also, you can speed up login() by using a weaker hasher while testing.

logout()[source]

If your site uses Django’s authentication system, the logout() method can be used to simulate the effect of a user logging out of your site.

After you call this method, the test client will have all the cookies and session data cleared to defaults. Subsequent requests will appear to come from an AnonymousUser.

Testing responses

The get() and post() methods both return a Response object. This Response object is not the same as the HttpResponse object returned by Django views; the test response object has some additional data useful for test code to verify.

Specifically, a Response object has the following attributes:

class Response

client

The test client that was used to make the request that resulted in the response.

content

The body of the response, as a bytestring. This is the final page content as rendered by the view, or any error message.

context

The template Context instance that was used to render the template that produced the response content.

If the rendered page used multiple templates, then context will be a list of Context objects, in the order in which they were rendered.

Regardless of the number of templates used during rendering, you can retrieve context values using the [] operator. For example, the context variable name could be retrieved using:

>>> response = client.get('/foo/')
>>> response.context['name']
'Arthur'

Not using Django templates?

This attribute is only populated when using the DjangoTemplates backend. If you’re using another template engine, context_data may be a suitable alternative on responses with that attribute.

json(**kwargs)

New in Django 1.9.

The body of the response, parsed as JSON. Extra keyword arguments are passed to json.loads(). For example:

>>> response = client.get('/foo/')
>>> response.json()['name']
'Arthur'

If the Content-Type header is not "application/json", then a ValueError will be raised when trying to parse the response.

request

The request data that stimulated the response.

wsgi_request

The WSGIRequest instance generated by the test handler that generated the response.

status_code

The HTTP status of the response, as an integer. For a full list of defined codes, see the IANA status code registry.

templates

A list of Template instances used to render the final content, in the order they were rendered. For each template in the list, use template.name to get the template’s file name, if the template was loaded from a file. (The name is a string such as 'admin/index.html'.)

Not using Django templates?

This attribute is only populated when using the DjangoTemplates backend. If you’re using another template engine, template_name may be a suitable alternative if you only need the name of the template used for rendering.

resolver_match

New in Django 1.8:
An instance of ResolverMatch for the response. You can use the func attribute, for example, to verify the view that served the response:

# my_view here is a function based view
self.assertEqual(response.resolver_match.func, my_view)

# class-based views need to be compared by name, as the functions
# generated by as_view() won't be equal
self.assertEqual(response.resolver_match.func.__name__, MyView.as_view().__name__)

If the given URL is not found, accessing this attribute will raise a Resolver404 exception.

You can also use dictionary syntax on the response object to query the value of any settings in the HTTP headers. For example, you could determine the content type of a response using response['Content-Type'].

Exceptions

If you point the test client at a view that raises an exception, that exception will be visible in the test case. You can then use a standard try ... except block or assertRaises() to test for exceptions.

The only exceptions that are not visible to the test client are Http404, PermissionDenied, SystemExit, and SuspiciousOperation. Django catches these exceptions internally and converts them into the appropriate HTTP response codes. In these cases, you can check response.status_code in your test.

Persistent state

The test client is stateful. If a response returns a cookie, then that cookie will be stored in the test client and sent with all subsequent get() and post() requests.

Expiration policies for these cookies are not followed. If you want a cookie to expire, either delete it manually or create a new Client instance (which will effectively delete all cookies).

A test client has two attributes that store persistent state information. You can access these properties as part of a test condition.

Client.cookies

A Python SimpleCookie object, containing the current values of all the client cookies. See the documentation of the http.cookies module for more.

Client.session

A dictionary-like object containing session information. See the session documentation for full details.

To modify the session and then save it, it must be stored in a variable first (because a new SessionStore is created every time this property is accessed):

def test_something(self):
session = self.client.session
session['somekey'] = 'test'
session.save()

Example

The following is a simple unit test using the test client:

import unittest
from django.test import Client

class SimpleTest(unittest.TestCase):
def setUp(self):
# Every test needs a client.
self.client = Client()

def test_details(self):
# Issue a GET request.
response = self.client.get('/customer/details/')

# Check that the response is 200 OK.
self.assertEqual(response.status_code, 200)

# Check that the rendered context contains 5 customers.
self.assertEqual(len(response.context['customers']), 5)

See also

django.test.RequestFactory

Provided test case classes

Normal Python unit test classes extend a base class of unittest.TestCase. Django provides a few extensions of this base class:

Hierarchy of Django unit testing classes

Converting a normal unittest.TestCase to any of the subclasses is easy: change the base class of your test from unittest.TestCase to the subclass. All of the standard Python unit test functionality will be available, and it will be augmented with some useful additions as described in each section below.

SimpleTestCase

class SimpleTestCase[source]

A subclass of unittest.TestCase that adds this functionality:

- Some useful assertions like:

- Checking that a callable raises a certain exception.

- Testing form field rendering and error treatment.

- Testing HTML responses for the presence/lack of a given fragment.

- Verifying that a template has/hasn't been used to generate a given response content.

- Verifying a HTTP redirect is performed by the app.

- Robustly testing two HTML fragments for equality/inequality or containment.

- Robustly testing two XML fragments for equality/inequality.

- Robustly testing two JSON fragments for equality.

- The ability to run tests with modified settings.

- Using the client Client.

- Custom test-time URL maps.

If your tests make any database queries, use subclasses TransactionTestCase or TestCase.

SimpleTestCase.allow_database_queries

New in Django 1.9.

SimpleTestCase disallows database queries by default. This helps to avoid executing write queries which will affect other tests since each SimpleTestCase test isn’t run in a transaction. If you aren’t concerned about this problem, you can disable this behavior by setting the allow_database_queries class attribute to True on your test class.

Warning

SimpleTestCase and its subclasses (e.g. TestCase, ...) rely on setUpClass() and tearDownClass() to perform some class-wide initialization (e.g. overriding settings). If you need to override those methods, don’t forget to call the super implementation:

class MyTestCase(TestCase):

@classmethod
def setUpClass(cls):
super(MyTestCase, cls).setUpClass()
...

@classmethod
def tearDownClass(cls):
...
super(MyTestCase, cls).tearDownClass()

Be sure to account for Python’s behavior if an exception is raised during setUpClass(). If that happens, neither the tests in the class nor tearDownClass() are run. In the case of django.test.TestCase, this will leak the transaction created in super() which results in various symptoms including a segmentation fault on some platforms (reported on OS X). If you want to intentionally raise an exception such as unittest.SkipTest in setUpClass(), be sure to do it before calling super() to avoid this.

TransactionTestCase

class TransactionTestCase[source]

TransactionTestCase inherits from SimpleTestCase to add some database-specific features:

- Resetting the database to a known state at the beginning of each test to ease testing and using the ORM.

- Database fixtures.

- Test skipping based on database backend features.

- The remaining specialized assert* methods.

Django’s TestCase class is a more commonly used subclass of TransactionTestCase that makes use of database transaction facilities to speed up the process of resetting the database to a known state at the beginning of each test. A consequence of this, however, is that some database behaviors cannot be tested within a Django TestCase class. For instance, you cannot test that a block of code is executing within a transaction, as is required when using select_for_update(). In those cases, you should use TransactionTestCase.

Changed in Django 1.8:
In older versions of Django, the effects of transaction commit and rollback could not be tested within a TestCase. With the completion of the deprecation cycle of the old-style transaction management in Django 1.8, transaction management commands (e.g. transaction.commit()) are no longer disabled within TestCase.

TransactionTestCase and TestCase are identical except for the manner in which the database is reset to a known state and the ability for test code to test the effects of commit and rollback:

- A TransactionTestCase resets the database after the test runs by truncating all tables. A TransactionTestCase may call commit and rollback and observe the effects of these calls on the database.

- A TestCase, on the other hand, does not truncate tables after a test. Instead, it encloses the test code in a database transaction that is rolled back at the end of the test. This guarantees that the rollback at the end of the test restores the database to its initial state.

Warning

TestCase running on a database that does not support rollback (e.g. MySQL with the MyISAM storage engine), and all instances of TransactionTestCase, will roll back at the end of the test by deleting all data from the test database.

Apps will not see their data reloaded; if you need this functionality (for example, third-party apps should enable this) you can set serialized_rollback = True inside the TestCase body.

TestCase

class TestCase[source]

This is the most common class to use for writing tests in Django. It inherits from TransactionTestCase (and by extension SimpleTestCase). If your Django application doesn’t use a database, use SimpleTestCase.

The class:

- Wraps the tests within two nested atomic() blocks: one for the whole class and one for each test. Therefore, if you want to test some specific database transaction behavior, use TransactionTestCase.

It also provides an additional method:

classmethod TestCase.setUpTestData()[source]

New in Django 1.8.

The class-level atomic block described above allows the creation of initial data at the class level, once for the whole TestCase. This technique allows for faster tests as compared to using setUp().

For example:

from django.test import TestCase

class MyTests(TestCase):
@classmethod
def setUpTestData(cls):
# Set up data for the whole TestCase
cls.foo = Foo.objects.create(bar="Test")
...

def test1(self):
# Some test using self.foo
...

def test2(self):
# Some other test using self.foo
...

Note that if the tests are run on a database with no transaction support (for instance, MySQL with the MyISAM engine), setUpTestData() will be called before each test, negating the speed benefits.

Be careful not to modify any objects created in setUpTestData() in your test methods. Modifications to in-memory objects from setup work done at the class level will persist between test methods. If you do need to modify them, you could reload them in the setUp() method with refresh_from_db(), for example.

LiveServerTestCase

class LiveServerTestCase[source]

LiveServerTestCase does basically the same as TransactionTestCase with one extra feature: it launches a live Django server in the background on setup, and shuts it down on teardown. This allows the use of automated test clients other than the Django dummy client such as, for example, the Selenium client, to execute a series of functional tests inside a browser and simulate a real user’s actions.

By default the live server listens on localhost and picks the first available port in the 8081-8179 range. Its full URL can be accessed with self.live_server_url during the tests.

Changed in Django 1.9:
In earlier versions, the live server’s default address was always 'localhost:8081'.

If you’d like to select another address, you may pass a different one using the test --liveserver option, for example:

$ ./manage.py test --liveserver=localhost:8082

Changed in Django 1.9:
In older versions live_server_url could only be accessed from an instance. It now is a class property and can be accessed from class methods like setUpClass().

Another way of changing the default server address is by setting the DJANGO_LIVE_TEST_SERVER_ADDRESS environment variable somewhere in your code (for example, in a custom test runner):

import os
os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = 'localhost:8082'

In the case where the tests are run by multiple processes in parallel (for example, in the context of several simultaneous continuous integration builds), the processes will compete for the same address, and therefore your tests might randomly fail with an “Address already in use” error. To avoid this problem, you can pass a comma-separated list of ports or ranges of ports (at least as many as the number of potential parallel processes). For example:

$ ./manage.py test --liveserver=localhost:8082,8090-8100,9000-9200,7041

Then, during test execution, each new live test server will try every specified port until it finds one that is free and takes it.

To demonstrate how to use LiveServerTestCase, let’s write a simple Selenium test. First of all, you need to install the selenium package into your Python path:

$ pip install selenium

Then, add a LiveServerTestCase-based test to your app’s tests module (for example: myapp/tests.py). For this example, we’ll assume you’re using the staticfiles app and want to have static files served during the execution of your tests similar to what we get at development time with DEBUG=True, i.e. without having to collect them using collectstatic. We’ll use the StaticLiveServerTestCase subclass which provides that functionality. Replace it with django.test.LiveServerTestCase if you don’t need that.

The code for this test may look as follows:

from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium.webdriver.firefox.webdriver import WebDriver

class MySeleniumTests(StaticLiveServerTestCase):
fixtures = ['user-data.json']

@classmethod
def setUpClass(cls):
super(MySeleniumTests, cls).setUpClass()
cls.selenium = WebDriver()

@classmethod
def tearDownClass(cls):
cls.selenium.quit()
super(MySeleniumTests, cls).tearDownClass()

def test_login(self):
self.selenium.get('%s%s' % (self.live_server_url, '/login/'))
username_input = self.selenium.find_element_by_name("username")
username_input.send_keys('myuser')
password_input = self.selenium.find_element_by_name("password")
password_input.send_keys('secret')
self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()

Finally, you may run the test as follows:

$ ./manage.py test myapp.tests.MySeleniumTests.test_login

This example will automatically open Firefox then go to the login page, enter the credentials and press the “Log in” button. Selenium offers other drivers in case you do not have Firefox installed or wish to use another browser. The example above is just a tiny fraction of what the Selenium client can do; check out the full reference for more details.

Note

When using an in-memory SQLite database to run the tests, the same database connection will be shared by two threads in parallel: the thread in which the live server is run and the thread in which the test case is run. It’s important to prevent simultaneous database queries via this shared connection by the two threads, as that may sometimes randomly cause the tests to fail. So you need to ensure that the two threads don’t access the database at the same time. In particular, this means that in some cases (for example, just after clicking a link or submitting a form), you might need to check that a response is received by Selenium and that the next page is loaded before proceeding with further test execution. Do this, for example, by making Selenium wait until the <body> HTML tag is found in the response (requires Selenium > 2.13):

def test_login(self):
from selenium.webdriver.support.wait import WebDriverWait
timeout = 2
...
self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
# Wait until the response is received
WebDriverWait(self.selenium, timeout).until(
lambda driver: driver.find_element_by_tag_name('body'))

The tricky thing here is that there’s really no such thing as a “page load,” especially in modern Web apps that generate HTML dynamically after the server generates the initial document. So, simply checking for the presence of <body> in the response might not necessarily be appropriate for all use cases. Please refer to the Selenium FAQ and Selenium documentation for more information.

Test cases features

Default test client

SimpleTestCase.client

Every test case in a django.test.*TestCase instance has access to an instance of a Django test client. This client can be accessed as self.client. This client is recreated for each test, so you don’t have to worry about state (such as cookies) carrying over from one test to another.

This means, instead of instantiating a Client in each test:

import unittest
from django.test import Client

class SimpleTest(unittest.TestCase):
def test_details(self):
client = Client()
response = client.get('/customer/details/')
self.assertEqual(response.status_code, 200)

def test_index(self):
client = Client()
response = client.get('/customer/index/')
self.assertEqual(response.status_code, 200)

...you can just refer to self.client, like so:

from django.test import TestCase

class SimpleTest(TestCase):
def test_details(self):
response = self.client.get('/customer/details/')
self.assertEqual(response.status_code, 200)

def test_index(self):
response = self.client.get('/customer/index/')
self.assertEqual(response.status_code, 200)

Customizing the test client

SimpleTestCase.client_class

If you want to use a different Client class (for example, a subclass with customized behavior), use the client_class class attribute:

from django.test import TestCase, Client

class MyTestClient(Client):
# Specialized methods for your environment
...

class MyTest(TestCase):
client_class = MyTestClient

def test_my_stuff(self):
# Here self.client is an instance of MyTestClient...
call_some_test_code()

Fixture loading

TransactionTestCase.fixtures

A test case for a database-backed website isn’t much use if there isn’t any data in the database. Tests are more readable and it’s more maintainable to create objects using the ORM, for example in TestCase.setUpTestData(), however, you can also use fixtures.

A fixture is a collection of data that Django knows how to import into a database. For example, if your site has user accounts, you might set up a fixture of fake user accounts in order to populate your database during tests.

The most straightforward way of creating a fixture is to use the manage.py dumpdata command. This assumes you already have some data in your database. See the dumpdata documentation for more details.

Once you’ve created a fixture and placed it in a fixtures directory in one of your INSTALLED_APPS, you can use it in your unit tests by specifying a fixtures class attribute on your django.test.TestCase subclass:

from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
fixtures = ['mammals.json', 'birds']

def setUp(self):
# Test definitions as before.
call_setup_methods()

def testFluffyAnimals(self):
# A test that uses the fixtures.
call_some_test_code()

Here’s specifically what will happen:

- At the start of each test, before setUp() is run, Django will flush the database, returning the database to the state it was in directly after migrate was called.

- Then, all the named fixtures are installed. In this example, Django will install any JSON fixture named mammals, followed by any fixture named birds. See the loaddata documentation for more details on defining and installing fixtures.

For performance reasons, TestCase loads fixtures once for the entire test class, before setUpTestData(), instead of before each test, and it uses transactions to clean the database before each test. In any case, you can be certain that the outcome of a test will not be affected by another test or by the order of test execution.

By default, fixtures are only loaded into the default database. If you are using multiple databases and set multi_db=True, fixtures will be loaded into all databases.

URLconf configuration

SimpleTestCase.urls

Deprecated since version 1.8: Use @override_settings(ROOT_URLCONF=...) instead for URLconf configuration.

If your application provides views, you may want to include tests that use the test client to exercise those views. However, an end user is free to deploy the views in your application at any URL of their choosing. This means that your tests can’t rely upon the fact that your views will be available at a particular URL.

In order to provide a reliable URL space for your test, django.test.*TestCase classes provide the ability to customize the URLconf configuration for the duration of the execution of a test suite. If your *TestCase instance defines an urls attribute, the *TestCase will use the value of that attribute as the ROOT_URLCONF for the duration of that test.

For example:

from django.test import TestCase

class TestMyViews(TestCase):
urls = 'myapp.test_urls'

def test_index_page_view(self):
# Here you'd test your view using ``Client``.
call_some_test_code()

This test case will use the contents of myapp.test_urls as the URLconf for the duration of the test case.

Multi-database support

TransactionTestCase.multi_db

Django sets up a test database corresponding to every database that is defined in the DATABASES definition in your settings file. However, a big part of the time taken to run a Django TestCase is consumed by the call to flush that ensures that you have a clean database at the start of each test run. If you have multiple databases, multiple flushes are required (one for each database), which can be a time consuming activity – especially if your tests don’t need to test multi-database activity.

As an optimization, Django only flushes the default database at the start of each test run. If your setup contains multiple databases, and you have a test that requires every database to be clean, you can use the multi_db attribute on the test suite to request a full flush.

For example:

class TestMyViews(TestCase):
multi_db = True

def test_index_page_view(self):
call_some_test_code()

This test case will flush all the test databases before running test_index_page_view.

The multi_db flag also affects into which databases the attr:TransactionTestCase.fixtures are loaded. By default (when multi_db=False), fixtures are only loaded into the default database. If multi_db=True, fixtures are loaded into all databases.

Overriding settings

Warning

Use the functions below to temporarily alter the value of settings in tests. Don’t manipulate django.conf.settings directly as Django won’t restore the original values after such manipulations.

SimpleTestCase.settings()[source]

For testing purposes it’s often useful to change a setting temporarily and revert to the original value after running the testing code. For this use case Django provides a standard Python context manager (see PEP 343) called settings(), which can be used like this:

from django.test import TestCase

class LoginTestCase(TestCase):

def test_login(self):

# First check for the default behavior
response = self.client.get('/sekrit/')
self.assertRedirects(response, '/accounts/login/?next=/sekrit/')

# Then override the LOGIN_URL setting
with self.settings(LOGIN_URL='/other/login/'):
response = self.client.get('/sekrit/')
self.assertRedirects(response, '/other/login/?next=/sekrit/')

This example will override the LOGIN_URL setting for the code in the with block and reset its value to the previous state afterwards.

SimpleTestCase.modify_settings()[source]

It can prove unwieldy to redefine settings that contain a list of values. In practice, adding or removing values is often sufficient. The modify_settings() context manager makes it easy:

from django.test import TestCase

class MiddlewareTestCase(TestCase):

def test_cache_middleware(self):
with self.modify_settings(MIDDLEWARE_CLASSES={
'append': 'django.middleware.cache.FetchFromCacheMiddleware',
'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
'remove': [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
],
}):
response = self.client.get('/')
# ...

For each action, you can supply either a list of values or a string. When the value already exists in the list, append and prepend have no effect; neither does remove when the value doesn’t exist.

override_settings()[source]

In case you want to override a setting for a test method, Django provides the override_settings() decorator (see PEP 318). It’s used like this:

from django.test import TestCase, override_settings

class LoginTestCase(TestCase):

@override_settings(LOGIN_URL='/other/login/')
def test_login(self):
response = self.client.get('/sekrit/')
self.assertRedirects(response, '/other/login/?next=/sekrit/')

The decorator can also be applied to TestCase classes:

from django.test import TestCase, override_settings

@override_settings(LOGIN_URL='/other/login/')
class LoginTestCase(TestCase):

def test_login(self):
response = self.client.get('/sekrit/')
self.assertRedirects(response, '/other/login/?next=/sekrit/')

modify_settings()[source]

Likewise, Django provides the modify_settings() decorator:

from django.test import TestCase, modify_settings

class MiddlewareTestCase(TestCase):

@modify_settings(MIDDLEWARE_CLASSES={
'append': 'django.middleware.cache.FetchFromCacheMiddleware',
'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
})
def test_cache_middleware(self):
response = self.client.get('/')
# ...

The decorator can also be applied to test case classes:

from django.test import TestCase, modify_settings

@modify_settings(MIDDLEWARE_CLASSES={
'append': 'django.middleware.cache.FetchFromCacheMiddleware',
'prepend': 'django.middleware.cache.UpdateCacheMiddleware',
})
class MiddlewareTestCase(TestCase):

def test_cache_middleware(self):
response = self.client.get('/')
# ...

Note

When given a class, these decorators modify the class directly and return it; they don’t create and return a modified copy of it. So if you try to tweak the above examples to assign the return value to a different name than LoginTestCase or MiddlewareTestCase, you may be surprised to find that the original test case classes are still equally affected by the decorator. For a given class, modify_settings() is always applied after override_settings().

Warning

The settings file contains some settings that are only consulted during initialization of Django internals. If you change them with override_settings, the setting is changed if you access it via the django.conf.settings module, however, Django’s internals access it differently. Effectively, using override_settings() or modify_settings() with these settings is probably not going to do what you expect it to do.

We do not recommend altering the DATABASES setting. Altering the CACHES setting is possible, but a bit tricky if you are using internals that make using of caching, like django.contrib.sessions. For example, you will have to reinitialize the session backend in a test that uses cached sessions and overrides CACHES.

Finally, avoid aliasing your settings as module-level constants as override_settings() won’t work on such values since they are only evaluated the first time the module is imported.

You can also simulate the absence of a setting by deleting it after settings have been overridden, like this:

@override_settings()
def test_something(self):
del settings.LOGIN_URL
...

When overriding settings, make sure to handle the cases in which your app’s code uses a cache or similar feature that retains state even if the setting is changed. Django provides the django.test.signals.setting_changed signal that lets you register callbacks to clean up and otherwise reset state when settings are changed.

Django itself uses this signal to reset various data:

Overridden settings

Data reset

USE_TZ, TIME_ZONE

Databases timezone

TEMPLATES

Template engines

SERIALIZATION_MODULES

Serializers cache

LOCALE_PATHS, LANGUAGE_CODE

Default translation and loaded translations

MEDIA_ROOT, DEFAULT_FILE_STORAGE

Default file storage

Emptying the test outbox

If you use any of Django’s custom TestCase classes, the test runner will clear the contents of the test email outbox at the start of each test case.

For more detail on email services during tests, see Email services below.

Assertions

As Python’s normal unittest.TestCase class implements assertion methods such as assertTrue() and assertEqual(), Django’s custom TestCase class provides a number of custom assertion methods that are useful for testing Web applications:

The failure messages given by most of these assertion methods can be customized with the msg_prefix argument. This string will be prefixed to any failure message generated by the assertion. This allows you to provide additional details that may help you to identify the location and cause of a failure in your test suite.

SimpleTestCase.assertRaisesMessage(expected_exception, expected_message, callable, *args, **kwargs)[source]

SimpleTestCase.assertRaisesMessage(expected_exception, expected_message)

Asserts that execution of callable raises expected_exception and that expected_message is found in the exception’s message. Any other outcome is reported as a failure. It’s a simpler version of unittest.TestCase.assertRaisesRegex() with the difference that expected_message isn’t treated as a regular expression.

If only the expected_exception and expected_message parameters are given, returns a context manager so that the code being tested can be written inline rather than as a function:

with self.assertRaisesMessage(ValueError, 'invalid literal for int()'):
int('a')

Deprecated since version 1.9: Passing callable as a keyword argument called callable_obj is deprecated. Pass the callable as a positional argument instead.

SimpleTestCase.assertFieldOutput(fieldclass, valid, invalid, field_args=None, field_kwargs=None, empty_value='')[source]

Asserts that a form field behaves correctly with various inputs.

Parameters:

- fieldclass – the class of the field to be tested.

- valid – a dictionary mapping valid inputs to their expected cleaned values.

- invalid – a dictionary mapping invalid inputs to one or more raised error messages.

- field_args – the args passed to instantiate the field.

- field_kwargs – the kwargs passed to instantiate the field.

- empty_value – the expected clean output for inputs in empty_values.

For example, the following code tests that an EmailField accepts a@a.com as a valid email address, but rejects aaa with a reasonable error message:

self.assertFieldOutput(EmailField, {'a@a.com': 'a@a.com'}, {'aaa': ['Enter a valid email address.']})

SimpleTestCase.assertFormError(response, form, field, errors, msg_prefix='')[source]

Asserts that a field on a form raises the provided list of errors when rendered on the form.

form is the name the Form instance was given in the template context.

field is the name of the field on the form to check. If field has a value of None, non-field errors (errors you can access via form.non_field_errors()) will be checked.

errors is an error string, or a list of error strings, that are expected as a result of form validation.

SimpleTestCase.assertFormsetError(response, formset, form_index, field, errors, msg_prefix='')[source]

Asserts that the formset raises the provided list of errors when rendered.

formset is the name the Formset instance was given in the template context.

form_index is the number of the form within the Formset. If form_index has a value of None, non-form errors (errors you can access via formset.non_form_errors()) will be checked.

field is the name of the field on the form to check. If field has a value of None, non-field errors (errors you can access via form.non_field_errors()) will be checked.

errors is an error string, or a list of error strings, that are expected as a result of form validation.

SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)[source]

Asserts that a Response instance produced the given status_code and that text appears in the content of the response. If count is provided, text must occur exactly count times in the response.

Set html to True to handle text as HTML. The comparison with the response content will be based on HTML semantics instead of character-by-character equality. Whitespace is ignored in most cases, attribute ordering is not significant. See assertHTMLEqual() for more details.

SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)[source]

Asserts that a Response instance produced the given status_code and that text does not appear in the content of the response.

Set html to True to handle text as HTML. The comparison with the response content will be based on HTML semantics instead of character-by-character equality. Whitespace is ignored in most cases, attribute ordering is not significant. See assertHTMLEqual() for more details.

SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='', count=None)[source]

Asserts that the template with the given name was used in rendering the response.

The name is a string such as 'admin/index.html'.

New in Django 1.8:
The count argument is an integer indicating the number of times the template should be rendered. Default is None, meaning that the template should be rendered one or more times.

You can use this as a context manager, like this:

with self.assertTemplateUsed('index.html'):
render_to_string('index.html')
with self.assertTemplateUsed(template_name='index.html'):
render_to_string('index.html')

SimpleTestCase.assertTemplateNotUsed(response, template_name, msg_prefix='')[source]

Asserts that the template with the given name was not used in rendering the response.

You can use this as a context manager in the same way as assertTemplateUsed().

SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)[source]

Asserts that the response returned a status_code redirect status, redirected to expected_url (including any GET data), and that the final page was received with target_status_code.

If your request used the follow argument, the expected_url and target_status_code will be the url and status code for the final point of the redirect chain.

If fetch_redirect_response is False, the final page won’t be loaded. Since the test client can’t fetch externals URLs, this is particularly useful if expected_url isn’t part of your Django app.

Scheme is handled correctly when making comparisons between two URLs. If there isn’t any scheme specified in the location where we are redirected to, the original request’s scheme is used. If present, the scheme in expected_url is the one used to make the comparisons to.

Deprecated since version 1.9: The host argument is deprecated, as redirections are no longer forced to be absolute URLs.

SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)[source]

Asserts that the strings html1 and html2 are equal. The comparison is based on HTML semantics. The comparison takes following things into account:

- Whitespace before and after HTML tags is ignored.

- All types of whitespace are considered equivalent.

- All open tags are closed implicitly, e.g. when a surrounding tag is closed or the HTML document ends.

- Empty tags are equivalent to their self-closing version.

- The ordering of attributes of an HTML element is not significant.

- Attributes without an argument are equal to attributes that equal in name and value (see the examples).

The following examples are valid tests and don’t raise any AssertionError:

self.assertHTMLEqual(
'<p>Hello <b>world!</p>',
'''<p>
Hello   <b>world! <b/>
</p>'''
)
self.assertHTMLEqual(
'<input type="checkbox" checked="checked" id="id_accept_terms" />',
'<input id="id_accept_terms" type="checkbox" checked>'
)

html1 and html2 must be valid HTML. An AssertionError will be raised if one of them cannot be parsed.

Output in case of error can be customized with the msg argument.

SimpleTestCase.assertHTMLNotEqual(html1, html2, msg=None)[source]

Asserts that the strings html1 and html2 are not equal. The comparison is based on HTML semantics. See assertHTMLEqual() for details.

html1 and html2 must be valid HTML. An AssertionError will be raised if one of them cannot be parsed.

Output in case of error can be customized with the msg argument.

SimpleTestCase.assertXMLEqual(xml1, xml2, msg=None)[source]

Asserts that the strings xml1 and xml2 are equal. The comparison is based on XML semantics. Similarly to assertHTMLEqual(), the comparison is made on parsed content, hence only semantic differences are considered, not syntax differences. When invalid XML is passed in any parameter, an AssertionError is always raised, even if both string are identical.

Output in case of error can be customized with the msg argument.

SimpleTestCase.assertXMLNotEqual(xml1, xml2, msg=None)[source]

Asserts that the strings xml1 and xml2 are not equal. The comparison is based on XML semantics. See assertXMLEqual() for details.

Output in case of error can be customized with the msg argument.

SimpleTestCase.assertInHTML(needle, haystack, count=None, msg_prefix='')[source]

Asserts that the HTML fragment needle is contained in the haystack one.

If the count integer argument is specified, then additionally the number of needle occurrences will be strictly verified.

Whitespace in most cases is ignored, and attribute ordering is not significant. The passed-in arguments must be valid HTML.

SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)[source]

Asserts that the JSON fragments raw and expected_data are equal. Usual JSON non-significant whitespace rules apply as the heavyweight is delegated to the json library.

Output in case of error can be customized with the msg argument.

SimpleTestCase.assertJSONNotEqual(raw, expected_data, msg=None)[source]

New in Django 1.8.

Asserts that the JSON fragments raw and expected_data are not equal. See assertJSONEqual() for further details.

Output in case of error can be customized with the msg argument.

TransactionTestCase.assertQuerysetEqual(qs, values, transform=repr, ordered=True, msg=None)[source]

Asserts that a queryset qs returns a particular list of values values.

The comparison of the contents of qs and values is performed using the function transform; by default, this means that the repr() of each value is compared. Any other callable can be used if repr() doesn’t provide a unique or helpful comparison.

By default, the comparison is also ordering dependent. If qs doesn’t provide an implicit ordering, you can set the ordered parameter to False, which turns the comparison into a collections.Counter comparison. If the order is undefined (if the given qs isn’t ordered and the comparison is against more than one ordered values), a ValueError is raised.

Output in case of error can be customized with the msg argument.

TransactionTestCase.assertNumQueries(num, func, *args, **kwargs)[source]

Asserts that when func is called with *args and **kwargs that num database queries are executed.

If a "using" key is present in kwargs it is used as the database alias for which to check the number of queries. If you wish to call a function with a using parameter you can do it by wrapping the call with a lambda to add an extra parameter:

self.assertNumQueries(7, lambda: my_function(using=7))

You can also use this as a context manager:

with self.assertNumQueries(2):
Person.objects.create(name="Aaron")
Person.objects.create(name="Daniel")

Email services

If any of your Django views send email using Django’s email functionality, you probably don’t want to send email each time you run a test using that view. For this reason, Django’s test runner automatically redirects all Django-sent email to a dummy outbox. This lets you test every aspect of sending email – from the number of messages sent to the contents of each message – without actually sending the messages.

The test runner accomplishes this by transparently replacing the normal email backend with a testing backend. (Don’t worry – this has no effect on any other email senders outside of Django, such as your machine’s mail server, if you’re running one.)

django.core.mail.outbox

During test running, each outgoing email is saved in django.core.mail.outbox. This is a simple list of all EmailMessage instances that have been sent. The outbox attribute is a special attribute that is created only when the locmem email backend is used. It doesn’t normally exist as part of the django.core.mail module and you can’t import it directly. The code below shows how to access this attribute correctly.

Here’s an example test that examines django.core.mail.outbox for length and contents:

from django.core import mail
from django.test import TestCase

class EmailTest(TestCase):
def test_send_email(self):
# Send message.
mail.send_mail(
'Subject here', 'Here is the message.',
'from@example.com', ['to@example.com'],
fail_silently=False,
)

# Test that one message has been sent.
self.assertEqual(len(mail.outbox), 1)

# Verify that the subject of the first message is correct.
self.assertEqual(mail.outbox[0].subject, 'Subject here')

As noted previously, the test outbox is emptied at the start of every test in a Django *TestCase. To empty the outbox manually, assign the empty list to mail.outbox:

from django.core import mail

# Empty the test outbox
mail.outbox = []

Management Commands

Management commands can be tested with the call_command() function. The output can be redirected into a StringIO instance:

from django.core.management import call_command
from django.test import TestCase
from django.utils.six import StringIO

class ClosepollTest(TestCase):
def test_command_output(self):
out = StringIO()
call_command('closepoll', stdout=out)
self.assertIn('Expected output', out.getvalue())

Skipping tests

The unittest library provides the @skipIf and @skipUnless decorators to allow you to skip tests if you know ahead of time that those tests are going to fail under certain conditions.

For example, if your test requires a particular optional library in order to succeed, you could decorate the test case with @skipIf. Then, the test runner will report that the test wasn’t executed and why, instead of failing the test or omitting the test altogether.

To supplement these test skipping behaviors, Django provides two additional skip decorators. Instead of testing a generic boolean, these decorators check the capabilities of the database, and skip the test if the database doesn’t support a specific named feature.

The decorators use a string identifier to describe database features. This string corresponds to attributes of the database connection features class. See django.db.backends.BaseDatabaseFeatures class for a full list of database features that can be used as a basis for skipping tests.

skipIfDBFeature(*feature_name_strings)[source]

Skip the decorated test or TestCase if all of the named database features are supported.

For example, the following test will not be executed if the database supports transactions (e.g., it would not run under PostgreSQL, but it would under MySQL with MyISAM tables):

class MyTests(TestCase):
@skipIfDBFeature('supports_transactions')
def test_transaction_behavior(self):
# ... conditional test code
pass

Changed in Django 1.8:
skipIfDBFeature can accept multiple feature strings.

skipUnlessDBFeature(*feature_name_strings)[source]

Skip the decorated test or TestCase if any of the named database features are not supported.

For example, the following test will only be executed if the database supports transactions (e.g., it would run under PostgreSQL, but not under MySQL with MyISAM tables):

class MyTests(TestCase):
@skipUnlessDBFeature('supports_transactions')
def test_transaction_behavior(self):
# ... conditional test code
pass

Changed in Django 1.8:
skipUnlessDBFeature can accept multiple feature strings.

Advanced testing topics

The request factory

class RequestFactory[source]

The RequestFactory shares the same API as the test client. However, instead of behaving like a browser, the RequestFactory provides a way to generate a request instance that can be used as the first argument to any view. This means you can test a view function the same way as you would test any other function – as a black box, with exactly known inputs, testing for specific outputs.

The API for the RequestFactory is a slightly restricted subset of the test client API:

- It only has access to the HTTP methods get(), post(), put(), delete(), head(), options(), and trace().

- These methods accept all the same arguments except for follows. Since this is just a factory for producing requests, it’s up to you to handle the response.

- It does not support middleware. Session and authentication attributes must be supplied by the test itself if required for the view to function properly.

Example

The following is a simple unit test using the request factory:

from django.contrib.auth.models import AnonymousUser, User
from django.test import TestCase, RequestFactory

from .views import MyView, my_view

class SimpleTest(TestCase):
def setUp(self):
# Every test needs access to the request factory.
self.factory = RequestFactory()
self.user = User.objects.create_user(
username='jacob', email='jacob@…', password='top_secret')

def test_details(self):
# Create an instance of a GET request.
request = self.factory.get('/customer/details')

# Recall that middleware are not supported. You can simulate a
# logged-in user by setting request.user manually.
request.user = self.user

# Or you can simulate an anonymous user by setting request.user to
# an AnonymousUser instance.
request.user = AnonymousUser()

# Test my_view() as if it were deployed at /customer/details
response = my_view(request)
# Use this syntax for class-based views.
response = MyView.as_view()(request)
self.assertEqual(response.status_code, 200)

Tests and multiple databases

Testing primary/replica configurations

If you’re testing a multiple database configuration with primary/replica (referred to as master/slave by some databases) replication, this strategy of creating test databases poses a problem. When the test databases are created, there won’t be any replication, and as a result, data created on the primary won’t be seen on the replica.

To compensate for this, Django allows you to define that a database is a test mirror. Consider the following (simplified) example database configuration:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject',
'HOST': 'dbprimary',
# ... plus some other settings
},
'replica': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject',
'HOST': 'dbreplica',
'TEST': {
'MIRROR': 'default',
},
# ... plus some other settings
}
}

In this setup, we have two database servers: dbprimary, described by the database alias default, and dbreplica described by the alias replica. As you might expect, dbreplica has been configured by the database administrator as a read replica of dbprimary, so in normal activity, any write to default will appear on replica.

If Django created two independent test databases, this would break any tests that expected replication to occur. However, the replica database has been configured as a test mirror (using the MIRROR test setting), indicating that under testing, replica should be treated as a mirror of default.

When the test environment is configured, a test version of replica will not be created. Instead the connection to replica will be redirected to point at default. As a result, writes to default will appear on replica – but because they are actually the same database, not because there is data replication between the two databases.

Controlling creation order for test databases

By default, Django will assume all databases depend on the default database and therefore always create the default database first. However, no guarantees are made on the creation order of any other databases in your test setup.

If your database configuration requires a specific creation order, you can specify the dependencies that exist using the DEPENDENCIES test setting. Consider the following (simplified) example database configuration:

DATABASES = {
'default': {
# ... db settings
'TEST': {
'DEPENDENCIES': ['diamonds'],
},
},
'diamonds': {
... db settings
'TEST': {
'DEPENDENCIES': [],
},
},
'clubs': {
# ... db settings
'TEST': {
'DEPENDENCIES': ['diamonds'],
},
},
'spades': {
# ... db settings
'TEST': {
'DEPENDENCIES': ['diamonds', 'hearts'],
},
},
'hearts': {
# ... db settings
'TEST': {
'DEPENDENCIES': ['diamonds', 'clubs'],
},
}
}

Under this configuration, the diamonds database will be created first, as it is the only database alias without dependencies. The default and clubs alias will be created next (although the order of creation of this pair is not guaranteed), then hearts, and finally spades.

If there are any circular dependencies in the DEPENDENCIES definition, an ImproperlyConfigured exception will be raised.

Advanced features of TransactionTestCase

TransactionTestCase.available_apps

Warning

This attribute is a private API. It may be changed or removed without a deprecation period in the future, for instance to accommodate changes in application loading.

It’s used to optimize Django’s own test suite, which contains hundreds of models but no relations between models in different applications.

By default, available_apps is set to None. After each test, Django calls flush to reset the database state. This empties all tables and emits the post_migrate signal, which re-creates one content type and three permissions for each model. This operation gets expensive proportionally to the number of models.

Setting available_apps to a list of applications instructs Django to behave as if only the models from these applications were available. The behavior of TransactionTestCase changes as follows:

- post_migrate is fired before each test to create the content types and permissions for each model in available apps, in case they’re missing.

- After each test, Django empties only tables corresponding to models in available apps. However, at the database level, truncation may cascade to related models in unavailable apps. Furthermore post_migrate isn’t fired; it will be fired by the next TransactionTestCase, after the correct set of applications is selected.

Since the database isn’t fully flushed, if a test creates instances of models not included in available_apps, they will leak and they may cause unrelated tests to fail. Be careful with tests that use sessions; the default session engine stores them in the database.

Since post_migrate isn’t emitted after flushing the database, its state after a TransactionTestCase isn’t the same as after a TestCase: it’s missing the rows created by listeners to post_migrate. Considering the order in which tests are executed, this isn’t an issue, provided either all TransactionTestCase in a given test suite declare available_apps, or none of them.

available_apps is mandatory in Django’s own test suite.

TransactionTestCase.reset_sequences

Setting reset_sequences = True on a TransactionTestCase will make sure sequences are always reset before the test run:

class TestsThatDependsOnPrimaryKeySequences(TransactionTestCase):
reset_sequences = True

def test_animal_pk(self):
lion = Animal.objects.create(name="lion", sound="roar")
# lion.pk is guaranteed to always be 1
self.assertEqual(lion.pk, 1)

Unless you are explicitly testing primary keys sequence numbers, it is recommended that you do not hard code primary key values in tests.

Using reset_sequences = True will slow down the test, since the primary key reset is an relatively expensive database operation.

Using the Django test runner to test reusable applications

If you are writing a reusable application you may want to use the Django test runner to run your own test suite and thus benefit from the Django testing infrastructure.

A common practice is a tests directory next to the application code, with the following structure:

runtests.py
polls/
__init__.py
models.py
...
tests/
__init__.py
models.py
test_settings.py
tests.py

Let’s take a look inside a couple of those files:

runtests.py

#!/usr/bin/env python
import os
import sys

import django
from django.conf import settings
from django.test.utils import get_runner

if __name__ == "__main__":
os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.test_settings'
django.setup()
TestRunner = get_runner(settings)
test_runner = TestRunner()
failures = test_runner.run_tests(["tests"])
sys.exit(bool(failures))

This is the script that you invoke to run the test suite. It sets up the Django environment, creates the test database and runs the tests.

For the sake of clarity, this example contains only the bare minimum necessary to use the Django test runner. You may want to add command-line options for controlling verbosity, passing in specific test labels to run, etc.

tests/test_settings.py

SECRET_KEY = 'fake-key'
INSTALLED_APPS = [
"tests",
]

This file contains the Django settings required to run your app’s tests.

Again, this is a minimal example; your tests may require additional settings to run.

Since the tests package is included in INSTALLED_APPS when running your tests, you can define test-only models in its models.py file.

Using different testing frameworks

Clearly, unittest is not the only Python testing framework. While Django doesn’t provide explicit support for alternative frameworks, it does provide a way to invoke tests constructed for an alternative framework as if they were normal Django tests.

When you run ./manage.py test, Django looks at the TEST_RUNNER setting to determine what to do. By default, TEST_RUNNER points to 'django.test.runner.DiscoverRunner'. This class defines the default Django testing behavior. This behavior involves:

1. Performing global pre-test setup.

2. Looking for tests in any file below the current directory whose name matches the pattern test*.py.

3. Creating the test databases.

4. Running migrate to install models and initial data into the test databases.

5. Running the tests that were found.

6. Destroying the test databases.

7. Performing global post-test teardown.

If you define your own test runner class and point TEST_RUNNER at that class, Django will execute your test runner whenever you run ./manage.py test. In this way, it is possible to use any test framework that can be executed from Python code, or to modify the Django test execution process to satisfy whatever testing requirements you may have.

Defining a test runner

A test runner is a class defining a run_tests() method. Django ships with a DiscoverRunner class that defines the default Django testing behavior. This class defines the run_tests() entry point, plus a selection of other methods that are used to by run_tests() to set up, execute and tear down the test suite.

class DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_sql=False, **kwargs)[source]

DiscoverRunner will search for tests in any file matching pattern.

top_level can be used to specify the directory containing your top-level Python modules. Usually Django can figure this out automatically, so it’s not necessary to specify this option. If specified, it should generally be the directory containing your manage.py file.

verbosity determines the amount of notification and debug information that will be printed to the console; 0 is no output, 1 is normal output, and 2 is verbose output.

If interactive is True, the test suite has permission to ask the user for instructions when the test suite is executed. An example of this behavior would be asking for permission to delete an existing test database. If interactive is False, the test suite must be able to run without any manual intervention.

If failfast is True, the test suite will stop running after the first test failure is detected.

If keepdb is True, the test suite will use the existing database, or create one if necessary. If False, a new database will be created, prompting the user to remove the existing one, if present.

If reverse is True, test cases will be executed in the opposite order. This could be useful to debug tests that aren’t properly isolated and have side effects. Grouping by test class is preserved when using this option.

If debug_sql is True, failing test cases will output SQL queries logged to the django.db.backends logger as well as the traceback. If verbosity is 2, then queries in all tests are output.

Django may, from time to time, extend the capabilities of the test runner by adding new arguments. The **kwargs declaration allows for this expansion. If you subclass DiscoverRunner or write your own test runner, ensure it accepts **kwargs.

Your test runner may also define additional command-line options. Create or override an add_arguments(cls, parser) class method and add custom arguments by calling parser.add_argument() inside the method, so that the test command will be able to use those arguments.

Changed in Django 1.8:
Previously, you had to provide an option_list attribute to a subclassed test runner to add options to the list of command-line options that the test command could use.

The keepdb, reverse, and debug_sql arguments were added.

Attributes

DiscoverRunner.test_suite

The class used to build the test suite. By default it is set to unittest.TestSuite. This can be overridden if you wish to implement different logic for collecting tests.

DiscoverRunner.test_runner

This is the class of the low-level test runner which is used to execute the individual tests and format the results. By default it is set to unittest.TextTestRunner. Despite the unfortunate similarity in naming conventions, this is not the same type of class as DiscoverRunner, which covers a broader set of responsibilities. You can override this attribute to modify the way tests are run and reported.

DiscoverRunner.test_loader

This is the class that loads tests, whether from TestCases or modules or otherwise and bundles them into test suites for the runner to execute. By default it is set to unittest.defaultTestLoader. You can override this attribute if your tests are going to be loaded in unusual ways.

DiscoverRunner.option_list

This is the tuple of optparse options which will be fed into the management command’s OptionParser for parsing arguments. See the documentation for Python’s optparse module for more details.

Deprecated since version 1.8: You should now override the add_arguments() class method to add custom arguments accepted by the test management command.

Methods

DiscoverRunner.run_tests(test_labels, extra_tests=None, **kwargs)[source]

Run the test suite.

test_labels allows you to specify which tests to run and supports several formats (see DiscoverRunner.build_suite() for a list of supported formats).

extra_tests is a list of extra TestCase instances to add to the suite that is executed by the test runner. These extra tests are run in addition to those discovered in the modules listed in test_labels.

This method should return the number of tests that failed.

classmethod DiscoverRunner.add_arguments(parser)[source]

New in Django 1.8.

Override this class method to add custom arguments accepted by the test management command. See argparse.ArgumentParser.add_argument() for details about adding arguments to a parser.

DiscoverRunner.setup_test_environment(**kwargs)[source]

Sets up the test environment by calling setup_test_environment() and setting DEBUG to False.

DiscoverRunner.build_suite(test_labels, extra_tests=None, **kwargs)[source]

Constructs a test suite that matches the test labels provided.

test_labels is a list of strings describing the tests to be run. A test label can take one of four forms:

- path.to.test_module.TestCase.test_method – Run a single test method in a test case.

- path.to.test_module.TestCase – Run all the test methods in a test case.

- path.to.module – Search for and run all tests in the named Python package or module.

- path/to/directory – Search for and run all tests below the named directory.

If test_labels has a value of None, the test runner will search for tests in all files below the current directory whose names match its pattern (see above).

extra_tests is a list of extra TestCase instances to add to the suite that is executed by the test runner. These extra tests are run in addition to those discovered in the modules listed in test_labels.

Returns a TestSuite instance ready to be run.

DiscoverRunner.setup_databases(**kwargs)[source]

Creates the test databases.

Returns a data structure that provides enough detail to undo the changes that have been made. This data will be provided to the teardown_databases() function at the conclusion of testing.

DiscoverRunner.run_suite(suite, **kwargs)[source]

Runs the test suite.

Returns the result produced by the running the test suite.

DiscoverRunner.teardown_databases(old_config, **kwargs)[source]

Destroys the test databases, restoring pre-test conditions.

old_config is a data structure defining the changes in the database configuration that need to be reversed. It is the return value of the setup_databases() method.

DiscoverRunner.teardown_test_environment(**kwargs)[source]

Restores the pre-test environment.

DiscoverRunner.suite_result(suite, result, **kwargs)[source]

Computes and returns a return code based on a test suite, and the result from that test suite.

Testing utilities

django.test.utils

To assist in the creation of your own test runner, Django provides a number of utility methods in the django.test.utils module.

setup_test_environment()[source]

Performs any global pre-test setup, such as the installing the instrumentation of the template rendering system and setting up the dummy email outbox.

teardown_test_environment()[source]

Performs any global post-test teardown, such as removing the black magic hooks into the template system and restoring normal email services.

django.db.connection.creation

The creation module of the database backend also provides some utilities that can be useful during testing.

create_test_db(verbosity=1, autoclobber=False, serialize=True, keepdb=False)

Creates a new test database and runs migrate against it.

verbosity has the same behavior as in run_tests().

autoclobber describes the behavior that will occur if a database with the same name as the test database is discovered:

- If autoclobber is False, the user will be asked to approve destroying the existing database. sys.exit is called if the user does not approve.

- If autoclobber is True, the database will be destroyed without consulting the user.

serialize determines if Django serializes the database into an in-memory JSON string before running tests (used to restore the database state between tests if you don’t have transactions). You can set this to False to speed up creation time if you don’t have any test classes with serialized_rollback=True.

If you are using the default test runner, you can control this with the the SERIALIZE entry in the TEST dictionary.

keepdb determines if the test run should use an existing database, or create a new one. If True, the existing database will be used, or created if not present. If False, a new database will be created, prompting the user to remove the existing one, if present.

Returns the name of the test database that it created.

create_test_db() has the side effect of modifying the value of NAME in DATABASES to match the name of the test database.

Changed in Django 1.8:
The keepdb argument was added.

destroy_test_db(old_database_name, verbosity=1, keepdb=False)

Destroys the database whose name is the value of NAME in DATABASES, and sets NAME to the value of old_database_name.

The verbosity argument has the same behavior as for DiscoverRunner.

If the keepdb argument is True, then the connection to the database will be closed, but the database will not be destroyed.

Changed in Django 1.8:
The keepdb argument was added.

Integration with coverage.py

Code coverage describes how much source code has been tested. It shows which parts of your code are being exercised by tests and which are not. It’s an important part of testing applications, so it’s strongly recommended to check the coverage of your tests.

Django can be easily integrated with coverage.py, a tool for measuring code coverage of Python programs. First, install coverage.py. Next, run the following from your project folder containing manage.py:

coverage run --source='.' manage.py test myapp

This runs your tests and collects coverage data of the executed files in your project. You can see a report of this data by typing following command:

coverage report

Note that some Django code was executed while running tests, but it is not listed here because of the source flag passed to the previous command.

For more options like annotated HTML listings detailing missed lines, see the coverage.py docs.

User authentication in Django

Django comes with a user authentication system. It handles user accounts, groups, permissions and cookie-based user sessions. This section of the documentation explains how the default implementation works out of the box, as well as how to extend and customize it to suit your project’s needs.

Overview

The Django authentication system handles both authentication and authorization. Briefly, authentication verifies a user is who they claim to be, and authorization determines what an authenticated user is allowed to do. Here the term authentication is used to refer to both tasks.

The auth system consists of:

- Users

- Permissions: Binary (yes/no) flags designating whether a user may perform a certain task.

- Groups: A generic way of applying labels and permissions to more than one user.

- A configurable password hashing system

- Forms and view tools for logging in users, or restricting content

- A pluggable backend system

The authentication system in Django aims to be very generic and doesn’t provide some features commonly found in web authentication systems. Solutions for some of these common problems have been implemented in third-party packages:

- Password strength checking

- Throttling of login attempts

- Authentication against third-parties (OAuth, for example)

Installation

Authentication support is bundled as a Django contrib module in django.contrib.auth. By default, the required configuration is already included in the settings.py generated by django-admin startproject, these consist of two items listed in your INSTALLED_APPS setting:

1. 'django.contrib.auth' contains the core of the authentication framework, and its default models.

2. 'django.contrib.contenttypes' is the Django content type system, which allows permissions to be associated with models you create.

and these items in your MIDDLEWARE_CLASSES setting:

1. SessionMiddleware manages sessions across requests.

2. AuthenticationMiddleware associates users with requests using sessions.

3. SessionAuthenticationMiddleware logs users out of their other sessions after a password change.

With these settings in place, running the command manage.py migrate creates the necessary database tables for auth related models and permissions for any models defined in your installed apps.

Usage

Using Django’s default implementation

- Working with User objects

- Permissions and authorization

- Authentication in web requests

- Managing users in the admin

API reference for the default implementation

Customizing Users and authentication

Password management in Django

Using the Django authentication system

This document explains the usage of Django’s authentication system in its default configuration. This configuration has evolved to serve the most common project needs, handling a reasonably wide range of tasks, and has a careful implementation of passwords and permissions. For projects where authentication needs differ from the default, Django supports extensive extension and customization of authentication.

Django authentication provides both authentication and authorization together and is generally referred to as the authentication system, as these features are somewhat coupled.

User objects

User objects are the core of the authentication system. They typically represent the people interacting with your site and are used to enable things like restricting access, registering user profiles, associating content with creators etc. Only one class of user exists in Django’s authentication framework, i.e., 'superusers' or admin 'staff' users are just user objects with special attributes set, not different classes of user objects.

The primary attributes of the default user are:

- username

- password

- email

- first_name

- last_name

See the full API documentation for full reference, the documentation that follows is more task oriented.

Creating users

The most direct way to create users is to use the included create_user() helper function:

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# At this point, user is a User object that has already been saved
# to the database. You can continue to change its attributes
# if you want to change other fields.
>>> user.last_name = 'Lennon'
>>> user.save()

If you have the Django admin installed, you can also create users interactively.

Creating superusers

Create superusers using the createsuperuser command:

$ python manage.py createsuperuser --username=joe --email=joe@example.com

You will be prompted for a password. After you enter one, the user will be created immediately. If you leave off the --username or --email options, it will prompt you for those values.

Changing passwords

Django does not store raw (clear text) passwords on the user model, but only a hash (see documentation of how passwords are managed for full details). Because of this, do not attempt to manipulate the password attribute of the user directly. This is why a helper function is used when creating a user.

To change a user’s password, you have several options:

manage.py changepassword *username* offers a method of changing a User’s password from the command line. It prompts you to change the password of a given user which you must enter twice. If they both match, the new password will be changed immediately. If you do not supply a user, the command will attempt to change the password whose username matches the current system user.

You can also change a password programmatically, using set_password():

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='john')
>>> u.set_password('new password')
>>> u.save()

If you have the Django admin installed, you can also change user’s passwords on the authentication system’s admin pages.

Django also provides views and forms that may be used to allow users to change their own passwords.

Changing a user’s password will log out all their sessions if the SessionAuthenticationMiddleware is enabled. See Session invalidation on password change for details.

Authenticating users

authenticate(**credentials)[source]

To authenticate a given username and password, use authenticate(). It takes credentials in the form of keyword arguments, for the default configuration this is username and password, and it returns a User object if the password is valid for the given username. If the password is invalid, authenticate() returns None. Example:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
# the password verified for the user
if user.is_active:
print("User is valid, active and authenticated")
else:
print("The password is valid, but the account has been disabled!")
else:
# the authentication system was unable to verify the username and password
print("The username and password were incorrect.")

Note

This is a low level way to authenticate a set of credentials; for example, it’s used by the RemoteUserMiddleware. Unless you are writing your own authentication system, you probably won’t use this. Rather if you are looking for a way to limit access to logged in users, see the login_required() decorator.

Permissions and Authorization

Django comes with a simple permissions system. It provides a way to assign permissions to specific users and groups of users.

It’s used by the Django admin site, but you’re welcome to use it in your own code.

The Django admin site uses permissions as follows:

- Access to view the “add” form and add an object is limited to users with the “add” permission for that type of object.

- Access to view the change list, view the “change” form and change an object is limited to users with the “change” permission for that type of object.

- Access to delete an object is limited to users with the “delete” permission for that type of object.

Permissions can be set not only per type of object, but also per specific object instance. By using the has_add_permission(), has_change_permission() and has_delete_permission() methods provided by the ModelAdmin class, it is possible to customize permissions for different object instances of the same type.

User objects have two many-to-many fields: groups and user_permissions. User objects can access their related objects in the same way as any other Django model:

myuser.groups = [group_list]
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions = [permission_list]
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

Default permissions

When django.contrib.auth is listed in your INSTALLED_APPS setting, it will ensure that three default permissions – add, change and delete – are created for each Django model defined in one of your installed applications.

These permissions will be created when you run manage.py migrate; the first time you run migrate after adding django.contrib.auth to INSTALLED_APPS, the default permissions will be created for all previously-installed models, as well as for any new models being installed at that time. Afterward, it will create default permissions for new models each time you run manage.py migrate (the function that creates permissions is connected to the post_migrate signal).

Assuming you have an application with an app_label foo and a model named Bar, to test for basic permissions you should use:

- add: user.has_perm('foo.add_bar')

- change: user.has_perm('foo.change_bar')

- delete: user.has_perm('foo.delete_bar')

The Permission model is rarely accessed directly.

Groups

django.contrib.auth.models.Group models are a generic way of categorizing users so you can apply permissions, or some other label, to those users. A user can belong to any number of groups.

A user in a group automatically has the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission.

Beyond permissions, groups are a convenient way to categorize users to give them some label, or extended functionality. For example, you could create a group 'Special users', and you could write code that could, say, give them access to a members-only portion of your site, or send them members-only email messages.

Programmatically creating permissions

While custom permissions can be defined within a model’s Meta class, you can also create permissions directly. For example, you can create the can_publish permission for a BlogPost model in myapp:

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
codename='can_publish',
name='Can Publish Posts',
content_type=content_type,
)

The permission can then be assigned to a User via its user_permissions attribute or to a Group via its permissions attribute.

Permission caching

The ModelBackend caches permissions on the User object after the first time they need to be fetched for a permissions check. This is typically fine for the request-response cycle since permissions are not typically checked immediately after they are added (in the admin, for example). If you are adding permissions and checking them immediately afterward, in a test or view for example, the easiest solution is to re-fetch the User from the database. For example:

from django.contrib.auth.models import Permission, User
from django.shortcuts import get_object_or_404

def user_gains_perms(request, user_id):
user = get_object_or_404(User, pk=user_id)
# any permission check will cache the current set of permissions
user.has_perm('myapp.change_bar')

permission = Permission.objects.get(codename='change_bar')
user.user_permissions.add(permission)

# Checking the cached permission set
user.has_perm('myapp.change_bar')  # False

# Request new instance of User
# Be aware that user.refresh_from_db() won't clear the cache.
user = get_object_or_404(User, pk=user_id)

# Permission cache is repopulated from the database
user.has_perm('myapp.change_bar')  # True

...

Authentication in Web requests

Django uses sessions and middleware to hook the authentication system into request objects.

These provide a request.user attribute on every request which represents the current user. If the current user has not logged in, this attribute will be set to an instance of AnonymousUser, otherwise it will be an instance of User.

You can tell them apart with is_authenticated(), like so:

if request.user.is_authenticated():
# Do something for authenticated users.
...
else:
# Do something for anonymous users.
...

How to log a user in

If you have an authenticated user you want to attach to the current session - this is done with a login() function.

login(request, user)[source]

To log a user in, from a view, use login(). It takes an HttpRequest object and a User object. login() saves the user’s ID in the session, using Django’s session framework.

Note that any data set during the anonymous session is retained in the session after a user logs in.

This example shows how you might use both authenticate() and login():

from django.contrib.auth import authenticate, login

def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
...
else:
# Return an 'invalid login' error message.
...

Calling authenticate() first

When you’re manually logging a user in, you must successfully authenticate the user with authenticate() before you call login(). authenticate() sets an attribute on the User noting which authentication backend successfully authenticated that user (see the backends documentation for details), and this information is needed later during the login process. An error will be raised if you try to login a user object retrieved from the database directly.

Selecting the authentication backend

When a user logs in, the user’s ID and the backend that was used for authentication are saved in the user’s session. This allows the same authentication backend to fetch the user’s details on a future request. The authentication backend to save in the session is selected as follows:

1. Use the value of the optional backend argument, if provided.

2. Use the value of the user.backend attribute, if present. This allows pairing authenticate() and login(): authenticate() sets the user.backend attribute on the User object it returns.

3. Use the backend in AUTHENTICATION_BACKENDS, if there is only one.

4. Otherwise, raise an exception.

In cases 1 and 2, the value of the backend argument or the user.backend attribute should be a dotted import path string (like that found in AUTHENTICATION_BACKENDS), not the actual backend class.

How to log a user out

logout(request)[source]

To log out a user who has been logged in via django.contrib.auth.login(), use django.contrib.auth.logout() within your view. It takes an HttpRequest object and has no return value. Example:

from django.contrib.auth import logout

def logout_view(request):
logout(request)
# Redirect to a success page.

Note that logout() doesn’t throw any errors if the user wasn’t logged in.

When you call logout(), the session data for the current request is completely cleaned out. All existing data is removed. This is to prevent another person from using the same Web browser to log in and have access to the previous user’s session data. If you want to put anything into the session that will be available to the user immediately after logging out, do that after calling django.contrib.auth.logout().

Limiting access to logged-in users

The raw way

The simple, raw way to limit access to pages is to check request.user.is_authenticated() and either redirect to a login page:

from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
if not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
# ...

...or display an error message:

from django.shortcuts import render

def my_view(request):
if not request.user.is_authenticated():
return render(request, 'myapp/login_error.html')
# ...

The login_required decorator

login_required(redirect_field_name='next', login_url=None)[source]

As a shortcut, you can use the convenient login_required() decorator:

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
...

login_required() does the following:

- If the user isn’t logged in, redirect to settings.LOGIN_URL, passing the current absolute path in the query string. Example: /accounts/login/?next=/polls/3/.

- If the user is logged in, execute the view normally. The view code is free to assume the user is logged in.

By default, the path that the user should be redirected to upon successful authentication is stored in a query string parameter called "next". If you would prefer to use a different name for this parameter, login_required() takes an optional redirect_field_name parameter:

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
...

Note that if you provide a value to redirect_field_name, you will most likely need to customize your login template as well, since the template context variable which stores the redirect path will use the value of redirect_field_name as its key rather than "next" (the default).

login_required() also takes an optional login_url parameter. Example:

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
...

Note that if you don’t specify the login_url parameter, you’ll need to ensure that the settings.LOGIN_URL and your login view are properly associated. For example, using the defaults, add the following lines to your URLconf:

from django.contrib.auth import views as auth_views

url(r'^accounts/login/$', auth_views.login),

The settings.LOGIN_URL also accepts view function names and named URL patterns. This allows you to freely remap your login view within your URLconf without having to update the setting.

Note

The login_required decorator does NOT check the is_active flag on a user.

See also

If you are writing custom views for Django’s admin (or need the same authorization check that the built-in views use), you may find the django.contrib.admin.views.decorators.staff_member_required() decorator a useful alternative to login_required().

The LoginRequired mixin

When using class-based views, you can achieve the same behavior as with login_required by using the LoginRequiredMixin. This mixin should be at the leftmost position in the inheritance list.

class LoginRequiredMixin

New in Django 1.9.

If a view is using this mixin, all requests by non-authenticated users will be redirected to the login page or shown an HTTP 403 Forbidden error, depending on the raise_exception parameter.

You can set any of the parameters of AccessMixin to customize the handling of unauthorized users:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'

Note

Just as the login_required decorator, this mixin does NOT check the is_active flag on a user.

Limiting access to logged-in users that pass a test

To limit access based on certain permissions or some other test, you’d do essentially the same thing as described in the previous section.

The simple way is to run your test on request.user in the view directly. For example, this view checks to make sure the user has an email in the desired domain and if not, redirects to the login page:

from django.shortcuts import redirect

def my_view(request):
if not request.user.email.endswith('@example.com'):
return redirect('/login/?next=%s' % request.path)
# ...

user_passes_test(test_func, login_url=None, redirect_field_name='next')[source]

As a shortcut, you can use the convenient user_passes_test decorator which performs a redirect when the callable returns False:

from django.contrib.auth.decorators import user_passes_test

def email_check(user):
return user.email.endswith('@example.com')

@user_passes_test(email_check)
def my_view(request):
...

user_passes_test() takes a required argument: a callable that takes a User object and returns True if the user is allowed to view the page. Note that user_passes_test() does not automatically check that the User is not anonymous.

user_passes_test() takes two optional arguments:

login_url

Lets you specify the URL that users who don’t pass the test will be redirected to. It may be a login page and defaults to settings.LOGIN_URL if you don’t specify one.

redirect_field_name

Same as for login_required(). Setting it to None removes it from the URL, which you may want to do if you are redirecting users that don’t pass the test to a non-login page where there’s no “next page”.

For example:

@user_passes_test(email_check, login_url='/login/')
def my_view(request):
...

class UserPassesTestMixin

New in Django 1.9.

When using class-based views, you can use the UserPassesTestMixin to do this.

test_func()

You have to override the test_func() method of the class to provide the test that is performed. Furthermore, you can set any of the parameters of AccessMixin to customize the handling of unauthorized users:

from django.contrib.auth.mixins import UserPassesTestMixin

class MyView(UserPassesTestMixin, View):

def test_func(self):
return self.request.user.email.endswith('@example.com')

get_test_func()

You can also override the get_test_func() method to have the mixin use a differently named function for its checks (instead of test_func()).

Stacking UserPassesTestMixin

Due to the way UserPassesTestMixin is implemented, you cannot stack them in your inheritance list. The following does NOT work:

class TestMixin1(UserPassesTestMixin):
def test_func(self):
return self.request.user.email.endswith('@example.com')

class TestMixin2(UserPassesTestMixin):
def test_func(self):
return self.request.user.username.startswith('django')

class MyView(TestMixin1, TestMixin2, View):
...

If TestMixin1 would call super() and take that result into account, TestMixin1 wouldn’t work standalone anymore.

The permission_required decorator

permission_required(perm, login_url=None, raise_exception=False)[source]

It’s a relatively common task to check whether a user has a particular permission. For that reason, Django provides a shortcut for that case: the permission_required() decorator.:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
...

Just like the has_perm() method, permission names take the form "<app label>.<permission codename>" (i.e. polls.can_vote for a permission on a model in the polls application).

The decorator may also take an iterable of permissions, in which case the user must have all of the permissions in order to access the view.

Note that permission_required() also takes an optional login_url parameter:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
...

As in the login_required() decorator, login_url defaults to settings.LOGIN_URL.

If the raise_exception parameter is given, the decorator will raise PermissionDenied, prompting the 403 (HTTP Forbidden) view instead of redirecting to the login page.

If you want to use raise_exception but also give your users a chance to login first, you can add the login_required() decorator:

from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('polls.can_vote', raise_exception=True)
def my_view(request):
...

Changed in Django 1.9:
In older versions, the permission parameter only worked with strings, lists, and tuples instead of strings and any iterable.

The PermissionRequiredMixin mixin

To apply permission checks to class-based views, you can use the PermissionRequiredMixin:

class PermissionRequiredMixin

New in Django 1.9.

This mixin, just like the permission_required decorator, checks whether the user accessing a view has all given permissions. You should specify the permission (or an iterable of permissions) using the permission_required parameter:

from django.contrib.auth.mixins import PermissionRequiredMixin

class MyView(PermissionRequiredMixin, View):
permission_required = 'polls.can_vote'
# Or multiple of permissions:
permission_required = ('polls.can_open', 'polls.can_edit')

You can set any of the parameters of AccessMixin to customize the handling of unauthorized users.

You may also override these methods:

get_permission_required()

Returns an iterable of permission names used by the mixin. Defaults to the permission_required attribute, converted to a tuple if necessary.

has_permission()

Returns a boolean denoting whether the current user has permission to execute the decorated view. By default, this returns the result of calling has_perms() with the list of permissions returned by get_permission_required().

Redirecting unauthorized requests in class-based views

To ease the handling of access restrictions in class-based views, the AccessMixin can be used to redirect a user to the login page or issue an HTTP 403 Forbidden response.

class AccessMixin

New in Django 1.9.

login_url

Default return value for get_login_url(). Defaults to None in which case get_login_url() falls back to settings.LOGIN_URL.

permission_denied_message

Default return value for get_permission_denied_message(). Defaults to an empty string.

redirect_field_name

Default return value for get_redirect_field_name(). Defaults to "next".

raise_exception

If this attribute is set to True, a PermissionDenied exception will be raised instead of the redirect. Defaults to False.

get_login_url()

Returns the URL that users who don’t pass the test will be redirected to. Returns login_url if set, or settings.LOGIN_URL otherwise.

get_permission_denied_message()

When raise_exception is True, this method can be used to control the error message passed to the error handler for display to the user. Returns the permission_denied_message attribute by default.

get_redirect_field_name()

Returns the name of the query parameter that will contain the URL the user should be redirected to after a successful login. If you set this to None, a query parameter won’t be added. Returns the redirect_field_name attribute by default.

handle_no_permission()

Depending on the value of raise_exception, the method either raises a PermissionDenied exception or redirects the user to the login_url, optionally including the redirect_field_name if it is set.

Session invalidation on password change

Warning

This protection only applies if SessionAuthenticationMiddleware is enabled in MIDDLEWARE_CLASSES. It’s included if settings.py was generated by startproject on Django ≥ 1.7.

Session verification will become mandatory in Django 1.10 regardless of whether or not SessionAuthenticationMiddleware is enabled. If you have a pre-1.7 project or one generated using a template that doesn’t include SessionAuthenticationMiddleware, consider enabling it before then after reading the upgrade considerations below.

If your AUTH_USER_MODEL inherits from AbstractBaseUser or implements its own get_session_auth_hash() method, authenticated sessions will include the hash returned by this function. In the AbstractBaseUser case, this is an HMAC of the password field. If the SessionAuthenticationMiddleware is enabled, Django verifies that the hash sent along with each request matches the one that’s computed server-side. This allows a user to log out all of their sessions by changing their password.

The default password change views included with Django, django.contrib.auth.views.password_change() and the user_change_password view in the django.contrib.auth admin, update the session with the new password hash so that a user changing their own password won’t log themselves out. If you have a custom password change view and wish to have similar behavior, use this function:

update_session_auth_hash(request, user)

This function takes the current request and the updated user object from which the new session hash will be derived and updates the session hash appropriately. Example usage:

from django.contrib.auth import update_session_auth_hash

def password_change(request):
if request.method == 'POST':
form = PasswordChangeForm(user=request.user, data=request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
else:
...

If you are upgrading an existing site and wish to enable this middleware without requiring all your users to re-login afterward, you should first upgrade to Django 1.7 and run it for a while so that as sessions are naturally recreated as users login, they include the session hash as described above. Once you start running your site with SessionAuthenticationMiddleware, any users who have not logged in and had their session updated with the verification hash will have their existing session invalidated and be required to login.

Note

Since get_session_auth_hash() is based on SECRET_KEY, updating your site to use a new secret will invalidate all existing sessions.

Authentication Views

Django provides several views that you can use for handling login, logout, and password management. These make use of the stock auth forms but you can pass in your own forms as well.

Django provides no default template for the authentication views. You should create your own templates for the views you want to use. The template context is documented in each view, see All authentication views.

Using the views

There are different methods to implement these views in your project. The easiest way is to include the provided URLconf in django.contrib.auth.urls in your own URLconf, for example:

urlpatterns = [
url('^', include('django.contrib.auth.urls')),
]

This will include the following URL patterns:

^login/$ [name='login']
^logout/$ [name='logout']
^password_change/$ [name='password_change']
^password_change/done/$ [name='password_change_done']
^password_reset/$ [name='password_reset']
^password_reset/done/$ [name='password_reset_done']
^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$ [name='password_reset_confirm']
^reset/done/$ [name='password_reset_complete']

The views provide a URL name for easier reference. See the URL documentation for details on using named URL patterns.

If you want more control over your URLs, you can reference a specific view in your URLconf:

from django.contrib.auth import views as auth_views

urlpatterns = [
url('^change-password/$', auth_views.password_change),
]

The views have optional arguments you can use to alter the behavior of the view. For example, if you want to change the template name a view uses, you can provide the template_name argument. A way to do this is to provide keyword arguments in the URLconf, these will be passed on to the view. For example:

urlpatterns = [
url(
'^change-password/$',
auth_views.password_change,
{'template_name': 'change-password.html'}
),
]

All views return a TemplateResponse instance, which allows you to easily customize the response data before rendering. A way to do this is to wrap a view in your own view:

from django.contrib.auth import views

def change_password(request):
template_response = views.password_change(request)
# Do something with `template_response`
return template_response

For more details, see the TemplateResponse documentation.

All authentication views

This is a list with all the views django.contrib.auth provides. For implementation details see Using the views.

login(request, template_name=`registration/login.html`, redirect_field_name='next', authentication_form=AuthenticationForm, current_app=None, extra_context=None)

URL name: login

See the URL documentation for details on using named URL patterns.

Optional arguments:

- template_name: The name of a template to display for the view used to log the user in. Defaults to registration/login.html.

- redirect_field_name: The name of a GET field containing the URL to redirect to after login. Defaults to next.

- authentication_form: A callable (typically just a form class) to use for authentication. Defaults to AuthenticationForm.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

Here’s what django.contrib.auth.views.login does:

- If called via GET, it displays a login form that POSTs to the same URL. More on this in a bit.

- If called via POST with user submitted credentials, it tries to log the user in. If login is successful, the view redirects to the URL specified in next. If next isn’t provided, it redirects to settings.LOGIN_REDIRECT_URL (which defaults to /accounts/profile/). If login isn’t successful, it redisplays the login form.

It’s your responsibility to provide the html for the login template , called registration/login.html by default. This template gets passed four template context variables:

- form: A Form object representing the AuthenticationForm.

- next: The URL to redirect to after successful login. This may contain a query string, too.

- site: The current Site, according to the SITE_ID setting. If you don’t have the site framework installed, this will be set to an instance of RequestSite, which derives the site name and domain from the current HttpRequest.

- site_name: An alias for site.name. If you don’t have the site framework installed, this will be set to the value of request.META['SERVER_NAME']. For more on sites, see The “sites” framework.

If you’d prefer not to call the template registration/login.html, you can pass the template_name parameter via the extra arguments to the view in your URLconf. For example, this URLconf line would use myapp/login.html instead:

url(r'^accounts/login/$', auth_views.login, {'template_name': 'myapp/login.html'}),

You can also specify the name of the GET field which contains the URL to redirect to after login by passing redirect_field_name to the view. By default, the field is called next.

Here’s a sample registration/login.html template you can use as a starting point. It assumes you have a base.html template that defines a content block:

{% extends "base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}

<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>

{# Assumes you setup the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>

{% endblock %}

If you have customized authentication (see Customizing Authentication) you can pass a custom authentication form to the login view via the authentication_form parameter. This form must accept a request keyword argument in its __init__ method, and provide a get_user() method which returns the authenticated user object (this method is only ever called after successful form validation).

logout(request, next_page=None, template_name='registration/logged_out.html', redirect_field_name='next', current_app=None, extra_context=None)

Logs a user out.

URL name: logout

Optional arguments:

- next_page: The URL to redirect to after logout.

- template_name: The full name of a template to display after logging the user out. Defaults to registration/logged_out.html if no argument is supplied.

- redirect_field_name: The name of a GET field containing the URL to redirect to after log out. Defaults to next. Overrides the next_page URL if the given GET parameter is passed.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

Template context:

- title: The string “Logged out”, localized.

- site: The current Site, according to the SITE_ID setting. If you don’t have the site framework installed, this will be set to an instance of RequestSite, which derives the site name and domain from the current HttpRequest.

- site_name: An alias for site.name. If you don’t have the site framework installed, this will be set to the value of request.META['SERVER_NAME']. For more on sites, see The “sites” framework.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

logout_then_login(request, login_url=None, current_app=None, extra_context=None)

Logs a user out, then redirects to the login page.

URL name: No default URL provided

Optional arguments:

- login_url: The URL of the login page to redirect to. Defaults to settings.LOGIN_URL if not supplied.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

password_change(request, template_name='registration/password_change_form.html', post_change_redirect=None, password_change_form=PasswordChangeForm, current_app=None, extra_context=None)

Allows a user to change their password.

URL name: password_change

Optional arguments:

- template_name: The full name of a template to use for displaying the password change form. Defaults to registration/password_change_form.html if not supplied.

- post_change_redirect: The URL to redirect to after a successful password change.

- password_change_form: A custom “change password” form which must accept a user keyword argument. The form is responsible for actually changing the user’s password. Defaults to PasswordChangeForm.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

Template context:

- form: The password change form (see password_change_form above).

password_change_done(request, template_name='registration/password_change_done.html', current_app=None, extra_context=None)

The page shown after a user has changed their password.

URL name: password_change_done

Optional arguments:

- template_name: The full name of a template to use. Defaults to registration/password_change_done.html if not supplied.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', email_template_name='registration/password_reset_email.html', subject_template_name='registration/password_reset_subject.txt', password_reset_form=PasswordResetForm, token_generator=default_token_generator, post_reset_redirect=None, from_email=None, current_app=None, extra_context=None, html_email_template_name=None, extra_email_context=None)

Allows a user to reset their password by generating a one-time use link that can be used to reset the password, and sending that link to the user’s registered email address.

If the email address provided does not exist in the system, this view won’t send an email, but the user won’t receive any error message either. This prevents information leaking to potential attackers. If you want to provide an error message in this case, you can subclass PasswordResetForm and use the password_reset_form argument.

Users flagged with an unusable password (see set_unusable_password() aren’t allowed to request a password reset to prevent misuse when using an external authentication source like LDAP. Note that they won’t receive any error message since this would expose their account’s existence but no mail will be sent either.

URL name: password_reset

Optional arguments:

- template_name: The full name of a template to use for displaying the password reset form. Defaults to registration/password_reset_form.html if not supplied.

- email_template_name: The full name of a template to use for generating the email with the reset password link. Defaults to registration/password_reset_email.html if not supplied.

- subject_template_name: The full name of a template to use for the subject of the email with the reset password link. Defaults to registration/password_reset_subject.txt if not supplied.

- password_reset_form: Form that will be used to get the email of the user to reset the password for. Defaults to PasswordResetForm.

- token_generator: Instance of the class to check the one time link. This will default to default_token_generator, it’s an instance of django.contrib.auth.tokens.PasswordResetTokenGenerator.

- post_reset_redirect: The URL to redirect to after a successful password reset request.

- from_email: A valid email address. By default Django uses the DEFAULT_FROM_EMAIL.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

- html_email_template_name: The full name of a template to use for generating a text/html multipart email with the password reset link. By default, HTML email is not sent.

- extra_email_context: A dictionary of context data that will available in the email template.

Deprecated since version 1.8: The is_admin_site argument is deprecated and will be removed in Django 1.10.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

New in Django 1.9:
The extra_email_context parameter was added.

Template context:

- form: The form (see password_reset_form above) for resetting the user’s password.

Email template context:

- email: An alias for user.email

- user: The current User, according to the email form field. Only active users are able to reset their passwords (User.is_active is True).

- site_name: An alias for site.name. If you don’t have the site framework installed, this will be set to the value of request.META['SERVER_NAME']. For more on sites, see The “sites” framework.

- domain: An alias for site.domain. If you don’t have the site framework installed, this will be set to the value of request.get_host().

- protocol: http or https

- uid: The user’s primary key encoded in base 64.

- token: Token to check that the reset link is valid.

Sample registration/password_reset_email.html (email body template):

Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

The same template context is used for subject template. Subject must be single line plain text string.

password_reset_done(request, template_name='registration/password_reset_done.html', current_app=None, extra_context=None)

The page shown after a user has been emailed a link to reset their password. This view is called by default if the password_reset() view doesn’t have an explicit post_reset_redirect URL set.

URL name: password_reset_done

Note

If the email address provided does not exist in the system, the user is inactive, or has an unusable password, the user will still be redirected to this view but no email will be sent.

Optional arguments:

- template_name: The full name of a template to use. Defaults to registration/password_reset_done.html if not supplied.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

password_reset_confirm(request, uidb64=None, token=None, template_name='registration/password_reset_confirm.html', token_generator=default_token_generator, set_password_form=SetPasswordForm, post_reset_redirect=None, current_app=None, extra_context=None)

Presents a form for entering a new password.

URL name: password_reset_confirm

Optional arguments:

- uidb64: The user’s id encoded in base 64. Defaults to None.

- token: Token to check that the password is valid. Defaults to None.

- template_name: The full name of a template to display the confirm password view. Default value is registration/password_reset_confirm.html.

- token_generator: Instance of the class to check the password. This will default to default_token_generator, it’s an instance of django.contrib.auth.tokens.PasswordResetTokenGenerator.

- set_password_form: Form that will be used to set the password. Defaults to SetPasswordForm

- post_reset_redirect: URL to redirect after the password reset done. Defaults to None.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Template context:

- form: The form (see set_password_form above) for setting the new user’s password.

- validlink: Boolean, True if the link (combination of uidb64 and token) is valid or unused yet.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

password_reset_complete(request, template_name='registration/password_reset_complete.html', current_app=None, extra_context=None)

Presents a view which informs the user that the password has been successfully changed.

URL name: password_reset_complete

Optional arguments:

- template_name: The full name of a template to display the view. Defaults to registration/password_reset_complete.html.

- current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

- extra_context: A dictionary of context data that will be added to the default context data passed to the template.

Deprecated since version 1.9: The current_app parameter is deprecated and will be removed in Django 2.0. Callers should set request.current_app instead.

Helper functions

redirect_to_login(next, login_url=None, redirect_field_name='next')

Redirects to the login page, and then back to another URL after a successful login.

Required arguments:

- next: The URL to redirect to after a successful login.

Optional arguments:

- login_url: The URL of the login page to redirect to. Defaults to settings.LOGIN_URL if not supplied.

- redirect_field_name: The name of a GET field containing the URL to redirect to after log out. Overrides next if the given GET parameter is passed.

Built-in forms

If you don’t want to use the built-in views, but want the convenience of not having to write forms for this functionality, the authentication system provides several built-in forms located in django.contrib.auth.forms:

Note

The built-in authentication forms make certain assumptions about the user model that they are working with. If you’re using a custom User model, it may be necessary to define your own forms for the authentication system. For more information, refer to the documentation about using the built-in authentication forms with custom user models.

class AdminPasswordChangeForm

A form used in the admin interface to change a user’s password.

Takes the user as the first positional argument.

class AuthenticationForm

A form for logging a user in.

Takes request as its first positional argument, which is stored on the form instance for use by sub-classes.

confirm_login_allowed(user)

By default, AuthenticationForm rejects users whose is_active flag is set to False. You may override this behavior with a custom policy to determine which users can log in. Do this with a custom form that subclasses AuthenticationForm and overrides the confirm_login_allowed() method. This method should raise a ValidationError if the given user may not log in.

For example, to allow all users to log in regardless of “active” status:

from django.contrib.auth.forms import AuthenticationForm

class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
def confirm_login_allowed(self, user):
pass

Or to allow only some active users to log in:

class PickyAuthenticationForm(AuthenticationForm):
def confirm_login_allowed(self, user):
if not user.is_active:
raise forms.ValidationError(
_("This account is inactive."),
code='inactive',
)
if user.username.startswith('b'):
raise forms.ValidationError(
_("Sorry, accounts starting with 'b' aren't welcome here."),
code='no_b_users',
)

class PasswordChangeForm

A form for allowing a user to change their password.

class PasswordResetForm

A form for generating and emailing a one-time use link to reset a user’s password.

send_email(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None)

New in Django 1.8.

Uses the arguments to send an EmailMultiAlternatives. Can be overridden to customize how the email is sent to the user.

Parameters:

- subject_template_name – the template for the subject.

- email_template_name – the template for the email body.

- context – context passed to the subject_template, email_template, and html_email_template (if it is not None).

- from_email – the sender’s email.

- to_email – the email of the requester.

- html_email_template_name – the template for the HTML body; defaults to None, in which case a plain text email is sent.

By default, save() populates the context with the same variables that password_reset() passes to its email context.

class SetPasswordForm

A form that lets a user change their password without entering the old password.

class UserChangeForm

A form used in the admin interface to change a user’s information and permissions.

class UserCreationForm

A form for creating a new user.

Authentication data in templates

The currently logged-in user and their permissions are made available in the template context when you use RequestContext.

Technicality

Technically, these variables are only made available in the template context if you use RequestContext and the 'django.contrib.auth.context_processors.auth' context processor is enabled. It is in the default generated settings file. For more, see the RequestContext docs.

Users

When rendering a template RequestContext, the currently logged-in user, either a User instance or an AnonymousUser instance, is stored in the template variable {{ user }}:

{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}

This template context variable is not available if a RequestContext is not being used.

Permissions

The currently logged-in user’s permissions are stored in the template variable {{ perms }}. This is an instance of django.contrib.auth.context_processors.PermWrapper, which is a template-friendly proxy of permissions.

In the {{ perms }} object, single-attribute lookup is a proxy to User.has_module_perms. This example would display True if the logged-in user had any permissions in the foo app:

{{ perms.foo }}

Two-level-attribute lookup is a proxy to User.has_perm. This example would display True if the logged-in user had the permission foo.can_vote:

{{ perms.foo.can_vote }}

Thus, you can check permissions in template {% if %} statements:

{% if perms.foo %}
<p>You have permission to do something in the foo app.</p>
{% if perms.foo.can_vote %}
<p>You can vote!</p>
{% endif %}
{% if perms.foo.can_drive %}
<p>You can drive!</p>
{% endif %}
{% else %}
<p>You don't have permission to do anything in the foo app.</p>
{% endif %}

It is possible to also look permissions up by {% if in %} statements. For example:

{% if 'foo' in perms %}
{% if 'foo.can_vote' in perms %}
<p>In lookup works, too.</p>
{% endif %}
{% endif %}

Managing users in the admin

When you have both django.contrib.admin and django.contrib.auth installed, the admin provides a convenient way to view and manage users, groups, and permissions. Users can be created and deleted like any Django model. Groups can be created, and permissions can be assigned to users or groups. A log of user edits to models made within the admin is also stored and displayed.

Creating users

You should see a link to “Users” in the “Auth” section of the main admin index page. The “Add user” admin page is different than standard admin pages in that it requires you to choose a username and password before allowing you to edit the rest of the user’s fields.

Also note: if you want a user account to be able to create users using the Django admin site, you’ll need to give them permission to add users and change users (i.e., the “Add user” and “Change user” permissions). If an account has permission to add users but not to change them, that account won’t be able to add users. Why? Because if you have permission to add users, you have the power to create superusers, which can then, in turn, change other users. So Django requires add and change permissions as a slight security measure.

Be thoughtful about how you allow users to manage permissions. If you give a non-superuser the ability to edit users, this is ultimately the same as giving them superuser status because they will be able to elevate permissions of users including themselves!

Changing passwords

User passwords are not displayed in the admin (nor stored in the database), but the password storage details are displayed. Included in the display of this information is a link to a password change form that allows admins to change user passwords.

Password management in Django

Password management is something that should generally not be reinvented unnecessarily, and Django endeavors to provide a secure and flexible set of tools for managing user passwords. This document describes how Django stores passwords, how the storage hashing can be configured, and some utilities to work with hashed passwords.

See also

Even though users may use strong passwords, attackers might be able to eavesdrop on their connections. Use HTTPS to avoid sending passwords (or any other sensitive data) over plain HTTP connections because they will be vulnerable to password sniffing.

How Django stores passwords

Django provides a flexible password storage system and uses PBKDF2 by default.

The password attribute of a User object is a string in this format:

<algorithm>$<iterations>$<salt>$<hash>

Those are the components used for storing a User’s password, separated by the dollar-sign character and consist of: the hashing algorithm, the number of algorithm iterations (work factor), the random salt, and the resulting password hash. The algorithm is one of a number of one-way hashing or password storage algorithms Django can use; see below. Iterations describe the number of times the algorithm is run over the hash. Salt is the random seed used and the hash is the result of the one-way function.

By default, Django uses the PBKDF2 algorithm with a SHA256 hash, a password stretching mechanism recommended by NIST. This should be sufficient for most users: it’s quite secure, requiring massive amounts of computing time to break.

However, depending on your requirements, you may choose a different algorithm, or even use a custom algorithm to match your specific security situation. Again, most users shouldn’t need to do this – if you’re not sure, you probably don’t. If you do, please read on:

Django chooses the algorithm to use by consulting the PASSWORD_HASHERS setting. This is a list of hashing algorithm classes that this Django installation supports. The first entry in this list (that is, settings.PASSWORD_HASHERS[0]) will be used to store passwords, and all the other entries are valid hashers that can be used to check existing passwords. This means that if you want to use a different algorithm, you’ll need to modify PASSWORD_HASHERS to list your preferred algorithm first in the list.

The default for PASSWORD_HASHERS is:

PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]

This means that Django will use PBKDF2 to store all passwords, but will support checking passwords stored with PBKDF2SHA1, bcrypt, SHA1, etc. The next few sections describe a couple of common ways advanced users may want to modify this setting.

Using bcrypt with Django

Bcrypt is a popular password storage algorithm that’s specifically designed for long-term password storage. It’s not the default used by Django since it requires the use of third-party libraries, but since many people may want to use it Django supports bcrypt with minimal effort.

To use Bcrypt as your default storage algorithm, do the following:

1. Install the bcrypt library. This can be done by running pip install django[bcrypt], or by downloading the library and installing it with python setup.py install.

2. Modify PASSWORD_HASHERS to list BCryptSHA256PasswordHasher first. That is, in your settings file, you’d put:

PASSWORD_HASHERS = [
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]

(You need to keep the other entries in this list, or else Django won’t be able to upgrade passwords; see below).

That’s it – now your Django install will use Bcrypt as the default storage algorithm.

Password truncation with BCryptPasswordHasher

The designers of bcrypt truncate all passwords at 72 characters which means that bcrypt(password_with_100_chars) == bcrypt(password_with_100_chars[:72]). The original BCryptPasswordHasher does not have any special handling and thus is also subject to this hidden password length limit. BCryptSHA256PasswordHasher fixes this by first hashing the password using sha256. This prevents the password truncation and so should be preferred over the BCryptPasswordHasher. The practical ramification of this truncation is pretty marginal as the average user does not have a password greater than 72 characters in length and even being truncated at 72 the compute powered required to brute force bcrypt in any useful amount of time is still astronomical. Nonetheless, we recommend you use BCryptSHA256PasswordHasher anyway on the principle of “better safe than sorry”.

Other bcrypt implementations

There are several other implementations that allow bcrypt to be used with Django. Django’s bcrypt support is NOT directly compatible with these. To upgrade, you will need to modify the hashes in your database to be in the form bcrypt$(raw bcrypt output). For example: bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy.

Increasing the work factor

The PBKDF2 and bcrypt algorithms use a number of iterations or rounds of hashing. This deliberately slows down attackers, making attacks against hashed passwords harder. However, as computing power increases, the number of iterations needs to be increased. We’ve chosen a reasonable default (and will increase it with each release of Django), but you may wish to tune it up or down, depending on your security needs and available processing power. To do so, you’ll subclass the appropriate algorithm and override the iterations parameters. For example, to increase the number of iterations used by the default PBKDF2 algorithm:

1. Create a subclass of django.contrib.auth.hashers.PBKDF2PasswordHasher:

from django.contrib.auth.hashers import PBKDF2PasswordHasher

class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):
"""
A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.
"""
iterations = PBKDF2PasswordHasher.iterations * 100

Save this somewhere in your project. For example, you might put this in a file like myproject/hashers.py.

2. Add your new hasher as the first entry in PASSWORD_HASHERS:

PASSWORD_HASHERS = [
'myproject.hashers.MyPBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]

That’s it – now your Django install will use more iterations when it stores passwords using PBKDF2.

Password upgrading

When users log in, if their passwords are stored with anything other than the preferred algorithm, Django will automatically upgrade the algorithm to the preferred one. This means that old installs of Django will get automatically more secure as users log in, and it also means that you can switch to new (and better) storage algorithms as they get invented.

However, Django can only upgrade passwords that use algorithms mentioned in PASSWORD_HASHERS, so as you upgrade to new systems you should make sure never to remove entries from this list. If you do, users using unmentioned algorithms won’t be able to upgrade. Hashed passwords will be updated when increasing (or decreasing) the number of PBKDF2 iterations or bcrypt rounds.

Be aware that if all the passwords in your database aren’t encoded in the default hasher’s algorithm, you may be vulnerable to a user enumeration timing attack due to a difference between the duration of a login request for a user with a password encoded in a non-default algorithm and the duration of a login request for a nonexistent user (which runs the default hasher). You may be able to mitigate this by upgrading older password hashes.

Changed in Django 1.9:
Passwords updates when changing the number of bcrypt rounds was added.

Password upgrading without requiring a login

If you have an existing database with an older, weak hash such as MD5 or SHA1, you might want to upgrade those hashes yourself instead of waiting for the upgrade to happen when a user logs in (which may never happen if a user doesn’t return to your site). In this case, you can use a “wrapped” password hasher.

For this example, we’ll migrate a collection of SHA1 hashes to use PBKDF2(SHA1(password)) and add the corresponding password hasher for checking if a user entered the correct password on login. We assume we’re using the built-in User model and that our project has an accounts app. You can modify the pattern to work with any algorithm or with a custom user model.

First, we’ll add the custom hasher:

accounts/hashers.py

from django.contrib.auth.hashers import (
PBKDF2PasswordHasher, SHA1PasswordHasher,
)

class PBKDF2WrappedSHA1PasswordHasher(PBKDF2PasswordHasher):
algorithm = 'pbkdf2_wrapped_sha1'

def encode_sha1_hash(self, sha1_hash, salt, iterations=None):
return super(PBKDF2WrappedSHA1PasswordHasher, self).encode(sha1_hash, salt, iterations)

def encode(self, password, salt, iterations=None):
_, _, sha1_hash = SHA1PasswordHasher().encode(password, salt).split('$', 2)
return self.encode_sha1_hash(sha1_hash, salt, iterations)

The data migration might look something like:

accounts/migrations/0002_migrate_sha1_passwords.py

from django.db import migrations

from ..hashers import PBKDF2WrappedSHA1PasswordHasher

def forwards_func(apps, schema_editor):
User = apps.get_model('auth', 'User')
users = User.objects.filter(password__startswith='sha1$')
hasher = PBKDF2WrappedSHA1PasswordHasher()
for user in users:
algorithm, salt, sha1_hash = user.password.split('$', 2)
user.password = hasher.encode_sha1_hash(sha1_hash, salt)
user.save(update_fields=['password'])

class Migration(migrations.Migration):

dependencies = [
('accounts', '0001_initial'),
# replace this with the latest migration in contrib.auth
('auth', '####_migration_name'),
]

operations = [
migrations.RunPython(forwards_func),
]

Be aware that this migration will take on the order of several minutes for several thousand users, depending on the speed of your hardware.

Finally, we’ll add a PASSWORD_HASHERS setting:

mysite/settings.py

PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'accounts.hashers.PBKDF2WrappedSHA1PasswordHasher',
]

Include any other hashers that your site uses in this list.

Writing your own hasher

New in Django 1.9.3.

If you write your own password hasher that contains a work factor such as a number of iterations, you should implement a harden_runtime(self, password, encoded) method to bridge the runtime gap between the work factor supplied in the encoded password and the default work factor of the hasher. This prevents a user enumeration timing attack due to difference between a login request for a user with a password encoded in an older number of iterations and a nonexistent user (which runs the default hasher’s default number of iterations).

Taking PBKDF2 as example, if encoded contains 20,000 iterations and the hasher’s default iterations is 30,000, the method should run password through another 10,000 iterations of PBKDF2.

If your hasher doesn’t have a work factor, implement the method as a no-op (pass).

Manually managing a user’s password

The django.contrib.auth.hashers module provides a set of functions to create and validate hashed password. You can use them independently from the User model.

check_password(password, encoded)[source]

If you’d like to manually authenticate a user by comparing a plain-text password to the hashed password in the database, use the convenience function check_password(). It takes two arguments: the plain-text password to check, and the full value of a user’s password field in the database to check against, and returns True if they match, False otherwise.

make_password(password, salt=None, hasher='default')[source]

Creates a hashed password in the format used by this application. It takes one mandatory argument: the password in plain-text. Optionally, you can provide a salt and a hashing algorithm to use, if you don’t want to use the defaults (first entry of PASSWORD_HASHERS setting). Currently supported algorithms are: 'pbkdf2_sha256', 'pbkdf2_sha1', 'bcrypt_sha256' (see Using bcrypt with Django), 'bcrypt', 'sha1', 'md5', 'unsalted_md5' (only for backward compatibility) and 'crypt' if you have the crypt library installed. If the password argument is None, an unusable password is returned (a one that will be never accepted by check_password()).

is_password_usable(encoded_password)[source]

Checks if the given string is a hashed password that has a chance of being verified against check_password().

Password validation

New in Django 1.9.

Users often choose poor passwords. To help mitigate this problem, Django offers pluggable password validation. You can configure multiple password validators at the same time. A few validators are included in Django, but it’s simple to write your own as well.

Each password validator must provide a help text to explain the requirements to the user, validate a given password and return an error message if it does not meet the requirements, and optionally receive passwords that have been set. Validators can also have optional settings to fine tune their behavior.

Validation is controlled by the AUTH_PASSWORD_VALIDATORS setting. By default, validators are used in the forms to reset or change passwords. The default for the setting is an empty list, which means no validators are applied. In new projects created with the default startproject template, a simple set of validators is enabled.

Note

Password validation can prevent the use of many types of weak passwords. However, the fact that a password passes all the validators doesn’t guarantee that it is a strong password. There are many factors that can weaken a password that are not detectable by even the most advanced password validators.

Enabling password validation

Password validation is configured in the AUTH_PASSWORD_VALIDATORS setting:

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 9,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]

This example enables all four included validators:

- UserAttributeSimilarityValidator, which checks the similarity between the password and a set of attributes of the user.

- MinimumLengthValidator, which simply checks whether the password meets a minimum length. This validator is configured with a custom option: it now requires the minimum length to be nine characters, instead of the default eight.

- CommonPasswordValidator, which checks whether the password occurs in a list of common passwords. By default, it compares to an included list of 1000 common passwords.

- NumericPasswordValidator, which checks whether the password isn’t entirely numeric.

For UserAttributeSimilarityValidator and CommonPasswordValidator, we’re simply using the default settings in this example. NumericPasswordValidator has no settings.

The help texts and any errors from password validators are always returned in the order they are listed in AUTH_PASSWORD_VALIDATORS.

Included validators

Django includes four validators:

class MinimumLengthValidator(min_length=8)[source]

Validates whether the password meets a minimum length. The minimum length can be customized with the min_length parameter.

class UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7)[source]

Validates whether the password is sufficiently different from certain attributes of the user.

The user_attributes parameter should be an iterable of names of user attributes to compare to. If this argument is not provided, the default is used: 'username', 'first_name', 'last_name', 'email'. Attributes that don’t exist are ignored.

The maximum similarity the password can have, before it is rejected, can be set with the max_similarity parameter, on a scale of 0 to 1. A setting of 0 will cause all passwords to be rejected, whereas a setting of 1 will cause it to only reject passwords that are identical to an attribute’s value.

class CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH)[source]

Validates whether the password is not a common password. By default, this checks against a list of 1000 common password created by Mark Burnett.

The password_list_path can be set to the path of a custom file of common passwords. This file should contain one password per line and may be plain text or gzipped.

class NumericPasswordValidator[source]

Validates whether the password is not entirely numeric.

Integrating validation

There are a few functions in django.contrib.auth.password_validation that you can call from your own forms or other code to integrate password validation. This can be useful if you use custom forms for password setting, or if you have API calls that allow passwords to be set, for example.

validate_password(password, user=None, password_validators=None)[source]

Validates a password. If all validators find the password valid, returns None. If one or more validators reject the password, raises a ValidationError with all the error messages from the validators.

The user object is optional: if it’s not provided, some validators may not be able to perform any validation and will accept any password.

password_changed(password, user=None, password_validators=None)[source]

Informs all validators that the password has been changed. This can be used by validators such as one that prevents password reuse. This should be called once the password has been successfully changed.

For subclasses of AbstractBaseUser, the password field will be marked as “dirty” when calling set_password() which triggers a call to password_changed() after the user is saved.

password_validators_help_texts(password_validators=None)[source]

Returns a list of the help texts of all validators. These explain the password requirements to the user.

password_validators_help_text_html(password_validators=None)

Returns an HTML string with all help texts in an <ul>. This is helpful when adding password validation to forms, as you can pass the output directly to the help_text parameter of a form field.

get_password_validators(validator_config)[source]

Returns a set of validator objects based on the validator_config parameter. By default, all functions use the validators defined in AUTH_PASSWORD_VALIDATORS, but by calling this function with an alternate set of validators and then passing the result into the password_validators parameter of the other functions, your custom set of validators will be used instead. This is useful when you have a typical set of validators to use for most scenarios, but also have a special situation that requires a custom set. If you always use the same set of validators, there is no need to use this function, as the configuration from AUTH_PASSWORD_VALIDATORS is used by default.

The structure of validator_config is identical to the structure of AUTH_PASSWORD_VALIDATORS. The return value of this function can be passed into the password_validators parameter of the functions listed above.

Note that where the password is passed to one of these functions, this should always be the clear text password - not a hashed password.

Writing your own validator

If Django’s built-in validators are not sufficient, you can write your own password validators. Validators are fairly simple classes. They must implement two methods:

- validate(self, password, user=None): validate a password. Return None if the password is valid, or raise a ValidationError with an error message if the password is not valid. You must be able to deal with user being None - if that means your validator can’t run, simply return None for no error.

- get_help_text(): provide a help text to explain the requirements to the user.

Any items in the OPTIONS in AUTH_PASSWORD_VALIDATORS for your validator will be passed to the constructor. All constructor arguments should have a default value.

Here’s a basic example of a validator, with one optional setting:

from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _

class MinimumLengthValidator(object):
def __init__(self, min_length=8):
self.min_length = min_length

def validate(self, password, user=None):
if len(password) < self.min_length:
raise ValidationError(
_("This password must contain at least %(min_length)d characters."),
code='password_too_short',
params={'min_length': self.min_length},
)

def get_help_text(self):
return _(
"Your password must contain at least %(min_length)d characters."
% {'min_length': self.min_length}
)

You can also implement password_changed(password, user=None), which will be called after a successful password change. That can be used to prevent password reuse, for example. However, if you decide to store a user’s previous passwords, you should never do so in clear text.

Customizing authentication in Django

The authentication that comes with Django is good enough for most common cases, but you may have needs not met by the out-of-the-box defaults. To customize authentication to your projects needs involves understanding what points of the provided system are extensible or replaceable. This document provides details about how the auth system can be customized.

Authentication backends provide an extensible system for when a username and password stored with the User model need to be authenticated against a different service than Django’s default.

You can give your models custom permissions that can be checked through Django’s authorization system.

You can extend the default User model, or substitute a completely customized model.

Other authentication sources

There may be times you have the need to hook into another authentication source – that is, another source of usernames and passwords or authentication methods.

For example, your company may already have an LDAP setup that stores a username and password for every employee. It’d be a hassle for both the network administrator and the users themselves if users had separate accounts in LDAP and the Django-based applications.

So, to handle situations like this, the Django authentication system lets you plug in other authentication sources. You can override Django’s default database-based scheme, or you can use the default system in tandem with other systems.

See the authentication backend reference for information on the authentication backends included with Django.

Specifying authentication backends

Behind the scenes, Django maintains a list of “authentication backends” that it checks for authentication. When somebody calls django.contrib.auth.authenticate() – as described in How to log a user in – Django tries authenticating across all of its authentication backends. If the first authentication method fails, Django tries the second one, and so on, until all backends have been attempted.

The list of authentication backends to use is specified in the AUTHENTICATION_BACKENDS setting. This should be a list of Python path names that point to Python classes that know how to authenticate. These classes can be anywhere on your Python path.

By default, AUTHENTICATION_BACKENDS is set to:

['django.contrib.auth.backends.ModelBackend']

That’s the basic authentication backend that checks the Django users database and queries the built-in permissions. It does not provide protection against brute force attacks via any rate limiting mechanism. You may either implement your own rate limiting mechanism in a custom auth backend, or use the mechanisms provided by most Web servers.

The order of AUTHENTICATION_BACKENDS matters, so if the same username and password is valid in multiple backends, Django will stop processing at the first positive match.

If a backend raises a PermissionDenied exception, authentication will immediately fail. Django won’t check the backends that follow.

Note

Once a user has authenticated, Django stores which backend was used to authenticate the user in the user’s session, and re-uses the same backend for the duration of that session whenever access to the currently authenticated user is needed. This effectively means that authentication sources are cached on a per-session basis, so if you change AUTHENTICATION_BACKENDS, you’ll need to clear out session data if you need to force users to re-authenticate using different methods. A simple way to do that is simply to execute Session.objects.all().delete().

Writing an authentication backend

An authentication backend is a class that implements two required methods: get_user(user_id) and authenticate(**credentials), as well as a set of optional permission related authorization methods.

The get_user method takes a user_id – which could be a username, database ID or whatever, but has to be the primary key of your User object – and returns a User object.

The authenticate method takes credentials as keyword arguments. Most of the time, it’ll just look like this:

class MyBackend(object):
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.
...

But it could also authenticate a token, like so:

class MyBackend(object):
def authenticate(self, token=None):
# Check the token and return a User.
...

Either way, authenticate should check the credentials it gets, and it should return a User object that matches those credentials, if the credentials are valid. If they’re not valid, it should return None.

The Django admin is tightly coupled to the Django User object. The best way to deal with this is to create a Django User object for each user that exists for your backend (e.g., in your LDAP directory, your external SQL database, etc.) You can either write a script to do this in advance, or your authenticate method can do it the first time a user logs in.

Here’s an example backend that authenticates against a username and password variable defined in your settings.py file and creates a Django User object the first time a user authenticates:

from django.conf import settings
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User

class SettingsBackend(object):
"""
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.

Use the login name, and a hash of the password. For example:

ADMIN_LOGIN = 'admin'
ADMIN_PASSWORD = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
"""

def authenticate(self, username=None, password=None):
login_valid = (settings.ADMIN_LOGIN == username)
pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
if login_valid and pwd_valid:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# Create a new user. Note that we can set password
# to anything, because it won't be checked; the password
# from settings.py will.
user = User(username=username, password='get from settings.py')
user.is_staff = True
user.is_superuser = True
user.save()
return user
return None

def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

Handling authorization in custom backends

Custom auth backends can provide their own permissions.

The user model will delegate permission lookup functions (get_group_permissions(), get_all_permissions(), has_perm(), and has_module_perms()) to any authentication backend that implements these functions.

The permissions given to the user will be the superset of all permissions returned by all backends. That is, Django grants a permission to a user that any one backend grants.

New in Django 1.8:
If a backend raises a PermissionDenied exception in has_perm() or has_module_perms(), the authorization will immediately fail and Django won’t check the backends that follow.

The simple backend above could implement permissions for the magic admin fairly simply:

class SettingsBackend(object):
...
def has_perm(self, user_obj, perm, obj=None):
if user_obj.username == settings.ADMIN_LOGIN:
return True
else:
return False

This gives full permissions to the user granted access in the above example. Notice that in addition to the same arguments given to the associated django.contrib.auth.models.User functions, the backend auth functions all take the user object, which may be an anonymous user, as an argument.

A full authorization implementation can be found in the ModelBackend class in django/contrib/auth/backends.py, which is the default backend and queries the auth_permission table most of the time. If you wish to provide custom behavior for only part of the backend API, you can take advantage of Python inheritance and subclass ModelBackend instead of implementing the complete API in a custom backend.

Authorization for anonymous users

An anonymous user is one that is not authenticated i.e. they have provided no valid authentication details. However, that does not necessarily mean they are not authorized to do anything. At the most basic level, most websites authorize anonymous users to browse most of the site, and many allow anonymous posting of comments etc.

Django’s permission framework does not have a place to store permissions for anonymous users. However, the user object passed to an authentication backend may be an django.contrib.auth.models.AnonymousUser object, allowing the backend to specify custom authorization behavior for anonymous users. This is especially useful for the authors of re-usable apps, who can delegate all questions of authorization to the auth backend, rather than needing settings, for example, to control anonymous access.

Authorization for inactive users

An inactive user is a one that is authenticated but has its attribute is_active set to False. However this does not mean they are not authorized to do anything. For example they are allowed to activate their account.

The support for anonymous users in the permission system allows for a scenario where anonymous users have permissions to do something while inactive authenticated users do not.

Do not forget to test for the is_active attribute of the user in your own backend permission methods.

Handling object permissions

Django’s permission framework has a foundation for object permissions, though there is no implementation for it in the core. That means that checking for object permissions will always return False or an empty list (depending on the check performed). An authentication backend will receive the keyword parameters obj and user_obj for each object related authorization method and can return the object level permission as appropriate.

Custom permissions

To create custom permissions for a given model object, use the permissions model Meta attribute.

This example Task model creates three custom permissions, i.e., actions users can or cannot do with Task instances, specific to your application:

class Task(models.Model):
...
class Meta:
permissions = (
("view_task", "Can see available tasks"),
("change_task_status", "Can change the status of tasks"),
("close_task", "Can remove a task by setting its status as closed"),
)

The only thing this does is create those extra permissions when you run manage.py migrate (the function that creates permissions is connected to the post_migrate signal). Your code is in charge of checking the value of these permissions when a user is trying to access the functionality provided by the application (viewing tasks, changing the status of tasks, closing tasks.) Continuing the above example, the following checks if a user may view tasks:

user.has_perm('app.view_task')

Extending the existing User model

There are two ways to extend the default User model without substituting your own model. If the changes you need are purely behavioral, and don’t require any change to what is stored in the database, you can create a proxy model based on User. This allows for any of the features offered by proxy models including default ordering, custom managers, or custom model methods.

If you wish to store information related to User, you can use a OneToOneField to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user. For example you might create an Employee model:

from django.contrib.auth.models import User

class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.CharField(max_length=100)

Assuming an existing Employee Fred Smith who has both a User and Employee model, you can access the related information using Django’s standard related model conventions:

>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department

To add a profile model’s fields to the user page in the admin, define an InlineModelAdmin (for this example, we’ll use a StackedInline) in your app’s admin.py and add it to a UserAdmin class which is registered with the User class:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User

from my_user_profile_app.models import Employee

# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class EmployeeInline(admin.StackedInline):
model = Employee
can_delete = False
verbose_name_plural = 'employee'

# Define a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (EmployeeInline, )

# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

These profile models are not special in any way - they are just Django models that happen to have a one-to-one link with a User model. As such, they do not get auto created when a user is created, but a django.db.models.signals.post_save could be used to create or update related models as appropriate.

Note that using related models results in additional queries or joins to retrieve the related data, and depending on your needs substituting the User model and adding the related fields may be your better option. However existing links to the default User model within your project’s apps may justify the extra database load.

Substituting a custom User model

Some kinds of projects may have authentication requirements for which Django’s built-in User model is not always appropriate. For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.

Django allows you to override the default User model by providing a value for the AUTH_USER_MODEL setting that references a custom model:

AUTH_USER_MODEL = 'myapp.MyUser'

This dotted pair describes the name of the Django app (which must be in your INSTALLED_APPS), and the name of the Django model that you wish to use as your User model.

Warning

Changing AUTH_USER_MODEL has a big effect on your database structure. It changes the tables that are available, and it will affect the construction of foreign keys and many-to-many relationships. If you intend to set AUTH_USER_MODEL, you should set it before creating any migrations or running manage.py migrate for the first time.

Changing this setting after you have tables created is not supported by makemigrations and will result in you having to manually fix your schema, port your data from the old user table, and possibly manually reapply some migrations.

Warning

Due to limitations of Django’s dynamic dependency feature for swappable models, you must ensure that the model referenced by AUTH_USER_MODEL is created in the first migration of its app (usually called 0001_initial); otherwise, you will have dependency issues.

In addition, you may run into a CircularDependencyError when running your migrations as Django won’t be able to automatically break the dependency loop due to the dynamic dependency. If you see this error, you should break the loop by moving the models depended on by your User model into a second migration (you can try making two normal models that have a ForeignKey to each other and seeing how makemigrations resolves that circular dependency if you want to see how it’s usually done)

Reusable apps and AUTH_USER_MODEL

Reusable apps shouldn’t implement a custom user model. A project may use many apps, and two reusable apps that implemented a custom user model couldn’t be used together. If you need to store per user information in your app, use a ForeignKey or OneToOneField to settings.AUTH_USER_MODEL as described below.

Referencing the User model

If you reference User directly (for example, by referring to it in a foreign key), your code will not work in projects where the AUTH_USER_MODEL setting has been changed to a different User model.

get_user_model()[source]

Instead of referring to User directly, you should reference the user model using django.contrib.auth.get_user_model(). This method will return the currently active User model – the custom User model if one is specified, or User otherwise.

When you define a foreign key or many-to-many relations to the User model, you should specify the custom model using the AUTH_USER_MODEL setting. For example:

from django.conf import settings
from django.db import models

class Article(models.Model):
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)

When connecting to signals sent by the User model, you should specify the custom model using the AUTH_USER_MODEL setting. For example:

from django.conf import settings
from django.db.models.signals import post_save

def post_save_receiver(sender, instance, created, **kwargs):
pass

post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)

Generally speaking, you should reference the User model with the AUTH_USER_MODEL setting in code that is executed at import time. get_user_model() only works once Django has imported all models.

Specifying a custom User model

Model design considerations

Think carefully before handling information not directly related to authentication in your custom User Model.

It may be better to store app-specific user information in a model that has a relation with the User model. That allows each app to specify its own user data requirements without risking conflicts with other apps. On the other hand, queries to retrieve this related information will involve a database join, which may have an effect on performance.

Django expects your custom User model to meet some minimum requirements.

1. If you use the default authentication backend, then your model must have a single unique field that can be used for identification purposes. This can be a username, an email address, or any other unique attribute. A non-unique username field is allowed if you use a custom authentication backend that can support it.

2. Your model must provide a way to address the user in a “short” and “long” form. The most common interpretation of this would be to use the user’s given name as the “short” identifier, and the user’s full name as the “long” identifier. However, there are no constraints on what these two methods return - if you want, they can return exactly the same value.

Changed in Django 1.8:
Older versions of Django required your model to have an integer primary key as well.

The easiest way to construct a compliant custom User model is to inherit from AbstractBaseUser. AbstractBaseUser provides the core implementation of a User model, including hashed passwords and tokenized password resets. You must then provide some key implementation details:

class models.CustomUser

USERNAME_FIELD

A string describing the name of the field on the User model that is used as the unique identifier. This will usually be a username of some kind, but it can also be an email address, or any other unique identifier. The field must be unique (i.e., have unique=True set in its definition), unless you use a custom authentication backend that can support non-unique usernames.

In the following example, the field identifier is used as the identifying field:

class MyUser(AbstractBaseUser):
identifier = models.CharField(max_length=40, unique=True)
...
USERNAME_FIELD = 'identifier'

New in Django 1.8.

USERNAME_FIELD now supports ForeignKeys. Since there is no way to pass model instances during the createsuperuser prompt, expect the user to enter the value of to_field value (the primary_key by default) of an existing instance.

REQUIRED_FIELDS

A list of the field names that will be prompted for when creating a user via the createsuperuser management command. The user will be prompted to supply a value for each of these fields. It must include any field for which blank is False or undefined and may include additional fields you want prompted for when a user is created interactively. REQUIRED_FIELDS has no effect in other parts of Django, like creating a user in the admin.

For example, here is the partial definition for a User model that defines two required fields - a date of birth and height:

class MyUser(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']

Note

REQUIRED_FIELDS must contain all required fields on your User model, but should not contain the USERNAME_FIELD or password as these fields will always be prompted for.

New in Django 1.8.

REQUIRED_FIELDS now supports ForeignKeys. Since there is no way to pass model instances during the createsuperuser prompt, expect the user to enter the value of to_field value (the primary_key by default) of an existing instance.

is_active

A boolean attribute that indicates whether the user is considered “active”. This attribute is provided as an attribute on AbstractBaseUser defaulting to True. How you choose to implement it will depend on the details of your chosen auth backends. See the documentation of the is_active attribute on the built-in user model for details.

get_full_name()

A longer formal identifier for the user. A common interpretation would be the full name of the user, but it can be any string that identifies the user.

get_short_name()

A short, informal identifier for the user. A common interpretation would be the first name of the user, but it can be any string that identifies the user in an informal way. It may also return the same value as django.contrib.auth.models.User.get_full_name().

Importing AbstractBaseUser

New in Django 1.9.

AbstractBaseUser and BaseUserManager are importable from django.contrib.auth.base_user so that they can be imported without including django.contrib.auth in INSTALLED_APPS (this raised a deprecation warning in older versions and is no longer supported in Django 1.9).

The following methods are available on any subclass of AbstractBaseUser:

class models.AbstractBaseUser

get_username()

Returns the value of the field nominated by USERNAME_FIELD.

is_anonymous()

Always returns False. This is a way of differentiating from AnonymousUser objects. Generally, you should prefer using is_authenticated() to this method.

is_authenticated()

Always returns True. This is a way to tell if the user has been authenticated. This does not imply any permissions, and doesn’t check if the user is active - it only indicates that the user has provided a valid username and password.

set_password(raw_password)

Sets the user’s password to the given raw string, taking care of the password hashing. Doesn’t save the AbstractBaseUser object.

When the raw_password is None, the password will be set to an unusable password, as if set_unusable_password() were used.

check_password(raw_password)

Returns True if the given raw string is the correct password for the user. (This takes care of the password hashing in making the comparison.)

set_unusable_password()

Marks the user as having no password set. This isn’t the same as having a blank string for a password. check_password() for this user will never return True. Doesn’t save the AbstractBaseUser object.

You may need this if authentication for your application takes place against an existing external source such as an LDAP directory.

has_usable_password()

Returns False if set_unusable_password() has been called for this user.

get_session_auth_hash()

Returns an HMAC of the password field. Used for Session invalidation on password change.

You should also define a custom manager for your User model. If your User model defines username, email, is_staff, is_active, is_superuser, last_login, and date_joined fields the same as Django’s default User, you can just install Django’s UserManager; however, if your User model defines different fields, you will need to define a custom manager that extends BaseUserManager providing two additional methods:

class models.CustomUserManager

create_user(*username_field*, password=None, **other_fields)

The prototype of create_user() should accept the username field, plus all required fields as arguments. For example, if your user model uses email as the username field, and has date_of_birth as a required field, then create_user should be defined as:

def create_user(self, email, date_of_birth, password=None):
# create user here
...

create_superuser(*username_field*, password, **other_fields)

The prototype of create_superuser() should accept the username field, plus all required fields as arguments. For example, if your user model uses email as the username field, and has date_of_birth as a required field, then create_superuser should be defined as:

def create_superuser(self, email, date_of_birth, password):
# create superuser here
...

Unlike create_user(), create_superuser() must require the caller to provide a password.

BaseUserManager provides the following utility methods:

class models.BaseUserManager

classmethod normalize_email(email)

Normalizes email addresses by lowercasing the domain portion of the email address.

get_by_natural_key(username)

Retrieves a user instance using the contents of the field nominated by USERNAME_FIELD.

make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')

Returns a random password with the given length and given string of allowed characters. Note that the default value of allowed_chars doesn’t contain letters that can cause user confusion, including:

- i, l, I, and 1 (lowercase letter i, lowercase letter L, uppercase letter i, and the number one)

- o, O, and 0 (lowercase letter o, uppercase letter o, and zero)

Extending Django’s default User

If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you could simply subclass django.contrib.auth.models.AbstractUser and add your custom profile fields, although we’d recommend a separate model as described in the “Model design considerations” note of Specifying a custom User model. AbstractUser provides the full implementation of the default User as an abstract model.

Custom users and the built-in auth forms

Django’s built-in forms and views make certain assumptions about the user model that they are working with.

The following forms are compatible with any subclass of AbstractBaseUser:

- AuthenticationForm: Uses the username field specified by USERNAME_FIELD.

- SetPasswordForm

- PasswordChangeForm

- AdminPasswordChangeForm

The following forms make assumptions about the user model and can be used as-is if those assumptions are met:

- PasswordResetForm: Assumes that the user model has a field named email that can be used to identify the user and a boolean field named is_active to prevent password resets for inactive users.

Finally, the following forms are tied to User and need to be rewritten or extended to work with a custom user model:

- UserCreationForm

- UserChangeForm

If your custom user model is a simple subclass of AbstractUser, then you can extend these forms in this manner:

from django.contrib.auth.forms import UserCreationForm
from myapp.models import CustomUser

class CustomUserCreationForm(UserCreationForm):

class Meta(UserCreationForm.Meta):
model = CustomUser
fields = UserCreationForm.Meta.fields + ('custom_field',)

Custom users and django.contrib.admin

If you want your custom User model to also work with Admin, your User model must define some additional attributes and methods. These methods allow the admin to control access of the User to admin content:

class models.CustomUser

is_staff

Returns True if the user is allowed to have access to the admin site.

is_active

Returns True if the user account is currently active.

has_perm(perm, obj=None):

Returns True if the user has the named permission. If obj is provided, the permission needs to be checked against a specific object instance.

has_module_perms(app_label):

Returns True if the user has permission to access models in the given app.

You will also need to register your custom User model with the admin. If your custom User model extends django.contrib.auth.models.AbstractUser, you can use Django’s existing django.contrib.auth.admin.UserAdmin class. However, if your User model extends AbstractBaseUser, you’ll need to define a custom ModelAdmin class. It may be possible to subclass the default django.contrib.auth.admin.UserAdmin; however, you’ll need to override any of the definitions that refer to fields on django.contrib.auth.models.AbstractUser that aren’t on your custom User class.

Custom users and permissions

To make it easy to include Django’s permission framework into your own User class, Django provides PermissionsMixin. This is an abstract model you can include in the class hierarchy for your User model, giving you all the methods and database fields necessary to support Django’s permission model.

PermissionsMixin provides the following methods and attributes:

class models.PermissionsMixin

is_superuser

Boolean. Designates that this user has all permissions without explicitly assigning them.

get_group_permissions(obj=None)

Returns a set of permission strings that the user has, through their groups.

If obj is passed in, only returns the group permissions for this specific object.

get_all_permissions(obj=None)

Returns a set of permission strings that the user has, both through group and user permissions.

If obj is passed in, only returns the permissions for this specific object.

has_perm(perm, obj=None)

Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>" (see permissions). If the user is inactive, this method will always return False.

If obj is passed in, this method won’t check for a permission for the model, but for this specific object.

has_perms(perm_list, obj=None)

Returns True if the user has each of the specified permissions, where each perm is in the format "<app label>.<permission codename>". If the user is inactive, this method will always return False.

If obj is passed in, this method won’t check for permissions for the model, but for the specific object.

has_module_perms(package_name)

Returns True if the user has any permissions in the given package (the Django app label). If the user is inactive, this method will always return False.

PermissionsMixin and ModelBackend

If you don’t include the PermissionsMixin, you must ensure you don’t invoke the permissions methods on ModelBackend. ModelBackend assumes that certain fields are available on your user model. If your User model doesn’t provide those fields, you will receive database errors when you check permissions.

Custom users and proxy models

One limitation of custom User models is that installing a custom User model will break any proxy model extending User. Proxy models must be based on a concrete base class; by defining a custom User model, you remove the ability of Django to reliably identify the base class.

If your project uses proxy models, you must either modify the proxy to extend the User model that is currently in use in your project, or merge your proxy’s behavior into your User subclass.

A full example

Here is an example of an admin-compliant custom user app. This user model uses an email address as the username, and has a required date of birth; it provides no permission checking, beyond a simple admin flag on the user account. This model would be compatible with all the built-in auth forms and views, except for the User creation forms. This example illustrates how most of the components work together, but is not intended to be copied directly into projects for production use.

This code would all live in a models.py file for a custom authentication app:

from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)

class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')

user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)

user.set_password(password)
user.save(using=self._db)
return user

def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
date_of_birth=date_of_birth,
)
user.is_admin = True
user.save(using=self._db)
return user

class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)

objects = MyUserManager()

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']

def get_full_name(self):
# The user is identified by their email address
return self.email

def get_short_name(self):
# The user is identified by their email address
return self.email

def __str__(self):              # __unicode__ on Python 2
return self.email

def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True

def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True

@property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin

Then, to register this custom User model with Django’s admin, the following code would be required in the app’s admin.py file:

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from customauth.models import MyUser

class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

class Meta:
model = MyUser
fields = ('email', 'date_of_birth')

def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2

def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user

class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()

class Meta:
model = MyUser
fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')

def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]

class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm

# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('date_of_birth',)}),
('Permissions', {'fields': ('is_admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()

# Now register the new UserAdmin...
admin.site.register(MyUser, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)

Finally, specify the custom model as the default user model for your project using the AUTH_USER_MODEL setting in your settings.py:

AUTH_USER_MODEL = 'customauth.MyUser'

Django’s cache framework

A fundamental trade-off in dynamic websites is, well, they’re dynamic. Each time a user requests a page, the Web server makes all sorts of calculations – from database queries to template rendering to business logic – to create the page that your site’s visitor sees. This is a lot more expensive, from a processing-overhead perspective, than your standard read-a-file-off-the-filesystem server arrangement.

For most Web applications, this overhead isn’t a big deal. Most Web applications aren’t washingtonpost.com or slashdot.org; they’re simply small- to medium-sized sites with so-so traffic. But for medium- to high-traffic sites, it’s essential to cut as much overhead as possible.

That’s where caching comes in.

To cache something is to save the result of an expensive calculation so that you don’t have to perform the calculation next time. Here’s some pseudocode explaining how this would work for a dynamically generated Web page:

given a URL, try finding that page in the cache
if the page is in the cache:
return the cached page
else:
generate the page
save the generated page in the cache (for next time)
return the generated page

Django comes with a robust cache system that lets you save dynamic pages so they don’t have to be calculated for each request. For convenience, Django offers different levels of cache granularity: You can cache the output of specific views, you can cache only the pieces that are difficult to produce, or you can cache your entire site.

Django also works well with “downstream” caches, such as Squid and browser-based caches. These are the types of caches that you don’t directly control but to which you can provide hints (via HTTP headers) about which parts of your site should be cached, and how.

See also

The Cache Framework design philosophy explains a few of the design decisions of the framework.

Setting up the cache

The cache system requires a small amount of setup. Namely, you have to tell it where your cached data should live – whether in a database, on the filesystem or directly in memory. This is an important decision that affects your cache’s performance; yes, some cache types are faster than others.

Your cache preference goes in the CACHES setting in your settings file. Here’s an explanation of all available values for CACHES.

Memcached

The fastest, most efficient type of cache supported natively by Django, Memcached is an entirely memory-based cache server, originally developed to handle high loads at LiveJournal.com and subsequently open-sourced by Danga Interactive. It is used by sites such as Facebook and Wikipedia to reduce database access and dramatically increase site performance.

Memcached runs as a daemon and is allotted a specified amount of RAM. All it does is provide a fast interface for adding, retrieving and deleting data in the cache. All data is stored directly in memory, so there’s no overhead of database or filesystem usage.

After installing Memcached itself, you’ll need to install a Memcached binding. There are several Python Memcached bindings available; the two most common are python-memcached and pylibmc.

To use Memcached with Django:

- Set BACKEND to django.core.cache.backends.memcached.MemcachedCache or django.core.cache.backends.memcached.PyLibMCCache (depending on your chosen memcached binding)

- Set LOCATION to ip:port values, where ip is the IP address of the Memcached daemon and port is the port on which Memcached is running, or to a unix:path value, where path is the path to a Memcached Unix socket file.

In this example, Memcached is running on localhost (127.0.0.1) port 11211, using the python-memcached binding:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}

In this example, Memcached is available through a local Unix socket file /tmp/memcached.sock using the python-memcached binding:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
}

When using the pylibmc binding, do not include the unix:/ prefix:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '/tmp/memcached.sock',
}
}

One excellent feature of Memcached is its ability to share a cache over multiple servers. This means you can run Memcached daemons on multiple machines, and the program will treat the group of machines as a single cache, without the need to duplicate cache values on each machine. To take advantage of this feature, include all server addresses in LOCATION, either separated by semicolons or as a list.

In this example, the cache is shared over Memcached instances running on IP address 172.19.26.240 and 172.19.26.242, both on port 11211:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}

In the following example, the cache is shared over Memcached instances running on the IP addresses 172.19.26.240 (port 11211), 172.19.26.242 (port 11212), and 172.19.26.244 (port 11213):

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11212',
'172.19.26.244:11213',
]
}
}

A final point about Memcached is that memory-based caching has a disadvantage: because the cached data is stored in memory, the data will be lost if your server crashes. Clearly, memory isn’t intended for permanent data storage, so don’t rely on memory-based caching as your only data storage. Without a doubt, none of the Django caching backends should be used for permanent storage – they’re all intended to be solutions for caching, not storage – but we point this out here because memory-based caching is particularly temporary.

Database caching

Django can store its cached data in your database. This works best if you’ve got a fast, well-indexed database server.

To use a database table as your cache backend:

- Set BACKEND to django.core.cache.backends.db.DatabaseCache

- Set LOCATION to tablename, the name of the database table. This name can be whatever you want, as long as it’s a valid table name that’s not already being used in your database.

In this example, the cache table’s name is my_cache_table:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
}
}

Creating the cache table

Before using the database cache, you must create the cache table with this command:

python manage.py createcachetable

This creates a table in your database that is in the proper format that Django’s database-cache system expects. The name of the table is taken from LOCATION.

If you are using multiple database caches, createcachetable creates one table for each cache.

If you are using multiple databases, createcachetable observes the allow_migrate() method of your database routers (see below).

Like migrate, createcachetable won’t touch an existing table. It will only create missing tables.

To print the SQL that would be run, rather than run it, use the createcachetable --dry-run option.

Multiple databases

If you use database caching with multiple databases, you’ll also need to set up routing instructions for your database cache table. For the purposes of routing, the database cache table appears as a model named CacheEntry, in an application named django_cache. This model won’t appear in the models cache, but the model details can be used for routing purposes.

For example, the following router would direct all cache read operations to cache_replica, and all write operations to cache_primary. The cache table will only be synchronized onto cache_primary:

class CacheRouter(object):
"""A router to control all database cache operations"""

def db_for_read(self, model, **hints):
"All cache read operations go to the replica"
if model._meta.app_label == 'django_cache':
return 'cache_replica'
return None

def db_for_write(self, model, **hints):
"All cache write operations go to primary"
if model._meta.app_label == 'django_cache':
return 'cache_primary'
return None

def allow_migrate(self, db, app_label, model_name=None, **hints):
"Only install the cache model on primary"
if app_label == 'django_cache':
return db == 'cache_primary'
return None

If you don’t specify routing directions for the database cache model, the cache backend will use the default database.

Of course, if you don’t use the database cache backend, you don’t need to worry about providing routing instructions for the database cache model.

Filesystem caching

The file-based backend serializes and stores each cache value as a separate file. To use this backend set BACKEND to "django.core.cache.backends.filebased.FileBasedCache" and LOCATION to a suitable directory. For example, to store cached data in /var/tmp/django_cache, use this setting:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}

If you’re on Windows, put the drive letter at the beginning of the path, like this:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': 'c:/foo/bar',
}
}

The directory path should be absolute – that is, it should start at the root of your filesystem. It doesn’t matter whether you put a slash at the end of the setting.

Make sure the directory pointed-to by this setting exists and is readable and writable by the system user under which your Web server runs. Continuing the above example, if your server runs as the user apache, make sure the directory /var/tmp/django_cache exists and is readable and writable by the user apache.

Local-memory caching

This is the default cache if another is not specified in your settings file. If you want the speed advantages of in-memory caching but don’t have the capability of running Memcached, consider the local-memory cache backend. This cache is per-process (see below) and thread-safe. To use it, set BACKEND to "django.core.cache.backends.locmem.LocMemCache". For example:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}

The cache LOCATION is used to identify individual memory stores. If you only have one locmem cache, you can omit the LOCATION; however, if you have more than one local memory cache, you will need to assign a name to at least one of them in order to keep them separate.

Note that each process will have its own private cache instance, which means no cross-process caching is possible. This obviously also means the local memory cache isn’t particularly memory-efficient, so it’s probably not a good choice for production environments. It’s nice for development.

Dummy caching (for development)

Finally, Django comes with a “dummy” cache that doesn’t actually cache – it just implements the cache interface without doing anything.

This is useful if you have a production site that uses heavy-duty caching in various places but a development/test environment where you don’t want to cache and don’t want to have to change your code to special-case the latter. To activate dummy caching, set BACKEND like so:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}

Using a custom cache backend

While Django includes support for a number of cache backends out-of-the-box, sometimes you might want to use a customized cache backend. To use an external cache backend with Django, use the Python import path as the BACKEND of the CACHES setting, like so:

CACHES = {
'default': {
'BACKEND': 'path.to.backend',
}
}

If you’re building your own backend, you can use the standard cache backends as reference implementations. You’ll find the code in the django/core/cache/backends/ directory of the Django source.

Note: Without a really compelling reason, such as a host that doesn’t support them, you should stick to the cache backends included with Django. They’ve been well-tested and are easy to use.

Cache arguments

Each cache backend can be given additional arguments to control caching behavior. These arguments are provided as additional keys in the CACHES setting. Valid arguments are as follows:

- TIMEOUT: The default timeout, in seconds, to use for the cache. This argument defaults to 300 seconds (5 minutes). You can set TIMEOUT to None so that, by default, cache keys never expire. A value of 0 causes keys to immediately expire (effectively “don’t cache”).

- OPTIONS: Any options that should be passed to the cache backend. The list of valid options will vary with each backend, and cache backends backed by a third-party library will pass their options directly to the underlying cache library.

Cache backends that implement their own culling strategy (i.e., the locmem, filesystem and database backends) will honor the following options:

- MAX_ENTRIES: The maximum number of entries allowed in the cache before old values are deleted. This argument defaults to 300.

- CULL_FREQUENCY: The fraction of entries that are culled when MAX_ENTRIES is reached. The actual ratio is 1 / CULL_FREQUENCY, so set CULL_FREQUENCY to 2 to cull half the entries when MAX_ENTRIES is reached. This argument should be an integer and defaults to 3.

A value of 0 for CULL_FREQUENCY means that the entire cache will be dumped when MAX_ENTRIES is reached. On some backends (database in particular) this makes culling much faster at the expense of more cache misses.

- KEY_PREFIX: A string that will be automatically included (prepended by default) to all cache keys used by the Django server.

See the cache documentation for more information.

- VERSION: The default version number for cache keys generated by the Django server.

See the cache documentation for more information.

- KEY_FUNCTION A string containing a dotted path to a function that defines how to compose a prefix, version and key into a final cache key.

See the cache documentation for more information.

In this example, a filesystem backend is being configured with a timeout of 60 seconds, and a maximum capacity of 1000 items:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
'TIMEOUT': 60,
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}

Invalid arguments are silently ignored, as are invalid values of known arguments.

The per-site cache

Once the cache is set up, the simplest way to use caching is to cache your entire site. You’ll need to add 'django.middleware.cache.UpdateCacheMiddleware' and 'django.middleware.cache.FetchFromCacheMiddleware' to your MIDDLEWARE_CLASSES setting, as in this example:

MIDDLEWARE_CLASSES = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]

Note

No, that’s not a typo: the “update” middleware must be first in the list, and the “fetch” middleware must be last. The details are a bit obscure, but see Order of MIDDLEWARE_CLASSES below if you’d like the full story.

Then, add the following required settings to your Django settings file:

- CACHE_MIDDLEWARE_ALIAS – The cache alias to use for storage.

- CACHE_MIDDLEWARE_SECONDS – The number of seconds each page should be cached.

- CACHE_MIDDLEWARE_KEY_PREFIX – If the cache is shared across multiple sites using the same Django installation, set this to the name of the site, or some other string that is unique to this Django instance, to prevent key collisions. Use an empty string if you don’t care.

FetchFromCacheMiddleware caches GET and HEAD responses with status 200, where the request and response headers allow. Responses to requests for the same URL with different query parameters are considered to be unique pages and are cached separately. This middleware expects that a HEAD request is answered with the same response headers as the corresponding GET request; in which case it can return a cached GET response for HEAD request.

Additionally, UpdateCacheMiddleware automatically sets a few headers in each HttpResponse:

- Sets the Last-Modified header to the current date/time when a fresh (not cached) version of the page is requested.

- Sets the Expires header to the current date/time plus the defined CACHE_MIDDLEWARE_SECONDS.

- Sets the Cache-Control header to give a max age for the page – again, from the CACHE_MIDDLEWARE_SECONDS setting.

See Middleware for more on middleware.

If a view sets its own cache expiry time (i.e. it has a max-age section in its Cache-Control header) then the page will be cached until the expiry time, rather than CACHE_MIDDLEWARE_SECONDS. Using the decorators in django.views.decorators.cache you can easily set a view’s expiry time (using the cache_control decorator) or disable caching for a view (using the never_cache decorator). See the using other headers section for more on these decorators.

If USE_I18N is set to True then the generated cache key will include the name of the active language – see also How Django discovers language preference). This allows you to easily cache multilingual sites without having to create the cache key yourself.

Cache keys also include the active language when USE_L10N is set to True and the current time zone when USE_TZ is set to True.

The per-view cache

django.views.decorators.cache.cache_page()

A more granular way to use the caching framework is by caching the output of individual views. django.views.decorators.cache defines a cache_page decorator that will automatically cache the view’s response for you. It’s easy to use:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):
...

cache_page takes a single argument: the cache timeout, in seconds. In the above example, the result of the my_view() view will be cached for 15 minutes. (Note that we’ve written it as 60 * 15 for the purpose of readability. 60 * 15 will be evaluated to 900 – that is, 15 minutes multiplied by 60 seconds per minute.)

The per-view cache, like the per-site cache, is keyed off of the URL. If multiple URLs point at the same view, each URL will be cached separately. Continuing the my_view example, if your URLconf looks like this:

urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', my_view),
]

then requests to /foo/1/ and /foo/23/ will be cached separately, as you may expect. But once a particular URL (e.g., /foo/23/) has been requested, subsequent requests to that URL will use the cache.

cache_page can also take an optional keyword argument, cache, which directs the decorator to use a specific cache (from your CACHES setting) when caching view results. By default, the default cache will be used, but you can specify any cache you want:

@cache_page(60 * 15, cache="special_cache")
def my_view(request):
...

You can also override the cache prefix on a per-view basis. cache_page takes an optional keyword argument, key_prefix, which works in the same way as the CACHE_MIDDLEWARE_KEY_PREFIX setting for the middleware. It can be used like this:

@cache_page(60 * 15, key_prefix="site1")
def my_view(request):
...

The key_prefix and cache arguments may be specified together. The key_prefix argument and the KEY_PREFIX specified under CACHES will be concatenated.

Specifying per-view cache in the URLconf

The examples in the previous section have hard-coded the fact that the view is cached, because cache_page alters the my_view function in place. This approach couples your view to the cache system, which is not ideal for several reasons. For instance, you might want to reuse the view functions on another, cache-less site, or you might want to distribute the views to people who might want to use them without being cached. The solution to these problems is to specify the per-view cache in the URLconf rather than next to the view functions themselves.

Doing so is easy: simply wrap the view function with cache_page when you refer to it in the URLconf. Here’s the old URLconf from earlier:

urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', my_view),
]

Here’s the same thing, with my_view wrapped in cache_page:

from django.views.decorators.cache import cache_page

urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
]

Template fragment caching

If you’re after even more control, you can also cache template fragments using the cache template tag. To give your template access to this tag, put {% load cache %} near the top of your template.

The {% cache %} template tag caches the contents of the block for a given amount of time. It takes at least two arguments: the cache timeout, in seconds, and the name to give the cache fragment. The name will be taken as is, do not use a variable. For example:

{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}

Sometimes you might want to cache multiple copies of a fragment depending on some dynamic data that appears inside the fragment. For example, you might want a separate cached copy of the sidebar used in the previous example for every user of your site. Do this by passing additional arguments to the {% cache %} template tag to uniquely identify the cache fragment:

{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}

It’s perfectly fine to specify more than one argument to identify the fragment. Simply pass as many arguments to {% cache %} as you need.

If USE_I18N is set to True the per-site middleware cache will respect the active language. For the cache template tag you could use one of the translation-specific variables available in templates to achieve the same result:

{% load i18n %}
{% load cache %}

{% get_current_language as LANGUAGE_CODE %}

{% cache 600 welcome LANGUAGE_CODE %}
{% trans "Welcome to example.com" %}
{% endcache %}

The cache timeout can be a template variable, as long as the template variable resolves to an integer value. For example, if the template variable my_timeout is set to the value 600, then the following two examples are equivalent:

{% cache 600 sidebar %} ... {% endcache %}
{% cache my_timeout sidebar %} ... {% endcache %}

This feature is useful in avoiding repetition in templates. You can set the timeout in a variable, in one place, and just reuse that value.

By default, the cache tag will try to use the cache called “template_fragments”. If no such cache exists, it will fall back to using the default cache. You may select an alternate cache backend to use with the using keyword argument, which must be the last argument to the tag.

{% cache 300 local-thing ...  using="localcache" %}

It is considered an error to specify a cache name that is not configured.

django.core.cache.utils.make_template_fragment_key(fragment_name, vary_on=None)

If you want to obtain the cache key used for a cached fragment, you can use make_template_fragment_key. fragment_name is the same as second argument to the cache template tag; vary_on is a list of all additional arguments passed to the tag. This function can be useful for invalidating or overwriting a cached item, for example:

>>> from django.core.cache import cache
>>> from django.core.cache.utils import make_template_fragment_key
# cache key for {% cache 500 sidebar username %}
>>> key = make_template_fragment_key('sidebar', [username])
>>> cache.delete(key) # invalidates cached template fragment

The low-level cache API

Sometimes, caching an entire rendered page doesn’t gain you very much and is, in fact, inconvenient overkill.

Perhaps, for instance, your site includes a view whose results depend on several expensive queries, the results of which change at different intervals. In this case, it would not be ideal to use the full-page caching that the per-site or per-view cache strategies offer, because you wouldn’t want to cache the entire result (since some of the data changes often), but you’d still want to cache the results that rarely change.

For cases like this, Django exposes a simple, low-level cache API. You can use this API to store objects in the cache with any level of granularity you like. You can cache any Python object that can be pickled safely: strings, dictionaries, lists of model objects, and so forth. (Most common Python objects can be pickled; refer to the Python documentation for more information about pickling.)

Accessing the cache

django.core.cache.caches

You can access the caches configured in the CACHES setting through a dict-like object: django.core.cache.caches. Repeated requests for the same alias in the same thread will return the same object.

>>> from django.core.cache import caches
>>> cache1 = caches['myalias']
>>> cache2 = caches['myalias']
>>> cache1 is cache2
True

If the named key does not exist, InvalidCacheBackendError will be raised.

To provide thread-safety, a different instance of the cache backend will be returned for each thread.

django.core.cache.cache

As a shortcut, the default cache is available as django.core.cache.cache:

>>> from django.core.cache import cache

This object is equivalent to caches['default'].

Basic usage

The basic interface is set(key, value, timeout) and get(key):

>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'

The timeout argument is optional and defaults to the timeout argument of the appropriate backend in the CACHES setting (explained above). It’s the number of seconds the value should be stored in the cache. Passing in None for timeout will cache the value forever. A timeout of 0 won’t cache the value.

If the object doesn’t exist in the cache, cache.get() returns None:

>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get('my_key')
None

We advise against storing the literal value None in the cache, because you won’t be able to distinguish between your stored None value and a cache miss signified by a return value of None.

cache.get() can take a default argument. This specifies which value to return if the object doesn’t exist in the cache:

>>> cache.get('my_key', 'has expired')
'has expired'

To add a key only if it doesn’t already exist, use the add() method. It takes the same parameters as set(), but it will not attempt to update the cache if the key specified is already present:

>>> cache.set('add_key', 'Initial value')
>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'

If you need to know whether add() stored a value in the cache, you can check the return value. It will return True if the value was stored, False otherwise.

If you want to get a key’s value or set a value if the key isn’t in the cache, there is the get_or_set() method. It takes the same parameters as get() but the default is set as the new cache value for that key, rather than simply returned:

>>> cache.get('my_new_key')  # returns None
>>> cache.get_or_set('my_new_key', 'my new value', 100)
'my new value'

You can also pass any callable as a default value:

>>> import datetime
>>> cache.get_or_set('some-timestamp-key', datetime.datetime.now)
datetime.datetime(2014, 12, 11, 0, 15, 49, 457920)

Changed in Django 1.9:
The get_or_set() method was added.

There’s also a get_many() interface that only hits the cache once. get_many() returns a dictionary with all the keys you asked for that actually exist in the cache (and haven’t expired):

>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}

To set multiple values more efficiently, use set_many() to pass a dictionary of key-value pairs:

>>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}

Like cache.set(), set_many() takes an optional timeout parameter.

You can delete keys explicitly with delete(). This is an easy way of clearing the cache for a particular object:

>>> cache.delete('a')

If you want to clear a bunch of keys at once, delete_many() can take a list of keys to be cleared:

>>> cache.delete_many(['a', 'b', 'c'])

Finally, if you want to delete all the keys in the cache, use cache.clear(). Be careful with this; clear() will remove everything from the cache, not just the keys set by your application.

>>> cache.clear()

You can also increment or decrement a key that already exists using the incr() or decr() methods, respectively. By default, the existing cache value will incremented or decremented by 1. Other increment/decrement values can be specified by providing an argument to the increment/decrement call. A ValueError will be raised if you attempt to increment or decrement a nonexistent cache key.:

>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6

Note

incr()/decr() methods are not guaranteed to be atomic. On those backends that support atomic increment/decrement (most notably, the memcached backend), increment and decrement operations will be atomic. However, if the backend doesn’t natively provide an increment/decrement operation, it will be implemented using a two-step retrieve/update.

You can close the connection to your cache with close() if implemented by the cache backend.

>>> cache.close()

Note

For caches that don’t implement close methods it is a no-op.

Cache key prefixing

If you are sharing a cache instance between servers, or between your production and development environments, it’s possible for data cached by one server to be used by another server. If the format of cached data is different between servers, this can lead to some very hard to diagnose problems.

To prevent this, Django provides the ability to prefix all cache keys used by a server. When a particular cache key is saved or retrieved, Django will automatically prefix the cache key with the value of the KEY_PREFIX cache setting.

By ensuring each Django instance has a different KEY_PREFIX, you can ensure that there will be no collisions in cache values.

Cache versioning

When you change running code that uses cached values, you may need to purge any existing cached values. The easiest way to do this is to flush the entire cache, but this can lead to the loss of cache values that are still valid and useful.

Django provides a better way to target individual cache values. Django’s cache framework has a system-wide version identifier, specified using the VERSION cache setting. The value of this setting is automatically combined with the cache prefix and the user-provided cache key to obtain the final cache key.

By default, any key request will automatically include the site default cache key version. However, the primitive cache functions all include a version argument, so you can specify a particular cache key version to set or get. For example:

>>> # Set version 2 of a cache key
>>> cache.set('my_key', 'hello world!', version=2)
>>> # Get the default version (assuming version=1)
>>> cache.get('my_key')
None
>>> # Get version 2 of the same key
>>> cache.get('my_key', version=2)
'hello world!'

The version of a specific key can be incremented and decremented using the incr_version() and decr_version() methods. This enables specific keys to be bumped to a new version, leaving other keys unaffected. Continuing our previous example:

>>> # Increment the version of 'my_key'
>>> cache.incr_version('my_key')
>>> # The default version still isn't available
>>> cache.get('my_key')
None
# Version 2 isn't available, either
>>> cache.get('my_key', version=2)
None
>>> # But version 3 *is* available
>>> cache.get('my_key', version=3)
'hello world!'

Cache key transformation

As described in the previous two sections, the cache key provided by a user is not used verbatim – it is combined with the cache prefix and key version to provide a final cache key. By default, the three parts are joined using colons to produce a final string:

def make_key(key, key_prefix, version):
return ':'.join([key_prefix, str(version), key])

If you want to combine the parts in different ways, or apply other processing to the final key (e.g., taking a hash digest of the key parts), you can provide a custom key function.

The KEY_FUNCTION cache setting specifies a dotted-path to a function matching the prototype of make_key() above. If provided, this custom key function will be used instead of the default key combining function.

Cache key warnings

Memcached, the most commonly-used production cache backend, does not allow cache keys longer than 250 characters or containing whitespace or control characters, and using such keys will cause an exception. To encourage cache-portable code and minimize unpleasant surprises, the other built-in cache backends issue a warning (django.core.cache.backends.base.CacheKeyWarning) if a key is used that would cause an error on memcached.

If you are using a production backend that can accept a wider range of keys (a custom backend, or one of the non-memcached built-in backends), and want to use this wider range without warnings, you can silence CacheKeyWarning with this code in the management module of one of your INSTALLED_APPS:

import warnings

from django.core.cache import CacheKeyWarning

warnings.simplefilter("ignore", CacheKeyWarning)

If you want to instead provide custom key validation logic for one of the built-in backends, you can subclass it, override just the validate_key method, and follow the instructions for using a custom cache backend. For instance, to do this for the locmem backend, put this code in a module:

from django.core.cache.backends.locmem import LocMemCache

class CustomLocMemCache(LocMemCache):
def validate_key(self, key):
"""Custom validation, raising exceptions or warnings as needed."""
...

...and use the dotted Python path to this class in the BACKEND portion of your CACHES setting.

Downstream caches

So far, this document has focused on caching your own data. But another type of caching is relevant to Web development, too: caching performed by “downstream” caches. These are systems that cache pages for users even before the request reaches your website.

Here are a few examples of downstream caches:

- Your ISP may cache certain pages, so if you requested a page from https://example.com/, your ISP would send you the page without having to access example.com directly. The maintainers of example.com have no knowledge of this caching; the ISP sits between example.com and your Web browser, handling all of the caching transparently.

- Your Django website may sit behind a proxy cache, such as Squid Web Proxy Cache (http://www.squid-cache.org/), that caches pages for performance. In this case, each request first would be handled by the proxy, and it would be passed to your application only if needed.

- Your Web browser caches pages, too. If a Web page sends out the appropriate headers, your browser will use the local cached copy for subsequent requests to that page, without even contacting the Web page again to see whether it has changed.

Downstream caching is a nice efficiency boost, but there’s a danger to it: Many Web pages’ contents differ based on authentication and a host of other variables, and cache systems that blindly save pages based purely on URLs could expose incorrect or sensitive data to subsequent visitors to those pages.

For example, say you operate a Web email system, and the contents of the “inbox” page obviously depend on which user is logged in. If an ISP blindly cached your site, then the first user who logged in through that ISP would have their user-specific inbox page cached for subsequent visitors to the site. That’s not cool.

Fortunately, HTTP provides a solution to this problem. A number of HTTP headers exist to instruct downstream caches to differ their cache contents depending on designated variables, and to tell caching mechanisms not to cache particular pages. We’ll look at some of these headers in the sections that follow.

Using Vary headers

The Vary header defines which request headers a cache mechanism should take into account when building its cache key. For example, if the contents of a Web page depend on a user’s language preference, the page is said to “vary on language.”

By default, Django’s cache system creates its cache keys using the requested fully-qualified URL – e.g., "https://www.example.com/stories/2005/?order_by=author". This means every request to that URL will use the same cached version, regardless of user-agent differences such as cookies or language preferences. However, if this page produces different content based on some difference in request headers – such as a cookie, or a language, or a user-agent – you’ll need to use the Vary header to tell caching mechanisms that the page output depends on those things.

To do this in Django, use the convenient django.views.decorators.vary.vary_on_headers() view decorator, like so:

from django.views.decorators.vary import vary_on_headers

@vary_on_headers('User-Agent')
def my_view(request):
...

In this case, a caching mechanism (such as Django’s own cache middleware) will cache a separate version of the page for each unique user-agent.

The advantage to using the vary_on_headers decorator rather than manually setting the Vary header (using something like response['Vary'] = 'user-agent') is that the decorator adds to the Vary header (which may already exist), rather than setting it from scratch and potentially overriding anything that was already in there.

You can pass multiple headers to vary_on_headers():

@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
...

This tells downstream caches to vary on both, which means each combination of user-agent and cookie will get its own cache value. For example, a request with the user-agent Mozilla and the cookie value foo=bar will be considered different from a request with the user-agent Mozilla and the cookie value foo=ham.

Because varying on cookie is so common, there’s a django.views.decorators.vary.vary_on_cookie() decorator. These two views are equivalent:

@vary_on_cookie
def my_view(request):
...

@vary_on_headers('Cookie')
def my_view(request):
...

The headers you pass to vary_on_headers are not case sensitive; "User-Agent" is the same thing as "user-agent".

You can also use a helper function, django.utils.cache.patch_vary_headers(), directly. This function sets, or adds to, the Vary header. For example:

from django.shortcuts import render
from django.utils.cache import patch_vary_headers

def my_view(request):
...
response = render(request, 'template_name', context)
patch_vary_headers(response, ['Cookie'])
return response

patch_vary_headers takes an HttpResponse instance as its first argument and a list/tuple of case-insensitive header names as its second argument.

For more on Vary headers, see the official Vary spec.

Controlling cache: Using other headers

Other problems with caching are the privacy of data and the question of where data should be stored in a cascade of caches.

A user usually faces two kinds of caches: their own browser cache (a private cache) and their provider’s cache (a public cache). A public cache is used by multiple users and controlled by someone else. This poses problems with sensitive data–you don’t want, say, your bank account number stored in a public cache. So Web applications need a way to tell caches which data is private and which is public.

The solution is to indicate a page’s cache should be “private.” To do this in Django, use the cache_control view decorator. Example:

from django.views.decorators.cache import cache_control

@cache_control(private=True)
def my_view(request):
...

This decorator takes care of sending out the appropriate HTTP header behind the scenes.

Note that the cache control settings “private” and “public” are mutually exclusive. The decorator ensures that the “public” directive is removed if “private” should be set (and vice versa). An example use of the two directives would be a blog site that offers both private and public entries. Public entries may be cached on any shared cache. The following code uses django.utils.cache.patch_cache_control(), the manual way to modify the cache control header (it is internally called by the cache_control decorator):

from django.views.decorators.cache import patch_cache_control
from django.views.decorators.vary import vary_on_cookie

@vary_on_cookie
def list_blog_entries_view(request):
if request.user.is_anonymous():
response = render_only_public_entries()
patch_cache_control(response, public=True)
else:
response = render_private_and_public_entries(request.user)
patch_cache_control(response, private=True)

return response

You can control downstream caches in other ways as well (see RFC 7234 for details on HTTP caching). For example, even if you don’t use Django’s server-side cache framework, you can still tell clients to cache a view for a certain amount of time with the max-age directive:

from django.views.decorators.cache import cache_control

@cache_control(max_age=3600)
def my_view(request):
...

(If you do use the caching middleware, it already sets the max-age with the value of the CACHE_MIDDLEWARE_SECONDS setting. In that case, the custom max_age from the cache_control decorator will take precedence, and the header values will be merged correctly.)

Any valid Cache-Control response directive is valid in cache_control(). Here are some more examples:

- no_transform=True

- must_revalidate=True

- stale_while_revalidate=num_seconds

The full list of known directives can be found in the IANA registry (note that not all of them apply to responses).

If you want to use headers to disable caching altogether, django.views.decorators.cache.never_cache() is a view decorator that adds headers to ensure the response won’t be cached by browsers or other caches. Example:

from django.views.decorators.cache import never_cache

@never_cache
def myview(request):
...

Order of MIDDLEWARE_CLASSES

If you use caching middleware, it’s important to put each half in the right place within the MIDDLEWARE_CLASSES setting. That’s because the cache middleware needs to know which headers by which to vary the cache storage. Middleware always adds something to the Vary response header when it can.

UpdateCacheMiddleware runs during the response phase, where middleware is run in reverse order, so an item at the top of the list runs last during the response phase. Thus, you need to make sure that UpdateCacheMiddleware appears before any other middleware that might add something to the Vary header. The following middleware modules do so:

- SessionMiddleware adds Cookie

- GZipMiddleware adds Accept-Encoding

- LocaleMiddleware adds Accept-Language

FetchFromCacheMiddleware, on the other hand, runs during the request phase, where middleware is applied first-to-last, so an item at the top of the list runs first during the request phase. The FetchFromCacheMiddleware also needs to run after other middleware updates the Vary header, so FetchFromCacheMiddleware must be after any item that does so.

Conditional View Processing

HTTP clients can send a number of headers to tell the server about copies of a resource that they have already seen. This is commonly used when retrieving a Web page (using an HTTP GET request) to avoid sending all the data for something the client has already retrieved. However, the same headers can be used for all HTTP methods (POST, PUT, DELETE, etc.).

For each page (response) that Django sends back from a view, it might provide two HTTP headers: the ETag header and the Last-Modified header. These headers are optional on HTTP responses. They can be set by your view function, or you can rely on the CommonMiddleware middleware to set the ETag header.

When the client next requests the same resource, it might send along a header such as either If-modified-since or If-unmodified-since, containing the date of the last modification time it was sent, or either If-match or If-none-match, containing the last ETag it was sent. If the current version of the page matches the ETag sent by the client, or if the resource has not been modified, a 304 status code can be sent back, instead of a full response, telling the client that nothing has changed. Depending on the header, if the page has been modified or does not match the ETag sent by the client, a 412 status code (Precondition Failed) may be returned.

When you need more fine-grained control you may use per-view conditional processing functions.

Changed in Django 1.8:
Support for the If-unmodified-since header was added to conditional view processing.

The condition decorator

Sometimes (in fact, quite often) you can create functions to rapidly compute the ETag value or the last-modified time for a resource, without needing to do all the computations needed to construct the full view. Django can then use these functions to provide an “early bailout” option for the view processing. Telling the client that the content has not been modified since the last request, perhaps.

These two functions are passed as parameters to the django.views.decorators.http.condition decorator. This decorator uses the two functions (you only need to supply one, if you can’t compute both quantities easily and quickly) to work out if the headers in the HTTP request match those on the resource. If they don’t match, a new copy of the resource must be computed and your normal view is called.

The condition decorator’s signature looks like this:

condition(etag_func=None, last_modified_func=None)

The two functions, to compute the ETag and the last modified time, will be passed the incoming request object and the same parameters, in the same order, as the view function they are helping to wrap. The function passed last_modified_func should return a standard datetime value specifying the last time the resource was modified, or None if the resource doesn’t exist. The function passed to the etag decorator should return a string representing the Etag for the resource, or None if it doesn’t exist.

Using this feature usefully is probably best explained with an example. Suppose you have this pair of models, representing a simple blog system:

import datetime
from django.db import models

class Blog(models.Model):
...

class Entry(models.Model):
blog = models.ForeignKey(Blog)
published = models.DateTimeField(default=datetime.datetime.now)
...

If the front page, displaying the latest blog entries, only changes when you add a new blog entry, you can compute the last modified time very quickly. You need the latest published date for every entry associated with that blog. One way to do this would be:

def latest_entry(request, blog_id):
return Entry.objects.filter(blog=blog_id).latest("published").published

You can then use this function to provide early detection of an unchanged page for your front page view:

from django.views.decorators.http import condition

@condition(last_modified_func=latest_entry)
def front_page(request, blog_id):
...

Shortcuts for only computing one value

As a general rule, if you can provide functions to compute both the ETag and the last modified time, you should do so. You don’t know which headers any given HTTP client will send you, so be prepared to handle both. However, sometimes only one value is easy to compute and Django provides decorators that handle only ETag or only last-modified computations.

The django.views.decorators.http.etag and django.views.decorators.http.last_modified decorators are passed the same type of functions as the condition decorator. Their signatures are:

etag(etag_func)
last_modified(last_modified_func)

We could write the earlier example, which only uses a last-modified function, using one of these decorators:

@last_modified(latest_entry)
def front_page(request, blog_id):
...

...or:

def front_page(request, blog_id):
...
front_page = last_modified(latest_entry)(front_page)

Use condition when testing both conditions

It might look nicer to some people to try and chain the etag and last_modified decorators if you want to test both preconditions. However, this would lead to incorrect behavior.

# Bad code. Don't do this!
@etag(etag_func)
@last_modified(last_modified_func)
def my_view(request):
# ...

# End of bad code.

The first decorator doesn’t know anything about the second and might answer that the response is not modified even if the second decorators would determine otherwise. The condition decorator uses both callback functions simultaneously to work out the right action to take.

Using the decorators with other HTTP methods

The condition decorator is useful for more than only GET and HEAD requests (HEAD requests are the same as GET in this situation). It can also be used to provide checking for POST, PUT and DELETE requests. In these situations, the idea isn’t to return a “not modified” response, but to tell the client that the resource they are trying to change has been altered in the meantime.

For example, consider the following exchange between the client and server:

1. Client requests /foo/.

2. Server responds with some content with an ETag of "abcd1234".

3. Client sends an HTTP PUT request to /foo/ to update the resource. It also sends an If-Match: "abcd1234" header to specify the version it is trying to update.

4. Server checks to see if the resource has changed, by computing the ETag the same way it does for a GET request (using the same function). If the resource has changed, it will return a 412 status code, meaning “precondition failed”.

5. Client sends a GET request to /foo/, after receiving a 412 response, to retrieve an updated version of the content before updating it.

The important thing this example shows is that the same functions can be used to compute the ETag and last modification values in all situations. In fact, you should use the same functions, so that the same values are returned every time.

Comparison with middleware conditional processing

You may notice that Django already provides simple and straightforward conditional GET handling via the django.middleware.http.ConditionalGetMiddleware and CommonMiddleware. While certainly being easy to use and suitable for many situations, those pieces of middleware functionality have limitations for advanced usage:

- They are applied globally to all views in your project

- They don’t save you from generating the response itself, which may be expensive

- They are only appropriate for HTTP GET requests.

You should choose the most appropriate tool for your particular problem here. If you have a way to compute ETags and modification times quickly and if some view takes a while to generate the content, you should consider using the condition decorator described in this document. If everything already runs fairly quickly, stick to using the middleware and the amount of network traffic sent back to the clients will still be reduced if the view hasn’t changed.

Cryptographic signing

The golden rule of Web application security is to never trust data from untrusted sources. Sometimes it can be useful to pass data through an untrusted medium. Cryptographically signed values can be passed through an untrusted channel safe in the knowledge that any tampering will be detected.

Django provides both a low-level API for signing values and a high-level API for setting and reading signed cookies, one of the most common uses of signing in Web applications.

You may also find signing useful for the following:

- Generating “recover my account” URLs for sending to users who have lost their password.

- Ensuring data stored in hidden form fields has not been tampered with.

- Generating one-time secret URLs for allowing temporary access to a protected resource, for example a downloadable file that a user has paid for.

Protecting the SECRET_KEY

When you create a new Django project using startproject, the settings.py file is generated automatically and gets a random SECRET_KEY value. This value is the key to securing signed data – it is vital you keep this secure, or attackers could use it to generate their own signed values.

Using the low-level API

Django’s signing methods live in the django.core.signing module. To sign a value, first instantiate a Signer instance:

>>> from django.core.signing import Signer
>>> signer = Signer()
>>> value = signer.sign('My string')
>>> value
'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'

The signature is appended to the end of the string, following the colon. You can retrieve the original value using the unsign method:

>>> original = signer.unsign(value)
>>> original
'My string'

If the signature or value have been altered in any way, a django.core.signing.BadSignature exception will be raised:

>>> from django.core import signing
>>> value += 'm'
>>> try:
...    original = signer.unsign(value)
... except signing.BadSignature:
...    print("Tampering detected!")

By default, the Signer class uses the SECRET_KEY setting to generate signatures. You can use a different secret by passing it to the Signer constructor:

>>> signer = Signer('my-other-secret')
>>> value = signer.sign('My string')
>>> value
'My string:EkfQJafvGyiofrdGnuthdxImIJw'

class Signer(key=None, sep=':', salt=None)[source]

Returns a signer which uses key to generate signatures and sep to separate values. sep cannot be in the URL safe base64 alphabet. This alphabet contains alphanumeric characters, hyphens, and underscores.

Using the salt argument

If you do not wish for every occurrence of a particular string to have the same signature hash, you can use the optional salt argument to the Signer class. Using a salt will seed the signing hash function with both the salt and your SECRET_KEY:

>>> signer = Signer()
>>> signer.sign('My string')
'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
>>> signer = Signer(salt='extra')
>>> signer.sign('My string')
'My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw'
>>> signer.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw')
'My string'

Using salt in this way puts the different signatures into different namespaces. A signature that comes from one namespace (a particular salt value) cannot be used to validate the same plaintext string in a different namespace that is using a different salt setting. The result is to prevent an attacker from using a signed string generated in one place in the code as input to another piece of code that is generating (and verifying) signatures using a different salt.

Unlike your SECRET_KEY, your salt argument does not need to stay secret.

Verifying timestamped values

TimestampSigner is a subclass of Signer that appends a signed timestamp to the value. This allows you to confirm that a signed value was created within a specified period of time:

>>> from datetime import timedelta
>>> from django.core.signing import TimestampSigner
>>> signer = TimestampSigner()
>>> value = signer.sign('hello')
>>> value
'hello:1NMg5H:oPVuCqlJWmChm1rA2lyTUtelC-c'
>>> signer.unsign(value)
'hello'
>>> signer.unsign(value, max_age=10)
...
SignatureExpired: Signature age 15.5289158821 > 10 seconds
>>> signer.unsign(value, max_age=20)
'hello'
>>> signer.unsign(value, max_age=timedelta(seconds=20))
'hello'

class TimestampSigner(key=None, sep=':', salt=None)[source]

sign(value)[source]

Sign value and append current timestamp to it.

unsign(value, max_age=None)[source]

Checks if value was signed less than max_age seconds ago, otherwise raises SignatureExpired. The max_age parameter can accept an integer or a datetime.timedelta object.

Changed in Django 1.8:
Previously, the max_age parameter only accepted an integer.

Protecting complex data structures

If you wish to protect a list, tuple or dictionary you can do so using the signing module’s dumps and loads functions. These imitate Python’s pickle module, but use JSON serialization under the hood. JSON ensures that even if your SECRET_KEY is stolen an attacker will not be able to execute arbitrary commands by exploiting the pickle format:

>>> from django.core import signing
>>> value = signing.dumps({"foo": "bar"})
>>> value
'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI'
>>> signing.loads(value)
{'foo': 'bar'}

Because of the nature of JSON (there is no native distinction between lists and tuples) if you pass in a tuple, you will get a list from signing.loads(object):

>>> from django.core import signing
>>> value = signing.dumps(('a','b','c'))
>>> signing.loads(value)
['a', 'b', 'c']

dumps(obj, key=None, salt='django.core.signing', compress=False)[source]

Returns URL-safe, sha1 signed base64 compressed JSON string. Serialized object is signed using TimestampSigner.

loads(string, key=None, salt='django.core.signing', max_age=None)[source]

Reverse of dumps(), raises BadSignature if signature fails. Checks max_age (in seconds) if given.

Sending email

Although Python makes sending email relatively easy via the smtplib module, Django provides a couple of light wrappers over it. These wrappers are provided to make sending email extra quick, to make it easy to test email sending during development, and to provide support for platforms that can’t use SMTP.

The code lives in the django.core.mail module.

Quick example

In two lines:

from django.core.mail import send_mail

send_mail(
'Subject here',
'Here is the message.',
'from@example.com',
['to@example.com'],
fail_silently=False,
)

Mail is sent using the SMTP host and port specified in the EMAIL_HOST and EMAIL_PORT settings. The EMAIL_HOST_USER and EMAIL_HOST_PASSWORD settings, if set, are used to authenticate to the SMTP server, and the EMAIL_USE_TLS and EMAIL_USE_SSL settings control whether a secure connection is used.

Note

The character set of email sent with django.core.mail will be set to the value of your DEFAULT_CHARSET setting.

send_mail()

send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)[source]

The simplest way to send email is using django.core.mail.send_mail().

The subject, message, from_email and recipient_list parameters are required.

- subject: A string.

- message: A string.

- from_email: A string.

- recipient_list: A list of strings, each an email address. Each member of recipient_list will see the other recipients in the “To:” field of the email message.

- fail_silently: A boolean. If it’s False, send_mail will raise an smtplib.SMTPException. See the smtplib docs for a list of possible exceptions, all of which are subclasses of SMTPException.

- auth_user: The optional username to use to authenticate to the SMTP server. If this isn’t provided, Django will use the value of the EMAIL_HOST_USER setting.

- auth_password: The optional password to use to authenticate to the SMTP server. If this isn’t provided, Django will use the value of the EMAIL_HOST_PASSWORD setting.

- connection: The optional email backend to use to send the mail. If unspecified, an instance of the default backend will be used. See the documentation on Email backends for more details.

- html_message: If html_message is provided, the resulting email will be a multipart/alternative email with message as the text/plain content type and html_message as the text/html content type.

The return value will be the number of successfully delivered messages (which can be 0 or 1 since it can only send one message).

send_mass_mail()

send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)[source]

django.core.mail.send_mass_mail() is intended to handle mass emailing.

datatuple is a tuple in which each element is in this format:

(subject, message, from_email, recipient_list)

fail_silently, auth_user and auth_password have the same functions as in send_mail().

Each separate element of datatuple results in a separate email message. As in send_mail(), recipients in the same recipient_list will all see the other addresses in the email messages’ “To:” field.

For example, the following code would send two different messages to two different sets of recipients; however, only one connection to the mail server would be opened:

message1 = ('Subject here', 'Here is the message', 'from@example.com', ['first@example.com', 'other@example.com'])
message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com'])
send_mass_mail((message1, message2), fail_silently=False)

The return value will be the number of successfully delivered messages.

send_mass_mail() vs. send_mail()

The main difference between send_mass_mail() and send_mail() is that send_mail() opens a connection to the mail server each time it’s executed, while send_mass_mail() uses a single connection for all of its messages. This makes send_mass_mail() slightly more efficient.

mail_admins()

mail_admins(subject, message, fail_silently=False, connection=None, html_message=None)[source]

django.core.mail.mail_admins() is a shortcut for sending an email to the site admins, as defined in the ADMINS setting.

mail_admins() prefixes the subject with the value of the EMAIL_SUBJECT_PREFIX setting, which is "[Django] " by default.

The “From:” header of the email will be the value of the SERVER_EMAIL setting.

This method exists for convenience and readability.

If html_message is provided, the resulting email will be a multipart/alternative email with message as the text/plain content type and html_message as the text/html content type.

mail_managers()

mail_managers(subject, message, fail_silently=False, connection=None, html_message=None)[source]

django.core.mail.mail_managers() is just like mail_admins(), except it sends an email to the site managers, as defined in the MANAGERS setting.

Examples

This sends a single email to john@example.com and jane@example.com, with them both appearing in the “To:”:

send_mail(
'Subject',
'Message.',
'from@example.com',
['john@example.com', 'jane@example.com'],
)

This sends a message to john@example.com and jane@example.com, with them both receiving a separate email:

datatuple = (
('Subject', 'Message.', 'from@example.com', ['john@example.com']),
('Subject', 'Message.', 'from@example.com', ['jane@example.com']),
)
send_mass_mail(datatuple)

Preventing header injection

Header injection is a security exploit in which an attacker inserts extra email headers to control the “To:” and “From:” in email messages that your scripts generate.

The Django email functions outlined above all protect against header injection by forbidding newlines in header values. If any subject, from_email or recipient_list contains a newline (in either Unix, Windows or Mac style), the email function (e.g. send_mail()) will raise django.core.mail.BadHeaderError (a subclass of ValueError) and, hence, will not send the email. It’s your responsibility to validate all data before passing it to the email functions.

If a message contains headers at the start of the string, the headers will simply be printed as the first bit of the email message.

Here’s an example view that takes a subject, message and from_email from the request’s POST data, sends that to admin@example.com and redirects to “/contact/thanks/” when it’s done:

from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect

def send_email(request):
subject = request.POST.get('subject', '')
message = request.POST.get('message', '')
from_email = request.POST.get('from_email', '')
if subject and message and from_email:
try:
send_mail(subject, message, from_email, ['admin@example.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return HttpResponseRedirect('/contact/thanks/')
else:
# In reality we'd use a form class
# to get proper validation errors.
return HttpResponse('Make sure all fields are entered and valid.')

The EmailMessage class

Django’s send_mail() and send_mass_mail() functions are actually thin wrappers that make use of the EmailMessage class.

Not all features of the EmailMessage class are available through the send_mail() and related wrapper functions. If you wish to use advanced features, such as BCC’ed recipients, file attachments, or multi-part email, you’ll need to create EmailMessage instances directly.

Note

This is a design feature. send_mail() and related functions were originally the only interface Django provided. However, the list of parameters they accepted was slowly growing over time. It made sense to move to a more object-oriented design for email messages and retain the original functions only for backwards compatibility.

EmailMessage is responsible for creating the email message itself. The email backend is then responsible for sending the email.

For convenience, EmailMessage provides a simple send() method for sending a single email. If you need to send multiple messages, the email backend API provides an alternative.

EmailMessage Objects

class EmailMessage[source]

The EmailMessage class is initialized with the following parameters (in the given order, if positional arguments are used). All parameters are optional and can be set at any time prior to calling the send() method.

- subject: The subject line of the email.

- body: The body text. This should be a plain text message.

- from_email: The sender’s address. Both fred@example.com and Fred <fred@example.com> forms are legal. If omitted, the DEFAULT_FROM_EMAIL setting is used.

- to: A list or tuple of recipient addresses.

- bcc: A list or tuple of addresses used in the “Bcc” header when sending the email.

- connection: An email backend instance. Use this parameter if you want to use the same connection for multiple messages. If omitted, a new connection is created when send() is called.

- attachments: A list of attachments to put on the message. These can be either email.MIMEBase.MIMEBase instances, or (filename, content, mimetype) triples.

- headers: A dictionary of extra headers to put on the message. The keys are the header name, values are the header values. It’s up to the caller to ensure header names and values are in the correct format for an email message. The corresponding attribute is extra_headers.

- cc: A list or tuple of recipient addresses used in the “Cc” header when sending the email.

- reply_to: A list or tuple of recipient addresses used in the “Reply-To” header when sending the email.

Changed in Django 1.8:
The reply_to parameter was added.

For example:

from django.core.mail import EmailMessage

email = EmailMessage(
'Hello',
'Body goes here',
'from@example.com',
['to1@example.com', 'to2@example.com'],
['bcc@example.com'],
reply_to=['another@example.com'],
headers={'Message-ID': 'foo'},
)

The class has the following methods:

- send(fail_silently=False) sends the message. If a connection was specified when the email was constructed, that connection will be used. Otherwise, an instance of the default backend will be instantiated and used. If the keyword argument fail_silently is True, exceptions raised while sending the message will be quashed. An empty list of recipients will not raise an exception.

- message() constructs a django.core.mail.SafeMIMEText object (a subclass of Python’s email.MIMEText.MIMEText class) or a django.core.mail.SafeMIMEMultipart object holding the message to be sent. If you ever need to extend the EmailMessage class, you’ll probably want to override this method to put the content you want into the MIME object.

- recipients() returns a list of all the recipients of the message, whether they’re recorded in the to, cc or bcc attributes. This is another method you might need to override when subclassing, because the SMTP server needs to be told the full list of recipients when the message is sent. If you add another way to specify recipients in your class, they need to be returned from this method as well.

- attach() creates a new file attachment and adds it to the message. There are two ways to call attach():

- You can pass it a single argument that is an email.MIMEBase.MIMEBase instance. This will be inserted directly into the resulting message.

- Alternatively, you can pass attach() three arguments: filename, content and mimetype. filename is the name of the file attachment as it will appear in the email, content is the data that will be contained inside the attachment and mimetype is the optional MIME type for the attachment. If you omit mimetype, the MIME content type will be guessed from the filename of the attachment.

For example:

message.attach('design.png', img_data, 'image/png')

If you specify a mimetype of message/rfc822, it will also accept django.core.mail.EmailMessage and email.message.Message.

In addition, message/rfc822 attachments will no longer be base64-encoded in violation of RFC 2046#section-5.2.1, which can cause issues with displaying the attachments in Evolution and Thunderbird.

- attach_file() creates a new attachment using a file from your filesystem. Call it with the path of the file to attach and, optionally, the MIME type to use for the attachment. If the MIME type is omitted, it will be guessed from the filename. The simplest use would be:

message.attach_file('/images/weather_map.png')

Sending alternative content types

It can be useful to include multiple versions of the content in an email; the classic example is to send both text and HTML versions of a message. With Django’s email library, you can do this using the EmailMultiAlternatives class. This subclass of EmailMessage has an attach_alternative() method for including extra versions of the message body in the email. All the other methods (including the class initialization) are inherited directly from EmailMessage.

To send a text and HTML combination, you could write:

from django.core.mail import EmailMultiAlternatives

subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

By default, the MIME type of the body parameter in an EmailMessage is "text/plain". It is good practice to leave this alone, because it guarantees that any recipient will be able to read the email, regardless of their mail client. However, if you are confident that your recipients can handle an alternative content type, you can use the content_subtype attribute on the EmailMessage class to change the main content type. The major type will always be "text", but you can change the subtype. For example:

msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html"  # Main content is now text/html
msg.send()

Email backends

The actual sending of an email is handled by the email backend.

The email backend class has the following methods:

- open() instantiates a long-lived email-sending connection.

- close() closes the current email-sending connection.

- send_messages(email_messages) sends a list of EmailMessage objects. If the connection is not open, this call will implicitly open the connection, and close the connection afterwards. If the connection is already open, it will be left open after mail has been sent.

It can also be used as a context manager, which will automatically call open() and close() as needed:

from django.core import mail

with mail.get_connection() as connection:
mail.EmailMessage(
subject1, body1, from1, [to1],
connection=connection,
).send()
mail.EmailMessage(
subject2, body2, from2, [to2],
connection=connection,
).send()

New in Django 1.8:
The context manager protocol was added.

Obtaining an instance of an email backend

The get_connection() function in django.core.mail returns an instance of the email backend that you can use.

get_connection(backend=None, fail_silently=False, *args, **kwargs)[source]

By default, a call to get_connection() will return an instance of the email backend specified in EMAIL_BACKEND. If you specify the backend argument, an instance of that backend will be instantiated.

The fail_silently argument controls how the backend should handle errors. If fail_silently is True, exceptions during the email sending process will be silently ignored.

All other arguments are passed directly to the constructor of the email backend.

Django ships with several email sending backends. With the exception of the SMTP backend (which is the default), these backends are only useful during testing and development. If you have special email sending requirements, you can write your own email backend.

SMTP backend

class backends.smtp.EmailBackend(host=None, port=None, username=None, password=None, use_tls=None, fail_silently=False, use_ssl=None, timeout=None, ssl_keyfile=None, ssl_certfile=None, **kwargs)

This is the default backend. Email will be sent through a SMTP server.

The value for each argument is retrieved from the matching setting if the argument is None:

- host: EMAIL_HOST

- port: EMAIL_PORT

- username: EMAIL_HOST_USER

- password: EMAIL_HOST_PASSWORD

- use_tls: EMAIL_USE_TLS

- use_ssl: EMAIL_USE_SSL

- timeout: EMAIL_TIMEOUT

- ssl_keyfile: EMAIL_SSL_KEYFILE

- ssl_certfile: EMAIL_SSL_CERTFILE

The SMTP backend is the default configuration inherited by Django. If you want to specify it explicitly, put the following in your settings:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

If unspecified, the default timeout will be the one provided by socket.getdefaulttimeout(), which defaults to None (no timeout).

Changed in Django 1.8:
The ssl_keyfile, and ssl_certfile parameters and corresponding settings were added. The ability to customize timeout using a setting (EMAIL_TIMEOUT) was added.

Console backend

Instead of sending out real emails the console backend just writes the emails that would be sent to the standard output. By default, the console backend writes to stdout. You can use a different stream-like object by providing the stream keyword argument when constructing the connection.

To specify this backend, put the following in your settings:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

This backend is not intended for use in production – it is provided as a convenience that can be used during development.

File backend

The file backend writes emails to a file. A new file is created for each new session that is opened on this backend. The directory to which the files are written is either taken from the EMAIL_FILE_PATH setting or from the file_path keyword when creating a connection with get_connection().

To specify this backend, put the following in your settings:

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location

This backend is not intended for use in production – it is provided as a convenience that can be used during development.

In-memory backend

The 'locmem' backend stores messages in a special attribute of the django.core.mail module. The outbox attribute is created when the first message is sent. It’s a list with an EmailMessage instance for each message that would be sent.

To specify this backend, put the following in your settings:

EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

This backend is not intended for use in production – it is provided as a convenience that can be used during development and testing.

Dummy backend

As the name suggests the dummy backend does nothing with your messages. To specify this backend, put the following in your settings:

EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

This backend is not intended for use in production – it is provided as a convenience that can be used during development.

Defining a custom email backend

If you need to change how emails are sent you can write your own email backend. The EMAIL_BACKEND setting in your settings file is then the Python import path for your backend class.

Custom email backends should subclass BaseEmailBackend that is located in the django.core.mail.backends.base module. A custom email backend must implement the send_messages(email_messages) method. This method receives a list of EmailMessage instances and returns the number of successfully delivered messages. If your backend has any concept of a persistent session or connection, you should also implement the open() and close() methods. Refer to smtp.EmailBackend for a reference implementation.

Sending multiple emails

Establishing and closing an SMTP connection (or any other network connection, for that matter) is an expensive process. If you have a lot of emails to send, it makes sense to reuse an SMTP connection, rather than creating and destroying a connection every time you want to send an email.

There are two ways you tell an email backend to reuse a connection.

Firstly, you can use the send_messages() method. send_messages() takes a list of EmailMessage instances (or subclasses), and sends them all using a single connection.

For example, if you have a function called get_notification_email() that returns a list of EmailMessage objects representing some periodic email you wish to send out, you could send these emails using a single call to send_messages:

from django.core import mail
connection = mail.get_connection()   # Use default email connection
messages = get_notification_email()
connection.send_messages(messages)

In this example, the call to send_messages() opens a connection on the backend, sends the list of messages, and then closes the connection again.

The second approach is to use the open() and close() methods on the email backend to manually control the connection. send_messages() will not manually open or close the connection if it is already open, so if you manually open the connection, you can control when it is closed. For example:

from django.core import mail
connection = mail.get_connection()

# Manually open the connection
connection.open()

# Construct an email message that uses the connection
email1 = mail.EmailMessage(
'Hello',
'Body goes here',
'from@example.com',
['to1@example.com'],
connection=connection,
)
email1.send() # Send the email

# Construct two more messages
email2 = mail.EmailMessage(
'Hello',
'Body goes here',
'from@example.com',
['to2@example.com'],
)
email3 = mail.EmailMessage(
'Hello',
'Body goes here',
'from@example.com',
['to3@example.com'],
)

# Send the two emails in a single call -
connection.send_messages([email2, email3])
# The connection was already open so send_messages() doesn't close it.
# We need to manually close the connection.
connection.close()

Configuring email for development

There are times when you do not want Django to send emails at all. For example, while developing a website, you probably don’t want to send out thousands of emails – but you may want to validate that emails will be sent to the right people under the right conditions, and that those emails will contain the correct content.

The easiest way to configure email for local development is to use the console email backend. This backend redirects all email to stdout, allowing you to inspect the content of mail.

The file email backend can also be useful during development – this backend dumps the contents of every SMTP connection to a file that can be inspected at your leisure.

Another approach is to use a “dumb” SMTP server that receives the emails locally and displays them to the terminal, but does not actually send anything. Python has a built-in way to accomplish this with a single command:

python -m smtpd -n -c DebuggingServer localhost:1025

This command will start a simple SMTP server listening on port 1025 of localhost. This server simply prints to standard output all email headers and the email body. You then only need to set the EMAIL_HOST and EMAIL_PORT accordingly. For a more detailed discussion of SMTP server options, see the Python documentation for the smtpd module.

For information about unit-testing the sending of emails in your application, see the Email services section of the testing documentation.

Internationalization and localization

Overview

The goal of internationalization and localization is to allow a single Web application to offer its content in languages and formats tailored to the audience.

Django has full support for translation of text, formatting of dates, times and numbers, and time zones.

Essentially, Django does two things:

- It allows developers and template authors to specify which parts of their apps should be translated or formatted for local languages and cultures.

- It uses these hooks to localize Web apps for particular users according to their preferences.

Obviously, translation depends on the target language, and formatting usually depends on the target country. This information is provided by browsers in the Accept-Language header. However, the time zone isn’t readily available.

Definitions

The words “internationalization” and “localization” often cause confusion; here’s a simplified definition:

internationalization

Preparing the software for localization. Usually done by developers.

localization

Writing the translations and local formats. Usually done by translators.

More details can be found in the W3C Web Internationalization FAQ, the Wikipedia article or the GNU gettext documentation.

Warning

Translation and formatting are controlled by USE_I18N and USE_L10N settings respectively. However, both features involve internationalization and localization. The names of the settings are an unfortunate result of Django’s history.

Here are some other terms that will help us to handle a common language:

locale name

A locale name, either a language specification of the form ll or a combined language and country specification of the form ll_CC. Examples: it, de_AT, es, pt_BR. The language part is always in lower case and the country part in upper case. The separator is an underscore.

language code

Represents the name of a language. Browsers send the names of the languages they accept in the Accept-Language HTTP header using this format. Examples: it, de-at, es, pt-br. Language codes are generally represented in lower-case, but the HTTP Accept-Language header is case-insensitive. The separator is a dash.

message file

A message file is a plain-text file, representing a single language, that contains all available translation strings and how they should be represented in the given language. Message files have a .po file extension.

translation string

A literal that can be translated.

format file

A format file is a Python module that defines the data formats for a given locale.

Translation

Overview

In order to make a Django project translatable, you have to add a minimal number of hooks to your Python code and templates. These hooks are called translation strings. They tell Django: “This text should be translated into the end user’s language, if a translation for this text is available in that language.” It’s your responsibility to mark translatable strings; the system can only translate strings it knows about.

Django then provides utilities to extract the translation strings into a message file. This file is a convenient way for translators to provide the equivalent of the translation strings in the target language. Once the translators have filled in the message file, it must be compiled. This process relies on the GNU gettext toolset.

Once this is done, Django takes care of translating Web apps on the fly in each available language, according to users’ language preferences.

Django’s internationalization hooks are on by default, and that means there’s a bit of i18n-related overhead in certain places of the framework. If you don’t use internationalization, you should take the two seconds to set USE_I18N = False in your settings file. Then Django will make some optimizations so as not to load the internationalization machinery.

Note

There is also an independent but related USE_L10N setting that controls if Django should implement format localization. See Format localization for more details.

Note

Make sure you’ve activated translation for your project (the fastest way is to check if MIDDLEWARE_CLASSES includes django.middleware.locale.LocaleMiddleware). If you haven’t yet, see How Django discovers language preference.

Internationalization: in Python code

Standard translation

Specify a translation string by using the function ugettext(). It’s convention to import this as a shorter alias, _, to save typing.

Note

Python’s standard library gettext module installs _() into the global namespace, as an alias for gettext(). In Django, we have chosen not to follow this practice, for a couple of reasons:

1. For international character set (Unicode) support, ugettext() is more useful than gettext(). Sometimes, you should be using ugettext_lazy() as the default translation method for a particular file. Without _() in the global namespace, the developer has to think about which is the most appropriate translation function.

2. The underscore character (_) is used to represent “the previous result” in Python’s interactive shell and doctest tests. Installing a global _() function causes interference. Explicitly importing ugettext() as _() avoids this problem.

In this example, the text "Welcome to my site." is marked as a translation string:

from django.utils.translation import ugettext as _
from django.http import HttpResponse

def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)

Obviously, you could code this without using the alias. This example is identical to the previous one:

from django.utils.translation import ugettext
from django.http import HttpResponse

def my_view(request):
output = ugettext("Welcome to my site.")
return HttpResponse(output)

Translation works on computed values. This example is identical to the previous two:

def my_view(request):
words = ['Welcome', 'to', 'my', 'site.']
output = _(' '.join(words))
return HttpResponse(output)

Translation works on variables. Again, here’s an identical example:

def my_view(request):
sentence = 'Welcome to my site.'
output = _(sentence)
return HttpResponse(output)

(The caveat with using variables or computed values, as in the previous two examples, is that Django’s translation-string-detecting utility, django-admin makemessages, won’t be able to find these strings. More on makemessages later.)

The strings you pass to _() or ugettext() can take placeholders, specified with Python’s standard named-string interpolation syntax. Example:

def my_view(request, m, d):
output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
return HttpResponse(output)

This technique lets language-specific translations reorder the placeholder text. For example, an English translation may be "Today is November 26.", while a Spanish translation may be "Hoy es 26 de Noviembre." – with the month and the day placeholders swapped.

For this reason, you should use named-string interpolation (e.g., %(day)s) instead of positional interpolation (e.g., %s or %d) whenever you have more than a single parameter. If you used positional interpolation, translations wouldn’t be able to reorder placeholder text.

Comments for translators

If you would like to give translators hints about a translatable string, you can add a comment prefixed with the Translators keyword on the line preceding the string, e.g.:

def my_view(request):
# Translators: This message appears on the home page only
output = ugettext("Welcome to my site.")

The comment will then appear in the resulting .po file associated with the translatable construct located below it and should also be displayed by most translation tools.

Note

Just for completeness, this is the corresponding fragment of the resulting .po file:

#. Translators: This message appears on the home page only
# path/to/python/file.py:123
msgid "Welcome to my site."
msgstr ""

This also works in templates. See Comments for translators in templates for more details.

Marking strings as no-op

Use the function django.utils.translation.ugettext_noop() to mark a string as a translation string without translating it. The string is later translated from a variable.

Use this if you have constant strings that should be stored in the source language because they are exchanged over systems or users – such as strings in a database – but should be translated at the last possible point in time, such as when the string is presented to the user.

Pluralization

Use the function django.utils.translation.ungettext() to specify pluralized messages.

ungettext takes three arguments: the singular translation string, the plural translation string and the number of objects.

This function is useful when you need your Django application to be localizable to languages where the number and complexity of plural forms is greater than the two forms used in English (‘object’ for the singular and ‘objects’ for all the cases where count is different from one, irrespective of its value.)

For example:

from django.utils.translation import ungettext
from django.http import HttpResponse

def hello_world(request, count):
page = ungettext(
'there is %(count)d object',
'there are %(count)d objects',
count) % {
'count': count,
}
return HttpResponse(page)

In this example the number of objects is passed to the translation languages as the count variable.

Note that pluralization is complicated and works differently in each language. Comparing count to 1 isn’t always the correct rule. This code looks sophisticated, but will produce incorrect results for some languages:

from django.utils.translation import ungettext
from myapp.models import Report

count = Report.objects.count()
if count == 1:
name = Report._meta.verbose_name
else:
name = Report._meta.verbose_name_plural

text = ungettext(
'There is %(count)d %(name)s available.',
'There are %(count)d %(name)s available.',
count
) % {
'count': count,
'name': name
}

Don’t try to implement your own singular-or-plural logic, it won’t be correct. In a case like this, consider something like the following:

text = ungettext(
'There is %(count)d %(name)s object available.',
'There are %(count)d %(name)s objects available.',
count
) % {
'count': count,
'name': Report._meta.verbose_name,
}

Note

When using ungettext(), make sure you use a single name for every extrapolated variable included in the literal. In the examples above, note how we used the name Python variable in both translation strings. This example, besides being incorrect in some languages as noted above, would fail:

text = ungettext(
'There is %(count)d %(name)s available.',
'There are %(count)d %(plural_name)s available.',
count
) % {
'count': Report.objects.count(),
'name': Report._meta.verbose_name,
'plural_name': Report._meta.verbose_name_plural
}

You would get an error when running django-admin compilemessages:

a format specification for argument 'name', as in 'msgstr[0]', doesn't exist in 'msgid'

Note

Plural form and po files

Django does not support custom plural equations in po files. As all translation catalogs are merged, only the plural form for the main Django po file (in django/conf/locale/<lang_code>/LC_MESSAGES/django.po) is considered. Plural forms in all other po files are ignored. Therefore, you should not use different plural equations in your project or application po files.

Contextual markers

Sometimes words have several meanings, such as "May" in English, which refers to a month name and to a verb. To enable translators to translate these words correctly in different contexts, you can use the django.utils.translation.pgettext() function, or the django.utils.translation.npgettext() function if the string needs pluralization. Both take a context string as the first variable.

In the resulting .po file, the string will then appear as often as there are different contextual markers for the same string (the context will appear on the msgctxt line), allowing the translator to give a different translation for each of them.

For example:

from django.utils.translation import pgettext

month = pgettext("month name", "May")

or:

from django.db import models
from django.utils.translation import pgettext_lazy

class MyThing(models.Model):
name = models.CharField(help_text=pgettext_lazy(
'help text for MyThing model', 'This is the help text'))

will appear in the .po file as:

msgctxt "month name"
msgid "May"
msgstr ""

Contextual markers are also supported by the trans and blocktrans template tags.

Lazy translation

Use the lazy versions of translation functions in django.utils.translation (easily recognizable by the lazy suffix in their names) to translate strings lazily – when the value is accessed rather than when they’re called.

These functions store a lazy reference to the string – not the actual translation. The translation itself will be done when the string is used in a string context, such as in template rendering.

This is essential when calls to these functions are located in code paths that are executed at module load time.

This is something that can easily happen when defining models, forms and model forms, because Django implements these such that their fields are actually class-level attributes. For that reason, make sure to use lazy translations in the following cases:

Model fields and relationships verbose_name and help_text option values

For example, to translate the help text of the name field in the following model, do the following:

from django.db import models
from django.utils.translation import ugettext_lazy as _

class MyThing(models.Model):
name = models.CharField(help_text=_('This is the help text'))

You can mark names of ForeignKey, ManyToManyField or OneToOneField relationship as translatable by using their verbose_name options:

class MyThing(models.Model):
kind = models.ForeignKey(
ThingKind,
on_delete=models.CASCADE,
related_name='kinds',
verbose_name=_('kind'),
)

Just like you would do in verbose_name you should provide a lowercase verbose name text for the relation as Django will automatically titlecase it when required.

Model verbose names values

It is recommended to always provide explicit verbose_name and verbose_name_plural options rather than relying on the fallback English-centric and somewhat naïve determination of verbose names Django performs by looking at the model’s class name:

from django.db import models
from django.utils.translation import ugettext_lazy as _

class MyThing(models.Model):
name = models.CharField(_('name'), help_text=_('This is the help text'))

class Meta:
verbose_name = _('my thing')
verbose_name_plural = _('my things')

Model methods short_description attribute values

For model methods, you can provide translations to Django and the admin site with the short_description attribute:

from django.db import models
from django.utils.translation import ugettext_lazy as _

class MyThing(models.Model):
kind = models.ForeignKey(
ThingKind,
on_delete=models.CASCADE,
related_name='kinds',
verbose_name=_('kind'),
)

def is_mouse(self):
return self.kind.type == MOUSE_TYPE
is_mouse.short_description = _('Is it a mouse?')

Working with lazy translation objects

The result of a ugettext_lazy() call can be used wherever you would use a unicode string (an object with type unicode) in Python. If you try to use it where a bytestring (a str object) is expected, things will not work as expected, since a ugettext_lazy() object doesn’t know how to convert itself to a bytestring. You can’t use a unicode string inside a bytestring, either, so this is consistent with normal Python behavior. For example:

# This is fine: putting a unicode proxy into a unicode string.
"Hello %s" % ugettext_lazy("people")

# This will not work, since you cannot insert a unicode object
# into a bytestring (nor can you insert our unicode proxy there)
b"Hello %s" % ugettext_lazy("people")

If you ever see output that looks like "hello <django.utils.functional...>", you have tried to insert the result of ugettext_lazy() into a bytestring. That’s a bug in your code.

If you don’t like the long ugettext_lazy name, you can just alias it as _ (underscore), like so:

from django.db import models
from django.utils.translation import ugettext_lazy as _

class MyThing(models.Model):
name = models.CharField(help_text=_('This is the help text'))

Using ugettext_lazy() and ungettext_lazy() to mark strings in models and utility functions is a common operation. When you’re working with these objects elsewhere in your code, you should ensure that you don’t accidentally convert them to strings, because they should be converted as late as possible (so that the correct locale is in effect). This necessitates the use of the helper function described next.

Lazy translations and plural

When using lazy translation for a plural string ([u]n[p]gettext_lazy), you generally don’t know the number argument at the time of the string definition. Therefore, you are authorized to pass a key name instead of an integer as the number argument. Then number will be looked up in the dictionary under that key during string interpolation. Here’s example:

from django import forms
from django.utils.translation import ungettext_lazy

class MyForm(forms.Form):
error_message = ungettext_lazy("You only provided %(num)d argument",
"You only provided %(num)d arguments", 'num')

def clean(self):
# ...
if error:
raise forms.ValidationError(self.error_message % {'num': number})

If the string contains exactly one unnamed placeholder, you can interpolate directly with the number argument:

class MyForm(forms.Form):
error_message = ungettext_lazy(
"You provided %d argument",
"You provided %d arguments",
)

def clean(self):
# ...
if error:
raise forms.ValidationError(self.error_message % number)

Joining strings: string_concat()

Standard Python string joins (''.join([...])) will not work on lists containing lazy translation objects. Instead, you can use django.utils.translation.string_concat(), which creates a lazy object that concatenates its contents and converts them to strings only when the result is included in a string. For example:

from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy
...
name = ugettext_lazy('John Lennon')
instrument = ugettext_lazy('guitar')
result = string_concat(name, ': ', instrument)

In this case, the lazy translations in result will only be converted to strings when result itself is used in a string (usually at template rendering time).

Other uses of lazy in delayed translations

For any other case where you would like to delay the translation, but have to pass the translatable string as argument to another function, you can wrap this function inside a lazy call yourself. For example:

from django.utils import six  # Python 3 compatibility
from django.utils.functional import lazy
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _

mark_safe_lazy = lazy(mark_safe, six.text_type)

And then later:

lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>"))

Localized names of languages

get_language_info()[source]

The get_language_info() function provides detailed information about languages:

>>> from django.utils.translation import activate, get_language_info
>>> activate('fr')
>>> li = get_language_info('de')
>>> print(li['name'], li['name_local'], li['name_translated'], li['bidi'])
German Deutsch Allemand False

The name, name_local, and name_translated attributes of the dictionary contain the name of the language in English, in the language itself, and in your current active language respectively. The bidi attribute is True only for bi-directional languages.

The source of the language information is the django.conf.locale module. Similar access to this information is available for template code. See below.

Changed in Django 1.9:
The 'name_translated' attribute was added.

Internationalization: in template code

Translations in Django templates uses two template tags and a slightly different syntax than in Python code. To give your template access to these tags, put {% load i18n %} toward the top of your template. As with all template tags, this tag needs to be loaded in all templates which use translations, even those templates that extend from other templates which have already loaded the i18n tag.

trans template tag

The {% trans %} template tag translates either a constant string (enclosed in single or double quotes) or variable content:

<title>{% trans "This is the title." %}</title>
<title>{% trans myvar %}</title>

If the noop option is present, variable lookup still takes place but the translation is skipped. This is useful when “stubbing out” content that will require translation in the future:

<title>{% trans "myvar" noop %}</title>

Internally, inline translations use an ugettext() call.

In case a template var (myvar above) is passed to the tag, the tag will first resolve such variable to a string at run-time and then look up that string in the message catalogs.

It’s not possible to mix a template variable inside a string within {% trans %}. If your translations require strings with variables (placeholders), use {% blocktrans %} instead.

If you’d like to retrieve a translated string without displaying it, you can use the following syntax:

{% trans "This is the title" as the_title %}

<title>{{ the_title }}</title>
<meta name="description" content="{{ the_title }}">

In practice you’ll use this to get a string you can use in multiple places in a template or so you can use the output as an argument for other template tags or filters:

{% trans "starting point" as start %}
{% trans "end point" as end %}
{% trans "La Grande Boucle" as race %}

<h1>
<a href="/" title="{% blocktrans %}Back to '{{ race }}' homepage{% endblocktrans %}">{{ race }}</a>
</h1>
<p>
{% for stage in tour_stages %}
{% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}<br />{% else %}, {% endif %}
{% endfor %}
</p>

{% trans %} also supports contextual markers using the context keyword:

{% trans "May" context "month name" %}

blocktrans template tag

Contrarily to the trans tag, the blocktrans tag allows you to mark complex sentences consisting of literals and variable content for translation by making use of placeholders:

{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}

To translate a template expression – say, accessing object attributes or using template filters – you need to bind the expression to a local variable for use within the translation block. Examples:

{% blocktrans with amount=article.price %}
That will cost $ {{ amount }}.
{% endblocktrans %}

{% blocktrans with myvar=value|filter %}
This will have {{ myvar }} inside.
{% endblocktrans %}

You can use multiple expressions inside a single blocktrans tag:

{% blocktrans with book_t=book|title author_t=author|title %}
This is {{ book_t }} by {{ author_t }}
{% endblocktrans %}

Note

The previous more verbose format is still supported: {% blocktrans with book|title as book_t and author|title as author_t %}

Other block tags (for example {% for %} or {% if %}) are not allowed inside a blocktrans tag.

If resolving one of the block arguments fails, blocktrans will fall back to the default language by deactivating the currently active language temporarily with the deactivate_all() function.

This tag also provides for pluralization. To use it:

- Designate and bind a counter value with the name count. This value will be the one used to select the right plural form.

- Specify both the singular and plural forms separating them with the {% plural %} tag within the {% blocktrans %} and {% endblocktrans %} tags.

An example:

{% blocktrans count counter=list|length %}
There is only one {{ name }} object.
{% plural %}
There are {{ counter }} {{ name }} objects.
{% endblocktrans %}

A more complex example:

{% blocktrans with amount=article.price count years=i.length %}
That will cost $ {{ amount }} per year.
{% plural %}
That will cost $ {{ amount }} per {{ years }} years.
{% endblocktrans %}

When you use both the pluralization feature and bind values to local variables in addition to the counter value, keep in mind that the blocktrans construct is internally converted to an ungettext call. This means the same notes regarding ungettext variables apply.

Reverse URL lookups cannot be carried out within the blocktrans and should be retrieved (and stored) beforehand:

{% url 'path.to.view' arg arg2 as the_url %}
{% blocktrans %}
This is a URL: {{ the_url }}
{% endblocktrans %}

If you’d like to retrieve a translated string without displaying it, you can use the following syntax:

{% blocktrans asvar the_title %}The title is {{ title }}.{% endblocktrans %}
<title>{{ the_title }}</title>
<meta name="description" content="{{ the_title }}">

In practice you’ll use this to get a string you can use in multiple places in a template or so you can use the output as an argument for other template tags or filters.

Changed in Django 1.9:
The asvar syntax was added.

{% blocktrans %} also supports contextual markers using the context keyword:

{% blocktrans with name=user.username context "greeting" %}Hi {{ name }}{% endblocktrans %}

Another feature {% blocktrans %} supports is the trimmed option. This option will remove newline characters from the beginning and the end of the content of the {% blocktrans %} tag, replace any whitespace at the beginning and end of a line and merge all lines into one using a space character to separate them. This is quite useful for indenting the content of a {% blocktrans %} tag without having the indentation characters end up in the corresponding entry in the PO file, which makes the translation process easier.

For instance, the following {% blocktrans %} tag:

{% blocktrans trimmed %}
First sentence.
Second paragraph.
{% endblocktrans %}

will result in the entry "First sentence. Second paragraph." in the PO file, compared to "\n  First sentence.\n  Second sentence.\n", if the trimmed option had not been specified.

String literals passed to tags and filters

You can translate string literals passed as arguments to tags and filters by using the familiar _() syntax:

{% some_tag _("Page not found") value|yesno:_("yes,no") %}

In this case, both the tag and the filter will see the translated string, so they don’t need to be aware of translations.

Note

In this example, the translation infrastructure will be passed the string "yes,no", not the individual strings "yes" and "no". The translated string will need to contain the comma so that the filter parsing code knows how to split up the arguments. For example, a German translator might translate the string "yes,no" as "ja,nein" (keeping the comma intact).

Comments for translators in templates

Just like with Python code, these notes for translators can be specified using comments, either with the comment tag:

{% comment %}Translators: View verb{% endcomment %}
{% trans "View" %}

{% comment %}Translators: Short intro blurb{% endcomment %}
<p>{% blocktrans %}A multiline translatable
literal.{% endblocktrans %}</p>

or with the {# ... #} one-line comment constructs:

{# Translators: Label of a button that triggers search #}
<button type="submit">{% trans "Go" %}</button>

{# Translators: This is a text of the base template #}
{% blocktrans %}Ambiguous translatable block of text{% endblocktrans %}

Note

Just for completeness, these are the corresponding fragments of the resulting .po file:

#. Translators: View verb
# path/to/template/file.html:10
msgid "View"
msgstr ""

#. Translators: Short intro blurb
# path/to/template/file.html:13
msgid ""
"A multiline translatable"
"literal."
msgstr ""

# ...

#. Translators: Label of a button that triggers search
# path/to/template/file.html:100
msgid "Go"
msgstr ""

#. Translators: This is a text of the base template
# path/to/template/file.html:103
msgid "Ambiguous translatable block of text"
msgstr ""

Switching language in templates

If you want to select a language within a template, you can use the language template tag:

{% load i18n %}

{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<p>{% trans "Welcome to our page" %}</p>

{% language 'en' %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<p>{% trans "Welcome to our page" %}</p>
{% endlanguage %}

While the first occurrence of “Welcome to our page” uses the current language, the second will always be in English.

Other tags

These tags also require a {% load i18n %}.

get_available_languages

{% get_available_languages as LANGUAGES %} returns a list of tuples in which the first element is the language code and the second is the language name (translated into the currently active locale).

get_current_language

{% get_current_language as LANGUAGE_CODE %} returns the current user’s preferred language as a string. Example: en-us. See How Django discovers language preference.

get_current_language_bidi

{% get_current_language_bidi as LANGUAGE_BIDI %} returns the current locale’s direction. If True, it’s a right-to-left language, e.g. Hebrew, Arabic. If False it’s a left-to-right language, e.g. English, French, German, etc.

If you enable the django.template.context_processors.i18n context processor then each RequestContext will have access to LANGUAGES, LANGUAGE_CODE, and LANGUAGE_BIDI as defined above.

Changed in Django 1.8:
The i18n context processor is not enabled by default for new projects.

get_language_info

You can also retrieve information about any of the available languages using provided template tags and filters. To get information about a single language, use the {% get_language_info %} tag:

{% get_language_info for LANGUAGE_CODE as lang %}
{% get_language_info for "pl" as lang %}

You can then access the information:

Language code: {{ lang.code }}<br />
Name of language: {{ lang.name_local }}<br />
Name in English: {{ lang.name }}<br />
Bi-directional: {{ lang.bidi }}
Name in the active language: {{ lang.name_translated }}

New in Django 1.9:
The name_translated attribute was added.

get_language_info_list

You can also use the {% get_language_info_list %} template tag to retrieve information for a list of languages (e.g. active languages as specified in LANGUAGES). See the section about the set_language redirect view for an example of how to display a language selector using {% get_language_info_list %}.

In addition to LANGUAGES style list of tuples, {% get_language_info_list %} supports simple lists of language codes. If you do this in your view:

context = {'available_languages': ['en', 'es', 'fr']}
return render(request, 'mytemplate.html', context)

you can iterate over those languages in the template:

{% get_language_info_list for available_languages as langs %}
{% for lang in langs %} ... {% endfor %}

Template filters

There are also simple filters available for convenience:

- {{ LANGUAGE_CODE|language_name }} (“German”)

- {{ LANGUAGE_CODE|language_name_local }} (“Deutsch”)

- {{ LANGUAGE_CODE|language_bidi }} (False)

- {{ LANGUAGE_CODE|language_name_translated }} (“německy”, when active language is Czech)

New in Django 1.9:
The language_name_translated filter was added.

Internationalization: in JavaScript code

Adding translations to JavaScript poses some problems:

- JavaScript code doesn’t have access to a gettext implementation.

- JavaScript code doesn’t have access to .po or .mo files; they need to be delivered by the server.

- The translation catalogs for JavaScript should be kept as small as possible.

Django provides an integrated solution for these problems: It passes the translations into JavaScript, so you can call gettext, etc., from within JavaScript.

The javascript_catalog view

javascript_catalog(request, domain='djangojs', packages=None)[source]

The main solution to these problems is the django.views.i18n.javascript_catalog() view, which sends out a JavaScript code library with functions that mimic the gettext interface, plus an array of translation strings. Those translation strings are taken from applications or Django core, according to what you specify in either the info_dict or the URL. Paths listed in LOCALE_PATHS are also included.

You hook it up like this:

from django.views.i18n import javascript_catalog

js_info_dict = {
'packages': ('your.app.package',),
}

urlpatterns = [
url(r'^jsi18n/$', javascript_catalog, js_info_dict, name='javascript-catalog'),
]

Each string in packages should be in Python dotted-package syntax (the same format as the strings in INSTALLED_APPS) and should refer to a package that contains a locale directory. If you specify multiple packages, all those catalogs are merged into one catalog. This is useful if you have JavaScript that uses strings from different applications.

The precedence of translations is such that the packages appearing later in the packages argument have higher precedence than the ones appearing at the beginning, this is important in the case of clashing translations for the same literal.

By default, the view uses the djangojs gettext domain. This can be changed by altering the domain argument.

You can make the view dynamic by putting the packages into the URL pattern:

urlpatterns = [
url(r'^jsi18n/(?P<packages>\S+?)/$', javascript_catalog, name='javascript-catalog'),
]

With this, you specify the packages as a list of package names delimited by ‘+’ signs in the URL. This is especially useful if your pages use code from different apps and this changes often and you don’t want to pull in one big catalog file. As a security measure, these values can only be either django.conf or any package from the INSTALLED_APPS setting.

You can also split the catalogs in multiple URLs and load them as you need in your sites:

js_info_dict_app = {
'packages': ('your.app.package',),
}

js_info_dict_other_app = {
'packages': ('your.other.app.package',),
}

urlpatterns = [
url(r'^jsi18n/app/$', javascript_catalog, js_info_dict_app),
url(r'^jsi18n/other_app/$', javascript_catalog, js_info_dict_other_app),
]

If you use more than one javascript_catalog on a site and some of them define the same strings, the strings in the catalog that was loaded last take precedence.

Changed in Django 1.9:
Before Django 1.9, the catalogs completely overwrote each other and you could only use one at a time.

The JavaScript translations found in the paths listed in the LOCALE_PATHS setting are also always included. To keep consistency with the translations lookup order algorithm used for Python and templates, the directories listed in LOCALE_PATHS have the highest precedence with the ones appearing first having higher precedence than the ones appearing later.

Using the JavaScript translation catalog

To use the catalog, just pull in the dynamically generated script like this:

<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>

This uses reverse URL lookup to find the URL of the JavaScript catalog view. When the catalog is loaded, your JavaScript code can use the following methods:

- gettext

- ngettext

- interpolate

- get_format

- gettext_noop

- pgettext

- npgettext

- pluralidx

gettext

The gettext function behaves similarly to the standard gettext interface within your Python code:

document.write(gettext('this is to be translated'));

ngettext

The ngettext function provides an interface to pluralize words and phrases:

var object_count = 1 // or 0, or 2, or 3, ...
s = ngettext('literal for the singular case',
'literal for the plural case', object_count);

interpolate

The interpolate function supports dynamically populating a format string. The interpolation syntax is borrowed from Python, so the interpolate function supports both positional and named interpolation:

- Positional interpolation: obj contains a JavaScript Array object whose elements values are then sequentially interpolated in their corresponding fmt placeholders in the same order they appear. For example:

fmts = ngettext('There is %s object. Remaining: %s',
'There are %s objects. Remaining: %s', 11);
s = interpolate(fmts, [11, 20]);
// s is 'There are 11 objects. Remaining: 20'

- Named interpolation: This mode is selected by passing the optional boolean named parameter as true. obj contains a JavaScript object or associative array. For example:

d = {
count: 10,
total: 50
};

fmts = ngettext('Total: %(total)s, there is %(count)s object',
'there are %(count)s of a total of %(total)s objects', d.count);
s = interpolate(fmts, d, true);

You shouldn’t go over the top with string interpolation, though: this is still JavaScript, so the code has to make repeated regular-expression substitutions. This isn’t as fast as string interpolation in Python, so keep it to those cases where you really need it (for example, in conjunction with ngettext to produce proper pluralizations).

get_format

The get_format function has access to the configured i18n formatting settings and can retrieve the format string for a given setting name:

document.write(get_format('DATE_FORMAT'));
// 'N j, Y'

It has access to the following settings:

- DATE_FORMAT

- DATE_INPUT_FORMATS

- DATETIME_FORMAT

- DATETIME_INPUT_FORMATS

- DECIMAL_SEPARATOR

- FIRST_DAY_OF_WEEK

- MONTH_DAY_FORMAT

- NUMBER_GROUPING

- SHORT_DATE_FORMAT

- SHORT_DATETIME_FORMAT

- THOUSAND_SEPARATOR

- TIME_FORMAT

- TIME_INPUT_FORMATS

- YEAR_MONTH_FORMAT

This is useful for maintaining formatting consistency with the Python-rendered values.

gettext_noop

This emulates the gettext function but does nothing, returning whatever is passed to it:

document.write(gettext_noop('this will not be translated'));

This is useful for stubbing out portions of the code that will need translation in the future.

pgettext

The pgettext function behaves like the Python variant (pgettext()), providing a contextually translated word:

document.write(pgettext('month name', 'May'));

npgettext

The npgettext function also behaves like the Python variant (npgettext()), providing a pluralized contextually translated word:

document.write(npgettext('group', 'party', 1));
// party
document.write(npgettext('group', 'party', 2));
// parties

pluralidx

The pluralidx function works in a similar way to the pluralize template filter, determining if a given count should use a plural form of a word or not:

document.write(pluralidx(0));
// true
document.write(pluralidx(1));
// false
document.write(pluralidx(2));
// true

In the simplest case, if no custom pluralization is needed, this returns false for the integer 1 and true for all other numbers.

However, pluralization is not this simple in all languages. If the language does not support pluralization, an empty value is provided.

Additionally, if there are complex rules around pluralization, the catalog view will render a conditional expression. This will evaluate to either a true (should pluralize) or false (should not pluralize) value.

The json_catalog view

New in Django 1.9.

json_catalog(request, domain='djangojs', packages=None)[source]

In order to use another client-side library to handle translations, you may want to take advantage of the json_catalog() view. It’s similar to javascript_catalog() but returns a JSON response.

The JSON object contains i18n formatting settings (those available for get_format), a plural rule (as a plural part of a GNU gettext Plural-Forms expression), and translation strings. The translation strings are taken from applications or Django’s own translations, according to what is specified either via urlpatterns arguments or as request parameters. Paths listed in LOCALE_PATHS are also included.

The view is hooked up to your application and configured in the same fashion as javascript_catalog() (namely, the domain and packages arguments behave identically):

from django.views.i18n import json_catalog

js_info_dict = {
'packages': ('your.app.package',),
}

urlpatterns = [
url(r'^jsoni18n/$', json_catalog, js_info_dict),
]

The response format is as follows:

{
"catalog": {
# Translations catalog
},
"formats": {
# Language formats for date, time, etc.
},
"plural": "..."  # Expression for plural forms, or null.
}

Note on performance

The javascript_catalog() view generates the catalog from .mo files on every request. Since its output is constant — at least for a given version of a site — it’s a good candidate for caching.

Server-side caching will reduce CPU load. It’s easily implemented with the cache_page() decorator. To trigger cache invalidation when your translations change, provide a version-dependent key prefix, as shown in the example below, or map the view at a version-dependent URL:

from django.views.decorators.cache import cache_page
from django.views.i18n import javascript_catalog

# The value returned by get_version() must change when translations change.
@cache_page(86400, key_prefix='js18n-%s' % get_version())
def cached_javascript_catalog(request, domain='djangojs', packages=None):
return javascript_catalog(request, domain, packages)

Client-side caching will save bandwidth and make your site load faster. If you’re using ETags (USE_ETAGS = True), you’re already covered. Otherwise, you can apply conditional decorators. In the following example, the cache is invalidated whenever you restart your application server:

from django.utils import timezone
from django.views.decorators.http import last_modified
from django.views.i18n import javascript_catalog

last_modified_date = timezone.now()

@last_modified(lambda req, **kw: last_modified_date)
def cached_javascript_catalog(request, domain='djangojs', packages=None):
return javascript_catalog(request, domain, packages)

You can even pre-generate the JavaScript catalog as part of your deployment procedure and serve it as a static file. This radical technique is implemented in django-statici18n.

Internationalization: in URL patterns

Django provides two mechanisms to internationalize URL patterns:

- Adding the language prefix to the root of the URL patterns to make it possible for LocaleMiddleware to detect the language to activate from the requested URL.

- Making URL patterns themselves translatable via the django.utils.translation.ugettext_lazy() function.

Warning

Using either one of these features requires that an active language be set for each request; in other words, you need to have django.middleware.locale.LocaleMiddleware in your MIDDLEWARE_CLASSES setting.

Language prefix in URL patterns

i18n_patterns(prefix, pattern_description, ...)[source]

Deprecated since version 1.8: The prefix argument to i18n_patterns() has been deprecated and will not be supported in Django 1.10. Simply pass a list of django.conf.urls.url() instances instead.

This function can be used in your root URLconf and Django will automatically prepend the current active language code to all URL patterns defined within i18n_patterns(). Example URL patterns:

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns

from about import views as about_views
from news import views as news_views
from sitemap.views import sitemap

urlpatterns = [
url(r'^sitemap\.xml$', sitemap, name='sitemap-xml'),
]

news_patterns = ([
url(r'^$', news_views.index, name='index'),
url(r'^category/(?P<slug>[\w-]+)/$', news_views.category, name='category'),
url(r'^(?P<slug>[\w-]+)/$', news_views.details, name='detail'),
], 'news')

urlpatterns += i18n_patterns(
url(r'^about/$', about_views.main, name='about'),
url(r'^news/', include(news_patterns, namespace='news')),
)

After defining these URL patterns, Django will automatically add the language prefix to the URL patterns that were added by the i18n_patterns function. Example:

>>> from django.core.urlresolvers import reverse
>>> from django.utils.translation import activate

>>> activate('en')
>>> reverse('sitemap-xml')
'/sitemap.xml'
>>> reverse('news:index')
'/en/news/'

>>> activate('nl')
>>> reverse('news:detail', kwargs={'slug': 'news-slug'})
'/nl/news/news-slug/'

Warning

i18n_patterns() is only allowed in your root URLconf. Using it within an included URLconf will throw an ImproperlyConfigured exception.

Warning

Ensure that you don’t have non-prefixed URL patterns that might collide with an automatically-added language prefix.

Translating URL patterns

URL patterns can also be marked translatable using the ugettext_lazy() function. Example:

from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import ugettext_lazy as _

from about import views as about_views
from news import views as news_views
from sitemaps.views import sitemap

urlpatterns = [
url(r'^sitemap\.xml$', sitemap, name='sitemap-xml'),
]

news_patterns = ([
url(r'^$', news_views.index, name='index'),
url(_(r'^category/(?P<slug>[\w-]+)/$'), news_views.category, name='category'),
url(r'^(?P<slug>[\w-]+)/$', news_views.details, name='detail'),
], 'news')

urlpatterns += i18n_patterns(
url(_(r'^about/$'), about_views.main, name='about'),
url(_(r'^news/'), include(news_patterns, namespace='news')),
)

After you’ve created the translations, the reverse() function will return the URL in the active language. Example:

>>> from django.core.urlresolvers import reverse
>>> from django.utils.translation import activate

>>> activate('en')
>>> reverse('news:category', kwargs={'slug': 'recent'})
'/en/news/category/recent/'

>>> activate('nl')
>>> reverse('news:category', kwargs={'slug': 'recent'})
'/nl/nieuws/categorie/recent/'

Warning

In most cases, it’s best to use translated URLs only within a language-code-prefixed block of patterns (using i18n_patterns()), to avoid the possibility that a carelessly translated URL causes a collision with a non-translated URL pattern.

Reversing in templates

If localized URLs get reversed in templates they always use the current language. To link to a URL in another language use the language template tag. It enables the given language in the enclosed template section:

{% load i18n %}

{% get_available_languages as languages %}

{% trans "View this category in:" %}
{% for lang_code, lang_name in languages %}
{% language lang_code %}
<a href="{% url 'category' slug=category.slug %}">{{ lang_name }}</a>
{% endlanguage %}
{% endfor %}

The language tag expects the language code as the only argument.

Localization: how to create language files

Once the string literals of an application have been tagged for later translation, the translation themselves need to be written (or obtained). Here’s how that works.

Message files

The first step is to create a message file for a new language. A message file is a plain-text file, representing a single language, that contains all available translation strings and how they should be represented in the given language. Message files have a .po file extension.

Django comes with a tool, django-admin makemessages, that automates the creation and upkeep of these files.

Gettext utilities

The makemessages command (and compilemessages discussed later) use commands from the GNU gettext toolset: xgettext, msgfmt, msgmerge and msguniq.

The minimum version of the gettext utilities supported is 0.15.

To create or update a message file, run this command:

django-admin makemessages -l de

...where de is the locale name for the message file you want to create. For example, pt_BR for Brazilian Portuguese, de_AT for Austrian German or id for Indonesian.

The script should be run from one of two places:

- The root directory of your Django project (the one that contains manage.py).

- The root directory of one of your Django apps.

The script runs over your project source tree or your application source tree and pulls out all strings marked for translation (see How Django discovers translations and be sure LOCALE_PATHS is configured correctly). It creates (or updates) a message file in the directory locale/LANG/LC_MESSAGES. In the de example, the file will be locale/de/LC_MESSAGES/django.po.

When you run makemessages from the root directory of your project, the extracted strings will be automatically distributed to the proper message files. That is, a string extracted from a file of an app containing a locale directory will go in a message file under that directory. A string extracted from a file of an app without any locale directory will either go in a message file under the directory listed first in LOCALE_PATHS or will generate an error if LOCALE_PATHS is empty.

By default django-admin makemessages examines every file that has the .html or .txt file extension. In case you want to override that default, use the --extension or -e option to specify the file extensions to examine:

django-admin makemessages -l de -e txt

Separate multiple extensions with commas and/or use -e or --extension multiple times:

django-admin makemessages -l de -e html,txt -e xml

Warning

When creating message files from JavaScript source code you need to use the special ‘djangojs’ domain, not -e js.

Using Jinja2 templates?

makemessages doesn’t understand the syntax of Jinja2 templates. To extract strings from a project containing Jinja2 templates, use Message Extracting from Babel instead.

Here’s an example babel.cfg configuration file:

# Extraction from Python source files
[python: **.py]

# Extraction from Jinja2 templates
[jinja2: **.jinja]
extensions = jinja2.ext.with_

Make sure you list all extensions you’re using! Otherwise Babel won’t recognize the tags defined by these extensions and will ignore Jinja2 templates containing them entirely.

Babel provides similar features to makemessages, can replace it in general, and doesn’t depend on gettext. For more information, read its documentation about working with message catalogs.

No gettext?

If you don’t have the gettext utilities installed, makemessages will create empty files. If that’s the case, either install the gettext utilities or just copy the English message file (locale/en/LC_MESSAGES/django.po) if available and use it as a starting point; it’s just an empty translation file.

Working on Windows?

If you’re using Windows and need to install the GNU gettext utilities so makemessages works, see gettext on Windows for more information.

The format of .po files is straightforward. Each .po file contains a small bit of metadata, such as the translation maintainer’s contact information, but the bulk of the file is a list of messages – simple mappings between translation strings and the actual translated text for the particular language.

For example, if your Django app contained a translation string for the text "Welcome to my site.", like so:

_("Welcome to my site.")

...then django-admin makemessages will have created a .po file containing the following snippet – a message:

#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""

A quick explanation:

- msgid is the translation string, which appears in the source. Don’t change it.

- msgstr is where you put the language-specific translation. It starts out empty, so it’s your responsibility to change it. Make sure you keep the quotes around your translation.

- As a convenience, each message includes, in the form of a comment line prefixed with # and located above the msgid line, the filename and line number from which the translation string was gleaned.

Long messages are a special case. There, the first string directly after the msgstr (or msgid) is an empty string. Then the content itself will be written over the next few lines as one string per line. Those strings are directly concatenated. Don’t forget trailing spaces within the strings; otherwise, they’ll be tacked together without whitespace!

Mind your charset

Due to the way the gettext tools work internally and because we want to allow non-ASCII source strings in Django’s core and your applications, you must use UTF-8 as the encoding for your PO files (the default when PO files are created). This means that everybody will be using the same encoding, which is important when Django processes the PO files.

To reexamine all source code and templates for new translation strings and update all message files for all languages, run this:

django-admin makemessages -a

Compiling message files

After you create your message file – and each time you make changes to it – you’ll need to compile it into a more efficient form, for use by gettext. Do this with the django-admin compilemessages utility.

This tool runs over all available .po files and creates .mo files, which are binary files optimized for use by gettext. In the same directory from which you ran django-admin makemessages, run django-admin compilemessages like this:

django-admin compilemessages

That’s it. Your translations are ready for use.

Changed in Django 1.9:
compilemessages now matches the operation of makemessages, scanning the project tree for .po files to compile.

Working on Windows?

If you’re using Windows and need to install the GNU gettext utilities so django-admin compilemessages works see gettext on Windows for more information.

.po files: Encoding and BOM usage.

Django only supports .po files encoded in UTF-8 and without any BOM (Byte Order Mark) so if your text editor adds such marks to the beginning of files by default then you will need to reconfigure it.

Creating message files from JavaScript source code

You create and update the message files the same way as the other Django message files – with the django-admin makemessages tool. The only difference is you need to explicitly specify what in gettext parlance is known as a domain in this case the djangojs domain, by providing a -d djangojs parameter, like this:

django-admin makemessages -d djangojs -l de

This would create or update the message file for JavaScript for German. After updating message files, just run django-admin compilemessages the same way as you do with normal Django message files.

gettext on Windows

This is only needed for people who either want to extract message IDs or compile message files (.po). Translation work itself just involves editing existing files of this type, but if you want to create your own message files, or want to test or compile a changed message file, download a precompiled binary installer.

You may also use gettext binaries you have obtained elsewhere, so long as the xgettext --version command works properly. Do not attempt to use Django translation utilities with a gettext package if the command xgettext --version entered at a Windows command prompt causes a popup window saying “xgettext.exe has generated errors and will be closed by Windows”.

Customizing the makemessages command

If you want to pass additional parameters to xgettext, you need to create a custom makemessages command and override its xgettext_options attribute:

from django.core.management.commands import makemessages

class Command(makemessages.Command):
xgettext_options = makemessages.Command.xgettext_options + ['--keyword=mytrans']

If you need more flexibility, you could also add a new argument to your custom makemessages command:

from django.core.management.commands import makemessages

class Command(makemessages.Command):

def add_arguments(self, parser):
super(Command, self).add_arguments(parser)
parser.add_argument(
'--extra-keyword',
dest='xgettext_keywords',
action='append',
)

def handle(self, *args, **options):
xgettext_keywords = options.pop('xgettext_keywords')
if xgettext_keywords:
self.xgettext_options = (
makemessages.Command.xgettext_options[:] +
['--keyword=%s' % kwd for kwd in xgettext_keywords]
)
super(Command, self).handle(*args, **options)

Miscellaneous

The set_language redirect view

set_language(request)[source]

As a convenience, Django comes with a view, django.views.i18n.set_language(), that sets a user’s language preference and redirects to a given URL or, by default, back to the previous page.

Activate this view by adding the following line to your URLconf:

url(r'^i18n/', include('django.conf.urls.i18n')),

(Note that this example makes the view available at /i18n/setlang/.)

Warning

Make sure that you don’t include the above URL within i18n_patterns() - it needs to be language-independent itself to work correctly.

The view expects to be called via the POST method, with a language parameter set in request. If session support is enabled, the view saves the language choice in the user’s session. Otherwise, it saves the language choice in a cookie that is by default named django_language. (The name can be changed through the LANGUAGE_COOKIE_NAME setting.)

After setting the language choice, Django redirects the user, following this algorithm:

- Django looks for a next parameter in the POST data.

- If that doesn’t exist, or is empty, Django tries the URL in the Referrer header.

- If that’s empty – say, if a user’s browser suppresses that header – then the user will be redirected to / (the site root) as a fallback.

Here’s example HTML template code:

{% load i18n %}

<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>

In this example, Django looks up the URL of the page to which the user will be redirected in the redirect_to context variable.

Explicitly setting the active language

You may want to set the active language for the current session explicitly. Perhaps a user’s language preference is retrieved from another system, for example. You’ve already been introduced to django.utils.translation.activate(). That applies to the current thread only. To persist the language for the entire session, also modify LANGUAGE_SESSION_KEY in the session:

from django.utils import translation
user_language = 'fr'
translation.activate(user_language)
request.session[translation.LANGUAGE_SESSION_KEY] = user_language

You would typically want to use both: django.utils.translation.activate() will change the language for this thread, and modifying the session makes this preference persist in future requests.

If you are not using sessions, the language will persist in a cookie, whose name is configured in LANGUAGE_COOKIE_NAME. For example:

from django.utils import translation
from django import http
from django.conf import settings
user_language = 'fr'
translation.activate(user_language)
response = http.HttpResponse(...)
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user_language)

Using translations outside views and templates

While Django provides a rich set of i18n tools for use in views and templates, it does not restrict the usage to Django-specific code. The Django translation mechanisms can be used to translate arbitrary texts to any language that is supported by Django (as long as an appropriate translation catalog exists, of course). You can load a translation catalog, activate it and translate text to language of your choice, but remember to switch back to original language, as activating a translation catalog is done on per-thread basis and such change will affect code running in the same thread.

For example:

from django.utils import translation

def welcome_translated(language):
cur_language = translation.get_language()
try:
translation.activate(language)
text = translation.ugettext('welcome')
finally:
translation.activate(cur_language)
return text

Calling this function with the value ‘de’ will give you "Willkommen", regardless of LANGUAGE_CODE and language set by middleware.

Functions of particular interest are django.utils.translation.get_language() which returns the language used in the current thread, django.utils.translation.activate() which activates a translation catalog for the current thread, and django.utils.translation.check_for_language() which checks if the given language is supported by Django.

To help write more concise code, there is also a context manager django.utils.translation.override() that stores the current language on enter and restores it on exit. With it, the above example becomes:

from django.utils import translation

def welcome_translated(language):
with translation.override(language):
return translation.ugettext('welcome')

Language cookie

A number of settings can be used to adjust language cookie options:

- LANGUAGE_COOKIE_NAME

- LANGUAGE_COOKIE_AGE

- LANGUAGE_COOKIE_DOMAIN

- LANGUAGE_COOKIE_PATH

Implementation notes

Specialties of Django translation

Django’s translation machinery uses the standard gettext module that comes with Python. If you know gettext, you might note these specialties in the way Django does translation:

- The string domain is django or djangojs. This string domain is used to differentiate between different programs that store their data in a common message-file library (usually /usr/share/locale/). The django domain is used for Python and template translation strings and is loaded into the global translation catalogs. The djangojs domain is only used for JavaScript translation catalogs to make sure that those are as small as possible.

- Django doesn’t use xgettext alone. It uses Python wrappers around xgettext and msgfmt. This is mostly for convenience.

How Django discovers language preference

Once you’ve prepared your translations – or, if you just want to use the translations that come with Django – you’ll just need to activate translation for your app.

Behind the scenes, Django has a very flexible model of deciding which language should be used – installation-wide, for a particular user, or both.

To set an installation-wide language preference, set LANGUAGE_CODE. Django uses this language as the default translation – the final attempt if no better matching translation is found through one of the methods employed by the locale middleware (see below).

If all you want is to run Django with your native language all you need to do is set LANGUAGE_CODE and make sure the corresponding message files and their compiled versions (.mo) exist.

If you want to let each individual user specify which language they prefer, then you also need to use the LocaleMiddleware. LocaleMiddleware enables language selection based on data from the request. It customizes content for each user.

To use LocaleMiddleware, add 'django.middleware.locale.LocaleMiddleware' to your MIDDLEWARE_CLASSES setting. Because middleware order matters, you should follow these guidelines:

- Make sure it’s one of the first middlewares installed.

- It should come after SessionMiddleware, because LocaleMiddleware makes use of session data. And it should come before CommonMiddleware because CommonMiddleware needs an activated language in order to resolve the requested URL.

- If you use CacheMiddleware, put LocaleMiddleware after it.

For example, your MIDDLEWARE_CLASSES might look like this:

MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
]

(For more on middleware, see the middleware documentation.)

LocaleMiddleware tries to determine the user’s language preference by following this algorithm:

- First, it looks for the language prefix in the requested URL. This is only performed when you are using the i18n_patterns function in your root URLconf. See Internationalization: in URL patterns for more information about the language prefix and how to internationalize URL patterns.

- Failing that, it looks for the LANGUAGE_SESSION_KEY key in the current user’s session.

- Failing that, it looks for a cookie.

The name of the cookie used is set by the LANGUAGE_COOKIE_NAME setting. (The default name is django_language.)

- Failing that, it looks at the Accept-Language HTTP header. This header is sent by your browser and tells the server which language(s) you prefer, in order by priority. Django tries each language in the header until it finds one with available translations.

- Failing that, it uses the global LANGUAGE_CODE setting.

Notes:

- In each of these places, the language preference is expected to be in the standard language format, as a string. For example, Brazilian Portuguese is pt-br.

- If a base language is available but the sublanguage specified is not, Django uses the base language. For example, if a user specifies de-at (Austrian German) but Django only has de available, Django uses de.

- Only languages listed in the LANGUAGES setting can be selected. If you want to restrict the language selection to a subset of provided languages (because your application doesn’t provide all those languages), set LANGUAGES to a list of languages. For example:

LANGUAGES = [
('de', _('German')),
('en', _('English')),
]

This example restricts languages that are available for automatic selection to German and English (and any sublanguage, like de-ch or en-us).

- If you define a custom LANGUAGES setting, as explained in the previous bullet, you can mark the language names as translation strings – but use ugettext_lazy() instead of ugettext() to avoid a circular import.

Here’s a sample settings file:

from django.utils.translation import ugettext_lazy as _

LANGUAGES = [
('de', _('German')),
('en', _('English')),
]

Once LocaleMiddleware determines the user’s preference, it makes this preference available as request.LANGUAGE_CODE for each HttpRequest. Feel free to read this value in your view code. Here’s a simple example:

from django.http import HttpResponse

def hello_world(request, count):
if request.LANGUAGE_CODE == 'de-at':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")

Note that, with static (middleware-less) translation, the language is in settings.LANGUAGE_CODE, while with dynamic (middleware) translation, it’s in request.LANGUAGE_CODE.

How Django discovers translations

At runtime, Django builds an in-memory unified catalog of literals-translations. To achieve this it looks for translations by following this algorithm regarding the order in which it examines the different file paths to load the compiled message files (.mo) and the precedence of multiple translations for the same literal:

1. The directories listed in LOCALE_PATHS have the highest precedence, with the ones appearing first having higher precedence than the ones appearing later.

2. Then, it looks for and uses if it exists a locale directory in each of the installed apps listed in INSTALLED_APPS. The ones appearing first have higher precedence than the ones appearing later.

3. Finally, the Django-provided base translation in django/conf/locale is used as a fallback.

See also

The translations for literals included in JavaScript assets are looked up following a similar but not identical algorithm. See the javascript_catalog view documentation for more details.

In all cases the name of the directory containing the translation is expected to be named using locale name notation. E.g. de, pt_BR, es_AR, etc.

This way, you can write applications that include their own translations, and you can override base translations in your project. Or, you can just build a big project out of several apps and put all translations into one big common message file specific to the project you are composing. The choice is yours.

All message file repositories are structured the same way. They are:

- All paths listed in LOCALE_PATHS in your settings file are searched for <language>/LC_MESSAGES/django.(po|mo)

- $APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

- $PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)

To create message files, you use the django-admin makemessages tool. And you use django-admin compilemessages to produce the binary .mo files that are used by gettext.

You can also run django-admin compilemessages --settings=path.to.settings to make the compiler process all the directories in your LOCALE_PATHS setting.

Format localization

Overview

Django’s formatting system is capable of displaying dates, times and numbers in templates using the format specified for the current locale. It also handles localized input in forms.

When it’s enabled, two users accessing the same content may see dates, times and numbers formatted in different ways, depending on the formats for their current locale.

The formatting system is disabled by default. To enable it, it’s necessary to set USE_L10N = True in your settings file.

Note

The default settings.py file created by django-admin startproject includes USE_L10N = True for convenience. Note, however, that to enable number formatting with thousand separators it is necessary to set USE_THOUSAND_SEPARATOR = True in your settings file. Alternatively, you could use intcomma to format numbers in your template.

Note

There is also an independent but related USE_I18N setting that controls if Django should activate translation. See Translation for more details.

Locale aware input in forms

When formatting is enabled, Django can use localized formats when parsing dates, times and numbers in forms. That means it tries different formats for different locales when guessing the format used by the user when inputting data on forms.

Note

Django uses different formats for displaying data to those it uses for parsing data. Most notably, the formats for parsing dates can’t use the %a (abbreviated weekday name), %A (full weekday name), %b (abbreviated month name), %B (full month name), or %p (AM/PM).

To enable a form field to localize input and output data simply use its localize argument:

class CashRegisterForm(forms.Form):
product = forms.CharField()
revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)

Controlling localization in templates

When you have enabled formatting with USE_L10N, Django will try to use a locale specific format whenever it outputs a value in a template.

However, it may not always be appropriate to use localized values – for example, if you’re outputting JavaScript or XML that is designed to be machine-readable, you will always want unlocalized values. You may also want to use localization in selected templates, rather than using localization everywhere.

To allow for fine control over the use of localization, Django provides the l10n template library that contains the following tags and filters.

Template tags

localize

Enables or disables localization of template variables in the contained block.

This tag allows a more fine grained control of localization than USE_L10N.

To activate or deactivate localization for a template block, use:

{% load l10n %}

{% localize on %}
{{ value }}
{% endlocalize %}

{% localize off %}
{{ value }}
{% endlocalize %}

Note

The value of USE_L10N isn’t respected inside of a {% localize %} block.

See localize and unlocalize for template filters that will do the same job on a per-variable basis.

Template filters

localize

Forces localization of a single value.

For example:

{% load l10n %}

{{ value|localize }}

To disable localization on a single value, use unlocalize. To control localization over a large section of a template, use the localize template tag.

unlocalize

Forces a single value to be printed without localization.

For example:

{% load l10n %}

{{ value|unlocalize }}

To force localization of a single value, use localize. To control localization over a large section of a template, use the localize template tag.

Creating custom format files

Django provides format definitions for many locales, but sometimes you might want to create your own, because a format files doesn’t exist for your locale, or because you want to overwrite some of the values.

Changed in Django 1.8:
The ability to specify FORMAT_MODULE_PATH as a list was added. Previously, only a single string value was supported.

To use custom formats, specify the path where you’ll place format files first. To do that, just set your FORMAT_MODULE_PATH setting to the package where format files will exist, for instance:

FORMAT_MODULE_PATH = [
'mysite.formats',
'some_app.formats',
]

Files are not placed directly in this directory, but in a directory named as the locale, and must be named formats.py. Be careful not to put sensitive information in these files as values inside can be exposed if you pass the string to django.utils.formats.get_format() (used by the date template filter).

To customize the English formats, a structure like this would be needed:

mysite/
formats/
__init__.py
en/
__init__.py
formats.py

where formats.py contains custom format definitions. For example:

from __future__ import unicode_literals

THOUSAND_SEPARATOR = '\xa0'

to use a non-breaking space (Unicode 00A0) as a thousand separator, instead of the default for English, a comma.

Limitations of the provided locale formats

Some locales use context-sensitive formats for numbers, which Django’s localization system cannot handle automatically.

Switzerland (German)

The Swiss number formatting depends on the type of number that is being formatted. For monetary values, a comma is used as the thousand separator and a decimal point for the decimal separator. For all other numbers, a comma is used as decimal separator and a space as thousand separator. The locale format provided by Django uses the generic separators, a comma for decimal and a space for thousand separators.

Time zones

Overview

When support for time zones is enabled, Django stores datetime information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms.

This is handy if your users live in more than one time zone and you want to display datetime information according to each user’s wall clock.

Even if your website is available in only one time zone, it’s still good practice to store data in UTC in your database. The main reason is Daylight Saving Time (DST). Many countries have a system of DST, where clocks are moved forward in spring and backward in autumn. If you’re working in local time, you’re likely to encounter errors twice a year, when the transitions happen. (The pytz documentation discusses these issues in greater detail.) This probably doesn’t matter for your blog, but it’s a problem if you over-bill or under-bill your customers by one hour, twice a year, every year. The solution to this problem is to use UTC in the code and use local time only when interacting with end users.

Time zone support is disabled by default. To enable it, set USE_TZ = True in your settings file. Installing pytz is highly recommended, but may not be mandatory depending on your particular database backend, operating system and time zone. If you encounter an exception querying dates or times, please try installing it before filing a bug. It’s as simple as:

$ pip install pytz

Note

The default settings.py file created by django-admin startproject includes USE_TZ = True for convenience.

Note

There is also an independent but related USE_L10N setting that controls whether Django should activate format localization. See Format localization for more details.

If you’re wrestling with a particular problem, start with the time zone FAQ.

Concepts

Naive and aware datetime objects

Python’s datetime.datetime objects have a tzinfo attribute that can be used to store time zone information, represented as an instance of a subclass of datetime.tzinfo. When this attribute is set and describes an offset, a datetime object is aware. Otherwise, it’s naive.

You can use is_aware() and is_naive() to determine whether datetimes are aware or naive.

When time zone support is disabled, Django uses naive datetime objects in local time. This is simple and sufficient for many use cases. In this mode, to obtain the current time, you would write:

import datetime

now = datetime.datetime.now()

When time zone support is enabled (USE_TZ=True), Django uses time-zone-aware datetime objects. If your code creates datetime objects, they should be aware too. In this mode, the example above becomes:

from django.utils import timezone

now = timezone.now()

Warning

Dealing with aware datetime objects isn’t always intuitive. For instance, the tzinfo argument of the standard datetime constructor doesn’t work reliably for time zones with DST. Using UTC is generally safe; if you’re using other time zones, you should review the pytz documentation carefully.

Note

Python’s datetime.time objects also feature a tzinfo attribute, and PostgreSQL has a matching time with time zone type. However, as PostgreSQL’s docs put it, this type “exhibits properties which lead to questionable usefulness”.

Django only supports naive time objects and will raise an exception if you attempt to save an aware time object, as a timezone for a time with no associated date does not make sense.

Interpretation of naive datetime objects

When USE_TZ is True, Django still accepts naive datetime objects, in order to preserve backwards-compatibility. When the database layer receives one, it attempts to make it aware by interpreting it in the default time zone and raises a warning.

Unfortunately, during DST transitions, some datetimes don’t exist or are ambiguous. In such situations, pytz raises an exception. Other tzinfo implementations, such as the local time zone used as a fallback when pytz isn’t installed, may raise an exception or return inaccurate results. That’s why you should always create aware datetime objects when time zone support is enabled.

In practice, this is rarely an issue. Django gives you aware datetime objects in the models and forms, and most often, new datetime objects are created from existing ones through timedelta arithmetic. The only datetime that’s often created in application code is the current time, and timezone.now() automatically does the right thing.

Default time zone and current time zone

The default time zone is the time zone defined by the TIME_ZONE setting.

The current time zone is the time zone that’s used for rendering.

You should set the current time zone to the end user’s actual time zone with activate(). Otherwise, the default time zone is used.

Note

As explained in the documentation of TIME_ZONE, Django sets environment variables so that its process runs in the default time zone. This happens regardless of the value of USE_TZ and of the current time zone.

When USE_TZ is True, this is useful to preserve backwards-compatibility with applications that still rely on local time. However, as explained above, this isn’t entirely reliable, and you should always work with aware datetimes in UTC in your own code. For instance, use utcfromtimestamp() instead of fromtimestamp() – and don’t forget to set tzinfo to utc.

Selecting the current time zone

The current time zone is the equivalent of the current locale for translations. However, there’s no equivalent of the Accept-Language HTTP header that Django could use to determine the user’s time zone automatically. Instead, Django provides time zone selection functions. Use them to build the time zone selection logic that makes sense for you.

Most websites that care about time zones just ask users in which time zone they live and store this information in the user’s profile. For anonymous users, they use the time zone of their primary audience or UTC. pytz provides helpers, like a list of time zones per country, that you can use to pre-select the most likely choices.

Here’s an example that stores the current timezone in the session. (It skips error handling entirely for the sake of simplicity.)

Add the following middleware to MIDDLEWARE_CLASSES:

import pytz

from django.utils import timezone

class TimezoneMiddleware(object):
def process_request(self, request):
tzname = request.session.get('django_timezone')
if tzname:
timezone.activate(pytz.timezone(tzname))
else:
timezone.deactivate()

Create a view that can set the current timezone:

from django.shortcuts import redirect, render

def set_timezone(request):
if request.method == 'POST':
request.session['django_timezone'] = request.POST['timezone']
return redirect('/')
else:
return render(request, 'template.html', {'timezones': pytz.common_timezones})

Include a form in template.html that will POST to this view:

{% load tz %}
{% get_current_timezone as TIME_ZONE %}
<form action="{% url 'set_timezone' %}" method="POST">
{% csrf_token %}
<label for="timezone">Time zone:</label>
<select name="timezone">
{% for tz in timezones %}
<option value="{{ tz }}"{% if tz == TIME_ZONE %} selected="selected"{% endif %}>{{ tz }}</option>
{% endfor %}
</select>
<input type="submit" value="Set" />
</form>

Time zone aware input in forms

When you enable time zone support, Django interprets datetimes entered in forms in the current time zone and returns aware datetime objects in cleaned_data.

If the current time zone raises an exception for datetimes that don’t exist or are ambiguous because they fall in a DST transition (the timezones provided by pytz do this), such datetimes will be reported as invalid values.

Time zone aware output in templates

When you enable time zone support, Django converts aware datetime objects to the current time zone when they’re rendered in templates. This behaves very much like format localization.

Warning

Django doesn’t convert naive datetime objects, because they could be ambiguous, and because your code should never produce naive datetimes when time zone support is enabled. However, you can force conversion with the template filters described below.

Conversion to local time isn’t always appropriate – you may be generating output for computers rather than for humans. The following filters and tags, provided by the tz template tag library, allow you to control the time zone conversions.

Template tags

localtime

Enables or disables conversion of aware datetime objects to the current time zone in the contained block.

This tag has exactly the same effects as the USE_TZ setting as far as the template engine is concerned. It allows a more fine grained control of conversion.

To activate or deactivate conversion for a template block, use:

{% load tz %}

{% localtime on %}
{{ value }}
{% endlocaltime %}

{% localtime off %}
{{ value }}
{% endlocaltime %}

Note

The value of USE_TZ isn’t respected inside of a {% localtime %} block.

timezone

Sets or unsets the current time zone in the contained block. When the current time zone is unset, the default time zone applies.

{% load tz %}

{% timezone "Europe/Paris" %}
Paris time: {{ value }}
{% endtimezone %}

{% timezone None %}
Server time: {{ value }}
{% endtimezone %}

get_current_timezone

You can get the name of the current time zone using the get_current_timezone tag:

{% get_current_timezone as TIME_ZONE %}

Alternatively, you can activate the tz() context processor and use the TIME_ZONE context variable.

Template filters

These filters accept both aware and naive datetimes. For conversion purposes, they assume that naive datetimes are in the default time zone. They always return aware datetimes.

localtime

Forces conversion of a single value to the current time zone.

For example:

{% load tz %}

{{ value|localtime }}

utc

Forces conversion of a single value to UTC.

For example:

{% load tz %}

{{ value|utc }}

timezone

Forces conversion of a single value to an arbitrary timezone.

The argument must be an instance of a tzinfo subclass or a time zone name. If it is a time zone name, pytz is required.

For example:

{% load tz %}

{{ value|timezone:"Europe/Paris" }}

Migration guide

Here’s how to migrate a project that was started before Django supported time zones.

Database

PostgreSQL

The PostgreSQL backend stores datetimes as timestamp with time zone. In practice, this means it converts datetimes from the connection’s time zone to UTC on storage, and from UTC to the connection’s time zone on retrieval.

As a consequence, if you’re using PostgreSQL, you can switch between USE_TZ = False and USE_TZ = True freely. The database connection’s time zone will be set to TIME_ZONE or UTC respectively, so that Django obtains correct datetimes in all cases. You don’t need to perform any data conversions.

Other databases

Other backends store datetimes without time zone information. If you switch from USE_TZ = False to USE_TZ = True, you must convert your data from local time to UTC – which isn’t deterministic if your local time has DST.

Code

The first step is to add USE_TZ = True to your settings file and install pytz (if possible). At this point, things should mostly work. If you create naive datetime objects in your code, Django makes them aware when necessary.

However, these conversions may fail around DST transitions, which means you aren’t getting the full benefits of time zone support yet. Also, you’re likely to run into a few problems because it’s impossible to compare a naive datetime with an aware datetime. Since Django now gives you aware datetimes, you’ll get exceptions wherever you compare a datetime that comes from a model or a form with a naive datetime that you’ve created in your code.

So the second step is to refactor your code wherever you instantiate datetime objects to make them aware. This can be done incrementally. django.utils.timezone defines some handy helpers for compatibility code: now(), is_aware(), is_naive(), make_aware(), and make_naive().

Finally, in order to help you locate code that needs upgrading, Django raises a warning when you attempt to save a naive datetime to the database:

RuntimeWarning: DateTimeField ModelName.field_name received a naive
datetime (2012-01-01 00:00:00) while time zone support is active.

During development, you can turn such warnings into exceptions and get a traceback by adding the following to your settings file:

import warnings
warnings.filterwarnings(
'error', r"DateTimeField .* received a naive datetime",
RuntimeWarning, r'django\.db\.models\.fields',
)

Fixtures

When serializing an aware datetime, the UTC offset is included, like this:

"2011-09-01T13:20:30+03:00"

For a naive datetime, it obviously isn’t:

"2011-09-01T13:20:30"

For models with DateTimeFields, this difference makes it impossible to write a fixture that works both with and without time zone support.

Fixtures generated with USE_TZ = False, or before Django 1.4, use the “naive” format. If your project contains such fixtures, after you enable time zone support, you’ll see RuntimeWarnings when you load them. To get rid of the warnings, you must convert your fixtures to the “aware” format.

You can regenerate fixtures with loaddata then dumpdata. Or, if they’re small enough, you can simply edit them to add the UTC offset that matches your TIME_ZONE to each serialized datetime.

FAQ

Setup

1. I don’t need multiple time zones. Should I enable time zone support?

Yes. When time zone support is enabled, Django uses a more accurate model of local time. This shields you from subtle and unreproducible bugs around Daylight Saving Time (DST) transitions.

In this regard, time zones are comparable to unicode in Python. At first it’s hard. You get encoding and decoding errors. Then you learn the rules. And some problems disappear – you never get mangled output again when your application receives non-ASCII input.

When you enable time zone support, you’ll encounter some errors because you’re using naive datetimes where Django expects aware datetimes. Such errors show up when running tests and they’re easy to fix. You’ll quickly learn how to avoid invalid operations.

On the other hand, bugs caused by the lack of time zone support are much harder to prevent, diagnose and fix. Anything that involves scheduled tasks or datetime arithmetic is a candidate for subtle bugs that will bite you only once or twice a year.

For these reasons, time zone support is enabled by default in new projects, and you should keep it unless you have a very good reason not to.

2. I’ve enabled time zone support. Am I safe?

Maybe. You’re better protected from DST-related bugs, but you can still shoot yourself in the foot by carelessly turning naive datetimes into aware datetimes, and vice-versa.

If your application connects to other systems – for instance, if it queries a Web service – make sure datetimes are properly specified. To transmit datetimes safely, their representation should include the UTC offset, or their values should be in UTC (or both!).

Finally, our calendar system contains interesting traps for computers:

>>> import datetime
>>> def one_year_before(value):       # DON'T DO THAT!
...     return value.replace(year=value.year - 1)
>>> one_year_before(datetime.datetime(2012, 3, 1, 10, 0))
datetime.datetime(2011, 3, 1, 10, 0)
>>> one_year_before(datetime.datetime(2012, 2, 29, 10, 0))
Traceback (most recent call last):
...
ValueError: day is out of range for month

(To implement this function, you must decide whether 2012-02-29 minus one year is 2011-02-28 or 2011-03-01, which depends on your business requirements.)

3. Should I install pytz?

Yes. Django has a policy of not requiring external dependencies, and for this reason pytz is optional. However, it’s much safer to install it.

As soon as you activate time zone support, Django needs a definition of the default time zone. When pytz is available, Django loads this definition from the tz database. This is the most accurate solution. Otherwise, it relies on the difference between local time and UTC, as reported by the operating system, to compute conversions. This is less reliable, especially around DST transitions.

Furthermore, if you want to support users in more than one time zone, pytz is the reference for time zone definitions.

4. How do I interact with a database that stores datetimes in local time?

Set the TIME_ZONE option to the appropriate time zone for this database in the DATABASES setting.

This is useful for connecting to a database that doesn’t support time zones and that isn’t managed by Django when USE_TZ is True.

Troubleshooting

1. My application crashes with TypeError: can't compare offset-naive and offset-aware datetimes – what’s wrong?

Let’s reproduce this error by comparing a naive and an aware datetime:

>>> import datetime
>>> from django.utils import timezone
>>> naive = datetime.datetime.utcnow()
>>> aware = timezone.now()
>>> naive == aware
Traceback (most recent call last):
...
TypeError: can't compare offset-naive and offset-aware datetimes

If you encounter this error, most likely your code is comparing these two things:

- a datetime provided by Django – for instance, a value read from a form or a model field. Since you enabled time zone support, it’s aware.

- a datetime generated by your code, which is naive (or you wouldn’t be reading this).

Generally, the correct solution is to change your code to use an aware datetime instead.

If you’re writing a pluggable application that’s expected to work independently of the value of USE_TZ, you may find django.utils.timezone.now() useful. This function returns the current date and time as a naive datetime when USE_TZ = False and as an aware datetime when USE_TZ = True. You can add or subtract datetime.timedelta as needed.

2. I see lots of RuntimeWarning: DateTimeField received a naive datetime (YYYY-MM-DD HH:MM:SS) while time zone support is active – is that bad?

When time zone support is enabled, the database layer expects to receive only aware datetimes from your code. This warning occurs when it receives a naive datetime. This indicates that you haven’t finished porting your code for time zone support. Please refer to the migration guide for tips on this process.

In the meantime, for backwards compatibility, the datetime is considered to be in the default time zone, which is generally what you expect.

3. now.date() is yesterday! (or tomorrow)

If you’ve always used naive datetimes, you probably believe that you can convert a datetime to a date by calling its date() method. You also consider that a date is a lot like a datetime, except that it’s less accurate.

None of this is true in a time zone aware environment:

>>> import datetime
>>> import pytz
>>> paris_tz = pytz.timezone("Europe/Paris")
>>> new_york_tz = pytz.timezone("America/New_York")
>>> paris = paris_tz.localize(datetime.datetime(2012, 3, 3, 1, 30))
# This is the correct way to convert between time zones with pytz.
>>> new_york = new_york_tz.normalize(paris.astimezone(new_york_tz))
>>> paris == new_york, paris.date() == new_york.date()
(True, False)
>>> paris - new_york, paris.date() - new_york.date()
(datetime.timedelta(0), datetime.timedelta(1))
>>> paris
datetime.datetime(2012, 3, 3, 1, 30, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
>>> new_york
datetime.datetime(2012, 3, 2, 19, 30, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)

As this example shows, the same datetime has a different date, depending on the time zone in which it is represented. But the real problem is more fundamental.

A datetime represents a point in time. It’s absolute: it doesn’t depend on anything. On the contrary, a date is a calendaring concept. It’s a period of time whose bounds depend on the time zone in which the date is considered. As you can see, these two concepts are fundamentally different, and converting a datetime to a date isn’t a deterministic operation.

What does this mean in practice?

Generally, you should avoid converting a datetime to date. For instance, you can use the date template filter to only show the date part of a datetime. This filter will convert the datetime into the current time zone before formatting it, ensuring the results appear correctly.

If you really need to do the conversion yourself, you must ensure the datetime is converted to the appropriate time zone first. Usually, this will be the current timezone:

>>> from django.utils import timezone
>>> timezone.activate(pytz.timezone("Asia/Singapore"))
# For this example, we just set the time zone to Singapore, but here's how
# you would obtain the current time zone in the general case.
>>> current_tz = timezone.get_current_timezone()
# Again, this is the correct way to convert between time zones with pytz.
>>> local = current_tz.normalize(paris.astimezone(current_tz))
>>> local
datetime.datetime(2012, 3, 3, 8, 30, tzinfo=<DstTzInfo 'Asia/Singapore' SGT+8:00:00 STD>)
>>> local.date()
datetime.date(2012, 3, 3)

4. I get an error “Are time zone definitions for your database and pytz installed?” pytz is installed, so I guess the problem is my database?

If you are using MySQL, see the Time zone definitions section of the MySQL notes for instructions on loading time zone definitions.

Usage

1. I have a string "2012-02-21 10:28:45" and I know it’s in the "Europe/Helsinki" time zone. How do I turn that into an aware datetime?

This is exactly what pytz is for.

>>> from django.utils.dateparse import parse_datetime
>>> naive = parse_datetime("2012-02-21 10:28:45")
>>> import pytz
>>> pytz.timezone("Europe/Helsinki").localize(naive, is_dst=None)
datetime.datetime(2012, 2, 21, 10, 28, 45, tzinfo=<DstTzInfo 'Europe/Helsinki' EET+2:00:00 STD>)

Note that localize is a pytz extension to the tzinfo API. Also, you may want to catch pytz.InvalidTimeError. The documentation of pytz contains more examples. You should review it before attempting to manipulate aware datetimes.

2. How can I obtain the local time in the current time zone?

Well, the first question is, do you really need to?

You should only use local time when you’re interacting with humans, and the template layer provides filters and tags to convert datetimes to the time zone of your choice.

Furthermore, Python knows how to compare aware datetimes, taking into account UTC offsets when necessary. It’s much easier (and possibly faster) to write all your model and view code in UTC. So, in most circumstances, the datetime in UTC returned by django.utils.timezone.now() will be sufficient.

For the sake of completeness, though, if you really want the local time in the current time zone, here’s how you can obtain it:

>>> from django.utils import timezone
>>> timezone.localtime(timezone.now())
datetime.datetime(2012, 3, 3, 20, 10, 53, 873365, tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)

In this example, pytz is installed and the current time zone is "Europe/Paris".

3. How can I see all available time zones?

pytz provides helpers, including a list of current time zones and a list of all available time zones – some of which are only of historical interest.

Logging

A quick logging primer

Django uses Python’s builtin logging module to perform system logging. The usage of this module is discussed in detail in Python’s own documentation. However, if you’ve never used Python’s logging framework (or even if you have), here’s a quick primer.

The cast of players

A Python logging configuration consists of four parts:

- Loggers

- Handlers

- Filters

- Formatters

Loggers

A logger is the entry point into the logging system. Each logger is a named bucket to which messages can be written for processing.

A logger is configured to have a log level. This log level describes the severity of the messages that the logger will handle. Python defines the following log levels:

- DEBUG: Low level system information for debugging purposes

- INFO: General system information

- WARNING: Information describing a minor problem that has occurred.

- ERROR: Information describing a major problem that has occurred.

- CRITICAL: Information describing a critical problem that has occurred.

Each message that is written to the logger is a Log Record. Each log record also has a log level indicating the severity of that specific message. A log record can also contain useful metadata that describes the event that is being logged. This can include details such as a stack trace or an error code.

When a message is given to the logger, the log level of the message is compared to the log level of the logger. If the log level of the message meets or exceeds the log level of the logger itself, the message will undergo further processing. If it doesn’t, the message will be ignored.

Once a logger has determined that a message needs to be processed, it is passed to a Handler.

Handlers

The handler is the engine that determines what happens to each message in a logger. It describes a particular logging behavior, such as writing a message to the screen, to a file, or to a network socket.

Like loggers, handlers also have a log level. If the log level of a log record doesn’t meet or exceed the level of the handler, the handler will ignore the message.

A logger can have multiple handlers, and each handler can have a different log level. In this way, it is possible to provide different forms of notification depending on the importance of a message. For example, you could install one handler that forwards ERROR and CRITICAL messages to a paging service, while a second handler logs all messages (including ERROR and CRITICAL messages) to a file for later analysis.

Filters

A filter is used to provide additional control over which log records are passed from logger to handler.

By default, any log message that meets log level requirements will be handled. However, by installing a filter, you can place additional criteria on the logging process. For example, you could install a filter that only allows ERROR messages from a particular source to be emitted.

Filters can also be used to modify the logging record prior to being emitted. For example, you could write a filter that downgrades ERROR log records to WARNING records if a particular set of criteria are met.

Filters can be installed on loggers or on handlers; multiple filters can be used in a chain to perform multiple filtering actions.

Formatters

Ultimately, a log record needs to be rendered as text. Formatters describe the exact format of that text. A formatter usually consists of a Python formatting string containing LogRecord attributes; however, you can also write custom formatters to implement specific formatting behavior.

Using logging

Once you have configured your loggers, handlers, filters and formatters, you need to place logging calls into your code. Using the logging framework is very simple. Here’s an example:

# import the logging library
import logging

# Get an instance of a logger
logger = logging.getLogger(__name__)

def my_view(request, arg1, arg):
...
if bad_mojo:
# Log an error message
logger.error('Something went wrong!')

And that’s it! Every time the bad_mojo condition is activated, an error log record will be written.

Naming loggers

The call to logging.getLogger() obtains (creating, if necessary) an instance of a logger. The logger instance is identified by a name. This name is used to identify the logger for configuration purposes.

By convention, the logger name is usually __name__, the name of the python module that contains the logger. This allows you to filter and handle logging calls on a per-module basis. However, if you have some other way of organizing your logging messages, you can provide any dot-separated name to identify your logger:

# Get an instance of a specific named logger
logger = logging.getLogger('project.interesting.stuff')

The dotted paths of logger names define a hierarchy. The project.interesting logger is considered to be a parent of the project.interesting.stuff logger; the project logger is a parent of the project.interesting logger.

Why is the hierarchy important? Well, because loggers can be set to propagate their logging calls to their parents. In this way, you can define a single set of handlers at the root of a logger tree, and capture all logging calls in the subtree of loggers. A logging handler defined in the project namespace will catch all logging messages issued on the project.interesting and project.interesting.stuff loggers.

This propagation can be controlled on a per-logger basis. If you don’t want a particular logger to propagate to its parents, you can turn off this behavior.

Making logging calls

The logger instance contains an entry method for each of the default log levels:

- logger.debug()

- logger.info()

- logger.warning()

- logger.error()

- logger.critical()

There are two other logging calls available:

- logger.log(): Manually emits a logging message with a specific log level.

- logger.exception(): Creates an ERROR level logging message wrapping the current exception stack frame.

Configuring logging

Of course, it isn’t enough to just put logging calls into your code. You also need to configure the loggers, handlers, filters and formatters to ensure that logging output is output in a useful way.

Python’s logging library provides several techniques to configure logging, ranging from a programmatic interface to configuration files. By default, Django uses the dictConfig format.

In order to configure logging, you use LOGGING to define a dictionary of logging settings. These settings describes the loggers, handlers, filters and formatters that you want in your logging setup, and the log levels and other properties that you want those components to have.

By default, the LOGGING setting is merged with Django’s default logging configuration using the following scheme.

If the disable_existing_loggers key in the LOGGING dictConfig is set to True (which is the default) then all loggers from the default configuration will be disabled. Disabled loggers are not the same as removed; the logger will still exist, but will silently discard anything logged to it, not even propagating entries to a parent logger. Thus you should be very careful using 'disable_existing_loggers': True; it’s probably not what you want. Instead, you can set disable_existing_loggers to False and redefine some or all of the default loggers; or you can set LOGGING_CONFIG to None and handle logging config yourself.

Logging is configured as part of the general Django setup() function. Therefore, you can be certain that loggers are always ready for use in your project code.

Examples

The full documentation for dictConfig format is the best source of information about logging configuration dictionaries. However, to give you a taste of what is possible, here are several examples.

First, here’s a simple configuration which writes all logging from the django logger to a local file:

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/path/to/django/debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}

If you use this example, be sure to change the 'filename' path to a location that’s writable by the user that’s running the Django application.

Second, here’s an example of how to make the logging system print Django’s logging to the console. It may be useful during local development.

By default, this config only sends messages of level INFO or higher to the console (same as Django’s default logging config, except that the default only displays log records when DEBUG=True). Django does not log many such messages. With this config, however, you can also set the environment variable DJANGO_LOG_LEVEL=DEBUG to see all of Django’s debug logging which is very verbose as it includes all database queries:

import os

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
},
},
}

Changed in Django 1.9:
Django’s default logging configuration changed. See the release notes for a description of the changes.

Finally, here’s an example of a fairly complex logging setup:

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
'loggers': {
'django': {
'handlers': ['console'],
'propagate': True,
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'myproject.custom': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
'filters': ['special']
}
}
}

This logging configuration does the following things:

- Identifies the configuration as being in ‘dictConfig version 1’ format. At present, this is the only dictConfig format version.

- Defines two formatters:

- simple, that just outputs the log level name (e.g., DEBUG) and the log message.

The format string is a normal Python formatting string describing the details that are to be output on each logging line. The full list of detail that can be output can be found in Formatter Objects.

- verbose, that outputs the log level name, the log message, plus the time, process, thread and module that generate the log message.

- Defines two filters:

- project.logging.SpecialFilter, using the alias special. If this filter required additional arguments, they can be provided as additional keys in the filter configuration dictionary. In this case, the argument foo will be given a value of bar when instantiating SpecialFilter.

- django.utils.log.RequireDebugTrue, which passes on records when DEBUG is True.

- Defines two handlers:

- console, a StreamHandler, which will print any DEBUG (or higher) message to stderr. This handler uses the simple output format.

- mail_admins, an AdminEmailHandler, which will email any ERROR (or higher) message to the site admins. This handler uses the special filter.

- Configures three loggers:

- django, which passes all messages to the console handler.

- django.request, which passes all ERROR messages to the mail_admins handler. In addition, this logger is marked to not propagate messages. This means that log messages written to django.request will not be handled by the django logger.

- myproject.custom, which passes all messages at INFO or higher that also pass the special filter to two handlers – the console, and mail_admins. This means that all INFO level messages (or higher) will be printed to the console; ERROR and CRITICAL messages will also be output via email.

Custom logging configuration

If you don’t want to use Python’s dictConfig format to configure your logger, you can specify your own configuration scheme.

The LOGGING_CONFIG setting defines the callable that will be used to configure Django’s loggers. By default, it points at Python’s logging.config.dictConfig() function. However, if you want to use a different configuration process, you can use any other callable that takes a single argument. The contents of LOGGING will be provided as the value of that argument when logging is configured.

Disabling logging configuration

If you don’t want to configure logging at all (or you want to manually configure logging using your own approach), you can set LOGGING_CONFIG to None. This will disable the configuration process for Django’s default logging. Here’s an example that disables Django’s logging configuration and then manually configures logging:

settings.py

LOGGING_CONFIG = None

import logging.config
logging.config.dictConfig(...)

Setting LOGGING_CONFIG to None only means that the automatic configuration process is disabled, not logging itself. If you disable the configuration process, Django will still make logging calls, falling back to whatever default logging behavior is defined.

Django’s logging extensions

Django provides a number of utilities to handle the unique requirements of logging in Web server environment.

Loggers

Django provides several built-in loggers.

django

django is the catch-all logger. No messages are posted directly to this logger.

django.request

Log messages related to the handling of requests. 5XX responses are raised as ERROR messages; 4XX responses are raised as WARNING messages.

Messages to this logger have the following extra context:

- status_code: The HTTP response code associated with the request.

- request: The request object that generated the logging message.

django.template

New in Django 1.9.

Log messages related to the rendering of templates.

- Missing context variables are logged as DEBUG messages.

- Uncaught exceptions raised during the rendering of an {% include %} are logged as WARNING messages when debug mode is off (helpful since {% include %} silences the exception and returns an empty string in that case).

django.db.backends

Messages relating to the interaction of code with the database. For example, every application-level SQL statement executed by a request is logged at the DEBUG level to this logger.

Messages to this logger have the following extra context:

- duration: The time taken to execute the SQL statement.

- sql: The SQL statement that was executed.

- params: The parameters that were used in the SQL call.

For performance reasons, SQL logging is only enabled when settings.DEBUG is set to True, regardless of the logging level or handlers that are installed.

This logging does not include framework-level initialization (e.g. SET TIMEZONE) or transaction management queries (e.g. BEGIN, COMMIT, and ROLLBACK). Turn on query logging in your database if you wish to view all database queries.

django.security.*

The security loggers will receive messages on any occurrence of SuspiciousOperation. There is a sub-logger for each sub-type of SuspiciousOperation. The level of the log event depends on where the exception is handled. Most occurrences are logged as a warning, while any SuspiciousOperation that reaches the WSGI handler will be logged as an error. For example, when an HTTP Host header is included in a request from a client that does not match ALLOWED_HOSTS, Django will return a 400 response, and an error message will be logged to the django.security.DisallowedHost logger.

These log events will reach the ‘django’ logger by default, which mails error events to admins when DEBUG=False. Requests resulting in a 400 response due to a SuspiciousOperation will not be logged to the django.request logger, but only to the django.security logger.

To silence a particular type of SuspiciousOperation, you can override that specific logger following this example:

'handlers': {
'null': {
'class': 'logging.NullHandler',
},
},
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
},

django.db.backends.schema

Logs the SQL queries that are executed during schema changes to the database by the migrations framework. Note that it won’t log the queries executed by RunPython.

Handlers

Django provides one log handler in addition to those provided by the Python logging module.

class AdminEmailHandler(include_html=False, email_backend=None)[source]

This handler sends an email to the site admins for each log message it receives.

If the log record contains a request attribute, the full details of the request will be included in the email. The email subject will include the phrase “internal IP” if the client’s IP address is in the INTERNAL_IPS setting; if not, it will include “EXTERNAL IP”.

If the log record contains stack trace information, that stack trace will be included in the email.

The include_html argument of AdminEmailHandler is used to control whether the traceback email includes an HTML attachment containing the full content of the debug Web page that would have been produced if DEBUG were True. To set this value in your configuration, include it in the handler definition for django.utils.log.AdminEmailHandler, like this:

'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True,
}
},

Note that this HTML version of the email contains a full traceback, with names and values of local variables at each level of the stack, plus the values of your Django settings. This information is potentially very sensitive, and you may not want to send it over email. Consider using something such as Sentry to get the best of both worlds – the rich information of full tracebacks plus the security of not sending the information over email. You may also explicitly designate certain sensitive information to be filtered out of error reports – learn more on Filtering error reports.

By setting the email_backend argument of AdminEmailHandler, the email backend that is being used by the handler can be overridden, like this:

'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'email_backend': 'django.core.mail.backends.filebased.EmailBackend',
}
},

By default, an instance of the email backend specified in EMAIL_BACKEND will be used.

send_mail(subject, message, *args, **kwargs)[source]

New in Django 1.8.

Sends emails to admin users. To customize this behavior, you can subclass the AdminEmailHandler class and override this method.

Filters

Django provides two log filters in addition to those provided by the Python logging module.

class CallbackFilter(callback)[source]

This filter accepts a callback function (which should accept a single argument, the record to be logged), and calls it for each record that passes through the filter. Handling of that record will not proceed if the callback returns False.

For instance, to filter out UnreadablePostError (raised when a user cancels an upload) from the admin emails, you would create a filter function:

from django.http import UnreadablePostError

def skip_unreadable_post(record):
if record.exc_info:
exc_type, exc_value = record.exc_info[:2]
if isinstance(exc_value, UnreadablePostError):
return False
return True

and then add it to your logging config:

'filters': {
'skip_unreadable_posts': {
'()': 'django.utils.log.CallbackFilter',
'callback': skip_unreadable_post,
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['skip_unreadable_posts'],
'class': 'django.utils.log.AdminEmailHandler'
}
},

class RequireDebugFalse[source]

This filter will only pass on records when settings.DEBUG is False.

This filter is used as follows in the default LOGGING configuration to ensure that the AdminEmailHandler only sends error emails to admins when DEBUG is False:

'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},

class RequireDebugTrue[source]

This filter is similar to RequireDebugFalse, except that records are passed only when DEBUG is True.

Django’s default logging configuration

By default, Django configures the following logging:

When DEBUG is True:

- The django catch-all logger sends all messages at the INFO level or higher to the console.

- The py.warnings logger, which handles messages from warnings.warn(), sends messages to the console.

When DEBUG is False:

- The django logger send messages with ERROR or CRITICAL level to AdminEmailHandler.

Changed in Django 1.9:
Django’s default logging configuration changed. See the release notes for a description of the changes.

See also Configuring logging to learn how you can complement or replace this default logging configuration.

Pagination

Django provides a few classes that help you manage paginated data – that is, data that’s split across several pages, with “Previous/Next” links. These classes live in django/core/paginator.py.

Example

Give Paginator a list of objects, plus the number of items you’d like to have on each page, and it gives you methods for accessing the items for each page:

>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)

>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)  # `<type 'rangeiterator'>` in Python 2.
<class 'range_iterator'>
>>> p.page_range
range(1, 3)

>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']

>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
1
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4

>>> p.page(0)
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)
Traceback (most recent call last):
...
EmptyPage: That page contains no results

Note

Note that you can give Paginator a list/tuple, a Django QuerySet, or any other object with a count() or __len__() method. When determining the number of objects contained in the passed object, Paginator will first try calling count(), then fallback to using len() if the passed object has no count() method. This allows objects such as Django’s QuerySet to use a more efficient count() method when available.

Using Paginator in a view

Here’s a slightly more complex example using Paginator in a view to paginate a queryset. We give both the view and the accompanying template to show how you can display the results. This example assumes you have a Contacts model that has already been imported.

The view function looks like this:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render

def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page

page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
contacts = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
contacts = paginator.page(paginator.num_pages)

return render(request, 'list.html', {'contacts': contacts})

In the template list.html, you’ll want to include navigation between pages along with any interesting information from the objects themselves:

{% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br />
...
{% endfor %}

<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">previous</a>
{% endif %}

<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>

{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}
</span>
</div>

Paginator objects

The Paginator class has this constructor:

class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)[source]

Required arguments

object_list

A list, tuple, QuerySet, or other sliceable object with a count() or __len__() method. For consistent pagination, QuerySets should be ordered, e.g. with an order_by() clause or with a default ordering on the model.

Performance issues paginating large QuerySets

If you’re using a QuerySet with a very large number of items, requesting high page numbers might be slow on some databases, because the resulting LIMIT/OFFSET query needs to count the number of OFFSET records which takes longer as the page number gets higher.

per_page

The maximum number of items to include on a page, not including orphans (see the orphans optional argument below).

Optional arguments

orphans

The minimum number of items allowed on the last page, defaults to zero. Use this when you don’t want to have a last page with very few items. If the last page would normally have a number of items less than or equal to orphans, then those items will be added to the previous page (which becomes the last page) instead of leaving the items on a page by themselves. For example, with 23 items, per_page=10, and orphans=3, there will be two pages; the first page with 10 items and the second (and last) page with 13 items.

allow_empty_first_page

Whether or not the first page is allowed to be empty. If False and object_list is empty, then an EmptyPage error will be raised.

Methods

Paginator.page(number)[source]

Returns a Page object with the given 1-based index. Raises InvalidPage if the given page number doesn’t exist.

Attributes

Paginator.count

The total number of objects, across all pages.

Note

When determining the number of objects contained in object_list, Paginator will first try calling object_list.count(). If object_list has no count() method, then Paginator will fallback to using len(object_list). This allows objects, such as Django’s QuerySet, to use a more efficient count() method when available.

Paginator.num_pages

The total number of pages.

Paginator.page_range

A 1-based range iterator of page numbers, e.g. yielding [1, 2, 3, 4].

Changed in Django 1.9:
In older versions, page_range returned a list instead of an iterator.

InvalidPage exceptions

exception InvalidPage[source]

A base class for exceptions raised when a paginator is passed an invalid page number.

The Paginator.page() method raises an exception if the requested page is invalid (i.e., not an integer) or contains no objects. Generally, it’s enough to catch the InvalidPage exception, but if you’d like more granularity, you can catch either of the following exceptions:

exception PageNotAnInteger[source]

Raised when page() is given a value that isn’t an integer.

exception EmptyPage[source]

Raised when page() is given a valid value but no objects exist on that page.

Both of the exceptions are subclasses of InvalidPage, so you can handle them both with a simple except InvalidPage.

Page objects

You usually won’t construct Page objects by hand – you’ll get them using Paginator.page().

class Page(object_list, number, paginator)[source]

A page acts like a sequence of Page.object_list when using len() or iterating it directly.

Methods

Page.has_next()[source]

Returns True if there’s a next page.

Page.has_previous()[source]

Returns True if there’s a previous page.

Page.has_other_pages()[source]

Returns True if there’s a next or previous page.

Page.next_page_number()[source]

Returns the next page number. Raises InvalidPage if next page doesn’t exist.

Page.previous_page_number()[source]

Returns the previous page number. Raises InvalidPage if previous page doesn’t exist.

Page.start_index()[source]

Returns the 1-based index of the first object on the page, relative to all of the objects in the paginator’s list. For example, when paginating a list of 5 objects with 2 objects per page, the second page’s start_index() would return 3.

Page.end_index()[source]

Returns the 1-based index of the last object on the page, relative to all of the objects in the paginator’s list. For example, when paginating a list of 5 objects with 2 objects per page, the second page’s end_index() would return 4.

Attributes

Page.object_list

The list of objects on this page.

Page.number

The 1-based page number for this page.

Page.paginator

The associated Paginator object.

Porting to Python 3

Django 1.5 is the first version of Django to support Python 3. The same code runs both on Python 2 (≥ 2.6.5) and Python 3 (≥ 3.2), thanks to the six compatibility layer.

This document is primarily targeted at authors of pluggable applications who want to support both Python 2 and 3. It also describes guidelines that apply to Django’s code.

Philosophy

This document assumes that you are familiar with the changes between Python 2 and Python 3. If you aren’t, read Python’s official porting guide first. Refreshing your knowledge of unicode handling on Python 2 and 3 will help; the Pragmatic Unicode presentation is a good resource.

Django uses the Python 2/3 Compatible Source strategy. Of course, you’re free to chose another strategy for your own code, especially if you don’t need to stay compatible with Python 2. But authors of pluggable applications are encouraged to use the same porting strategy as Django itself.

Writing compatible code is much easier if you target Python ≥ 2.6. Django 1.5 introduces compatibility tools such as django.utils.six, which is a customized version of the six module. For convenience, forwards-compatible aliases were introduced in Django 1.4.2. If your application takes advantage of these tools, it will require Django ≥ 1.4.2.

Obviously, writing compatible source code adds some overhead, and that can cause frustration. Django’s developers have found that attempting to write Python 3 code that’s compatible with Python 2 is much more rewarding than the opposite. Not only does that make your code more future-proof, but Python 3’s advantages (like the saner string handling) start shining quickly. Dealing with Python 2 becomes a backwards compatibility requirement, and we as developers are used to dealing with such constraints.

Porting tools provided by Django are inspired by this philosophy, and it’s reflected throughout this guide.

Porting tips

Unicode literals

This step consists in:

- Adding from __future__ import unicode_literals at the top of your Python modules – it’s best to put it in each and every module, otherwise you’ll keep checking the top of your files to see which mode is in effect;

- Removing the u prefix before unicode strings;

- Adding a b prefix before bytestrings.

Performing these changes systematically guarantees backwards compatibility.

However, Django applications generally don’t need bytestrings, since Django only exposes unicode interfaces to the programmer. Python 3 discourages using bytestrings, except for binary data or byte-oriented interfaces. Python 2 makes bytestrings and unicode strings effectively interchangeable, as long as they only contain ASCII data. Take advantage of this to use unicode strings wherever possible and avoid the b prefixes.

Note

Python 2’s u prefix is a syntax error in Python 3.2 but it will be allowed again in Python 3.3 thanks to PEP 414. Thus, this transformation is optional if you target Python ≥ 3.3. It’s still recommended, per the “write Python 3 code” philosophy.

String handling

Python 2’s unicode type was renamed str in Python 3, str() was renamed bytes, and basestring disappeared. six provides tools to deal with these changes.

Django also contains several string related classes and functions in the django.utils.encoding and django.utils.safestring modules. Their names used the words str, which doesn’t mean the same thing in Python 2 and Python 3, and unicode, which doesn’t exist in Python 3. In order to avoid ambiguity and confusion these concepts were renamed bytes and text.

Here are the name changes in django.utils.encoding:

Old name

New name

smart_str

smart_bytes

smart_unicode

smart_text

force_unicode

force_text

For backwards compatibility, the old names still work on Python 2. Under Python 3, smart_str is an alias for smart_text.

For forwards compatibility, the new names work as of Django 1.4.2.

Note

django.utils.encoding was deeply refactored in Django 1.5 to provide a more consistent API. Check its documentation for more information.

django.utils.safestring is mostly used via the mark_safe() and mark_for_escaping() functions, which didn’t change. In case you’re using the internals, here are the name changes:

Old name

New name

EscapeString

EscapeBytes

EscapeUnicode

EscapeText

SafeString

SafeBytes

SafeUnicode

SafeText

For backwards compatibility, the old names still work on Python 2. Under Python 3, EscapeString and SafeString are aliases for EscapeText and SafeText respectively.

For forwards compatibility, the new names work as of Django 1.4.2.

__str__() and __unicode__() methods

In Python 2, the object model specifies __str__() and  __unicode__() methods. If these methods exist, they must return str (bytes) and unicode (text) respectively.

The print statement and the str built-in call __str__() to determine the human-readable representation of an object. The unicode built-in calls  __unicode__() if it exists, and otherwise falls back to __str__() and decodes the result with the system encoding. Conversely, the Model base class automatically derives __str__() from  __unicode__() by encoding to UTF-8.

In Python 3, there’s simply __str__(), which must return str (text).

(It is also possible to define __bytes__(), but Django applications have little use for that method, because they hardly ever deal with bytes.)

Django provides a simple way to define __str__() and  __unicode__() methods that work on Python 2 and 3: you must define a __str__() method returning text and to apply the python_2_unicode_compatible() decorator.

On Python 3, the decorator is a no-op. On Python 2, it defines appropriate  __unicode__() and __str__() methods (replacing the original __str__() method in the process). Here’s an example:

from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible
class MyClass(object):
def __str__(self):
return "Instance of my class"

This technique is the best match for Django’s porting philosophy.

For forwards compatibility, this decorator is available as of Django 1.4.2.

Finally, note that __repr__() must return a str on all versions of Python.

dict and dict-like classes

dict.keys(), dict.items() and dict.values() return lists in Python 2 and iterators in Python 3. QueryDict and the dict-like classes defined in django.utils.datastructures behave likewise in Python 3.

six provides compatibility functions to work around this change: iterkeys(), iteritems(), and itervalues(). It also contains an undocumented iterlists function that works well for django.utils.datastructures.MultiValueDict and its subclasses.

HttpRequest and HttpResponse objects

According to PEP 3333:

- headers are always str objects,

- input and output streams are always bytes objects.

Specifically, HttpResponse.content contains bytes, which may become an issue if you compare it with a str in your tests. The preferred solution is to rely on assertContains() and assertNotContains(). These methods accept a response and a unicode string as arguments.

Coding guidelines

The following guidelines are enforced in Django’s source code. They’re also recommended for third-party applications that follow the same porting strategy.

Syntax requirements

Unicode

In Python 3, all strings are considered Unicode by default. The unicode type from Python 2 is called str in Python 3, and str becomes bytes.

You mustn’t use the u prefix before a unicode string literal because it’s a syntax error in Python 3.2. You must prefix byte strings with b.

In order to enable the same behavior in Python 2, every module must import unicode_literals from __future__:

from __future__ import unicode_literals

my_string = "This is an unicode literal"
my_bytestring = b"This is a bytestring"

If you need a byte string literal under Python 2 and a unicode string literal under Python 3, use the str builtin:

str('my string')

In Python 3, there aren’t any automatic conversions between str and bytes, and the codecs module became more strict. str.encode() always returns bytes, and bytes.decode always returns str. As a consequence, the following pattern is sometimes necessary:

value = value.encode('ascii', 'ignore').decode('ascii')

Be cautious if you have to index bytestrings.

Exceptions

When you capture exceptions, use the as keyword:

try:
...
except MyException as exc:
...

This older syntax was removed in Python 3:

try:
...
except MyException, exc:    # Don't do that!
...

The syntax to reraise an exception with a different traceback also changed. Use six.reraise().

Magic methods

Use the patterns below to handle magic methods renamed in Python 3.

Iterators

class MyIterator(six.Iterator):
def __iter__(self):
return self             # implement some logic here

def __next__(self):
raise StopIteration     # implement some logic here

Boolean evaluation

class MyBoolean(object):

def __bool__(self):
return True             # implement some logic here

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

Division

class MyDivisible(object):

def __truediv__(self, other):
return self / other     # implement some logic here

def __div__(self, other):   # Python 2 compatibility
return type(self).__truediv__(self, other)

def __itruediv__(self, other):
return self // other    # implement some logic here

def __idiv__(self, other):  # Python 2 compatibility
return type(self).__itruediv__(self, other)

Special methods are looked up on the class and not on the instance to reflect the behavior of the Python interpreter.

Writing compatible code with six

six is the canonical compatibility library for supporting Python 2 and 3 in a single codebase. Read its documentation!

A customized version of six is bundled with Django as of version 1.4.2. You can import it as django.utils.six.

Here are the most common changes required to write compatible code.

String handling

The basestring and unicode types were removed in Python 3, and the meaning of str changed. To test these types, use the following idioms:

isinstance(myvalue, six.string_types)       # replacement for basestring
isinstance(myvalue, six.text_type)          # replacement for unicode
isinstance(myvalue, bytes)                  # replacement for str

Python ≥ 2.6 provides bytes as an alias for str, so you don’t need six.binary_type.

long

The long type no longer exists in Python 3. 1L is a syntax error. Use six.integer_types check if a value is an integer or a long:

isinstance(myvalue, six.integer_types)      # replacement for (int, long)

xrange

If you use xrange on Python 2, import six.moves.range and use that instead. You can also import six.moves.xrange (it’s equivalent to six.moves.range) but the first technique allows you to simply drop the import when dropping support for Python 2.

Moved modules

Some modules were renamed in Python 3. The django.utils.six.moves module (based on the six.moves module) provides a compatible location to import them.

PY2

If you need different code in Python 2 and Python 3, check six.PY2:

if six.PY2:
# compatibility code for Python 2

This is a last resort solution when six doesn’t provide an appropriate function.

Django customized version of six

The version of six bundled with Django (django.utils.six) includes a few customizations for internal use only.

Security in Django

This document is an overview of Django’s security features. It includes advice on securing a Django-powered site.

Cross site scripting (XSS) protection

XSS attacks allow a user to inject client side scripts into the browsers of other users. This is usually achieved by storing the malicious scripts in the database where it will be retrieved and displayed to other users, or by getting users to click a link which will cause the attacker’s JavaScript to be executed by the user’s browser. However, XSS attacks can originate from any untrusted source of data, such as cookies or Web services, whenever the data is not sufficiently sanitized before including in a page.

Using Django templates protects you against the majority of XSS attacks. However, it is important to understand what protections it provides and its limitations.

Django templates escape specific characters which are particularly dangerous to HTML. While this protects users from most malicious input, it is not entirely foolproof. For example, it will not protect the following:

<style class={{ var }}>...</style>

If var is set to 'class1 onmouseover=javascript:func()', this can result in unauthorized JavaScript execution, depending on how the browser renders imperfect HTML. (Quoting the attribute value would fix this case.)

It is also important to be particularly careful when using is_safe with custom template tags, the safe template tag, mark_safe, and when autoescape is turned off.

In addition, if you are using the template system to output something other than HTML, there may be entirely separate characters and words which require escaping.

You should also be very careful when storing HTML in the database, especially when that HTML is retrieved and displayed.

Cross site request forgery (CSRF) protection

CSRF attacks allow a malicious user to execute actions using the credentials of another user without that user’s knowledge or consent.

Django has built-in protection against most types of CSRF attacks, providing you have enabled and used it where appropriate. However, as with any mitigation technique, there are limitations. For example, it is possible to disable the CSRF module globally or for particular views. You should only do this if you know what you are doing. There are other limitations if your site has subdomains that are outside of your control.

CSRF protection works by checking for a nonce in each POST request. This ensures that a malicious user cannot simply “replay” a form POST to your website and have another logged in user unwittingly submit that form. The malicious user would have to know the nonce, which is user specific (using a cookie).

When deployed with HTTPS, CsrfViewMiddleware will check that the HTTP referer header is set to a URL on the same origin (including subdomain and port). Because HTTPS provides additional security, it is imperative to ensure connections use HTTPS where it is available by forwarding insecure connection requests and using HSTS for supported browsers.

Be very careful with marking views with the csrf_exempt decorator unless it is absolutely necessary.

SQL injection protection

SQL injection is a type of attack where a malicious user is able to execute arbitrary SQL code on a database. This can result in records being deleted or data leakage.

By using Django’s querysets, the resulting SQL will be properly escaped by the underlying database driver. However, Django also gives developers power to write raw queries or execute custom sql. These capabilities should be used sparingly and you should always be careful to properly escape any parameters that the user can control. In addition, you should exercise caution when using extra() and RawSQL.

Clickjacking protection

Clickjacking is a type of attack where a malicious site wraps another site in a frame. This attack can result in an unsuspecting user being tricked into performing unintended actions on the target site.

Django contains clickjacking protection in the form of the X-Frame-Options middleware which in a supporting browser can prevent a site from being rendered inside a frame. It is possible to disable the protection on a per view basis or to configure the exact header value sent.

The middleware is strongly recommended for any site that does not need to have its pages wrapped in a frame by third party sites, or only needs to allow that for a small section of the site.

SSL/HTTPS

It is always better for security to deploy your site behind HTTPS. Without this, it is possible for malicious network users to sniff authentication credentials or any other information transferred between client and server, and in some cases – active network attackers – to alter data that is sent in either direction.

If you want the protection that HTTPS provides, and have enabled it on your server, there are some additional steps you may need:

- If necessary, set SECURE_PROXY_SSL_HEADER, ensuring that you have understood the warnings there thoroughly. Failure to do this can result in CSRF vulnerabilities, and failure to do it correctly can also be dangerous!

- Set SECURE_SSL_REDIRECT to True, so that requests over HTTP are redirected to HTTPS.

Please note the caveats under SECURE_PROXY_SSL_HEADER. For the case of a reverse proxy, it may be easier or more secure to configure the main Web server to do the redirect to HTTPS.

- Use ‘secure’ cookies.

If a browser connects initially via HTTP, which is the default for most browsers, it is possible for existing cookies to be leaked. For this reason, you should set your SESSION_COOKIE_SECURE and CSRF_COOKIE_SECURE settings to True. This instructs the browser to only send these cookies over HTTPS connections. Note that this will mean that sessions will not work over HTTP, and the CSRF protection will prevent any POST data being accepted over HTTP (which will be fine if you are redirecting all HTTP traffic to HTTPS).

- Use HTTP Strict Transport Security (HSTS)

HSTS is an HTTP header that informs a browser that all future connections to a particular site should always use HTTPS. Combined with redirecting requests over HTTP to HTTPS, this will ensure that connections always enjoy the added security of SSL provided one successful connection has occurred. HSTS may either be configured with SECURE_HSTS_SECONDS and SECURE_HSTS_INCLUDE_SUBDOMAINS or on the Web server.

Host header validation

Django uses the Host header provided by the client to construct URLs in certain cases. While these values are sanitized to prevent Cross Site Scripting attacks, a fake Host value can be used for Cross-Site Request Forgery, cache poisoning attacks, and poisoning links in emails.

Because even seemingly-secure web server configurations are susceptible to fake Host headers, Django validates Host headers against the ALLOWED_HOSTS setting in the django.http.HttpRequest.get_host() method.

This validation only applies via get_host(); if your code accesses the Host header directly from request.META you are bypassing this security protection.

For more details see the full ALLOWED_HOSTS documentation.

Warning

Previous versions of this document recommended configuring your web server to ensure it validates incoming HTTP Host headers. While this is still recommended, in many common web servers a configuration that seems to validate the Host header may not in fact do so. For instance, even if Apache is configured such that your Django site is served from a non-default virtual host with the ServerName set, it is still possible for an HTTP request to match this virtual host and supply a fake Host header. Thus, Django now requires that you set ALLOWED_HOSTS explicitly rather than relying on web server configuration.

Additionally, Django requires you to explicitly enable support for the X-Forwarded-Host header (via the USE_X_FORWARDED_HOST setting) if your configuration requires it.

Session security

Similar to the CSRF limitations requiring a site to be deployed such that untrusted users don’t have access to any subdomains, django.contrib.sessions also has limitations. See the session topic guide section on security for details.

User-uploaded content

Note

Consider serving static files from a cloud service or CDN to avoid some of these issues.

- If your site accepts file uploads, it is strongly advised that you limit these uploads in your Web server configuration to a reasonable size in order to prevent denial of service (DOS) attacks. In Apache, this can be easily set using the LimitRequestBody directive.

- If you are serving your own static files, be sure that handlers like Apache’s mod_php, which would execute static files as code, are disabled. You don’t want users to be able to execute arbitrary code by uploading and requesting a specially crafted file.

- Django’s media upload handling poses some vulnerabilities when that media is served in ways that do not follow security best practices. Specifically, an HTML file can be uploaded as an image if that file contains a valid PNG header followed by malicious HTML. This file will pass verification of the library that Django uses for ImageField image processing (Pillow). When this file is subsequently displayed to a user, it may be displayed as HTML depending on the type and configuration of your web server.

No bulletproof technical solution exists at the framework level to safely validate all user uploaded file content, however, there are some other steps you can take to mitigate these attacks:

1. One class of attacks can be prevented by always serving user uploaded content from a distinct top-level or second-level domain. This prevents any exploit blocked by same-origin policy protections such as cross site scripting. For example, if your site runs on example.com, you would want to serve uploaded content (the MEDIA_URL setting) from something like usercontent-example.com. It’s not sufficient to serve content from a subdomain like usercontent.example.com.

2. Beyond this, applications may choose to define a whitelist of allowable file extensions for user uploaded files and configure the web server to only serve such files.

Additional security topics

While Django provides good security protection out of the box, it is still important to properly deploy your application and take advantage of the security protection of the Web server, operating system and other components.

- Make sure that your Python code is outside of the Web server’s root. This will ensure that your Python code is not accidentally served as plain text (or accidentally executed).

- Take care with any user uploaded files.

- Django does not throttle requests to authenticate users. To protect against brute-force attacks against the authentication system, you may consider deploying a Django plugin or Web server module to throttle these requests.

- Keep your SECRET_KEY a secret.

- It is a good idea to limit the accessibility of your caching system and database using a firewall.

- Take a look at the Open Web Application Security Project (OWASP) Top 10 list which identifies some common vulnerabilities in web applications. While Django has tools to address some of the issues, other issues must be accounted for in the design of your project.

Performance and optimization

This document provides an overview of techniques and tools that can help get your Django code running more efficiently - faster, and using fewer system resources.

Introduction

Generally one’s first concern is to write code that works, whose logic functions as required to produce the expected output. Sometimes, however, this will not be enough to make the code work as efficiently as one would like.

In this case, what’s needed is something - and in practice, often a collection of things - to improve the code’s performance without, or only minimally, affecting its behavior.

General approaches

What are you optimizing for?

It’s important to have a clear idea what you mean by ‘performance’. There is not just one metric of it.

Improved speed might be the most obvious aim for a program, but sometimes other performance improvements might be sought, such as lower memory consumption or fewer demands on the database or network.

Improvements in one area will often bring about improved performance in another, but not always; sometimes one can even be at the expense of another. For example, an improvement in a program’s speed might cause it to use more memory. Even worse, it can be self-defeating - if the speed improvement is so memory-hungry that the system starts to run out of memory, you’ll have done more harm than good.

There are other trade-offs to bear in mind. Your own time is a valuable resource, more precious than CPU time. Some improvements might be too difficult to be worth implementing, or might affect the portability or maintainability of the code. Not all performance improvements are worth the effort.

So, you need to know what performance improvements you are aiming for, and you also need to know that you have a good reason for aiming in that direction - and for that you need:

Performance benchmarking

It’s no good just guessing or assuming where the inefficiencies lie in your code.

Django tools

django-debug-toolbar is a very handy tool that provides insights into what your code is doing and how much time it spends doing it. In particular it can show you all the SQL queries your page is generating, and how long each one has taken.

Third-party panels are also available for the toolbar, that can (for example) report on cache performance and template rendering times.

Third-party services

There are a number of free services that will analyze and report on the performance of your site’s pages from the perspective of a remote HTTP client, in effect simulating the experience of an actual user.

These can’t report on the internals of your code, but can provide a useful insight into your site’s overall performance, including aspects that can’t be adequately measured from within Django environment. Examples include:

- Yahoo’s Yslow

- Google PageSpeed

There are also several paid-for services that perform a similar analysis, including some that are Django-aware and can integrate with your codebase to profile its performance far more comprehensively.

Get things right from the start

Some work in optimization involves tackling performance shortcomings, but some of the work can simply be built in to what you’d do anyway, as part of the good practices you should adopt even before you start thinking about improving performance.

In this respect Python is an excellent language to work with, because solutions that look elegant and feel right usually are the best performing ones. As with most skills, learning what “looks right” takes practice, but one of the most useful guidelines is:

Work at the appropriate level

Django offers many different ways of approaching things, but just because it’s possible to do something in a certain way doesn’t mean that it’s the most appropriate way to do it. For example, you might find that you could calculate the same thing - the number of items in a collection, perhaps - in a QuerySet, in Python, or in a template.

However, it will almost always be faster to do this work at lower rather than higher levels. At higher levels the system has to deal with objects through multiple levels of abstraction and layers of machinery.

That is, the database can typically do things faster than Python can, which can do them faster than the template language can:

# QuerySet operation on the database
# fast, because that's what databases are good at
my_bicycles.count()

# counting Python objects
# slower, because it requires a database query anyway, and processing
# of the Python objects
len(my_bicycles)

# Django template filter
# slower still, because it will have to count them in Python anyway,
# and because of template language overheads
{{ my_bicycles|length }}

Generally speaking, the most appropriate level for the job is the lowest-level one that it is comfortable to code for.

Note

The example above is merely illustrative.

Firstly, in a real-life case you need to consider what is happening before and after your count to work out what’s an optimal way of doing it in that particular context. The database optimization documents describes a case where counting in the template would be better.

Secondly, there are other options to consider: in a real-life case, {{ my_bicycles.count }}, which invokes the QuerySet count() method directly from the template, might be the most appropriate choice.

Caching

Often it is expensive (that is, resource-hungry and slow) to compute a value, so there can be huge benefit in saving the value to a quickly accessible cache, ready for the next time it’s required.

It’s a sufficiently significant and powerful technique that Django includes a comprehensive caching framework, as well as other smaller pieces of caching functionality.

The caching framework

Django’s caching framework offers very significant opportunities for performance gains, by saving dynamic content so that it doesn’t need to be calculated for each request.

For convenience, Django offers different levels of cache granularity: you can cache the output of specific views, or only the pieces that are difficult to produce, or even an entire site.

Implementing caching should not be regarded as an alternative to improving code that’s performing poorly because it has been written badly. It’s one of the final steps towards producing well-performing code, not a shortcut.

cached_property

It’s common to have to call a class instance’s method more than once. If that function is expensive, then doing so can be wasteful.

Using the cached_property decorator saves the value returned by a property; the next time the function is called on that instance, it will return the saved value rather than re-computing it. Note that this only works on methods that take self as their only argument and that it changes the method to a property.

Certain Django components also have their own caching functionality; these are discussed below in the sections related to those components.

Understanding laziness

Laziness is a strategy complementary to caching. Caching avoids recomputation by saving results; laziness delays computation until it’s actually required.

Laziness allows us to refer to things before they are instantiated, or even before it’s possible to instantiate them. This has numerous uses.

For example, lazy translation can be used before the target language is even known, because it doesn’t take place until the translated string is actually required, such as in a rendered template.

Laziness is also a way to save effort by trying to avoid work in the first place. That is, one aspect of laziness is not doing anything until it has to be done, because it may not turn out to be necessary after all. Laziness can therefore have performance implications, and the more expensive the work concerned, the more there is to gain through laziness.

Python provides a number of tools for lazy evaluation, particularly through the generator and generator expression constructs. It’s worth reading up on laziness in Python to discover opportunities for making use of lazy patterns in your code.

Laziness in Django

Django is itself quite lazy. A good example of this can be found in the evaluation of QuerySets. QuerySets are lazy. Thus a QuerySet can be created, passed around and combined with other QuerySets, without actually incurring any trips to the database to fetch the items it describes. What gets passed around is the QuerySet object, not the collection of items that - eventually - will be required from the database.

On the other hand, certain operations will force the evaluation of a QuerySet. Avoiding the premature evaluation of a QuerySet can save making an expensive and unnecessary trip to the database.

Django also offers an allow_lazy() decorator. This allows a function that has been called with a lazy argument to behave lazily itself, only being evaluated when it needs to be. Thus the lazy argument - which could be an expensive one - will not be called upon for evaluation until it’s strictly required.

Databases

Database optimization

Django’s database layer provides various ways to help developers get the best performance from their databases. The database optimization documentation gathers together links to the relevant documentation and adds various tips that outline the steps to take when attempting to optimize your database usage.

Other database-related tips

Enabling Persistent connections can speed up connections to the database accounts for a significant part of the request processing time.

This helps a lot on virtualized hosts with limited network performance, for example.

HTTP performance

Middleware

Django comes with a few helpful pieces of middleware that can help optimize your site’s performance. They include:

ConditionalGetMiddleware

Adds support for modern browsers to conditionally GET responses based on the ETag and Last-Modified headers.

GZipMiddleware

Compresses responses for all modern browsers, saving bandwidth and transfer time. Note that GZipMiddleware is currently considered a security risk, and is vulnerable to attacks that nullify the protection provided by TLS/SSL. See the warning in GZipMiddleware for more information.

Sessions

Using cached sessions

Using cached sessions may be a way to increase performance by eliminating the need to load session data from a slower storage source like the database and instead storing frequently used session data in memory.

Static files

Static files, which by definition are not dynamic, make an excellent target for optimization gains.

CachedStaticFilesStorage

By taking advantage of web browsers’ caching abilities, you can eliminate network hits entirely for a given file after the initial download.

CachedStaticFilesStorage appends a content-dependent tag to the filenames of static files to make it safe for browsers to cache them long-term without missing future changes - when a file changes, so will the tag, so browsers will reload the asset automatically.

“Minification”

Several third-party Django tools and packages provide the ability to “minify” HTML, CSS, and JavaScript. They remove unnecessary whitespace, newlines, and comments, and shorten variable names, and thus reduce the size of the documents that your site publishes.

Template performance

Note that:

- using {% block %} is faster than using {% include %}

- heavily-fragmented templates, assembled from many small pieces, can affect performance

The cached template loader

Enabling the cached template loader often improves performance drastically, as it avoids compiling each template every time it needs to be rendered.

Using different versions of available software

It can sometimes be worth checking whether different and better-performing versions of the software that you’re using are available.

These techniques are targeted at more advanced users who want to push the boundaries of performance of an already well-optimized Django site.

However, they are not magic solutions to performance problems, and they’re unlikely to bring better than marginal gains to sites that don’t already do the more basic things the right way.

Note

It’s worth repeating: reaching for alternatives to software you’re already using is never the first answer to performance problems. When you reach this level of optimization, you need a formal benchmarking solution.

Newer is often - but not always - better

It’s fairly rare for a new release of well-maintained software to be less efficient, but the maintainers can’t anticipate every possible use-case - so while being aware that newer versions are likely to perform better, don’t simply assume that they always will.

This is true of Django itself. Successive releases have offered a number of improvements across the system, but you should still check the real-world performance of your application, because in some cases you may find that changes mean it performs worse rather than better.

Newer versions of Python, and also of Python packages, will often perform better too - but measure, rather than assume.

Note

Unless you’ve encountered an unusual performance problem in a particular version, you’ll generally find better features, reliability, and security in a new release and that these benefits are far more significant than any performance you might win or lose.

Alternatives to Django’s template language

For nearly all cases, Django’s built-in template language is perfectly adequate. However, if the bottlenecks in your Django project seem to lie in the template system and you have exhausted other opportunities to remedy this, a third-party alternative may be the answer.

Jinja2 can offer performance improvements, particularly when it comes to speed.

Alternative template systems vary in the extent to which they share Django’s templating language.

Note

If you experience performance issues in templates, the first thing to do is to understand exactly why. Using an alternative template system may prove faster, but the same gains may also be available without going to that trouble - for example, expensive processing and logic in your templates could be done more efficiently in your views.

Alternative software implementations

It may be worth checking whether Python software you’re using has been provided in a different implementation that can execute the same code faster.

However: most performance problems in well-written Django sites aren’t at the Python execution level, but rather in inefficient database querying, caching, and templates. If you’re relying on poorly-written Python code, your performance problems are unlikely to be solved by having it execute faster.

Using an alternative implementation may introduce compatibility, deployment, portability, or maintenance issues. It goes without saying that before adopting a non-standard implementation you should ensure it provides sufficient performance gains for your application to outweigh the potential risks.

With these caveats in mind, you should be aware of:

PyPy

PyPy is an implementation of Python in Python itself (the ‘standard’ Python implementation is in C). PyPy can offer substantial performance gains, typically for heavyweight applications.

A key aim of the PyPy project is compatibility with existing Python APIs and libraries. Django is compatible, but you will need to check the compatibility of other libraries you rely on.

C implementations of Python libraries

Some Python libraries are also implemented in C, and can be much faster. They aim to offer the same APIs. Note that compatibility issues and behavior differences are not unknown (and not always immediately evident).

Serializing Django objects

Django’s serialization framework provides a mechanism for “translating” Django models into other formats. Usually these other formats will be text-based and used for sending Django data over a wire, but it’s possible for a serializer to handle any format (text-based or not).

See also

If you just want to get some data from your tables into a serialized form, you could use the dumpdata management command.

Serializing data

At the highest level, serializing data is a very simple operation:

from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())

The arguments to the serialize function are the format to serialize the data to (see Serialization formats) and a QuerySet to serialize. (Actually, the second argument can be any iterator that yields Django model instances, but it’ll almost always be a QuerySet).

django.core.serializers.get_serializer(format)

You can also use a serializer object directly:

XMLSerializer = serializers.get_serializer("xml")
xml_serializer = XMLSerializer()
xml_serializer.serialize(queryset)
data = xml_serializer.getvalue()

This is useful if you want to serialize data directly to a file-like object (which includes an HttpResponse):

with open("file.xml", "w") as out:
xml_serializer.serialize(SomeModel.objects.all(), stream=out)

Note

Calling get_serializer() with an unknown format will raise a django.core.serializers.SerializerDoesNotExist exception.

Subset of fields

If you only want a subset of fields to be serialized, you can specify a fields argument to the serializer:

from django.core import serializers
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))

In this example, only the name and size attributes of each model will be serialized. The primary key is always serialized as the pk element in the resulting output; it never appears in the fields part.

Note

Depending on your model, you may find that it is not possible to deserialize a model that only serializes a subset of its fields. If a serialized object doesn’t specify all the fields that are required by a model, the deserializer will not be able to save deserialized instances.

Inherited models

If you have a model that is defined using an abstract base class, you don’t have to do anything special to serialize that model. Just call the serializer on the object (or objects) that you want to serialize, and the output will be a complete representation of the serialized object.

However, if you have a model that uses multi-table inheritance, you also need to serialize all of the base classes for the model. This is because only the fields that are locally defined on the model will be serialized. For example, consider the following models:

class Place(models.Model):
name = models.CharField(max_length=50)

class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)

If you only serialize the Restaurant model:

data = serializers.serialize('xml', Restaurant.objects.all())

the fields on the serialized output will only contain the serves_hot_dogs attribute. The name attribute of the base class will be ignored.

In order to fully serialize your Restaurant instances, you will need to serialize the Place models as well:

all_objects = list(Restaurant.objects.all()) + list(Place.objects.all())
data = serializers.serialize('xml', all_objects)

Deserializing data

Deserializing data is also a fairly simple operation:

for obj in serializers.deserialize("xml", data):
do_something_with(obj)

As you can see, the deserialize function takes the same format argument as serialize, a string or stream of data, and returns an iterator.

However, here it gets slightly complicated. The objects returned by the deserialize iterator aren’t simple Django objects. Instead, they are special DeserializedObject instances that wrap a created – but unsaved – object and any associated relationship data.

Calling DeserializedObject.save() saves the object to the database.

Note

If the pk attribute in the serialized data doesn’t exist or is null, a new instance will be saved to the database.

This ensures that deserializing is a non-destructive operation even if the data in your serialized representation doesn’t match what’s currently in the database. Usually, working with these DeserializedObject instances looks something like:

for deserialized_object in serializers.deserialize("xml", data):
if object_should_be_saved(deserialized_object):
deserialized_object.save()

In other words, the usual use is to examine the deserialized objects to make sure that they are “appropriate” for saving before doing so. Of course, if you trust your data source you could just save the object and move on.

The Django object itself can be inspected as deserialized_object.object. If fields in the serialized data do not exist on a model, a DeserializationError will be raised unless the ignorenonexistent argument is passed in as True:

serializers.deserialize("xml", data, ignorenonexistent=True)

Serialization formats

Django supports a number of serialization formats, some of which require you to install third-party Python modules:

Identifier

Information

xml

Serializes to and from a simple XML dialect.

json

Serializes to and from JSON.

yaml

Serializes to YAML (YAML Ain’t a Markup Language). This serializer is only available if PyYAML is installed.

XML

The basic XML serialization format is quite simple:

<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="123" model="sessions.session">
<field type="DateTimeField" name="expire_date">2013-01-16T08:16:59.844560+00:00</field>
<!-- ... -->
</object>
</django-objects>

The whole collection of objects that is either serialized or de-serialized is represented by a <django-objects>-tag which contains multiple <object>-elements. Each such object has two attributes: “pk” and “model”, the latter being represented by the name of the app (“sessions”) and the lowercase name of the model (“session”) separated by a dot.

Each field of the object is serialized as a <field>-element sporting the fields “type” and “name”. The text content of the element represents the value that should be stored.

Foreign keys and other relational fields are treated a little bit differently:

<object pk="27" model="auth.permission">
<!-- ... -->
<field to="contenttypes.contenttype" name="content_type" rel="ManyToOneRel">9</field>
<!-- ... -->
</object>

In this example we specify that the auth.Permission object with the PK 27 has a foreign key to the contenttypes.ContentType instance with the PK 9.

ManyToMany-relations are exported for the model that binds them. For instance, the auth.User model has such a relation to the auth.Permission model:

<object pk="1" model="auth.user">
<!-- ... -->
<field to="auth.permission" name="user_permissions" rel="ManyToManyRel">
<object pk="46"></object>
<object pk="47"></object>
</field>
</object>

This example links the given user with the permission models with PKs 46 and 47.

Control characters

Changed in Django 1.9.

If the content to be serialized contains control characters that are not accepted in the XML 1.0 standard, the serialization will fail with a ValueError exception. Read also the W3C’s explanation of HTML, XHTML, XML and Control Codes.

JSON

When staying with the same example data as before it would be serialized as JSON in the following way:

[
{
"pk": "4b678b301dfd8a4e0dad910de3ae245b",
"model": "sessions.session",
"fields": {
"expire_date": "2013-01-16T08:16:59.844Z",
...
}
}
]

The formatting here is a bit simpler than with XML. The whole collection is just represented as an array and the objects are represented by JSON objects with three properties: “pk”, “model” and “fields”. “fields” is again an object containing each field’s name and value as property and property-value respectively.

Foreign keys just have the PK of the linked object as property value. ManyToMany-relations are serialized for the model that defines them and are represented as a list of PKs.

Be aware that not all Django output can be passed unmodified to json. In particular, lazy translation objects need a custom json encoder. Something like this will work:

from django.utils.functional import Promise
from django.utils.encoding import force_text
from django.core.serializers.json import DjangoJSONEncoder

class LazyEncoder(DjangoJSONEncoder):
def default(self, obj):
if isinstance(obj, Promise):
return force_text(obj)
return super(LazyEncoder, self).default(obj)

Also note that GeoDjango provides a customized GeoJSON serializer.

DjangoJSONEncoder

class django.core.serializers.json.DjangoJSONEncoder

The JSON serializer uses DjangoJSONEncoder for encoding. A subclass of JSONEncoder, it handles these additional types:

datetime

A string of the form YYYY-MM-DDTHH:mm:ss.sssZ or YYYY-MM-DDTHH:mm:ss.sss+HH:MM as defined in ECMA-262.

date

A string of the form YYYY-MM-DD as defined in ECMA-262.

time

A string of the form HH:MM:ss.sss as defined in ECMA-262.

Decimal, UUID

A string representation of the object.

Changed in Django 1.8.4:
Support for UUID was added.

YAML

YAML serialization looks quite similar to JSON. The object list is serialized as a sequence mappings with the keys “pk”, “model” and “fields”. Each field is again a mapping with the key being name of the field and the value the value:

-   fields: {expire_date: !!timestamp '2013-01-16 08:16:59.844560+00:00'}
model: sessions.session
pk: 4b678b301dfd8a4e0dad910de3ae245b

Referential fields are again just represented by the PK or sequence of PKs.

Natural keys

The default serialization strategy for foreign keys and many-to-many relations is to serialize the value of the primary key(s) of the objects in the relation. This strategy works well for most objects, but it can cause difficulty in some circumstances.

Consider the case of a list of objects that have a foreign key referencing ContentType. If you’re going to serialize an object that refers to a content type, then you need to have a way to refer to that content type to begin with. Since ContentType objects are automatically created by Django during the database synchronization process, the primary key of a given content type isn’t easy to predict; it will depend on how and when migrate was executed. This is true for all models which automatically generate objects, notably including Permission, Group, and User.

Warning

You should never include automatically generated objects in a fixture or other serialized data. By chance, the primary keys in the fixture may match those in the database and loading the fixture will have no effect. In the more likely case that they don’t match, the fixture loading will fail with an IntegrityError.

There is also the matter of convenience. An integer id isn’t always the most convenient way to refer to an object; sometimes, a more natural reference would be helpful.

It is for these reasons that Django provides natural keys. A natural key is a tuple of values that can be used to uniquely identify an object instance without using the primary key value.

Deserialization of natural keys

Consider the following two models:

from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)

birthdate = models.DateField()

class Meta:
unique_together = (('first_name', 'last_name'),)

class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Person, on_delete=models.CASCADE)

Ordinarily, serialized data for Book would use an integer to refer to the author. For example, in JSON, a Book might be serialized as:

...
{
"pk": 1,
"model": "store.book",
"fields": {
"name": "Mostly Harmless",
"author": 42
}
}
...

This isn’t a particularly natural way to refer to an author. It requires that you know the primary key value for the author; it also requires that this primary key value is stable and predictable.

However, if we add natural key handling to Person, the fixture becomes much more humane. To add natural key handling, you define a default Manager for Person with a get_by_natural_key() method. In the case of a Person, a good natural key might be the pair of first and last name:

from django.db import models

class PersonManager(models.Manager):
def get_by_natural_key(self, first_name, last_name):
return self.get(first_name=first_name, last_name=last_name)

class Person(models.Model):
objects = PersonManager()

first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)

birthdate = models.DateField()

class Meta:
unique_together = (('first_name', 'last_name'),)

Now books can use that natural key to refer to Person objects:

...
{
"pk": 1,
"model": "store.book",
"fields": {
"name": "Mostly Harmless",
"author": ["Douglas", "Adams"]
}
}
...

When you try to load this serialized data, Django will use the get_by_natural_key() method to resolve ["Douglas", "Adams"] into the primary key of an actual Person object.

Note

Whatever fields you use for a natural key must be able to uniquely identify an object. This will usually mean that your model will have a uniqueness clause (either unique=True on a single field, or unique_together over multiple fields) for the field or fields in your natural key. However, uniqueness doesn’t need to be enforced at the database level. If you are certain that a set of fields will be effectively unique, you can still use those fields as a natural key.

Deserialization of objects with no primary key will always check whether the model’s manager has a get_by_natural_key() method and if so, use it to populate the deserialized object’s primary key.

Serialization of natural keys

So how do you get Django to emit a natural key when serializing an object? Firstly, you need to add another method – this time to the model itself:

class Person(models.Model):
objects = PersonManager()

first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)

birthdate = models.DateField()

def natural_key(self):
return (self.first_name, self.last_name)

class Meta:
unique_together = (('first_name', 'last_name'),)

That method should always return a natural key tuple – in this example, (first name, last name). Then, when you call serializers.serialize(), you provide use_natural_foreign_keys=True or use_natural_primary_keys=True arguments:

>>> serializers.serialize('json', [book1, book2], indent=2,
...      use_natural_foreign_keys=True, use_natural_primary_keys=True)

When use_natural_foreign_keys=True is specified, Django will use the natural_key() method to serialize any foreign key reference to objects of the type that defines the method.

When use_natural_primary_keys=True is specified, Django will not provide the primary key in the serialized data of this object since it can be calculated during deserialization:

...
{
"model": "store.person",
"fields": {
"first_name": "Douglas",
"last_name": "Adams",
"birth_date": "1952-03-11",
}
}
...

This can be useful when you need to load serialized data into an existing database and you cannot guarantee that the serialized primary key value is not already in use, and do not need to ensure that deserialized objects retain the same primary keys.

If you are using dumpdata to generate serialized data, use the dumpdata --natural-foreign and dumpdata --natural-primary command line flags to generate natural keys.

Note

You don’t need to define both natural_key() and get_by_natural_key(). If you don’t want Django to output natural keys during serialization, but you want to retain the ability to load natural keys, then you can opt to not implement the natural_key() method.

Conversely, if (for some strange reason) you want Django to output natural keys during serialization, but not be able to load those key values, just don’t define the get_by_natural_key() method.

Dependencies during serialization

Since natural keys rely on database lookups to resolve references, it is important that the data exists before it is referenced. You can’t make a “forward reference” with natural keys – the data you’re referencing must exist before you include a natural key reference to that data.

To accommodate this limitation, calls to dumpdata that use the dumpdata --natural-foreign option will serialize any model with a natural_key() method before serializing standard primary key objects.

However, this may not always be enough. If your natural key refers to another object (by using a foreign key or natural key to another object as part of a natural key), then you need to be able to ensure that the objects on which a natural key depends occur in the serialized data before the natural key requires them.

To control this ordering, you can define dependencies on your natural_key() methods. You do this by setting a dependencies attribute on the natural_key() method itself.

For example, let’s add a natural key to the Book model from the example above:

class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Person, on_delete=models.CASCADE)

def natural_key(self):
return (self.name,) + self.author.natural_key()

The natural key for a Book is a combination of its name and its author. This means that Person must be serialized before Book. To define this dependency, we add one extra line:

def natural_key(self):
return (self.name,) + self.author.natural_key()
natural_key.dependencies = ['example_app.person']

This definition ensures that all Person objects are serialized before any Book objects. In turn, any object referencing Book will be serialized after both Person and Book have been serialized.

Django settings

A Django settings file contains all the configuration of your Django installation. This document explains how settings work and which settings are available.

The basics

A settings file is just a Python module with module-level variables.

Here are a couple of example settings:

ALLOWED_HOSTS = ['www.example.com']
DEBUG = False
DEFAULT_FROM_EMAIL = 'webmaster@example.com'

Note

If you set DEBUG to False, you also need to properly set the ALLOWED_HOSTS setting.

Because a settings file is a Python module, the following apply:

- It doesn’t allow for Python syntax errors.

- It can assign settings dynamically using normal Python syntax. For example:

MY_SETTING = [str(i) for i in range(30)]

- It can import values from other settings files.

Designating the settings

DJANGO_SETTINGS_MODULE

When you use Django, you have to tell it which settings you’re using. Do this by using an environment variable, DJANGO_SETTINGS_MODULE.

The value of DJANGO_SETTINGS_MODULE should be in Python path syntax, e.g. mysite.settings. Note that the settings module should be on the Python import search path.

The django-admin utility

When using django-admin, you can either set the environment variable once, or explicitly pass in the settings module each time you run the utility.

Example (Unix Bash shell):

export DJANGO_SETTINGS_MODULE=mysite.settings
django-admin runserver

Example (Windows shell):

set DJANGO_SETTINGS_MODULE=mysite.settings
django-admin runserver

Use the --settings command-line argument to specify the settings manually:

django-admin runserver --settings=mysite.settings

On the server (mod_wsgi)

In your live server environment, you’ll need to tell your WSGI application what settings file to use. Do that with os.environ:

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

Read the Django mod_wsgi documentation for more information and other common elements to a Django WSGI application.

Default settings

A Django settings file doesn’t have to define any settings if it doesn’t need to. Each setting has a sensible default value. These defaults live in the module django/conf/global_settings.py.

Here’s the algorithm Django uses in compiling settings:

- Load settings from global_settings.py.

- Load settings from the specified settings file, overriding the global settings as necessary.

Note that a settings file should not import from global_settings, because that’s redundant.

Seeing which settings you’ve changed

There’s an easy way to view which of your settings deviate from the default settings. The command python manage.py diffsettings displays differences between the current settings file and Django’s default settings.

For more, see the diffsettings documentation.

Using settings in Python code

In your Django apps, use settings by importing the object django.conf.settings. Example:

from django.conf import settings

if settings.DEBUG:
# Do something

Note that django.conf.settings isn’t a module – it’s an object. So importing individual settings is not possible:

from django.conf.settings import DEBUG  # This won't work.

Also note that your code should not import from either global_settings or your own settings file. django.conf.settings abstracts the concepts of default settings and site-specific settings; it presents a single interface. It also decouples the code that uses settings from the location of your settings.

Altering settings at runtime

You shouldn’t alter settings in your applications at runtime. For example, don’t do this in a view:

from django.conf import settings

settings.DEBUG = True   # Don't do this!

The only place you should assign to settings is in a settings file.

Security

Because a settings file contains sensitive information, such as the database password, you should make every attempt to limit access to it. For example, change its file permissions so that only you and your Web server’s user can read it. This is especially important in a shared-hosting environment.

Available settings

For a full list of available settings, see the settings reference.

Creating your own settings

There’s nothing stopping you from creating your own settings, for your own Django apps. Just follow these guidelines:

- Setting names must be all uppercase.

- Don’t reinvent an already-existing setting.

For settings that are sequences, Django itself uses lists, but this is only a convention.

Using settings without setting DJANGO_SETTINGS_MODULE

In some cases, you might want to bypass the DJANGO_SETTINGS_MODULE environment variable. For example, if you’re using the template system by itself, you likely don’t want to have to set up an environment variable pointing to a settings module.

In these cases, you can configure Django’s settings manually. Do this by calling:

django.conf.settings.configure(default_settings, **settings)

Example:

from django.conf import settings

settings.configure(DEBUG=True)

Pass configure() as many keyword arguments as you’d like, with each keyword argument representing a setting and its value. Each argument name should be all uppercase, with the same name as the settings described above. If a particular setting is not passed to configure() and is needed at some later point, Django will use the default setting value.

Configuring Django in this fashion is mostly necessary – and, indeed, recommended – when you’re using a piece of the framework inside a larger application.

Consequently, when configured via settings.configure(), Django will not make any modifications to the process environment variables (see the documentation of TIME_ZONE for why this would normally occur). It’s assumed that you’re already in full control of your environment in these cases.

Custom default settings

If you’d like default values to come from somewhere other than django.conf.global_settings, you can pass in a module or class that provides the default settings as the default_settings argument (or as the first positional argument) in the call to configure().

In this example, default settings are taken from myapp_defaults, and the DEBUG setting is set to True, regardless of its value in myapp_defaults:

from django.conf import settings
from myapp import myapp_defaults

settings.configure(default_settings=myapp_defaults, DEBUG=True)

The following example, which uses myapp_defaults as a positional argument, is equivalent:

settings.configure(myapp_defaults, DEBUG=True)

Normally, you will not need to override the defaults in this fashion. The Django defaults are sufficiently tame that you can safely use them. Be aware that if you do pass in a new default module, it entirely replaces the Django defaults, so you must specify a value for every possible setting that might be used in that code you are importing. Check in django.conf.settings.global_settings for the full list.

Either configure() or DJANGO_SETTINGS_MODULE is required

If you’re not setting the DJANGO_SETTINGS_MODULE environment variable, you must call configure() at some point before using any code that reads settings.

If you don’t set DJANGO_SETTINGS_MODULE and don’t call configure(), Django will raise an ImportError exception the first time a setting is accessed.

If you set DJANGO_SETTINGS_MODULE, access settings values somehow, then call configure(), Django will raise a RuntimeError indicating that settings have already been configured. There is a property just for this purpose:

For example:

from django.conf import settings
if not settings.configured:
settings.configure(myapp_defaults, DEBUG=True)

Also, it’s an error to call configure() more than once, or to call configure() after any setting has been accessed.

It boils down to this: Use exactly one of either configure() or DJANGO_SETTINGS_MODULE. Not both, and not neither.

Calling django.setup() is required for “standalone” Django usage

If you’re using components of Django “standalone” – for example, writing a Python script which loads some Django templates and renders them, or uses the ORM to fetch some data – there’s one more step you’ll need in addition to configuring settings.

After you’ve either set DJANGO_SETTINGS_MODULE or called configure(), you’ll need to call django.setup() to load your settings and populate Django’s application registry. For example:

import django
from django.conf import settings
from myapp import myapp_defaults

settings.configure(default_settings=myapp_defaults, DEBUG=True)
django.setup()

# Now this script or any imported module can use any part of Django it needs.
from myapp import models

Note that calling django.setup() is only necessary if your code is truly standalone. When invoked by your Web server, or through django-admin, Django will handle this for you.

django.setup() may only be called once.

Therefore, avoid putting reusable application logic in standalone scripts so that you have to import from the script elsewhere in your application. If you can’t avoid that, put the call to django.setup() inside an if block:

if __name__ == '__main__':
import django
django.setup()

See also

The Settings Reference

Contains the complete list of core and contrib app settings.

Signals

Django includes a “signal dispatcher” which helps allow decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.

Django provides a set of built-in signals that let user code get notified by Django itself of certain actions. These include some useful notifications:

- django.db.models.signals.pre_save & django.db.models.signals.post_save

Sent before or after a model’s save() method is called.

- django.db.models.signals.pre_delete & django.db.models.signals.post_delete

Sent before or after a model’s delete() method or queryset’s delete() method is called.

- django.db.models.signals.m2m_changed

Sent when a ManyToManyField on a model is changed.

- django.core.signals.request_started & django.core.signals.request_finished

Sent when Django starts or finishes an HTTP request.

See the built-in signal documentation for a complete list, and a complete explanation of each signal.

You can also define and send your own custom signals; see below.

Listening to signals

To receive a signal, you need to register a receiver function that gets called when the signal is sent by using the Signal.connect() method:

Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)[source]

Parameters:

- receiver – The callback function which will be connected to this signal. See Receiver functions for more information.

- sender – Specifies a particular sender to receive signals from. See Connecting to signals sent by specific senders for more information.

- weak – Django stores signal handlers as weak references by default. Thus, if your receiver is a local function, it may be garbage collected. To prevent this, pass weak=False when you call the signal’s connect() method.

- dispatch_uid – A unique identifier for a signal receiver in cases where duplicate signals may be sent. See Preventing duplicate signals for more information.

Let’s see how this works by registering a signal that gets called after each HTTP request is finished. We’ll be connecting to the request_finished signal.

Receiver functions

First, we need to define a receiver function. A receiver can be any Python function or method:

def my_callback(sender, **kwargs):
print("Request finished!")

Notice that the function takes a sender argument, along with wildcard keyword arguments (**kwargs); all signal handlers must take these arguments.

We’ll look at senders a bit later, but right now look at the **kwargs argument. All signals send keyword arguments, and may change those keyword arguments at any time. In the case of request_finished, it’s documented as sending no arguments, which means we might be tempted to write our signal handling as my_callback(sender).

This would be wrong – in fact, Django will throw an error if you do so. That’s because at any point arguments could get added to the signal and your receiver must be able to handle those new arguments.

Connecting receiver functions

There are two ways you can connect a receiver to a signal. You can take the manual connect route:

from django.core.signals import request_finished

request_finished.connect(my_callback)

Alternatively, you can use a receiver() decorator:

receiver(signal)[source]

Parameters:

signal – A signal or a list of signals to connect a function to.

Here’s how you connect with the decorator:

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")

Now, our my_callback function will be called each time a request finishes.

Where should this code live?

Strictly speaking, signal handling and registration code can live anywhere you like, although it’s recommended to avoid the application’s root module and its models module to minimize side-effects of importing code.

In practice, signal handlers are usually defined in a signals submodule of the application they relate to. Signal receivers are connected in the ready() method of your application configuration class. If you’re using the receiver() decorator, simply import the signals submodule inside ready().

Note

The ready() method may be executed more than once during testing, so you may want to guard your signals from duplication, especially if you’re planning to send them within tests.

Connecting to signals sent by specific senders

Some signals get sent many times, but you’ll only be interested in receiving a certain subset of those signals. For example, consider the django.db.models.signals.pre_save signal sent before a model gets saved. Most of the time, you don’t need to know when any model gets saved – just when one specific model is saved.

In these cases, you can register to receive signals sent only by particular senders. In the case of django.db.models.signals.pre_save, the sender will be the model class being saved, so you can indicate that you only want signals sent by some model:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
...

The my_handler function will only be called when an instance of MyModel is saved.

Different signals use different objects as their senders; you’ll need to consult the built-in signal documentation for details of each particular signal.

Preventing duplicate signals

In some circumstances, the code connecting receivers to signals may run multiple times. This can cause your receiver function to be registered more than once, and thus called multiples times for a single signal event.

If this behavior is problematic (such as when using signals to send an email whenever a model is saved), pass a unique identifier as the dispatch_uid argument to identify your receiver function. This identifier will usually be a string, although any hashable object will suffice. The end result is that your receiver function will only be bound to the signal once for each unique dispatch_uid value:

from django.core.signals import request_finished

request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")

Defining and sending signals

Your applications can take advantage of the signal infrastructure and provide its own signals.

Defining signals

class Signal(providing_args=list)[source]

All signals are django.dispatch.Signal instances. The providing_args is a list of the names of arguments the signal will provide to listeners. This is purely documentational, however, as there is nothing that checks that the signal actually provides these arguments to its listeners.

For example:

import django.dispatch

pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

This declares a pizza_done signal that will provide receivers with toppings and size arguments.

Remember that you’re allowed to change this list of arguments at any time, so getting the API right on the first try isn’t necessary.

Sending signals

There are two ways to send signals in Django.

Signal.send(sender, **kwargs)[source]

Signal.send_robust(sender, **kwargs)[source]

To send a signal, call either Signal.send() (all built-in signals use this) or Signal.send_robust(). You must provide the sender argument (which is a class most of the time) and may provide as many other keyword arguments as you like.

For example, here’s how sending our pizza_done signal might look:

class PizzaStore(object):
...

def send_pizza(self, toppings, size):
pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
...

Both send() and send_robust() return a list of tuple pairs [(receiver, response), ... ], representing the list of called receiver functions and their response values.

send() differs from send_robust() in how exceptions raised by receiver functions are handled. send() does not catch any exceptions raised by receivers; it simply allows errors to propagate. Thus not all receivers may be notified of a signal in the face of an error.

send_robust() catches all errors derived from Python’s Exception class, and ensures all receivers are notified of the signal. If an error occurs, the error instance is returned in the tuple pair for the receiver that raised the error.

New in Django 1.8:
The tracebacks are present on the __traceback__ attribute of the errors returned when calling send_robust().

Disconnecting signals

Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)[source]

To disconnect a receiver from a signal, call Signal.disconnect(). The arguments are as described in Signal.connect(). The method returns True if a receiver was disconnected and False if not.

The receiver argument indicates the registered receiver to disconnect. It may be None if dispatch_uid is used to identify the receiver.

Changed in Django 1.8:
The boolean return value was added.

Deprecated since version 1.9: The weak argument is deprecated as it has no effect. It will be removed in Django 2.0.

System check framework

The system check framework is a set of static checks for validating Django projects. It detects common problems and provides hints for how to fix them. The framework is extensible so you can easily add your own checks.

Checks can be triggered explicitly via the check command. Checks are triggered implicitly before most commands, including runserver and migrate. For performance reasons, checks are not run as part of the WSGI stack that is used in deployment. If you need to run system checks on your deployment server, trigger them explicitly using check.

Serious errors will prevent Django commands (such as runserver) from running at all. Minor problems are reported to the console. If you have inspected the cause of a warning and are happy to ignore it, you can hide specific warnings using the SILENCED_SYSTEM_CHECKS setting in your project settings file.

A full list of all checks that can be raised by Django can be found in the System check reference.

Writing your own checks

The framework is flexible and allows you to write functions that perform any other kind of check you may require. The following is an example stub check function:

from django.core.checks import Error, register

@register()
def example_check(app_configs, **kwargs):
errors = []
# ... your check logic here
if check_failed:
errors.append(
Error(
'an error',
hint=None,
obj=checked_object,
id='myapp.E001',
)
)
return errors

The check function must accept an app_configs argument; this argument is the list of applications that should be inspected. If None, the check must be run on all installed apps in the project. The **kwargs argument is required for future expansion.

Messages

The function must return a list of messages. If no problems are found as a result of the check, the check function must return an empty list.

The warnings and errors raised by the check method must be instances of CheckMessage. An instance of CheckMessage encapsulates a single reportable error or warning. It also provides context and hints applicable to the message, and a unique identifier that is used for filtering purposes.

The concept is very similar to messages from the message framework or the logging framework. Messages are tagged with a level indicating the severity of the message.

There are also shortcuts to make creating messages with common levels easier. When using these classes you can omit the level argument because it is implied by the class name.

- Debug

- Info

- Warning

- Error

- Critical

Registering and labeling checks

Lastly, your check function must be registered explicitly with system check registry. Checks should be registered in a file that’s loaded when your application is loaded; for example, in the AppConfig.ready() method.

register(*tags)(function)

You can pass as many tags to register as you want in order to label your check. Tagging checks is useful since it allows you to run only a certain group of checks. For example, to register a compatibility check, you would make the following call:

from django.core.checks import register, Tags

@register(Tags.compatibility)
def my_check(app_configs, **kwargs):
# ... perform compatibility checks and collect errors
return errors

New in Django 1.8.

You can register “deployment checks” that are only relevant to a production settings file like this:

@register(Tags.security, deploy=True)
def my_check(app_configs, **kwargs):
...

These checks will only be run if the check --deploy option is used.

You can also use register as a function rather than a decorator by passing a callable object (usually a function) as the first argument to register.

The code below is equivalent to the code above:

def my_check(app_configs, **kwargs):
...
register(my_check, Tags.security, deploy=True)

Changed in Django 1.8:
The ability to use register as a function was added.

Field, model, and manager checks

In some cases, you won’t need to register your check function – you can piggyback on an existing registration.

Fields, models, and model managers all implement a check() method that is already registered with the check framework. If you want to add extra checks, you can extend the implementation on the base class, perform any extra checks you need, and append any messages to those generated by the base class. It’s recommended that you delegate each check to separate methods.

Consider an example where you are implementing a custom field named RangedIntegerField. This field adds min and max arguments to the constructor of IntegerField. You may want to add a check to ensure that users provide a min value that is less than or equal to the max value. The following code snippet shows how you can implement this check:

from django.core import checks
from django.db import models

class RangedIntegerField(models.IntegerField):
def __init__(self, min=None, max=None, **kwargs):
super(RangedIntegerField, self).__init__(**kwargs)
self.min = min
self.max = max

def check(self, **kwargs):
# Call the superclass
errors = super(RangedIntegerField, self).check(**kwargs)

# Do some custom checks and add messages to `errors`:
errors.extend(self._check_min_max_values(**kwargs))

# Return all errors and warnings
return errors

def _check_min_max_values(self, **kwargs):
if (self.min is not None and
self.max is not None and
self.min > self.max):
return [
checks.Error(
'min greater than max.',
hint='Decrease min or increase max.',
obj=self,
id='myapp.E001',
)
]
# When no error, return an empty list
return []

If you wanted to add checks to a model manager, you would take the same approach on your subclass of Manager.

If you want to add a check to a model class, the approach is almost the same: the only difference is that the check is a classmethod, not an instance method:

class MyModel(models.Model):
@classmethod
def check(cls, **kwargs):
errors = super(MyModel, cls).check(**kwargs)
# ... your own checks ...
return errors

Writing tests

Messages are comparable. That allows you to easily write tests:

from django.core.checks import Error
errors = checked_object.check()
expected_errors = [
Error(
'an error',
hint=None,
obj=checked_object,
id='myapp.E001',
)
]
self.assertEqual(errors, expected_errors)

External packages

Django ships with a variety of extra, optional tools that solve common problems (contrib.*). For easier maintenance and to trim the size of the codebase, a few of those applications have been moved out to separate projects.

Localflavor

django-localflavor is a collection of utilities for particular countries and cultures.

- GitHub

- Documentation

- PyPI

Comments

django-contrib-comments can be used to attach comments to any model, so you can use it for comments on blog entries, photos, book chapters, or anything else. Most users will be better served with a custom solution, or a hosted product like Disqus.

- GitHub

- Documentation

- PyPI

Formtools

django-formtools is a collection of assorted utilities to work with forms.

- GitHub

- Documentation

- PyPI

“How-to” guides

Here you’ll find short answers to “How do I....?” types of questions. These how-to guides don’t cover topics in depth – you’ll find that material in the Using Django and the API Reference. However, these guides will help you quickly accomplish common tasks.

- Authentication using REMOTE_USER

- Writing custom django-admin commands

- Writing custom model fields

- Custom Lookups

- Custom template tags and filters

- Writing a custom storage system

- Deploying Django

- Upgrading Django to a newer version

- Error reporting

- Providing initial data for models

- Running Django on Jython

- Integrating Django with a legacy database

- Outputting CSV with Django

- Outputting PDFs with Django

- Managing static files (e.g. images, JavaScript, CSS)

- Deploying static files

- How to install Django on Windows

- Writing database migrations

See also

The Django community aggregator, where we aggregate content from the global Django community. Many writers in the aggregator write this sort of how-to material.

Authentication using REMOTE_USER

This document describes how to make use of external authentication sources (where the Web server sets the REMOTE_USER environment variable) in your Django applications. This type of authentication solution is typically seen on intranet sites, with single sign-on solutions such as IIS and Integrated Windows Authentication or Apache and mod_authnz_ldap, CAS, Cosign, WebAuth, mod_auth_sspi, etc.

When the Web server takes care of authentication it typically sets the REMOTE_USER environment variable for use in the underlying application. In Django, REMOTE_USER is made available in the request.META attribute. Django can be configured to make use of the REMOTE_USER value using the RemoteUserMiddleware or PersistentRemoteUserMiddleware, and RemoteUserBackend classes found in django.contrib.auth.

Configuration

First, you must add the django.contrib.auth.middleware.RemoteUserMiddleware to the MIDDLEWARE_CLASSES setting after the django.contrib.auth.middleware.AuthenticationMiddleware:

MIDDLEWARE_CLASSES = [
'...',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.RemoteUserMiddleware',
'...',
]

Next, you must replace the ModelBackend with RemoteUserBackend in the AUTHENTICATION_BACKENDS setting:

AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.RemoteUserBackend',
]

With this setup, RemoteUserMiddleware will detect the username in request.META['REMOTE_USER'] and will authenticate and auto-login that user using the RemoteUserBackend.

Be aware that this particular setup disables authentication with the default ModelBackend. This means that if the REMOTE_USER value is not set then the user is unable to log in, even using Django’s admin interface. Adding 'django.contrib.auth.backends.ModelBackend' to the AUTHENTICATION_BACKENDS list will use ModelBackend as a fallback if REMOTE_USER is absent, which will solve these issues.

Django’s user management, such as the views in contrib.admin and the createsuperuser management command, doesn’t integrate with remote users. These interfaces work with users stored in the database regardless of AUTHENTICATION_BACKENDS.

Note

Since the RemoteUserBackend inherits from ModelBackend, you will still have all of the same permissions checking that is implemented in ModelBackend.

If your authentication mechanism uses a custom HTTP header and not REMOTE_USER, you can subclass RemoteUserMiddleware and set the header attribute to the desired request.META key. For example:

from django.contrib.auth.middleware import RemoteUserMiddleware

class CustomHeaderMiddleware(RemoteUserMiddleware):
header = 'HTTP_AUTHUSER'

Warning

Be very careful if using a RemoteUserMiddleware subclass with a custom HTTP header. You must be sure that your front-end web server always sets or strips that header based on the appropriate authentication checks, never permitting an end-user to submit a fake (or “spoofed”) header value. Since the HTTP headers X-Auth-User and X-Auth_User (for example) both normalize to the HTTP_X_AUTH_USER key in request.META, you must also check that your web server doesn’t allow a spoofed header using underscores in place of dashes.

This warning doesn’t apply to RemoteUserMiddleware in its default configuration with header = 'REMOTE_USER', since a key that doesn’t start with HTTP_ in request.META can only be set by your WSGI server, not directly from an HTTP request header.

If you need more control, you can create your own authentication backend that inherits from RemoteUserBackend and override one or more of its attributes and methods.

Using REMOTE_USER on login pages only

New in Django 1.9.

The RemoteUserMiddleware authentication middleware assumes that the HTTP request header REMOTE_USER is present with all authenticated requests. That might be expected and practical when Basic HTTP Auth with htpasswd or other simple mechanisms are used, but with Negotiate (GSSAPI/Kerberos) or other resource intensive authentication methods, the authentication in the front-end HTTP server is usually only set up for one or a few login URLs, and after successful authentication, the application is supposed to maintain the authenticated session itself.

PersistentRemoteUserMiddleware provides support for this use case. It will maintain the authenticated session until explicit logout by the user. The class can be used as a drop-in replacement of RemoteUserMiddleware in the documentation above.

Writing custom django-admin commands

Applications can register their own actions with manage.py. For example, you might want to add a manage.py action for a Django app that you’re distributing. In this document, we will be building a custom closepoll command for the polls application from the tutorial.

To do this, just add a management/commands directory to the application. Django will register a manage.py command for each Python module in that directory whose name doesn’t begin with an underscore. For example:

polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py

On Python 2, be sure to include __init__.py files in both the management and management/commands directories as done above or your command will not be detected.

In this example, the closepoll command will be made available to any project that includes the polls application in INSTALLED_APPS.

The _private.py module will not be available as a management command.

The closepoll.py module has only one requirement – it must define a class Command that extends BaseCommand or one of its subclasses.

Standalone scripts

Custom management commands are especially useful for running standalone scripts or for scripts that are periodically executed from the UNIX crontab or from Windows scheduled tasks control panel.

To implement the command, edit polls/management/commands/closepoll.py to look like this:

from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll

class Command(BaseCommand):
help = 'Closes the specified poll for voting'

def add_arguments(self, parser):
parser.add_argument('poll_id', nargs='+', type=int)

def handle(self, *args, **options):
for poll_id in options['poll_id']:
try:
poll = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise CommandError('Poll "%s" does not exist' % poll_id)

poll.opened = False
poll.save()

self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))

Changed in Django 1.8:
Before Django 1.8, management commands were based on the optparse module, and positional arguments were passed in *args while optional arguments were passed in **options. Now that management commands use argparse for argument parsing, all arguments are passed in **options by default, unless you name your positional arguments to args (compatibility mode). You are encouraged to exclusively use **options for new commands.

Note

When you are using management commands and wish to provide console output, you should write to self.stdout and self.stderr, instead of printing to stdout and stderr directly. By using these proxies, it becomes much easier to test your custom command. Note also that you don’t need to end messages with a newline character, it will be added automatically, unless you specify the ending parameter:

self.stdout.write("Unterminated line", ending='')

The new custom command can be called using python manage.py closepoll <poll_id>.

The handle() method takes one or more poll_ids and sets poll.opened to False for each one. If the user referenced any nonexistent polls, a CommandError is raised. The poll.opened attribute does not exist in the tutorial and was added to polls.models.Question for this example.

Accepting optional arguments

The same closepoll could be easily modified to delete a given poll instead of closing it by accepting additional command line options. These custom options can be added in the add_arguments() method like this:

class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('poll_id', nargs='+', type=int)

# Named (optional) arguments
parser.add_argument(
'--delete',
action='store_true',
dest='delete',
default=False,
help='Delete poll instead of closing it',
)

def handle(self, *args, **options):
# ...
if options['delete']:
poll.delete()
# ...

Changed in Django 1.8:
Previously, only the standard optparse library was supported and you would have to extend the command option_list variable with optparse.make_option().

The option (delete in our example) is available in the options dict parameter of the handle method. See the argparse Python documentation for more about add_argument usage.

In addition to being able to add custom command line options, all management commands can accept some default options such as --verbosity and --traceback.

Management commands and locales

By default, the BaseCommand.execute() method deactivates translations because some commands shipped with Django perform several tasks (for example, user-facing content rendering and database population) that require a project-neutral string language.

Changed in Django 1.8:
In previous versions, Django forced the “en-us” locale instead of deactivating translations.

If, for some reason, your custom management command needs to use a fixed locale, you should manually activate and deactivate it in your handle() method using the functions provided by the I18N support code:

from django.core.management.base import BaseCommand, CommandError
from django.utils import translation

class Command(BaseCommand):
...
can_import_settings = True

def handle(self, *args, **options):

# Activate a fixed locale, e.g. Russian
translation.activate('ru')

# Or you can activate the LANGUAGE_CODE # chosen in the settings:
from django.conf import settings
translation.activate(settings.LANGUAGE_CODE)

# Your command logic here
...

translation.deactivate()

Another need might be that your command simply should use the locale set in settings and Django should be kept from deactivating it. You can achieve it by using the BaseCommand.leave_locale_alone option.

When working on the scenarios described above though, take into account that system management commands typically have to be very careful about running in non-uniform locales, so you might need to:

- Make sure the USE_I18N setting is always True when running the command (this is a good example of the potential problems stemming from a dynamic runtime environment that Django commands avoid offhand by deactivating translations).

- Review the code of your command and the code it calls for behavioral differences when locales are changed and evaluate its impact on predictable behavior of your command.

Testing

Information on how to test custom management commands can be found in the testing docs.

Command objects

class BaseCommand[source]

The base class from which all management commands ultimately derive.

Use this class if you want access to all of the mechanisms which parse the command-line arguments and work out what code to call in response; if you don’t need to change any of that behavior, consider using one of its subclasses.

Subclassing the BaseCommand class requires that you implement the handle() method.

Attributes

All attributes can be set in your derived class and can be used in BaseCommand’s subclasses.

BaseCommand.args

A string listing the arguments accepted by the command, suitable for use in help messages; e.g., a command which takes a list of application names might set this to ‘<app_label app_label ...>’.

Deprecated since version 1.8: This should be done now in the add_arguments() method, by calling the parser.add_argument() method. See the closepoll example above.

BaseCommand.can_import_settings

A boolean indicating whether the command needs to be able to import Django settings; if True, execute() will verify that this is possible before proceeding. Default value is True.

BaseCommand.help

A short description of the command, which will be printed in the help message when the user runs the command python manage.py help <command>.

BaseCommand.missing_args_message

New in Django 1.8.

If your command defines mandatory positional arguments, you can customize the message error returned in the case of missing arguments. The default is output by argparse (“too few arguments”).

BaseCommand.option_list

This is the list of optparse options which will be fed into the command’s OptionParser for parsing arguments.

Deprecated since version 1.8: You should now override the add_arguments() method to add custom arguments accepted by your command. See the example above.

BaseCommand.output_transaction

A boolean indicating whether the command outputs SQL statements; if True, the output will automatically be wrapped with BEGIN; and COMMIT;. Default value is False.

BaseCommand.requires_system_checks

A boolean; if True, the entire Django project will be checked for potential problems prior to executing the command. Default value is True.

BaseCommand.leave_locale_alone

A boolean indicating whether the locale set in settings should be preserved during the execution of the command instead of being forcibly set to ‘en-us’.

Default value is False.

Make sure you know what you are doing if you decide to change the value of this option in your custom command if it creates database content that is locale-sensitive and such content shouldn’t contain any translations (like it happens e.g. with django.contrib.auth permissions) as making the locale differ from the de facto default ‘en-us’ might cause unintended effects. Seethe Management commands and locales section above for further details.

This option can’t be False when the can_import_settings option is set to False too because attempting to set the locale needs access to settings. This condition will generate a CommandError.

BaseCommand.style

An instance attribute that helps create colored output when writing to stdout or stderr. For example:

self.stdout.write(self.style.SUCCESS('...'))

See Syntax coloring to learn how to modify the color palette and to see the available styles (use uppercased versions of the “roles” described in that section).

If you pass the --no-color option when running your command, all self.style() calls will return the original string uncolored.

Methods

BaseCommand has a few methods that can be overridden but only the handle() method must be implemented.

Implementing a constructor in a subclass

If you implement __init__ in your subclass of BaseCommand, you must call BaseCommand’s __init__:

class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
# ...

BaseCommand.add_arguments(parser)[source]

New in Django 1.8.

Entry point to add parser arguments to handle command line arguments passed to the command. Custom commands should override this method to add both positional and optional arguments accepted by the command. Calling super() is not needed when directly subclassing BaseCommand.

BaseCommand.get_version()[source]

Returns the Django version, which should be correct for all built-in Django commands. User-supplied commands can override this method to return their own version.

BaseCommand.execute(*args, **options)[source]

Tries to execute this command, performing system checks if needed (as controlled by the requires_system_checks attribute). If the command raises a CommandError, it’s intercepted and printed to stderr.

Calling a management command in your code

execute() should not be called directly from your code to execute a command. Use call_command() instead.

BaseCommand.handle(*args, **options)[source]

The actual logic of the command. Subclasses must implement this method.

It may return a Unicode string which will be printed to stdout (wrapped by BEGIN; and COMMIT; if output_transaction is True).

BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)[source]

Uses the system check framework to inspect the entire Django project for potential problems. Serious problems are raised as a CommandError; warnings are output to stderr; minor notifications are output to stdout.

If app_configs and tags are both None, all system checks are performed. tags can be a list of check tags, like compatibility or models.

BaseCommand subclasses

class AppCommand

A management command which takes one or more installed application labels as arguments, and does something with each of them.

Rather than implementing handle(), subclasses must implement handle_app_config(), which will be called once for each application.

AppCommand.handle_app_config(app_config, **options)

Perform the command’s actions for app_config, which will be an AppConfig instance corresponding to an application label given on the command line.

class LabelCommand

A management command which takes one or more arbitrary arguments (labels) on the command line, and does something with each of them.

Rather than implementing handle(), subclasses must implement handle_label(), which will be called once for each label.

LabelCommand.handle_label(label, **options)

Perform the command’s actions for label, which will be the string as given on the command line.

class NoArgsCommand

Deprecated since version 1.8: Use BaseCommand instead, which takes no arguments by default.

A command which takes no arguments on the command line.

Rather than implementing handle(), subclasses must implement handle_noargs(); handle() itself is overridden to ensure no arguments are passed to the command.

NoArgsCommand.handle_noargs(**options)

Perform this command’s actions

Command exceptions

exception CommandError[source]

Exception class indicating a problem while executing a management command.

If this exception is raised during the execution of a management command from a command line console, it will be caught and turned into a nicely-printed error message to the appropriate output stream (i.e., stderr); as a result, raising this exception (with a sensible description of the error) is the preferred way to indicate that something has gone wrong in the execution of a command.

If a management command is called from code through call_command(), it’s up to you to catch the exception when needed.

Writing custom model fields

Introduction

The model reference documentation explains how to use Django’s standard field classes – CharField, DateField, etc. For many purposes, those classes are all you’ll need. Sometimes, though, the Django version won’t meet your precise requirements, or you’ll want to use a field that is entirely different from those shipped with Django.

Django’s built-in field types don’t cover every possible database column type – only the common types, such as VARCHAR and INTEGER. For more obscure column types, such as geographic polygons or even user-created types such as PostgreSQL custom types, you can define your own Django Field subclasses.

Alternatively, you may have a complex Python object that can somehow be serialized to fit into a standard database column type. This is another case where a Field subclass will help you use your object with your models.

Our example object

Creating custom fields requires a bit of attention to detail. To make things easier to follow, we’ll use a consistent example throughout this document: wrapping a Python object representing the deal of cards in a hand of Bridge. Don’t worry, you don’t have to know how to play Bridge to follow this example. You only need to know that 52 cards are dealt out equally to four players, who are traditionally called north, east, south and west. Our class looks something like this:

class Hand(object):
"""A hand of cards (bridge style)"""

def __init__(self, north, east, south, west):
# Input parameters are lists of cards ('Ah', '9s', etc.)
self.north = north
self.east = east
self.south = south
self.west = west

# ... (other possibly useful methods omitted) ...

This is just an ordinary Python class, with nothing Django-specific about it. We’d like to be able to do things like this in our models (we assume the hand attribute on the model is an instance of Hand):

example = MyModel.objects.get(pk=1)
print(example.hand.north)

new_hand = Hand(north, east, south, west)
example.hand = new_hand
example.save()

We assign to and retrieve from the hand attribute in our model just like any other Python class. The trick is to tell Django how to handle saving and loading such an object.

In order to use the Hand class in our models, we do not have to change this class at all. This is ideal, because it means you can easily write model support for existing classes where you cannot change the source code.

Note

You might only be wanting to take advantage of custom database column types and deal with the data as standard Python types in your models; strings, or floats, for example. This case is similar to our Hand example and we’ll note any differences as we go along.

Background theory

Database storage

The simplest way to think of a model field is that it provides a way to take a normal Python object – string, boolean, datetime, or something more complex like Hand – and convert it to and from a format that is useful when dealing with the database (and serialization, but, as we’ll see later, that falls out fairly naturally once you have the database side under control).

Fields in a model must somehow be converted to fit into an existing database column type. Different databases provide different sets of valid column types, but the rule is still the same: those are the only types you have to work with. Anything you want to store in the database must fit into one of those types.

Normally, you’re either writing a Django field to match a particular database column type, or there’s a fairly straightforward way to convert your data to, say, a string.

For our Hand example, we could convert the card data to a string of 104 characters by concatenating all the cards together in a pre-determined order – say, all the north cards first, then the east, south and west cards. So Hand objects can be saved to text or character columns in the database.

What does a field class do?

All of Django’s fields (and when we say fields in this document, we always mean model fields and not form fields) are subclasses of django.db.models.Field. Most of the information that Django records about a field is common to all fields – name, help text, uniqueness and so forth. Storing all that information is handled by Field. We’ll get into the precise details of what Field can do later on; for now, suffice it to say that everything descends from Field and then customizes key pieces of the class behavior.

It’s important to realize that a Django field class is not what is stored in your model attributes. The model attributes contain normal Python objects. The field classes you define in a model are actually stored in the Meta class when the model class is created (the precise details of how this is done are unimportant here). This is because the field classes aren’t necessary when you’re just creating and modifying attributes. Instead, they provide the machinery for converting between the attribute value and what is stored in the database or sent to the serializer.

Keep this in mind when creating your own custom fields. The Django Field subclass you write provides the machinery for converting between your Python instances and the database/serializer values in various ways (there are differences between storing a value and using a value for lookups, for example). If this sounds a bit tricky, don’t worry – it will become clearer in the examples below. Just remember that you will often end up creating two classes when you want a custom field:

- The first class is the Python object that your users will manipulate. They will assign it to the model attribute, they will read from it for displaying purposes, things like that. This is the Hand class in our example.

- The second class is the Field subclass. This is the class that knows how to convert your first class back and forth between its permanent storage form and the Python form.

Writing a field subclass

When planning your Field subclass, first give some thought to which existing Field class your new field is most similar to. Can you subclass an existing Django field and save yourself some work? If not, you should subclass the Field class, from which everything is descended.

Initializing your new field is a matter of separating out any arguments that are specific to your case from the common arguments and passing the latter to the __init__() method of Field (or your parent class).

In our example, we’ll call our field HandField. (It’s a good idea to call your Field subclass <Something>Field, so it’s easily identifiable as a Field subclass.) It doesn’t behave like any existing field, so we’ll subclass directly from Field:

from django.db import models

class HandField(models.Field):

description = "A hand of cards (bridge style)"

def __init__(self, *args, **kwargs):
kwargs['max_length'] = 104
super(HandField, self).__init__(*args, **kwargs)

Our HandField accepts most of the standard field options (see the list below), but we ensure it has a fixed length, since it only needs to hold 52 card values plus their suits; 104 characters in total.

Note

Many of Django’s model fields accept options that they don’t do anything with. For example, you can pass both editable and auto_now to a django.db.models.DateField and it will simply ignore the editable parameter (auto_now being set implies editable=False). No error is raised in this case.

This behavior simplifies the field classes, because they don’t need to check for options that aren’t necessary. They just pass all the options to the parent class and then don’t use them later on. It’s up to you whether you want your fields to be more strict about the options they select, or to use the simpler, more permissive behavior of the current fields.

The Field.__init__() method takes the following parameters:

- verbose_name

- name

- primary_key

- max_length

- unique

- blank

- null

- db_index

- rel: Used for related fields (like ForeignKey). For advanced use only.

- default

- editable

- serialize: If False, the field will not be serialized when the model is passed to Django’s serializers. Defaults to True.

- unique_for_date

- unique_for_month

- unique_for_year

- choices

- help_text

- db_column

- db_tablespace: Only for index creation, if the backend supports tablespaces. You can usually ignore this option.

- auto_created: True if the field was automatically created, as for the OneToOneField used by model inheritance. For advanced use only.

All of the options without an explanation in the above list have the same meaning they do for normal Django fields. See the field documentation for examples and details.

Field deconstruction

The counterpoint to writing your __init__() method is writing the deconstruct() method. This method tells Django how to take an instance of your new field and reduce it to a serialized form - in particular, what arguments to pass to __init__() to re-create it.

If you haven’t added any extra options on top of the field you inherited from, then there’s no need to write a new deconstruct() method. If, however, you’re changing the arguments passed in __init__() (like we are in HandField), you’ll need to supplement the values being passed.

The contract of deconstruct() is simple; it returns a tuple of four items: the field’s attribute name, the full import path of the field class, the positional arguments (as a list), and the keyword arguments (as a dict). Note this is different from the deconstruct() method for custom classes which returns a tuple of three things.

As a custom field author, you don’t need to care about the first two values; the base Field class has all the code to work out the field’s attribute name and import path. You do, however, have to care about the positional and keyword arguments, as these are likely the things you are changing.

For example, in our HandField class we’re always forcibly setting max_length in __init__(). The deconstruct() method on the base Field class will see this and try to return it in the keyword arguments; thus, we can drop it from the keyword arguments for readability:

from django.db import models

class HandField(models.Field):

def __init__(self, *args, **kwargs):
kwargs['max_length'] = 104
super(HandField, self).__init__(*args, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(HandField, self).deconstruct()
del kwargs["max_length"]
return name, path, args, kwargs

If you add a new keyword argument, you need to write code to put its value into kwargs yourself:

from django.db import models

class CommaSepField(models.Field):
"Implements comma-separated storage of lists"

def __init__(self, separator=",", *args, **kwargs):
self.separator = separator
super(CommaSepField, self).__init__(*args, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(CommaSepField, self).deconstruct()
# Only include kwarg if it's not the default
if self.separator != ",":
kwargs['separator'] = self.separator
return name, path, args, kwargs

More complex examples are beyond the scope of this document, but remember - for any configuration of your Field instance, deconstruct() must return arguments that you can pass to __init__ to reconstruct that state.

Pay extra attention if you set new default values for arguments in the Field superclass; you want to make sure they’re always included, rather than disappearing if they take on the old default value.

In addition, try to avoid returning values as positional arguments; where possible, return values as keyword arguments for maximum future compatibility. Of course, if you change the names of things more often than their position in the constructor’s argument list, you might prefer positional, but bear in mind that people will be reconstructing your field from the serialized version for quite a while (possibly years), depending how long your migrations live for.

You can see the results of deconstruction by looking in migrations that include the field, and you can test deconstruction in unit tests by just deconstructing and reconstructing the field:

name, path, args, kwargs = my_field_instance.deconstruct()
new_instance = MyField(*args, **kwargs)
self.assertEqual(my_field_instance.some_attribute, new_instance.some_attribute)

Changing a custom field’s base class

You can’t change the base class of a custom field because Django won’t detect the change and make a migration for it. For example, if you start with:

class CustomCharField(models.CharField):
...

and then decide that you want to use TextField instead, you can’t change the subclass like this:

class CustomCharField(models.TextField):
...

Instead, you must create a new custom field class and update your models to reference it:

class CustomCharField(models.CharField):
...

class CustomTextField(models.TextField):
...

As discussed in removing fields, you must retain the original CustomCharField class as long as you have migrations that reference it.

Documenting your custom field

As always, you should document your field type, so users will know what it is. In addition to providing a docstring for it, which is useful for developers, you can also allow users of the admin app to see a short description of the field type via the django.contrib.admindocs application. To do this simply provide descriptive text in a description class attribute of your custom field. In the above example, the description displayed by the admindocs application for a HandField will be ‘A hand of cards (bridge style)’.

In the django.contrib.admindocs display, the field description is interpolated with field.__dict__ which allows the description to incorporate arguments of the field. For example, the description for CharField is:

description = _("String (up to %(max_length)s)")

Useful methods

Once you’ve created your Field subclass, you might consider overriding a few standard methods, depending on your field’s behavior. The list of methods below is in approximately decreasing order of importance, so start from the top.

Custom database types

Say you’ve created a PostgreSQL custom type called mytype. You can subclass Field and implement the db_type() method, like so:

from django.db import models

class MytypeField(models.Field):
def db_type(self, connection):
return 'mytype'

Once you have MytypeField, you can use it in any model, just like any other Field type:

class Person(models.Model):
name = models.CharField(max_length=80)
something_else = MytypeField()

If you aim to build a database-agnostic application, you should account for differences in database column types. For example, the date/time column type in PostgreSQL is called timestamp, while the same column in MySQL is called datetime. The simplest way to handle this in a db_type() method is to check the connection.settings_dict['ENGINE'] attribute.

For example:

class MyDateField(models.Field):
def db_type(self, connection):
if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
return 'datetime'
else:
return 'timestamp'

The db_type() method is called by Django when the framework constructs the CREATE TABLE statements for your application – that is, when you first create your tables. It is also called when constructing a WHERE clause that includes the model field – that is, when you retrieve data using QuerySet methods like get(), filter(), and exclude() and have the model field as an argument. It’s not called at any other time, so it can afford to execute slightly complex code, such as the connection.settings_dict check in the above example.

Some database column types accept parameters, such as CHAR(25), where the parameter 25 represents the maximum column length. In cases like these, it’s more flexible if the parameter is specified in the model rather than being hard-coded in the db_type() method. For example, it wouldn’t make much sense to have a CharMaxlength25Field, shown here:

# This is a silly example of hard-coded parameters.
class CharMaxlength25Field(models.Field):
def db_type(self, connection):
return 'char(25)'

# In the model:
class MyModel(models.Model):
# ...
my_field = CharMaxlength25Field()

The better way of doing this would be to make the parameter specifiable at run time – i.e., when the class is instantiated. To do that, just implement Field.__init__(), like so:

# This is a much more flexible example.
class BetterCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(BetterCharField, self).__init__(*args, **kwargs)

def db_type(self, connection):
return 'char(%s)' % self.max_length

# In the model:
class MyModel(models.Model):
# ...
my_field = BetterCharField(25)

Finally, if your column requires truly complex SQL setup, return None from db_type(). This will cause Django’s SQL creation code to skip over this field. You are then responsible for creating the column in the right table in some other way, of course, but this gives you a way to tell Django to get out of the way.

Converting values to Python objects

Changed in Django 1.8:
Historically, Django provided a metaclass called SubfieldBase which always called to_python() on assignment. This did not play nicely with custom database transformations, aggregation, or values queries, so it has been replaced with from_db_value().

If your custom Field class deals with data structures that are more complex than strings, dates, integers, or floats, then you may need to override from_db_value() and to_python().

If present for the field subclass, from_db_value() will be called in all circumstances when the data is loaded from the database, including in aggregates and values() calls.

to_python() is called by deserialization and during the clean() method used from forms.

As a general rule, to_python() should deal gracefully with any of the following arguments:

- An instance of the correct type (e.g., Hand in our ongoing example).

- A string

- None (if the field allows null=True)

In our HandField class, we’re storing the data as a VARCHAR field in the database, so we need to be able to process strings and None in the from_db_value(). In to_python(), we need to also handle Hand instances:

import re

from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _

def parse_hand(hand_string):
"""Takes a string of cards and splits into a full hand."""
p1 = re.compile('.{26}')
p2 = re.compile('..')
args = [p2.findall(x) for x in p1.findall(hand_string)]
if len(args) != 4:
raise ValidationError(_("Invalid input for a Hand instance"))
return Hand(*args)

class HandField(models.Field):
# ...

def from_db_value(self, value, expression, connection, context):
if value is None:
return value
return parse_hand(value)

def to_python(self, value):
if isinstance(value, Hand):
return value

if value is None:
return value

return parse_hand(value)

Notice that we always return a Hand instance from these methods. That’s the Python object type we want to store in the model’s attribute.

For to_python(), if anything goes wrong during value conversion, you should raise a ValidationError exception.

Converting Python objects to query values

Since using a database requires conversion in both ways, if you override to_python() you also have to override get_prep_value() to convert Python objects back to query values.

For example:

class HandField(models.Field):
# ...

def get_prep_value(self, value):
return ''.join([''.join(l) for l in (value.north,
value.east, value.south, value.west)])

Warning

If your custom field uses the CHAR, VARCHAR or TEXT types for MySQL, you must make sure that get_prep_value() always returns a string type. MySQL performs flexible and unexpected matching when a query is performed on these types and the provided value is an integer, which can cause queries to include unexpected objects in their results. This problem cannot occur if you always return a string type from get_prep_value().

Converting query values to database values

Some data types (for example, dates) need to be in a specific format before they can be used by a database backend. get_db_prep_value() is the method where those conversions should be made. The specific connection that will be used for the query is passed as the connection parameter. This allows you to use backend-specific conversion logic if it is required.

For example, Django uses the following method for its BinaryField:

def get_db_prep_value(self, value, connection, prepared=False):
value = super(BinaryField, self).get_db_prep_value(value, connection, prepared)
if value is not None:
return connection.Database.Binary(value)
return value

In case your custom field needs a special conversion when being saved that is not the same as the conversion used for normal query parameters, you can override get_db_prep_save().

Preprocessing values before saving

If you want to preprocess the value just before saving, you can use pre_save(). For example, Django’s DateTimeField uses this method to set the attribute correctly in the case of auto_now or auto_now_add.

If you do override this method, you must return the value of the attribute at the end. You should also update the model’s attribute if you make any changes to the value so that code holding references to the model will always see the correct value.

Preparing values for use in database lookups

As with value conversions, preparing a value for database lookups is a two phase process.

get_prep_lookup() performs the first phase of lookup preparation: type conversion and data validation.

Prepares the value for passing to the database when used in a lookup (a WHERE constraint in SQL). The lookup_type parameter will be one of the valid Django filter lookups: exact, iexact, contains, icontains, gt, gte, lt, lte, in, startswith, istartswith, endswith, iendswith, range, year, month, day, isnull, search, regex, and iregex.

If you are using custom lookups, the lookup_type can be any lookup_name used by the project’s custom lookups.

Your method must be prepared to handle all of these lookup_type values and should raise either a ValueError if the value is of the wrong sort (a list when you were expecting an object, for example) or a TypeError if your field does not support that type of lookup. For many fields, you can get by with handling the lookup types that need special handling for your field and pass the rest to the get_db_prep_lookup() method of the parent class.

If you needed to implement get_db_prep_save(), you will usually need to implement get_prep_lookup(). If you don’t, get_prep_value() will be called by the default implementation, to manage exact, gt, gte, lt, lte, in and range lookups.

You may also want to implement this method to limit the lookup types that could be used with your custom field type.

Note that, for "range" and "in" lookups, get_prep_lookup will receive a list of objects (presumably of the right type) and will need to convert them to a list of things of the right type for passing to the database. Most of the time, you can reuse get_prep_value(), or at least factor out some common pieces.

For example, the following code implements get_prep_lookup to limit the accepted lookup types to exact and in:

class HandField(models.Field):
# ...

def get_prep_lookup(self, lookup_type, value):
# We only handle 'exact' and 'in'. All others are errors.
if lookup_type == 'exact':
return self.get_prep_value(value)
elif lookup_type == 'in':
return [self.get_prep_value(v) for v in value]
else:
raise TypeError('Lookup type %r not supported.' % lookup_type)

For performing database-specific data conversions required by a lookup, you can override get_db_prep_lookup().

Specifying the form field for a model field

To customize the form field used by ModelForm, you can override formfield().

The form field class can be specified via the form_class and choices_form_class arguments; the latter is used if the field has choices specified, the former otherwise. If these arguments are not provided, CharField or TypedChoiceField will be used.

All of the kwargs dictionary is passed directly to the form field’s __init__() method. Normally, all you need to do is set up a good default for the form_class (and maybe choices_form_class) argument and then delegate further handling to the parent class. This might require you to write a custom form field (and even a form widget). See the forms documentation for information about this.

Continuing our ongoing example, we can write the formfield() method as:

class HandField(models.Field):
# ...

def formfield(self, **kwargs):
# This is a fairly standard way to set up some defaults
# while letting the caller override them.
defaults = {'form_class': MyFormField}
defaults.update(kwargs)
return super(HandField, self).formfield(**defaults)

This assumes we’ve imported a MyFormField field class (which has its own default widget). This document doesn’t cover the details of writing custom form fields.

Emulating built-in field types

If you have created a db_type() method, you don’t need to worry about get_internal_type() – it won’t be used much. Sometimes, though, your database storage is similar in type to some other field, so you can use that other field’s logic to create the right column.

For example:

class HandField(models.Field):
# ...

def get_internal_type(self):
return 'CharField'

No matter which database backend we are using, this will mean that migrate and other SQL commands create the right column type for storing a string.

If get_internal_type() returns a string that is not known to Django for the database backend you are using – that is, it doesn’t appear in django.db.backends.<db_name>.base.DatabaseWrapper.data_types – the string will still be used by the serializer, but the default db_type() method will return None. See the documentation of db_type() for reasons why this might be useful. Putting a descriptive string in as the type of the field for the serializer is a useful idea if you’re ever going to be using the serializer output in some other place, outside of Django.

Converting field data for serialization

To customize how the values are serialized by a serializer, you can override value_to_string(). Using value_from_object() is the best way to get the field’s value prior to serialization. For example, since our HandField uses strings for its data storage anyway, we can reuse some existing conversion code:

class HandField(models.Field):
# ...

def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)

Some general advice

Writing a custom field can be a tricky process, particularly if you’re doing complex conversions between your Python types and your database and serialization formats. Here are a couple of tips to make things go more smoothly:

1. Look at the existing Django fields (in django/db/models/fields/__init__.py) for inspiration. Try to find a field that’s similar to what you want and extend it a little bit, instead of creating an entirely new field from scratch.

2. Put a __str__() (__unicode__() on Python 2) method on the class you’re wrapping up as a field. There are a lot of places where the default behavior of the field code is to call force_text() on the value. (In our examples in this document, value would be a Hand instance, not a HandField). So if your __str__() method (__unicode__() on Python 2) automatically converts to the string form of your Python object, you can save yourself a lot of work.

Writing a FileField subclass

In addition to the above methods, fields that deal with files have a few other special requirements which must be taken into account. The majority of the mechanics provided by FileField, such as controlling database storage and retrieval, can remain unchanged, leaving subclasses to deal with the challenge of supporting a particular type of file.

Django provides a File class, which is used as a proxy to the file’s contents and operations. This can be subclassed to customize how the file is accessed, and what methods are available. It lives at django.db.models.fields.files, and its default behavior is explained in the file documentation.

Once a subclass of File is created, the new FileField subclass must be told to use it. To do so, simply assign the new File subclass to the special attr_class attribute of the FileField subclass.

A few suggestions

In addition to the above details, there are a few guidelines which can greatly improve the efficiency and readability of the field’s code.

1. The source for Django’s own ImageField (in django/db/models/fields/files.py) is a great example of how to subclass FileField to support a particular type of file, as it incorporates all of the techniques described above.

2. Cache file attributes wherever possible. Since files may be stored in remote storage systems, retrieving them may cost extra time, or even money, that isn’t always necessary. Once a file is retrieved to obtain some data about its content, cache as much of that data as possible to reduce the number of times the file must be retrieved on subsequent calls for that information.

Custom Lookups

Django offers a wide variety of built-in lookups for filtering (for example, exact and icontains). This documentation explains how to write custom lookups and how to alter the working of existing lookups. For the API references of lookups, see the Lookup API reference.

A simple lookup example

Let’s start with a simple custom lookup. We will write a custom lookup ne which works opposite to exact. Author.objects.filter(name__ne='Jack') will translate to the SQL:

"author"."name" <> 'Jack'

This SQL is backend independent, so we don’t need to worry about different databases.

There are two steps to making this work. Firstly we need to implement the lookup, then we need to tell Django about it. The implementation is quite straightforward:

from django.db.models import Lookup

class NotEqual(Lookup):
lookup_name = 'ne'

def as_sql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return '%s <> %s' % (lhs, rhs), params

To register the NotEqual lookup we will just need to call register_lookup on the field class we want the lookup to be available. In this case, the lookup makes sense on all Field subclasses, so we register it with Field directly:

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

Lookup registration can also be done using a decorator pattern:

from django.db.models.fields import Field

@Field.register_lookup
class NotEqualLookup(Lookup):
# ...

Changed in Django 1.8:
The ability to use the decorator pattern was added.

We can now use foo__ne for any field foo. You will need to ensure that this registration happens before you try to create any querysets using it. You could place the implementation in a models.py file, or register the lookup in the ready() method of an AppConfig.

Taking a closer look at the implementation, the first required attribute is lookup_name. This allows the ORM to understand how to interpret name__ne and use NotEqual to generate the SQL. By convention, these names are always lowercase strings containing only letters, but the only hard requirement is that it must not contain the string __.

We then need to define the as_sql method. This takes a SQLCompiler object, called compiler, and the active database connection. SQLCompiler objects are not documented, but the only thing we need to know about them is that they have a compile() method which returns a tuple containing an SQL string, and the parameters to be interpolated into that string. In most cases, you don’t need to use it directly and can pass it on to process_lhs() and process_rhs().

A Lookup works against two values, lhs and rhs, standing for left-hand side and right-hand side. The left-hand side is usually a field reference, but it can be anything implementing the query expression API. The right-hand is the value given by the user. In the example Author.objects.filter(name__ne='Jack'), the left-hand side is a reference to the name field of the Author model, and 'Jack' is the right-hand side.

We call process_lhs and process_rhs to convert them into the values we need for SQL using the compiler object described before. These methods return tuples containing some SQL and the parameters to be interpolated into that SQL, just as we need to return from our as_sql method. In the above example, process_lhs returns ('"author"."name"', []) and process_rhs returns ('"%s"', ['Jack']). In this example there were no parameters for the left hand side, but this would depend on the object we have, so we still need to include them in the parameters we return.

Finally we combine the parts into an SQL expression with <>, and supply all the parameters for the query. We then return a tuple containing the generated SQL string and the parameters.

A simple transformer example

The custom lookup above is great, but in some cases you may want to be able to chain lookups together. For example, let’s suppose we are building an application where we want to make use of the abs() operator. We have an Experiment model which records a start value, end value, and the change (start - end). We would like to find all experiments where the change was equal to a certain amount (Experiment.objects.filter(change__abs=27)), or where it did not exceed a certain amount (Experiment.objects.filter(change__abs__lt=27)).

Note

This example is somewhat contrived, but it nicely demonstrates the range of functionality which is possible in a database backend independent manner, and without duplicating functionality already in Django.

We will start by writing a AbsoluteValue transformer. This will use the SQL function ABS() to transform the value before comparison:

from django.db.models import Transform

class AbsoluteValue(Transform):
lookup_name = 'abs'
function = 'ABS'

Next, let’s register it for IntegerField:

from django.db.models import IntegerField
IntegerField.register_lookup(AbsoluteValue)

We can now run the queries we had before. Experiment.objects.filter(change__abs=27) will generate the following SQL:

SELECT ... WHERE ABS("experiments"."change") = 27

By using Transform instead of Lookup it means we are able to chain further lookups afterwards. So Experiment.objects.filter(change__abs__lt=27) will generate the following SQL:

SELECT ... WHERE ABS("experiments"."change") < 27

Note that in case there is no other lookup specified, Django interprets change__abs=27 as change__abs__exact=27.

When looking for which lookups are allowable after the Transform has been applied, Django uses the output_field attribute. We didn’t need to specify this here as it didn’t change, but supposing we were applying AbsoluteValue to some field which represents a more complex type (for example a point relative to an origin, or a complex number) then we may have wanted to specify that the transform returns a FloatField type for further lookups. This can be done by adding an output_field attribute to the transform:

from django.db.models import FloatField, Transform

class AbsoluteValue(Transform):
lookup_name = 'abs'
function = 'ABS'

@property
def output_field(self):
return FloatField()

This ensures that further lookups like abs__lte behave as they would for a FloatField.

Writing an efficient abs__lt lookup

When using the above written abs lookup, the SQL produced will not use indexes efficiently in some cases. In particular, when we use change__abs__lt=27, this is equivalent to change__gt=-27 AND change__lt=27. (For the lte case we could use the SQL BETWEEN).

So we would like Experiment.objects.filter(change__abs__lt=27) to generate the following SQL:

SELECT .. WHERE "experiments"."change" < 27 AND "experiments"."change" > -27

The implementation is:

from django.db.models import Lookup

class AbsoluteValueLessThan(Lookup):
lookup_name = 'lt'

def as_sql(self, compiler, connection):
lhs, lhs_params = compiler.compile(self.lhs.lhs)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params + lhs_params + rhs_params
return '%s < %s AND %s > -%s' % (lhs, rhs, lhs, rhs), params

AbsoluteValue.register_lookup(AbsoluteValueLessThan)

There are a couple of notable things going on. First, AbsoluteValueLessThan isn’t calling process_lhs(). Instead it skips the transformation of the lhs done by AbsoluteValue and uses the original lhs. That is, we want to get "experiments"."change" not ABS("experiments"."change"). Referring directly to self.lhs.lhs is safe as AbsoluteValueLessThan can be accessed only from the AbsoluteValue lookup, that is the lhs is always an instance of AbsoluteValue.

Notice also that as both sides are used multiple times in the query the params need to contain lhs_params and rhs_params multiple times.

The final query does the inversion (27 to -27) directly in the database. The reason for doing this is that if the self.rhs is something else than a plain integer value (for example an F() reference) we can’t do the transformations in Python.

Note

In fact, most lookups with __abs could be implemented as range queries like this, and on most database backends it is likely to be more sensible to do so as you can make use of the indexes. However with PostgreSQL you may want to add an index on abs(change) which would allow these queries to be very efficient.

A bilateral transformer example

The AbsoluteValue example we discussed previously is a transformation which applies to the left-hand side of the lookup. There may be some cases where you want the transformation to be applied to both the left-hand side and the right-hand side. For instance, if you want to filter a queryset based on the equality of the left and right-hand side insensitively to some SQL function.

Let’s examine the simple example of case-insensitive transformation here. This transformation isn’t very useful in practice as Django already comes with a bunch of built-in case-insensitive lookups, but it will be a nice demonstration of bilateral transformations in a database-agnostic way.

We define an UpperCase transformer which uses the SQL function UPPER() to transform the values before comparison. We define bilateral = True to indicate that this transformation should apply to both lhs and rhs:

from django.db.models import Transform

class UpperCase(Transform):
lookup_name = 'upper'
function = 'UPPER'
bilateral = True

Next, let’s register it:

from django.db.models import CharField, TextField
CharField.register_lookup(UpperCase)
TextField.register_lookup(UpperCase)

Now, the queryset Author.objects.filter(name__upper="doe") will generate a case insensitive query like this:

SELECT ... WHERE UPPER("author"."name") = UPPER('doe')

Writing alternative implementations for existing lookups

Sometimes different database vendors require different SQL for the same operation. For this example we will rewrite a custom implementation for MySQL for the NotEqual operator. Instead of <> we will be using != operator. (Note that in reality almost all databases support both, including all the official databases supported by Django).

We can change the behavior on a specific backend by creating a subclass of NotEqual with a as_mysql method:

class MySQLNotEqual(NotEqual):
def as_mysql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return '%s != %s' % (lhs, rhs), params

Field.register_lookup(MySQLNotEqual)

We can then register it with Field. It takes the place of the original NotEqual class as it has the same lookup_name.

When compiling a query, Django first looks for as_%s % connection.vendor methods, and then falls back to as_sql. The vendor names for the in-built backends are sqlite, postgresql, oracle and mysql.

How Django determines the lookups and transforms which are used

In some cases you may wish to dynamically change which Transform or Lookup is returned based on the name passed in, rather than fixing it. As an example, you could have a field which stores coordinates or an arbitrary dimension, and wish to allow a syntax like .filter(coords__x7=4) to return the objects where the 7th coordinate has value 4. In order to do this, you would override get_lookup with something like:

class CoordinatesField(Field):
def get_lookup(self, lookup_name):
if lookup_name.startswith('x'):
try:
dimension = int(lookup_name[1:])
except ValueError:
pass
else:
return get_coordinate_lookup(dimension)
return super(CoordinatesField, self).get_lookup(lookup_name)

You would then define get_coordinate_lookup appropriately to return a Lookup subclass which handles the relevant value of dimension.

There is a similarly named method called get_transform(). get_lookup() should always return a Lookup subclass, and get_transform() a Transform subclass. It is important to remember that Transform objects can be further filtered on, and Lookup objects cannot.

When filtering, if there is only one lookup name remaining to be resolved, we will look for a Lookup. If there are multiple names, it will look for a Transform. In the situation where there is only one name and a Lookup is not found, we look for a Transform and then the exact lookup on that Transform. All call sequences always end with a Lookup. To clarify:

- .filter(myfield__mylookup) will call myfield.get_lookup('mylookup').

- .filter(myfield__mytransform__mylookup) will call myfield.get_transform('mytransform'), and then mytransform.get_lookup('mylookup').

- .filter(myfield__mytransform) will first call myfield.get_lookup('mytransform'), which will fail, so it will fall back to calling myfield.get_transform('mytransform') and then mytransform.get_lookup('exact').

Custom template tags and filters

Django’s template language comes with a wide variety of built-in tags and filters designed to address the presentation logic needs of your application. Nevertheless, you may find yourself needing functionality that is not covered by the core set of template primitives. You can extend the template engine by defining custom tags and filters using Python, and then make them available to your templates using the {% load %} tag.

Code layout

The most common place to specify custom template tags and filters is inside a Django app. If they relate to an existing app, it makes sense to bundle them there; otherwise, they can be added to a new app. When a Django app is added to INSTALLED_APPS, any tags it defines in the conventional location described below are automatically made available to load within templates.

The app should contain a templatetags directory, at the same level as models.py, views.py, etc. If this doesn’t already exist, create it - don’t forget the __init__.py file to ensure the directory is treated as a Python package.

Development server won’t automatically restart

After adding the templatetags module, you will need to restart your server before you can use the tags or filters in templates.

Your custom tags and filters will live in a module inside the templatetags directory. The name of the module file is the name you’ll use to load the tags later, so be careful to pick a name that won’t clash with custom tags and filters in another app.

For example, if your custom tags/filters are in a file called poll_extras.py, your app layout might look like this:

polls/
__init__.py
models.py
templatetags/
__init__.py
poll_extras.py
views.py

And in your template you would use the following:

{% load poll_extras %}

The app that contains the custom tags must be in INSTALLED_APPS in order for the {% load %} tag to work. This is a security feature: It allows you to host Python code for many template libraries on a single host machine without enabling access to all of them for every Django installation.

There’s no limit on how many modules you put in the templatetags package. Just keep in mind that a {% load %} statement will load tags/filters for the given Python module name, not the name of the app.

To be a valid tag library, the module must contain a module-level variable named register that is a template.Library instance, in which all the tags and filters are registered. So, near the top of your module, put the following:

from django import template

register = template.Library()

New in Django 1.9.

Alternatively, template tag modules can be registered through the 'libraries' argument to DjangoTemplates. This is useful if you want to use a different label from the template tag module name when loading template tags. It also enables you to register tags without installing an application.

Behind the scenes

For a ton of examples, read the source code for Django’s default filters and tags. They’re in django/template/defaultfilters.py and django/template/defaulttags.py, respectively.

For more information on the load tag, read its documentation.

Writing custom template filters

Custom filters are just Python functions that take one or two arguments:

- The value of the variable (input) – not necessarily a string.

- The value of the argument – this can have a default value, or be left out altogether.

For example, in the filter {{ var|foo:"bar" }}, the filter foo would be passed the variable var and the argument "bar".

Since the template language doesn’t provide exception handling, any exception raised from a template filter will be exposed as a server error. Thus, filter functions should avoid raising exceptions if there is a reasonable fallback value to return. In case of input that represents a clear bug in a template, raising an exception may still be better than silent failure which hides the bug.

Here’s an example filter definition:

def cut(value, arg):
"""Removes all values of arg from the given string"""
return value.replace(arg, '')

And here’s an example of how that filter would be used:

{{ somevariable|cut:"0" }}

Most filters don’t take arguments. In this case, just leave the argument out of your function. Example:

def lower(value): # Only one argument.
"""Converts a string into all lowercase"""
return value.lower()

Registering custom filters

django.template.Library.filter()

Once you’ve written your filter definition, you need to register it with your Library instance, to make it available to Django’s template language:

register.filter('cut', cut)
register.filter('lower', lower)

The Library.filter() method takes two arguments:

1. The name of the filter – a string.

2. The compilation function – a Python function (not the name of the function as a string).

You can use register.filter() as a decorator instead:

@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')

@register.filter
def lower(value):
return value.lower()

If you leave off the name argument, as in the second example above, Django will use the function’s name as the filter name.

Finally, register.filter() also accepts three keyword arguments, is_safe, needs_autoescape, and expects_localtime. These arguments are described in filters and auto-escaping and filters and time zones below.

Template filters that expect strings

django.template.defaultfilters.stringfilter()

If you’re writing a template filter that only expects a string as the first argument, you should use the decorator stringfilter. This will convert an object to its string value before being passed to your function:

from django import template
from django.template.defaultfilters import stringfilter

register = template.Library()

@register.filter
@stringfilter
def lower(value):
return value.lower()

This way, you’ll be able to pass, say, an integer to this filter, and it won’t cause an AttributeError (because integers don’t have lower() methods).

Filters and auto-escaping

When writing a custom filter, give some thought to how the filter will interact with Django’s auto-escaping behavior. Note that three types of strings can be passed around inside the template code:

- Raw strings are the native Python str or unicode types. On output, they’re escaped if auto-escaping is in effect and presented unchanged, otherwise.

- Safe strings are strings that have been marked safe from further escaping at output time. Any necessary escaping has already been done. They’re commonly used for output that contains raw HTML that is intended to be interpreted as-is on the client side.

Internally, these strings are of type SafeBytes or SafeText. They share a common base class of SafeData, so you can test for them using code like:

if isinstance(value, SafeData):
# Do something with the "safe" string.
...

- Strings marked as “needing escaping” are always escaped on output, regardless of whether they are in an autoescape block or not. These strings are only escaped once, however, even if auto-escaping applies.

Internally, these strings are of type EscapeBytes or EscapeText. Generally you don’t have to worry about these; they exist for the implementation of the escape filter.

Template filter code falls into one of two situations:

1. Your filter does not introduce any HTML-unsafe characters (<, >, ', " or &) into the result that were not already present. In this case, you can let Django take care of all the auto-escaping handling for you. All you need to do is set the is_safe flag to True when you register your filter function, like so:

@register.filter(is_safe=True)
def myfilter(value):
return value

This flag tells Django that if a “safe” string is passed into your filter, the result will still be “safe” and if a non-safe string is passed in, Django will automatically escape it, if necessary.

You can think of this as meaning “this filter is safe – it doesn’t introduce any possibility of unsafe HTML.”

The reason is_safe is necessary is because there are plenty of normal string operations that will turn a SafeData object back into a normal str or unicode object and, rather than try to catch them all, which would be very difficult, Django repairs the damage after the filter has completed.

For example, suppose you have a filter that adds the string xx to the end of any input. Since this introduces no dangerous HTML characters to the result (aside from any that were already present), you should mark your filter with is_safe:

@register.filter(is_safe=True)
def add_xx(value):
return '%sxx' % value

When this filter is used in a template where auto-escaping is enabled, Django will escape the output whenever the input is not already marked as “safe”.

By default, is_safe is False, and you can omit it from any filters where it isn’t required.

Be careful when deciding if your filter really does leave safe strings as safe. If you’re removing characters, you might inadvertently leave unbalanced HTML tags or entities in the result. For example, removing a > from the input might turn <a> into <a, which would need to be escaped on output to avoid causing problems. Similarly, removing a semicolon (;) can turn &amp; into &amp, which is no longer a valid entity and thus needs further escaping. Most cases won’t be nearly this tricky, but keep an eye out for any problems like that when reviewing your code.

Marking a filter is_safe will coerce the filter’s return value to a string. If your filter should return a boolean or other non-string value, marking it is_safe will probably have unintended consequences (such as converting a boolean False to the string ‘False’).

2. Alternatively, your filter code can manually take care of any necessary escaping. This is necessary when you’re introducing new HTML markup into the result. You want to mark the output as safe from further escaping so that your HTML markup isn’t escaped further, so you’ll need to handle the input yourself.

To mark the output as a safe string, use django.utils.safestring.mark_safe().

Be careful, though. You need to do more than just mark the output as safe. You need to ensure it really is safe, and what you do depends on whether auto-escaping is in effect. The idea is to write filters that can operate in templates where auto-escaping is either on or off in order to make things easier for your template authors.

In order for your filter to know the current auto-escaping state, set the needs_autoescape flag to True when you register your filter function. (If you don’t specify this flag, it defaults to False). This flag tells Django that your filter function wants to be passed an extra keyword argument, called autoescape, that is True if auto-escaping is in effect and False otherwise. It is recommended to set the default of the autoescape parameter to True, so that if you call the function from Python code it will have escaping enabled by default.

For example, let’s write a filter that emphasizes the first character of a string:

from django import template
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe

register = template.Library()

@register.filter(needs_autoescape=True)
def initial_letter_filter(text, autoescape=True):
first, other = text[0], text[1:]
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
result = '<strong>%s</strong>%s' % (esc(first), esc(other))
return mark_safe(result)

The needs_autoescape flag and the autoescape keyword argument mean that our function will know whether automatic escaping is in effect when the filter is called. We use autoescape to decide whether the input data needs to be passed through django.utils.html.conditional_escape or not. (In the latter case, we just use the identity function as the “escape” function.) The conditional_escape() function is like escape() except it only escapes input that is not a SafeData instance. If a SafeData instance is passed to conditional_escape(), the data is returned unchanged.

Finally, in the above example, we remember to mark the result as safe so that our HTML is inserted directly into the template without further escaping.

There’s no need to worry about the is_safe flag in this case (although including it wouldn’t hurt anything). Whenever you manually handle the auto-escaping issues and return a safe string, the is_safe flag won’t change anything either way.

Warning

Avoiding XSS vulnerabilities when reusing built-in filters

Changed in Django 1.8.

Django’s built-in filters have autoescape=True by default in order to get the proper autoescaping behavior and avoid a cross-site script vulnerability.

In older versions of Django, be careful when reusing Django’s built-in filters as autoescape defaults to None. You’ll need to pass autoescape=True to get autoescaping.

For example, if you wanted to write a custom filter called urlize_and_linebreaks that combined the urlize and linebreaksbr filters, the filter would look like:

from django.template.defaultfilters import linebreaksbr, urlize

@register.filter(needs_autoescape=True)
def urlize_and_linebreaks(text, autoescape=True):
return linebreaksbr(
urlize(text, autoescape=autoescape),
autoescape=autoescape
)

Then:

{{ comment|urlize_and_linebreaks }}

would be equivalent to:

{{ comment|urlize|linebreaksbr }}

Filters and time zones

If you write a custom filter that operates on datetime objects, you’ll usually register it with the expects_localtime flag set to True:

@register.filter(expects_localtime=True)
def businesshours(value):
try:
return 9 <= value.hour < 17
except AttributeError:
return ''

When this flag is set, if the first argument to your filter is a time zone aware datetime, Django will convert it to the current time zone before passing it to your filter when appropriate, according to rules for time zones conversions in templates.

Writing custom template tags

Tags are more complex than filters, because tags can do anything. Django provides a number of shortcuts that make writing most types of tags easier. First we’ll explore those shortcuts, then explain how to write a tag from scratch for those cases when the shortcuts aren’t powerful enough.

Simple tags

django.template.Library.simple_tag()

Many template tags take a number of arguments – strings or template variables – and return a result after doing some processing based solely on the input arguments and some external information. For example, a current_time tag might accept a format string and return the time as a string formatted accordingly.

To ease the creation of these types of tags, Django provides a helper function, simple_tag. This function, which is a method of django.template.Library, takes a function that accepts any number of arguments, wraps it in a render function and the other necessary bits mentioned above and registers it with the template system.

Our current_time function could thus be written like this:

import datetime
from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)

A few things to note about the simple_tag helper function:

- Checking for the required number of arguments, etc., has already been done by the time our function is called, so we don’t need to do that.

- The quotes around the argument (if any) have already been stripped away, so we just receive a plain string.

- If the argument was a template variable, our function is passed the current value of the variable, not the variable itself.

Unlike other tag utilities, simple_tag passes its output through conditional_escape() if the template context is in autoescape mode, to ensure correct HTML and protect you from XSS vulnerabilities.

If additional escaping is not desired, you will need to use mark_safe() if you are absolutely sure that your code does not contain XSS vulnerabilities. For building small HTML snippets, use of format_html() instead of mark_safe() is strongly recommended.

Changed in Django 1.9:
Auto-escaping for simple_tag as described in the previous two paragraphs was added.

If your template tag needs to access the current context, you can use the takes_context argument when registering your tag:

@register.simple_tag(takes_context=True)
def current_time(context, format_string):
timezone = context['timezone']
return your_get_current_time_method(timezone, format_string)

Note that the first argument must be called context.

For more information on how the takes_context option works, see the section on inclusion tags.

If you need to rename your tag, you can provide a custom name for it:

register.simple_tag(lambda x: x - 1, name='minusone')

@register.simple_tag(name='minustwo')
def some_function(value):
return value - 2

simple_tag functions may accept any number of positional or keyword arguments. For example:

@register.simple_tag
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
...
return ...

Then in the template any number of arguments, separated by spaces, may be passed to the template tag. Like in Python, the values for keyword arguments are set using the equal sign (“=”) and must be provided after the positional arguments. For example:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

New in Django 1.9.

It’s possible to store the tag results in a template variable rather than directly outputting it. This is done by using the as argument followed by the variable name. Doing so enables you to output the content yourself where you see fit:

{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
<p>The time is {{ the_time }}.</p>

Inclusion tags

django.template.Library.inclusion_tag()

Another common type of template tag is the type that displays some data by rendering another template. For example, Django’s admin interface uses custom template tags to display the buttons along the bottom of the “add/change” form pages. Those buttons always look the same, but the link targets change depending on the object being edited – so they’re a perfect case for using a small template that is filled with details from the current object. (In the admin’s case, this is the submit_row tag.)

These sorts of tags are called “inclusion tags”.

Writing inclusion tags is probably best demonstrated by example. Let’s write a tag that outputs a list of choices for a given Poll object, such as was created in the tutorials. We’ll use the tag like this:

{% show_results poll %}

...and the output will be something like this:

<ul>
<li>First choice</li>
<li>Second choice</li>
<li>Third choice</li>
</ul>

First, define the function that takes the argument and produces a dictionary of data for the result. The important point here is we only need to return a dictionary, not anything more complex. This will be used as a template context for the template fragment. Example:

def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}

Next, create the template used to render the tag’s output. This template is a fixed feature of the tag: the tag writer specifies it, not the template designer. Following our example, the template is very simple:

<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>

Now, create and register the inclusion tag by calling the inclusion_tag() method on a Library object. Following our example, if the above template is in a file called results.html in a directory that’s searched by the template loader, we’d register the tag like this:

# Here, register is a django.template.Library instance, as before
@register.inclusion_tag('results.html')
def show_results(poll):
...

Alternatively it is possible to register the inclusion tag using a django.template.Template instance:

from django.template.loader import get_template
t = get_template('results.html')
register.inclusion_tag(t)(show_results)

...when first creating the function.

Sometimes, your inclusion tags might require a large number of arguments, making it a pain for template authors to pass in all the arguments and remember their order. To solve this, Django provides a takes_context option for inclusion tags. If you specify takes_context in creating a template tag, the tag will have no required arguments, and the underlying Python function will have one argument – the template context as of when the tag was called.

For example, say you’re writing an inclusion tag that will always be used in a context that contains home_link and home_title variables that point back to the main page. Here’s what the Python function would look like:

@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}

Note that the first parameter to the function must be called context.

In that register.inclusion_tag() line, we specified takes_context=True and the name of the template. Here’s what the template link.html might look like:

Jump directly to <a href="{{ link }}">{{ title }}</a>.

Then, any time you want to use that custom tag, load its library and call it without any arguments, like so:

{% jump_link %}

Note that when you’re using takes_context=True, there’s no need to pass arguments to the template tag. It automatically gets access to the context.

The takes_context parameter defaults to False. When it’s set to True, the tag is passed the context object, as in this example. That’s the only difference between this case and the previous inclusion_tag example.

inclusion_tag functions may accept any number of positional or keyword arguments. For example:

@register.inclusion_tag('my_template.html')
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
...
return ...

Then in the template any number of arguments, separated by spaces, may be passed to the template tag. Like in Python, the values for keyword arguments are set using the equal sign (“=”) and must be provided after the positional arguments. For example:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

Assignment tags

django.template.Library.assignment_tag()

Deprecated since version 1.9: simple_tag can now store results in a template variable and should be used instead.

To ease the creation of tags setting a variable in the context, Django provides a helper function, assignment_tag. This function works the same way as simple_tag() except that it stores the tag’s result in a specified context variable instead of directly outputting it.

Our earlier current_time function could thus be written like this:

@register.assignment_tag
def get_current_time(format_string):
return datetime.datetime.now().strftime(format_string)

You may then store the result in a template variable using the as argument followed by the variable name, and output it yourself where you see fit:

{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
<p>The time is {{ the_time }}.</p>

Advanced custom template tags

Sometimes the basic features for custom template tag creation aren’t enough. Don’t worry, Django gives you complete access to the internals required to build a template tag from the ground up.

A quick overview

The template system works in a two-step process: compiling and rendering. To define a custom template tag, you specify how the compilation works and how the rendering works.

When Django compiles a template, it splits the raw template text into ‘’nodes’‘. Each node is an instance of django.template.Node and has a render() method. A compiled template is, simply, a list of Node objects. When you call render() on a compiled template object, the template calls render() on each Node in its node list, with the given context. The results are all concatenated together to form the output of the template.

Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function), and what the node’s render() method does.

Writing the compilation function

For each template tag the template parser encounters, it calls a Python function with the tag contents and the parser object itself. This function is responsible for returning a Node instance based on the contents of the tag.

For example, let’s write a full implementation of our simple template tag, {% current_time %}, that displays the current date/time, formatted according to a parameter given in the tag, in strftime() syntax. It’s a good idea to decide the tag syntax before anything else. In our case, let’s say the tag should be used like this:

<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>

The parser for this function should grab the parameter and create a Node object:

from django import template

def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError(
"%r tag requires a single argument" % token.contents.split()[0]
)
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError(
"%r tag's argument should be in quotes" % tag_name
)
return CurrentTimeNode(format_string[1:-1])

Notes:

- parser is the template parser object. We don’t need it in this example.

- token.contents is a string of the raw contents of the tag. In our example, it’s 'current_time "%Y-%m-%d %I:%M %p"'.

- The token.split_contents() method separates the arguments on spaces while keeping quoted strings together. The more straightforward token.contents.split() wouldn’t be as robust, as it would naively split on all spaces, including those within quoted strings. It’s a good idea to always use token.split_contents().

- This function is responsible for raising django.template.TemplateSyntaxError, with helpful messages, for any syntax error.

- The TemplateSyntaxError exceptions use the tag_name variable. Don’t hard-code the tag’s name in your error messages, because that couples the tag’s name to your function. token.contents.split()[0] will ‘’always’’ be the name of your tag – even when the tag has no arguments.

- The function returns a CurrentTimeNode with everything the node needs to know about this tag. In this case, it just passes the argument – "%Y-%m-%d %I:%M %p". The leading and trailing quotes from the template tag are removed in format_string[1:-1].

- The parsing is very low-level. The Django developers have experimented with writing small frameworks on top of this parsing system, using techniques such as EBNF grammars, but those experiments made the template engine too slow. It’s low-level because that’s fastest.

Writing the renderer

The second step in writing custom tags is to define a Node subclass that has a render() method.

Continuing the above example, we need to define CurrentTimeNode:

import datetime
from django import template

class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string

def render(self, context):
return datetime.datetime.now().strftime(self.format_string)

Notes:

- __init__() gets the format_string from do_current_time(). Always pass any options/parameters/arguments to a Node via its __init__().

- The render() method is where the work actually happens.

- render() should generally fail silently, particularly in a production environment. In some cases however, particularly if context.template.engine.debug is True, this method may raise an exception to make debugging easier. For example, several core tags raise django.template.TemplateSyntaxError if they receive the wrong number or type of arguments.

Ultimately, this decoupling of compilation and rendering results in an efficient template system, because a template can render multiple contexts without having to be parsed multiple times.

Auto-escaping considerations

The output from template tags is not automatically run through the auto-escaping filters (with the exception of simple_tag() as described above). However, there are still a couple of things you should keep in mind when writing a template tag.

If the render() function of your template stores the result in a context variable (rather than returning the result in a string), it should take care to call mark_safe() if appropriate. When the variable is ultimately rendered, it will be affected by the auto-escape setting in effect at the time, so content that should be safe from further escaping needs to be marked as such.

Also, if your template tag creates a new context for performing some sub-rendering, set the auto-escape attribute to the current context’s value. The __init__ method for the Context class takes a parameter called autoescape that you can use for this purpose. For example:

from django.template import Context

def render(self, context):
# ...
new_context = Context({'var': obj}, autoescape=context.autoescape)
# ... Do something with new_context ...

This is not a very common situation, but it’s useful if you’re rendering a template yourself. For example:

def render(self, context):
t = context.template.engine.get_template('small_fragment.html')
return t.render(Context({'var': obj}, autoescape=context.autoescape))

Changed in Django 1.8:
The template attribute of Context objects was added in Django 1.8. context.template.engine.get_template must be used instead of django.template.loader.get_template() because the latter now returns a wrapper whose render method doesn’t accept a Context.

If we had neglected to pass in the current context.autoescape value to our new Context in this example, the results would have always been automatically escaped, which may not be the desired behavior if the template tag is used inside a {% autoescape off %} block.

Thread-safety considerations

Once a node is parsed, its render method may be called any number of times. Since Django is sometimes run in multi-threaded environments, a single node may be simultaneously rendering with different contexts in response to two separate requests. Therefore, it’s important to make sure your template tags are thread safe.

To make sure your template tags are thread safe, you should never store state information on the node itself. For example, Django provides a builtin cycle template tag that cycles among a list of given strings each time it’s rendered:

{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}

A naive implementation of CycleNode might look something like this:

import itertools
from django import template

class CycleNode(template.Node):
def __init__(self, cyclevars):
self.cycle_iter = itertools.cycle(cyclevars)

def render(self, context):
return next(self.cycle_iter)

But, suppose we have two templates rendering the template snippet from above at the same time:

1. Thread 1 performs its first loop iteration, CycleNode.render() returns ‘row1’

2. Thread 2 performs its first loop iteration, CycleNode.render() returns ‘row2’

3. Thread 1 performs its second loop iteration, CycleNode.render() returns ‘row1’

4. Thread 2 performs its second loop iteration, CycleNode.render() returns ‘row2’

The CycleNode is iterating, but it’s iterating globally. As far as Thread 1 and Thread 2 are concerned, it’s always returning the same value. This is obviously not what we want!

To address this problem, Django provides a render_context that’s associated with the context of the template that is currently being rendered. The render_context behaves like a Python dictionary, and should be used to store Node state between invocations of the render method.

Let’s refactor our CycleNode implementation to use the render_context:

class CycleNode(template.Node):
def __init__(self, cyclevars):
self.cyclevars = cyclevars

def render(self, context):
if self not in context.render_context:
context.render_context[self] = itertools.cycle(self.cyclevars)
cycle_iter = context.render_context[self]
return next(cycle_iter)

Note that it’s perfectly safe to store global information that will not change throughout the life of the Node as an attribute. In the case of CycleNode, the cyclevars argument doesn’t change after the Node is instantiated, so we don’t need to put it in the render_context. But state information that is specific to the template that is currently being rendered, like the current iteration of the CycleNode, should be stored in the render_context.

Note

Notice how we used self to scope the CycleNode specific information within the render_context. There may be multiple CycleNodes in a given template, so we need to be careful not to clobber another node’s state information. The easiest way to do this is to always use self as the key into render_context. If you’re keeping track of several state variables, make render_context[self] a dictionary.

Registering the tag

Finally, register the tag with your module’s Library instance, as explained in writing custom template filters above. Example:

register.tag('current_time', do_current_time)

The tag() method takes two arguments:

1. The name of the template tag – a string. If this is left out, the name of the compilation function will be used.

2. The compilation function – a Python function (not the name of the function as a string).

As with filter registration, it is also possible to use this as a decorator:

@register.tag(name="current_time")
def do_current_time(parser, token):
...

@register.tag
def shout(parser, token):
...

If you leave off the name argument, as in the second example above, Django will use the function’s name as the tag name.

Passing template variables to the tag

Although you can pass any number of arguments to a template tag using token.split_contents(), the arguments are all unpacked as string literals. A little more work is required in order to pass dynamic content (a template variable) to a template tag as an argument.

While the previous examples have formatted the current time into a string and returned the string, suppose you wanted to pass in a DateTimeField from an object and have the template tag format that date-time:

<p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p>

Initially, token.split_contents() will return three values:

1. The tag name format_time.

2. The string 'blog_entry.date_updated' (without the surrounding quotes).

3. The formatting string '"%Y-%m-%d %I:%M %p"'. The return value from split_contents() will include the leading and trailing quotes for string literals like this.

Now your tag should begin to look like this:

from django import template

def do_format_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, date_to_be_formatted, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError(
"%r tag requires exactly two arguments" % token.contents.split()[0]
)
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError(
"%r tag's argument should be in quotes" % tag_name
)
return FormatTimeNode(date_to_be_formatted, format_string[1:-1])

You also have to change the renderer to retrieve the actual contents of the date_updated property of the blog_entry object. This can be accomplished by using the Variable() class in django.template.

To use the Variable class, simply instantiate it with the name of the variable to be resolved, and then call variable.resolve(context). So, for example:

class FormatTimeNode(template.Node):
def __init__(self, date_to_be_formatted, format_string):
self.date_to_be_formatted = template.Variable(date_to_be_formatted)
self.format_string = format_string

def render(self, context):
try:
actual_date = self.date_to_be_formatted.resolve(context)
return actual_date.strftime(self.format_string)
except template.VariableDoesNotExist:
return ''

Variable resolution will throw a VariableDoesNotExist exception if it cannot resolve the string passed to it in the current context of the page.

Setting a variable in the context

The above examples simply output a value. Generally, it’s more flexible if your template tags set template variables instead of outputting values. That way, template authors can reuse the values that your template tags create.

To set a variable in the context, just use dictionary assignment on the context object in the render() method. Here’s an updated version of CurrentTimeNode that sets a template variable current_time instead of outputting it:

import datetime
from django import template

class CurrentTimeNode2(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
context['current_time'] = datetime.datetime.now().strftime(self.format_string)
return ''

Note that render() returns the empty string. render() should always return string output. If all the template tag does is set a variable, render() should return the empty string.

Here’s how you’d use this new version of the tag:

{% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p>

Variable scope in context

Any variable set in the context will only be available in the same block of the template in which it was assigned. This behavior is intentional; it provides a scope for variables so that they don’t conflict with context in other blocks.

But, there’s a problem with CurrentTimeNode2: The variable name current_time is hard-coded. This means you’ll need to make sure your template doesn’t use {{ current_time }} anywhere else, because the {% current_time %} will blindly overwrite that variable’s value. A cleaner solution is to make the template tag specify the name of the output variable, like so:

{% current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p>

To do that, you’ll need to refactor both the compilation function and Node class, like so:

import re

class CurrentTimeNode3(template.Node):
def __init__(self, format_string, var_name):
self.format_string = format_string
self.var_name = var_name
def render(self, context):
context[self.var_name] = datetime.datetime.now().strftime(self.format_string)
return ''

def do_current_time(parser, token):
# This version uses a regular expression to parse tag contents.
try:
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError(
"%r tag requires arguments" % token.contents.split()[0]
)
m = re.search(r'(.*?) as (\w+)', arg)
if not m:
raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name)
format_string, var_name = m.groups()
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError(
"%r tag's argument should be in quotes" % tag_name
)
return CurrentTimeNode3(format_string[1:-1], var_name)

The difference here is that do_current_time() grabs the format string and the variable name, passing both to CurrentTimeNode3.

Finally, if you only need to have a simple syntax for your custom context-updating template tag, consider using the simple_tag() shortcut, which supports assigning the tag results to a template variable.

Parsing until another block tag

Template tags can work in tandem. For instance, the standard {% comment %} tag hides everything until {% endcomment %}. To create a template tag such as this, use parser.parse() in your compilation function.

Here’s how a simplified {% comment %} tag might be implemented:

def do_comment(parser, token):
nodelist = parser.parse(('endcomment',))
parser.delete_first_token()
return CommentNode()

class CommentNode(template.Node):
def render(self, context):
return ''

Note

The actual implementation of {% comment %} is slightly different in that it allows broken template tags to appear between {% comment %} and {% endcomment %}. It does so by calling parser.skip_past('endcomment') instead of parser.parse(('endcomment',)) followed by parser.delete_first_token(), thus avoiding the generation of a node list.

parser.parse() takes a tuple of names of block tags ‘’to parse until’‘. It returns an instance of django.template.NodeList, which is a list of all Node objects that the parser encountered ‘’before’’ it encountered any of the tags named in the tuple.

In "nodelist = parser.parse(('endcomment',))" in the above example, nodelist is a list of all nodes between the {% comment %} and {% endcomment %}, not counting {% comment %} and {% endcomment %} themselves.

After parser.parse() is called, the parser hasn’t yet “consumed” the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token().

CommentNode.render() simply returns an empty string. Anything between {% comment %} and {% endcomment %} is ignored.

Parsing until another block tag, and saving contents

In the previous example, do_comment() discarded everything between {% comment %} and {% endcomment %}. Instead of doing that, it’s possible to do something with the code between block tags.

For example, here’s a custom template tag, {% upper %}, that capitalizes everything between itself and {% endupper %}.

Usage:

{% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %}

As in the previous example, we’ll use parser.parse(). But this time, we pass the resulting nodelist to the Node:

def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)

class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()

The only new concept here is the self.nodelist.render(context) in UpperNode.render().

For more examples of complex rendering, see the source code of {% for %} in django/template/defaulttags.py and {% if %} in django/template/smartif.py.

Writing a custom storage system

If you need to provide custom file storage – a common example is storing files on some remote system – you can do so by defining a custom storage class. You’ll need to follow these steps:

1. Your custom storage system must be a subclass of django.core.files.storage.Storage:

from django.core.files.storage import Storage

class MyStorage(Storage):
...

2. Django must be able to instantiate your storage system without any arguments. This means that any settings should be taken from django.conf.settings:

from django.conf import settings
from django.core.files.storage import Storage

class MyStorage(Storage):
def __init__(self, option=None):
if not option:
option = settings.CUSTOM_STORAGE_OPTIONS
...

3. Your storage class must implement the _open() and _save() methods, along with any other methods appropriate to your storage class. See below for more on these methods.

In addition, if your class provides local file storage, it must override the path() method.

4. Your storage class must be deconstructible so it can be serialized when it’s used on a field in a migration. As long as your field has arguments that are themselves serializable, you can use the django.utils.deconstruct.deconstructible class decorator for this (that’s what Django uses on FileSystemStorage).

By default, the following methods raise NotImplementedError and will typically have to be overridden:

- Storage.delete()

- Storage.exists()

- Storage.listdir()

- Storage.size()

- Storage.url()

Note however that not all these methods are required and may be deliberately omitted. As it happens, it is possible to leave each method unimplemented and still have a working Storage.

By way of example, if listing the contents of certain storage backends turns out to be expensive, you might decide not to implement Storage.listdir.

Another example would be a backend that only handles writing to files. In this case, you would not need to implement any of the above methods.

Ultimately, which of these methods are implemented is up to you. Leaving some methods unimplemented will result in a partial (possibly broken) interface.

You’ll also usually want to use hooks specifically designed for custom storage objects. These are:

_open(name, mode='rb')

Required.

Called by Storage.open(), this is the actual mechanism the storage class uses to open the file. This must return a File object, though in most cases, you’ll want to return some subclass here that implements logic specific to the backend storage system.

_save(name, content)

Called by Storage.save(). The name will already have gone through get_valid_name() and get_available_name(), and the content will be a File object itself.

Should return the actual name of name of the file saved (usually the name passed in, but if the storage needs to change the file name return the new name instead).

get_valid_name(name)

Returns a filename suitable for use with the underlying storage system. The name argument passed to this method is either the original filename sent to the server or, if upload_to is a callable, the filename returned by that method after any path information is removed. Override this to customize how non-standard characters are converted to safe filenames.

Changed in Django 1.9:
In older versions, this method was not called when upload_to was a callable.

The code provided on Storage retains only alpha-numeric characters, periods and underscores from the original filename, removing everything else.

get_available_name(name, max_length=None)

Returns a filename that is available in the storage mechanism, possibly taking the provided filename into account. The name argument passed to this method will have already cleaned to a filename valid for the storage system, according to the get_valid_name() method described above.

The length of the filename will not exceed max_length, if provided. If a free unique filename cannot be found, a SuspiciousFileOperation exception is raised.

If a file with name already exists, an underscore plus a random 7 character alphanumeric string is appended to the filename before the extension.

Changed in Django 1.8:
The max_length argument was added.

Deploying Django

Django’s chock-full of shortcuts to make Web developer’s lives easier, but all those tools are of no use if you can’t easily deploy your sites. Since Django’s inception, ease of deployment has been a major goal.

- How to deploy with WSGI

- Deployment checklist

If you’re new to deploying Django and/or Python, we’d recommend you try mod_wsgi first. In most cases it’ll be the easiest, fastest, and most stable deployment choice.

How to deploy with WSGI

Django’s primary deployment platform is WSGI, the Python standard for web servers and applications.

Django’s startproject management command sets up a simple default WSGI configuration for you, which you can tweak as needed for your project, and direct any WSGI-compliant application server to use.

Django includes getting-started documentation for the following WSGI servers:

- How to use Django with Apache and mod_wsgi

- Authenticating against Django’s user database from Apache

- How to use Django with Gunicorn

- How to use Django with uWSGI

The application object

The key concept of deploying with WSGI is the application callable which the application server uses to communicate with your code. It’s commonly provided as an object named application in a Python module accessible to the server.

The startproject command creates a file <project_name>/wsgi.py that contains such an application callable.

It’s used both by Django’s development server and in production WSGI deployments.

WSGI servers obtain the path to the application callable from their configuration. Django’s built-in server, namely the runserver command, reads it from the WSGI_APPLICATION setting. By default, it’s set to <project_name>.wsgi.application, which points to the application callable in <project_name>/wsgi.py.

Configuring the settings module

When the WSGI server loads your application, Django needs to import the settings module — that’s where your entire application is defined.

Django uses the DJANGO_SETTINGS_MODULE environment variable to locate the appropriate settings module. It must contain the dotted path to the settings module. You can use a different value for development and production; it all depends on how you organize your settings.

If this variable isn’t set, the default wsgi.py sets it to mysite.settings, where mysite is the name of your project. That’s how runserver discovers the default settings file by default.

Note

Since environment variables are process-wide, this doesn’t work when you run multiple Django sites in the same process. This happens with mod_wsgi.

To avoid this problem, use mod_wsgi’s daemon mode with each site in its own daemon process, or override the value from the environment by enforcing os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings" in your wsgi.py.

Applying WSGI middleware

To apply WSGI middleware you can simply wrap the application object. For instance you could add these lines at the bottom of wsgi.py:

from helloworld.wsgi import HelloWorldApplication
application = HelloWorldApplication(application)

You could also replace the Django WSGI application with a custom WSGI application that later delegates to the Django WSGI application, if you want to combine a Django application with a WSGI application of another framework.

Note

Some third-party WSGI middleware do not call close on the response object after handling a request. In those cases the request_finished signal isn’t sent. This can result in idle connections to database and memcache servers.

How to use Django with Apache and mod_wsgi

Deploying Django with Apache and mod_wsgi is a tried and tested way to get Django into production.

mod_wsgi is an Apache module which can host any Python WSGI application, including Django. Django will work with any version of Apache which supports mod_wsgi.

The official mod_wsgi documentation is fantastic; it’s your source for all the details about how to use mod_wsgi. You’ll probably want to start with the installation and configuration documentation.

Basic configuration

Once you’ve got mod_wsgi installed and activated, edit your Apache server’s httpd.conf file and add the following. If you are using a version of Apache older than 2.4, replace Require all granted with Allow from all and also add the line Order deny,allow above it.

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

The first bit in the WSGIScriptAlias line is the base URL path you want to serve your application at (/ indicates the root url), and the second is the location of a “WSGI file” – see below – on your system, usually inside of your project package (mysite in this example). This tells Apache to serve any request below the given URL using the WSGI application defined in that file.

The WSGIPythonPath line ensures that your project package is available for import on the Python path; in other words, that import mysite works.

The <Directory> piece just ensures that Apache can access your wsgi.py file.

Next we’ll need to ensure this wsgi.py with a WSGI application object exists. As of Django version 1.4, startproject will have created one for you; otherwise, you’ll need to create it. See the WSGI overview documentation for the default contents you should put in this file, and what else you can add to it.

Warning

If multiple Django sites are run in a single mod_wsgi process, all of them will use the settings of whichever one happens to run first. This can be solved by changing:

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")

in wsgi.py, to:

os.environ["DJANGO_SETTINGS_MODULE"] = "{{ project_name }}.settings"

or by using mod_wsgi daemon mode and ensuring that each site runs in its own daemon process.

Fixing UnicodeEncodeError for file uploads

If you get a UnicodeEncodeError when uploading files with file names that contain non-ASCII characters, make sure Apache is configured to accept non-ASCII file names:

export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'

A common location to put this configuration is /etc/apache2/envvars.

See the Files section of the Unicode reference guide for details.

Using a virtualenv

If you install your project’s Python dependencies inside a virtualenv, you’ll need to add the path to this virtualenv’s site-packages directory to your Python path as well. To do this, add an additional path to your WSGIPythonPath directive, with multiple paths separated by a colon (:) if using a UNIX-like system, or a semicolon (;) if using Windows. If any part of a directory path contains a space character, the complete argument string to WSGIPythonPath must be quoted:

WSGIPythonPath /path/to/mysite.com:/path/to/your/venv/lib/python3.X/site-packages

Make sure you give the correct path to your virtualenv, and replace python3.X with the correct Python version (e.g. python3.4).

Using mod_wsgi daemon mode

“Daemon mode” is the recommended mode for running mod_wsgi (on non-Windows platforms). To create the required daemon process group and delegate the Django instance to run in it, you will need to add appropriate WSGIDaemonProcess and WSGIProcessGroup directives. A further change required to the above configuration if you use daemon mode is that you can’t use WSGIPythonPath; instead you should use the python-path option to WSGIDaemonProcess, for example:

WSGIDaemonProcess example.com python-path=/path/to/mysite.com:/path/to/venv/lib/python2.7/site-packages
WSGIProcessGroup example.com

If you want to serve your project in a subdirectory (https://example.com/mysite in this example), you can add WSGIScriptAlias to the configuration above:

WSGIScriptAlias /mysite /path/to/mysite.com/mysite/wsgi.py process-group=example.com

See the official mod_wsgi documentation for details on setting up daemon mode.

Serving files

Django doesn’t serve files itself; it leaves that job to whichever Web server you choose.

We recommend using a separate Web server – i.e., one that’s not also running Django – for serving media. Here are some good choices:

- Nginx

- A stripped-down version of Apache

If, however, you have no option but to serve media files on the same Apache VirtualHost as Django, you can set up Apache to serve some URLs as static media, and others using the mod_wsgi interface to Django.

This example sets up Django at the site root, but serves robots.txt, favicon.ico, and anything in the /static/ and /media/ URL space as a static file. All other URLs will be served using mod_wsgi:

Alias /robots.txt /path/to/mysite.com/static/robots.txt
Alias /favicon.ico /path/to/mysite.com/static/favicon.ico

Alias /media/ /path/to/mysite.com/media/
Alias /static/ /path/to/mysite.com/static/

<Directory /path/to/mysite.com/static>
Require all granted
</Directory>

<Directory /path/to/mysite.com/media>
Require all granted
</Directory>

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

If you are using a version of Apache older than 2.4, replace Require all granted with Allow from all and also add the line Order deny,allow above it.

Serving the admin files

When django.contrib.staticfiles is in INSTALLED_APPS, the Django development server automatically serves the static files of the admin app (and any other installed apps). This is however not the case when you use any other server arrangement. You’re responsible for setting up Apache, or whichever Web server you’re using, to serve the admin files.

The admin files live in (django/contrib/admin/static/admin) of the Django distribution.

We strongly recommend using django.contrib.staticfiles to handle the admin files (along with a Web server as outlined in the previous section; this means using the collectstatic management command to collect the static files in STATIC_ROOT, and then configuring your Web server to serve STATIC_ROOT at STATIC_URL), but here are three other approaches:

1. Create a symbolic link to the admin static files from within your document root (this may require +FollowSymLinks in your Apache configuration).

2. Use an Alias directive, as demonstrated above, to alias the appropriate URL (probably STATIC_URL + admin/) to the actual location of the admin files.

3. Copy the admin static files so that they live within your Apache document root.

Authenticating against Django’s user database from Apache

Django provides a handler to allow Apache to authenticate users directly against Django’s authentication backends. See the mod_wsgi authentication documentation.

Authenticating against Django’s user database from Apache

Since keeping multiple authentication databases in sync is a common problem when dealing with Apache, you can configure Apache to authenticate against Django’s authentication system directly. This requires Apache version >= 2.2 and mod_wsgi >= 2.0. For example, you could:

- Serve static/media files directly from Apache only to authenticated users.

- Authenticate access to a Subversion repository against Django users with a certain permission.

- Allow certain users to connect to a WebDAV share created with mod_dav.

Note

If you have installed a custom User model and want to use this default auth handler, it must support an is_active attribute. If you want to use group based authorization, your custom user must have a relation named ‘groups’, referring to a related object that has a ‘name’ field. You can also specify your own custom mod_wsgi auth handler if your custom cannot conform to these requirements.

Authentication with mod_wsgi

Note

The use of WSGIApplicationGroup %{GLOBAL} in the configurations below presumes that your Apache instance is running only one Django application. If you are running more than one Django application, please refer to the Defining Application Groups section of the mod_wsgi docs for more information about this setting.

Make sure that mod_wsgi is installed and activated and that you have followed the steps to setup Apache with mod_wsgi.

Next, edit your Apache configuration to add a location that you want only authenticated users to be able to view:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup %{GLOBAL}

<Location "/secret">
AuthType Basic
AuthName "Top Secret"
Require valid-user
AuthBasicProvider wsgi
WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
</Location>

The WSGIAuthUserScript directive tells mod_wsgi to execute the check_password function in specified wsgi script, passing the user name and password that it receives from the prompt. In this example, the WSGIAuthUserScript is the same as the WSGIScriptAlias that defines your application that is created by django-admin startproject.

Using Apache 2.2 with authentication

Make sure that mod_auth_basic and mod_authz_user are loaded.

These might be compiled statically into Apache, or you might need to use LoadModule to load them dynamically in your httpd.conf:

LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authz_user_module modules/mod_authz_user.so

Finally, edit your WSGI script mysite.wsgi to tie Apache’s authentication to your site’s authentication mechanisms by importing the check_password function:

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

from django.contrib.auth.handlers.modwsgi import check_password

from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()

Requests beginning with /secret/ will now require a user to authenticate.

The mod_wsgi access control mechanisms documentation provides additional details and information about alternative methods of authentication.

Authorization with mod_wsgi and Django groups

mod_wsgi also provides functionality to restrict a particular location to members of a group.

In this case, the Apache configuration should look like this:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

WSGIProcessGroup %{GLOBAL}
WSGIApplicationGroup %{GLOBAL}

<Location "/secret">
AuthType Basic
AuthName "Top Secret"
AuthBasicProvider wsgi
WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
WSGIAuthGroupScript /path/to/mysite.com/mysite/wsgi.py
Require group secret-agents
Require valid-user
</Location>

To support the WSGIAuthGroupScript directive, the same WSGI script mysite.wsgi must also import the groups_for_user function which returns a list groups the given user belongs to.

from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user

Requests for /secret/ will now also require user to be a member of the “secret-agents” group.

How to use Django with Gunicorn

Gunicorn (‘Green Unicorn’) is a pure-Python WSGI server for UNIX. It has no dependencies and is easy to install and use.

Installing Gunicorn

Installing gunicorn is as easy as pip install gunicorn. For more details, see the gunicorn documentation.

Running Django in Gunicorn as a generic WSGI application

When Gunicorn is installed, a gunicorn command is available which starts the Gunicorn server process. At its simplest, gunicorn just needs to be called with the location of a module containing a WSGI application object named application. So for a typical Django project, invoking gunicorn would look like:

gunicorn myproject.wsgi

This will start one process running one thread listening on 127.0.0.1:8000. It requires that your project be on the Python path; the simplest way to ensure that is to run this command from the same directory as your manage.py file.

See Gunicorn’s deployment documentation for additional tips.

How to use Django with uWSGI

uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C.

See also

The uWSGI docs offer a tutorial covering Django, nginx, and uWSGI (one possible deployment setup of many). The docs below are focused on how to integrate Django with uWSGI.

Prerequisite: uWSGI

The uWSGI wiki describes several installation procedures. Using pip, the Python package manager, you can install any uWSGI version with a single command. For example:

# Install current stable version.
$ pip install uwsgi

# Or install LTS (long term support).
$ pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz

Warning

Some distributions, including Debian and Ubuntu, ship an outdated version of uWSGI that does not conform to the WSGI specification. Versions prior to 1.2.6 do not call close on the response object after handling a request. In those cases the request_finished signal isn’t sent. This can result in idle connections to database and memcache servers.

uWSGI model

uWSGI operates on a client-server model. Your Web server (e.g., nginx, Apache) communicates with a django-uwsgi “worker” process to serve dynamic content. See uWSGI’s background documentation for more detail.

Configuring and starting the uWSGI server for Django

uWSGI supports multiple ways to configure the process. See uWSGI’s configuration documentation and examples.

Here’s an example command to start a uWSGI server:

uwsgi --chdir=/path/to/your/project \
--module=mysite.wsgi:application \
--env DJANGO_SETTINGS_MODULE=mysite.settings \
--master --pidfile=/tmp/project-master.pid \
--socket=127.0.0.1:49152 \      # can also be a file
--processes=5 \                 # number of worker processes
--uid=1000 --gid=2000 \         # if root, uwsgi can drop privileges
--harakiri=20 \                 # respawn processes taking more than 20 seconds
--max-requests=5000 \           # respawn processes after serving 5000 requests
--vacuum \                      # clear environment on exit
--home=/path/to/virtual/env \   # optional path to a virtualenv
--daemonize=/var/log/uwsgi/yourproject.log      # background the process

This assumes you have a top-level project package named mysite, and within it a module mysite/wsgi.py that contains a WSGI application object. This is the layout you’ll have if you ran django-admin startproject mysite (using your own project name in place of mysite) with a recent version of Django. If this file doesn’t exist, you’ll need to create it. See the How to deploy with WSGI documentation for the default contents you should put in this file and what else you can add to it.

The Django-specific options here are:

- chdir: The path to the directory that needs to be on Python’s import path – i.e., the directory containing the mysite package.

- module: The WSGI module to use – probably the mysite.wsgi module that startproject creates.

- env: Should probably contain at least DJANGO_SETTINGS_MODULE.

- home: Optional path to your project virtualenv.

Example ini configuration file:

[uwsgi]
chdir=/path/to/your/project
module=mysite.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000
daemonize=/var/log/uwsgi/yourproject.log

Example ini configuration file usage:

uwsgi --ini uwsgi.ini

Fixing UnicodeEncodeError for file uploads

If you get a UnicodeEncodeError when uploading files with file names that contain non-ASCII characters, make sure uWSGI is configured to accept non-ASCII file names by adding this to your uwsgi.ini:

env = LANG=en_US.UTF-8

See the Files section of the Unicode reference guide for details.

See the uWSGI docs on managing the uWSGI process for information on starting, stopping and reloading the uWSGI workers.

Deployment checklist

The Internet is a hostile environment. Before deploying your Django project, you should take some time to review your settings, with security, performance, and operations in mind.

Django includes many security features. Some are built-in and always enabled. Others are optional because they aren’t always appropriate, or because they’re inconvenient for development. For example, forcing HTTPS may not be suitable for all websites, and it’s impractical for local development.

Performance optimizations are another category of trade-offs with convenience. For instance, caching is useful in production, less so for local development. Error reporting needs are also widely different.

The following checklist includes settings that:

- must be set properly for Django to provide the expected level of security;

- are expected to be different in each environment;

- enable optional security features;

- enable performance optimizations;

- provide error reporting.

Many of these settings are sensitive and should be treated as confidential. If you’re releasing the source code for your project, a common practice is to publish suitable settings for development, and to use a private settings module for production.

Run manage.py check --deploy

Some of the checks described below can be automated using the check --deploy option. Be sure to run it against your production settings file as described in the option’s documentation.

Critical settings

SECRET_KEY

The secret key must be a large random value and it must be kept secret.

Make sure that the key used in production isn’t used anywhere else and avoid committing it to source control. This reduces the number of vectors from which an attacker may acquire the key.

Instead of hardcoding the secret key in your settings module, consider loading it from an environment variable:

import os
SECRET_KEY = os.environ['SECRET_KEY']

or from a file:

with open('/etc/secret_key.txt') as f:
SECRET_KEY = f.read().strip()

DEBUG

You must never enable debug in production.

You’re certainly developing your project with DEBUG = True, since this enables handy features like full tracebacks in your browser.

For a production environment, though, this is a really bad idea, because it leaks lots of information about your project: excerpts of your source code, local variables, settings, libraries used, etc.

Environment-specific settings

ALLOWED_HOSTS

When DEBUG = False, Django doesn’t work at all without a suitable value for ALLOWED_HOSTS.

This setting is required to protect your site against some CSRF attacks. If you use a wildcard, you must perform your own validation of the Host HTTP header, or otherwise ensure that you aren’t vulnerable to this category of attacks.

You should also configure the Web server that sits in front of Django to validate the host. It should respond with a static error page or ignore requests for incorrect hosts instead of forwarding the request to Django. This way you’ll avoid spurious errors in your Django logs (or emails if you have error reporting configured that way). For example, on nginx you might setup a default server to return “444 No Response” on an unrecognized host:

server {
listen 80 default_server;
return 444;
}

CACHES

If you’re using a cache, connection parameters may be different in development and in production.

Cache servers often have weak authentication. Make sure they only accept connections from your application servers.

If you’re using Memcached, consider using cached sessions to improve performance.

DATABASES

Database connection parameters are probably different in development and in production.

Database passwords are very sensitive. You should protect them exactly like SECRET_KEY.

For maximum security, make sure database servers only accept connections from your application servers.

If you haven’t set up backups for your database, do it right now!

EMAIL_BACKEND and related settings

If your site sends emails, these values need to be set correctly.

By default, Django sends email from webmaster@localhost and root@localhost. However, some mail providers reject email from these addresses. To use different sender addresses, modify the DEFAULT_FROM_EMAIL and SERVER_EMAIL settings.

STATIC_ROOT and STATIC_URL

Static files are automatically served by the development server. In production, you must define a STATIC_ROOT directory where collectstatic will copy them.

See Managing static files (e.g. images, JavaScript, CSS) for more information.

MEDIA_ROOT and MEDIA_URL

Media files are uploaded by your users. They’re untrusted! Make sure your web server never attempt to interpret them. For instance, if a user uploads a .php file , the web server shouldn’t execute it.

Now is a good time to check your backup strategy for these files.

HTTPS

Any website which allows users to log in should enforce site-wide HTTPS to avoid transmitting access tokens in clear. In Django, access tokens include the login/password, the session cookie, and password reset tokens. (You can’t do much to protect password reset tokens if you’re sending them by email.)

Protecting sensitive areas such as the user account or the admin isn’t sufficient, because the same session cookie is used for HTTP and HTTPS. Your web server must redirect all HTTP traffic to HTTPS, and only transmit HTTPS requests to Django.

Once you’ve set up HTTPS, enable the following settings.

CSRF_COOKIE_SECURE

Set this to True to avoid transmitting the CSRF cookie over HTTP accidentally.

SESSION_COOKIE_SECURE

Set this to True to avoid transmitting the session cookie over HTTP accidentally.

Performance optimizations

Setting DEBUG = False disables several features that are only useful in development. In addition, you can tune the following settings.

CONN_MAX_AGE

Enabling persistent database connections can result in a nice speed-up when connecting to the database accounts for a significant part of the request processing time.

This helps a lot on virtualized hosts with limited network performance.

TEMPLATES

Enabling the cached template loader often improves performance drastically, as it avoids compiling each template every time it needs to be rendered. See the template loaders docs for more information.

Error reporting

By the time you push your code to production, it’s hopefully robust, but you can’t rule out unexpected errors. Thankfully, Django can capture errors and notify you accordingly.

LOGGING

Review your logging configuration before putting your website in production, and check that it works as expected as soon as you have received some traffic.

See Logging for details on logging.

ADMINS and MANAGERS

ADMINS will be notified of 500 errors by email.

MANAGERS will be notified of 404 errors. IGNORABLE_404_URLS can help filter out spurious reports.

See Error reporting for details on error reporting by email.

Error reporting by email doesn’t scale very well

Consider using an error monitoring system such as Sentry before your inbox is flooded by reports. Sentry can also aggregate logs.

Customize the default error views

Django includes default views and templates for several HTTP error codes. You may want to override the default templates by creating the following templates in your root template directory: 404.html, 500.html, 403.html, and 400.html. The default views should suffice for 99% of Web applications, but if you desire to customize them, see these instructions which also contain details about the default templates:

- The 404 (page not found) view

- The 500 (server error) view

- The 403 (HTTP Forbidden) view

- The 400 (bad request) view

Python Options

It’s strongly recommended that you invoke the Python process running your Django application using the -R option or with the PYTHONHASHSEED environment variable set to random. This option is enabled by default starting with Python 3.3.

These options help protect your site from denial-of-service (DoS) attacks triggered by carefully crafted inputs. Such an attack can drastically increase CPU usage by causing worst-case performance when creating dict instances. See oCERT advisory #2011-003 for more information.

Upgrading Django to a newer version

While it can be a complex process at times, upgrading to the latest Django version has several benefits:

- New features and improvements are added.

- Bugs are fixed.

- Older version of Django will eventually no longer receive security updates. (see Supported versions).

- Upgrading as each new Django release is available makes future upgrades less painful by keeping your code base up to date.

Here are some things to consider to help make your upgrade process as smooth as possible.

Required Reading

If it’s your first time doing an upgrade, it is useful to read the guide on the different release processes.

Afterwards, you should familiarize yourself with the changes that were made in the new Django version(s):

- Read the release notes for each ‘final’ release from the one after your current Django version, up to and including the version to which you plan to upgrade.

- Look at the deprecation timeline for the relevant versions.

Pay particular attention to backwards incompatible changes to get a clear idea of what will be needed for a successful upgrade.

Dependencies

In most cases it will be necessary to upgrade to the latest version of your Django-related dependencies as well. If the Django version was recently released or if some of your dependencies are not well-maintained, some of your dependencies may not yet support the new Django version. In these cases you may have to wait until new versions of your dependencies are released.

Resolving deprecation warnings

Before upgrading, it’s a good idea to resolve any deprecation warnings raised by your project while using your current version of Django. Fixing these warnings before upgrading ensures that you’re informed about areas of the code that need altering.

In Python, deprecation warnings are silenced by default. You must turn them on using the -Wall Python command line option or the PYTHONWARNINGS environment variable. For example, to show warnings while running tests:

$ python -Wall manage.py test

If you’re not using the Django test runner, you may need to also ensure that any console output is not captured which would hide deprecation warnings. For example, if you use py.test:

$ PYTHONWARNINGS=all py.test tests --capture=no

Resolve any deprecation warnings with your current version of Django before continuing the upgrade process.

Third party applications might use deprecated APIs in order to support multiple versions of Django, so deprecation warnings in packages you’ve installed don’t necessarily indicate a problem. If a package doesn’t support the latest version of Django, consider raising an issue or sending a pull request for it.

Installation

Once you’re ready, it is time to install the new Django version. If you are using virtualenv and it is a major upgrade, you might want to set up a new environment with all the dependencies first.

Exactly which steps you will need to take depends on your installation process. The most convenient way is to use pip with the --upgrade or -U flag:

$ pip install -U Django

pip also automatically uninstalls the previous version of Django.

If you use some other installation process, you might have to manually uninstall the old Django version and should look at the complete installation instructions.

Testing

When the new environment is set up, run the full test suite for your application. Again, it’s useful to turn on deprecation warnings on so they’re shown in the test output (you can also use the flag if you test your app manually using manage.py runserver):

$ python -Wall manage.py test

After you have run the tests, fix any failures. While you have the release notes fresh in your mind, it may also be a good time to take advantage of new features in Django by refactoring your code to eliminate any deprecation warnings.

Deployment

When you are sufficiently confident your app works with the new version of Django, you’re ready to go ahead and deploy your upgraded Django project.

If you are using caching provided by Django, you should consider clearing your cache after upgrading. Otherwise you may run into problems, for example, if you are caching pickled objects as these objects are not guaranteed to be pickle-compatible across Django versions. A past instance of incompatibility was caching pickled HttpResponse objects, either directly or indirectly via the cache_page() decorator.

Error reporting

When you’re running a public site you should always turn off the DEBUG setting. That will make your server run much faster, and will also prevent malicious users from seeing details of your application that can be revealed by the error pages.

However, running with DEBUG set to False means you’ll never see errors generated by your site – everyone will just see your public error pages. You need to keep track of errors that occur in deployed sites, so Django can be configured to create reports with details about those errors.

Email reports

Server errors

When DEBUG is False, Django will email the users listed in the ADMINS setting whenever your code raises an unhandled exception and results in an internal server error (HTTP status code 500). This gives the administrators immediate notification of any errors. The ADMINS will get a description of the error, a complete Python traceback, and details about the HTTP request that caused the error.

Note

In order to send email, Django requires a few settings telling it how to connect to your mail server. At the very least, you’ll need to specify EMAIL_HOST and possibly EMAIL_HOST_USER and EMAIL_HOST_PASSWORD, though other settings may be also required depending on your mail server’s configuration. Consult the Django settings documentation for a full list of email-related settings.

By default, Django will send email from root@localhost. However, some mail providers reject all email from this address. To use a different sender address, modify the SERVER_EMAIL setting.

To activate this behavior, put the email addresses of the recipients in the ADMINS setting.

See also

Server error emails are sent using the logging framework, so you can customize this behavior by customizing your logging configuration.

404 errors

Django can also be configured to email errors about broken links (404 “page not found” errors). Django sends emails about 404 errors when:

- DEBUG is False;

- Your MIDDLEWARE_CLASSES setting includes django.middleware.common.BrokenLinkEmailsMiddleware.

If those conditions are met, Django will email the users listed in the MANAGERS setting whenever your code raises a 404 and the request has a referer. It doesn’t bother to email for 404s that don’t have a referer – those are usually just people typing in broken URLs or broken Web bots. It also ignores 404s when the referer is equal to the requested URL, since this behavior is from broken Web bots too.

Changed in Django 1.9:
In older versions, 404s were not ignored when the referer was equal to the requested URL.

Note

BrokenLinkEmailsMiddleware must appear before other middleware that intercepts 404 errors, such as LocaleMiddleware or FlatpageFallbackMiddleware. Put it towards the top of your MIDDLEWARE_CLASSES setting.

You can tell Django to stop reporting particular 404s by tweaking the IGNORABLE_404_URLS setting. It should be a list of compiled regular expression objects. For example:

import re
IGNORABLE_404_URLS = [
re.compile(r'\.(php|cgi)$'),
re.compile(r'^/phpmyadmin/'),
]

In this example, a 404 to any URL ending with .php or .cgi will not be reported. Neither will any URL starting with /phpmyadmin/.

The following example shows how to exclude some conventional URLs that browsers and crawlers often request:

import re
IGNORABLE_404_URLS = [
re.compile(r'^/apple-touch-icon.*\.png$'),
re.compile(r'^/favicon\.ico$'),
re.compile(r'^/robots\.txt$'),
]

(Note that these are regular expressions, so we put a backslash in front of periods to escape them.)

If you’d like to customize the behavior of django.middleware.common.BrokenLinkEmailsMiddleware further (for example to ignore requests coming from web crawlers), you should subclass it and override its methods.

See also

404 errors are logged using the logging framework. By default, these log records are ignored, but you can use them for error reporting by writing a handler and configuring logging appropriately.

Filtering error reports

Warning

Filtering sensitive data is a hard problem, and it’s nearly impossible to guarantee that sensitive won’t leak into an error report. Therefore, error reports should only be available to trusted team members and you should avoid transmitting error reports unencrypted over the Internet (such as through email).

Filtering sensitive information

Error reports are really helpful for debugging errors, so it is generally useful to record as much relevant information about those errors as possible. For example, by default Django records the full traceback for the exception raised, each traceback frame’s local variables, and the HttpRequest’s attributes.

However, sometimes certain types of information may be too sensitive and thus may not be appropriate to be kept track of, for example a user’s password or credit card number. So in addition to filtering out settings that appear to be sensitive as described in the DEBUG documentation, Django offers a set of function decorators to help you control which information should be filtered out of error reports in a production environment (that is, where DEBUG is set to False): sensitive_variables() and sensitive_post_parameters().

sensitive_variables(*variables)[source]

If a function (either a view or any regular callback) in your code uses local variables susceptible to contain sensitive information, you may prevent the values of those variables from being included in error reports using the sensitive_variables decorator:

from django.views.decorators.debug import sensitive_variables

@sensitive_variables('user', 'pw', 'cc')
def process_info(user):
pw = user.pass_word
cc = user.credit_card_number
name = user.name
...

In the above example, the values for the user, pw and cc variables will be hidden and replaced with stars (**********) in the error reports, whereas the value of the name variable will be disclosed.

To systematically hide all local variables of a function from error logs, do not provide any argument to the sensitive_variables decorator:

@sensitive_variables()
def my_function():
...

When using multiple decorators

If the variable you want to hide is also a function argument (e.g. ‘user’ in the following example), and if the decorated function has multiple decorators, then make sure to place @sensitive_variables at the top of the decorator chain. This way it will also hide the function argument as it gets passed through the other decorators:

@sensitive_variables('user', 'pw', 'cc')
@some_decorator
@another_decorator
def process_info(user):
...

sensitive_post_parameters(*parameters)[source]

If one of your views receives an HttpRequest object with POST parameters susceptible to contain sensitive information, you may prevent the values of those parameters from being included in the error reports using the sensitive_post_parameters decorator:

from django.views.decorators.debug import sensitive_post_parameters

@sensitive_post_parameters('pass_word', 'credit_card_number')
def record_user_profile(request):
UserProfile.create(
user=request.user,
password=request.POST['pass_word'],
credit_card=request.POST['credit_card_number'],
name=request.POST['name'],
)
...

In the above example, the values for the pass_word and credit_card_number POST parameters will be hidden and replaced with stars (**********) in the request’s representation inside the error reports, whereas the value of the name parameter will be disclosed.

To systematically hide all POST parameters of a request in error reports, do not provide any argument to the sensitive_post_parameters decorator:

@sensitive_post_parameters()
def my_view(request):
...

All POST parameters are systematically filtered out of error reports for certain django.contrib.auth.views views (login, password_reset_confirm, password_change, and add_view and user_change_password in the auth admin) to prevent the leaking of sensitive information such as user passwords.

Custom error reports

All sensitive_variables() and sensitive_post_parameters() do is, respectively, annotate the decorated function with the names of sensitive variables and annotate the HttpRequest object with the names of sensitive POST parameters, so that this sensitive information can later be filtered out of reports when an error occurs. The actual filtering is done by Django’s default error reporter filter: django.views.debug.SafeExceptionReporterFilter. This filter uses the decorators’ annotations to replace the corresponding values with stars (**********) when the error reports are produced. If you wish to override or customize this default behavior for your entire site, you need to define your own filter class and tell Django to use it via the DEFAULT_EXCEPTION_REPORTER_FILTER setting:

DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'

You may also control in a more granular way which filter to use within any given view by setting the HttpRequest’s exception_reporter_filter attribute:

def my_view(request):
if request.user.is_authenticated():
request.exception_reporter_filter = CustomExceptionReporterFilter()
...

Your custom filter class needs to inherit from django.views.debug.SafeExceptionReporterFilter and may override the following methods:

class SafeExceptionReporterFilter[source]

SafeExceptionReporterFilter.is_active(request)[source]

Returns True to activate the filtering operated in the other methods. By default the filter is active if DEBUG is False.

SafeExceptionReporterFilter.get_post_parameters(request)[source]

Returns the filtered dictionary of POST parameters. By default it replaces the values of sensitive parameters with stars (**********).

SafeExceptionReporterFilter.get_traceback_frame_variables(request, tb_frame)[source]

Returns the filtered dictionary of local variables for the given traceback frame. By default it replaces the values of sensitive variables with stars (**********).

See also

You can also set up custom error reporting by writing a custom piece of exception middleware. If you do write custom error handling, it’s a good idea to emulate Django’s built-in error handling and only report/log errors if DEBUG is False.

Providing initial data for models

It’s sometimes useful to pre-populate your database with hard-coded data when you’re first setting up an app. You can provide initial data via fixtures.

Providing initial data with fixtures

A fixture is a collection of data that Django knows how to import into a database. The most straightforward way of creating a fixture if you’ve already got some data is to use the manage.py dumpdata command. Or, you can write fixtures by hand; fixtures can be written as JSON, XML or YAML (with PyYAML installed) documents. The serialization documentation has more details about each of these supported serialization formats.

As an example, though, here’s what a fixture for a simple Person model might look like in JSON:

[
{
"model": "myapp.person",
"pk": 1,
"fields": {
"first_name": "John",
"last_name": "Lennon"
}
},
{
"model": "myapp.person",
"pk": 2,
"fields": {
"first_name": "Paul",
"last_name": "McCartney"
}
}
]

And here’s that same fixture as YAML:

- model: myapp.person
pk: 1
fields:
first_name: John
last_name: Lennon
- model: myapp.person
pk: 2
fields:
first_name: Paul
last_name: McCartney

You’ll store this data in a fixtures directory inside your app.

Loading data is easy: just call manage.py loaddata <fixturename>, where <fixturename> is the name of the fixture file you’ve created. Each time you run loaddata, the data will be read from the fixture and re-loaded into the database. Note this means that if you change one of the rows created by a fixture and then run loaddata again, you’ll wipe out any changes you’ve made.

Where Django finds fixture files

By default, Django looks in the fixtures directory inside each app for fixtures. You can set the FIXTURE_DIRS setting to a list of additional directories where Django should look.

When running manage.py loaddata, you can also specify a path to a fixture file, which overrides searching the usual directories.

See also

Fixtures are also used by the testing framework to help set up a consistent test environment.

Running Django on Jython

Jython is an implementation of Python that runs on the Java platform (JVM). This document will get you up and running with Django on top of Jython.

Installing Jython

Django works with Jython versions 2.7b2 and higher. See the Jython website for download and installation instructions.

Creating a servlet container

If you just want to experiment with Django, skip ahead to the next section; Django includes a lightweight Web server you can use for testing, so you won’t need to set up anything else until you’re ready to deploy Django in production.

If you want to use Django on a production site, use a Java servlet container, such as Apache Tomcat. Full JavaEE applications servers such as GlassFish or JBoss are also OK, if you need the extra features they include.

Installing Django

The next step is to install Django itself. This is exactly the same as installing Django on standard Python, so see Remove any old versions of Django and Install the Django code for instructions.

Installing Jython platform support libraries

The django-jython project contains database backends and management commands for Django/Jython development. Note that the builtin Django backends won’t work on top of Jython.

To install it, follow the installation instructions detailed on the project website. Also, read the database backends documentation there.

Differences with Django on Jython

At this point, Django on Jython should behave nearly identically to Django running on standard Python. However, are a few differences to keep in mind:

- Remember to use the jython command instead of python. The documentation uses python for consistency, but if you’re using Jython you’ll want to mentally replace python with jython every time it occurs.

- Similarly, you’ll need to use the JYTHONPATH environment variable instead of PYTHONPATH.

- Any part of Django that requires Pillow will not work.

Integrating Django with a legacy database

While Django is best suited for developing new applications, it’s quite possible to integrate it into legacy databases. Django includes a couple of utilities to automate as much of this process as possible.

This document assumes you know the Django basics, as covered in the tutorial.

Once you’ve got Django set up, you’ll follow this general process to integrate with an existing database.

Give Django your database parameters

You’ll need to tell Django what your database connection parameters are, and what the name of the database is. Do that by editing the DATABASES setting and assigning values to the following keys for the 'default' connection:

- NAME

- ENGINE

- USER

- PASSWORD

- HOST

- PORT

Auto-generate the models

Django comes with a utility called inspectdb that can create models by introspecting an existing database. You can view the output by running this command:

$ python manage.py inspectdb

Save this as a file by using standard Unix output redirection:

$ python manage.py inspectdb > models.py

This feature is meant as a shortcut, not as definitive model generation. See the documentation of inspectdb for more information.

Once you’ve cleaned up your models, name the file models.py and put it in the Python package that holds your app. Then add the app to your INSTALLED_APPS setting.

By default, inspectdb creates unmanaged models. That is, managed = False in the model’s Meta class tells Django not to manage each table’s creation, modification, and deletion:

class Person(models.Model):
id = models.IntegerField(primary_key=True)
first_name = models.CharField(max_length=70)
class Meta:
managed = False
db_table = 'CENSUS_PERSONS'

If you do want to allow Django to manage the table’s lifecycle, you’ll need to change the managed option above to True (or simply remove it because True is its default value).

Install the core Django tables

Next, run the migrate command to install any extra needed database records such as admin permissions and content types:

$ python manage.py migrate

Test and tweak

Those are the basic steps – from here you’ll want to tweak the models Django generated until they work the way you’d like. Try accessing your data via the Django database API, and try editing objects via Django’s admin site, and edit the models file accordingly.

Outputting CSV with Django

This document explains how to output CSV (Comma Separated Values) dynamically using Django views. To do this, you can either use the Python CSV library or the Django template system.

Using the Python CSV library

Python comes with a CSV library, csv. The key to using it with Django is that the csv module’s CSV-creation capability acts on file-like objects, and Django’s HttpResponse objects are file-like objects.

Here’s an example:

import csv
from django.http import HttpResponse

def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'

writer = csv.writer(response)
writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])

return response

The code and comments should be self-explanatory, but a few things deserve a mention:

- The response gets a special MIME type, text/csv. This tells browsers that the document is a CSV file, rather than an HTML file. If you leave this off, browsers will probably interpret the output as HTML, which will result in ugly, scary gobbledygook in the browser window.

- The response gets an additional Content-Disposition header, which contains the name of the CSV file. This filename is arbitrary; call it whatever you want. It’ll be used by browsers in the “Save as...” dialog, etc.

- Hooking into the CSV-generation API is easy: Just pass response as the first argument to csv.writer. The csv.writer function expects a file-like object, and HttpResponse objects fit the bill.

- For each row in your CSV file, call writer.writerow, passing it an iterable object such as a list or tuple.

- The CSV module takes care of quoting for you, so you don’t have to worry about escaping strings with quotes or commas in them. Just pass writerow() your raw strings, and it’ll do the right thing.

Handling Unicode on Python 2

Python 2’s csv module does not support Unicode input. Since Django uses Unicode internally this means strings read from sources such as HttpRequest are potentially problematic. There are a few options for handling this:

- Manually encode all Unicode objects to a compatible encoding.

- Use the UnicodeWriter class provided in the csv module’s examples section.

- Use the python-unicodecsv module, which aims to be a drop-in replacement for csv that gracefully handles Unicode.

For more information, see the Python documentation of the csv module.

Streaming large CSV files

When dealing with views that generate very large responses, you might want to consider using Django’s StreamingHttpResponse instead. For example, by streaming a file that takes a long time to generate you can avoid a load balancer dropping a connection that might have otherwise timed out while the server was generating the response.

In this example, we make full use of Python generators to efficiently handle the assembly and transmission of a large CSV file:

import csv

from django.utils.six.moves import range
from django.http import StreamingHttpResponse

class Echo(object):
"""An object that implements just the write method of the file-like
interface.
"""
def write(self, value):
"""Write the value by returning it, instead of storing in a buffer."""
return value

def some_streaming_csv_view(request):
"""A view that streams a large CSV file."""
# Generate a sequence of rows. The range is based on the maximum number of
# rows that can be handled by a single sheet in most spreadsheet
# applications.
rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
pseudo_buffer = Echo()
writer = csv.writer(pseudo_buffer)
response = StreamingHttpResponse((writer.writerow(row) for row in rows),
content_type="text/csv")
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
return response

Using the template system

Alternatively, you can use the Django template system to generate CSV. This is lower-level than using the convenient Python csv module, but the solution is presented here for completeness.

The idea here is to pass a list of items to your template, and have the template output the commas in a for loop.

Here’s an example, which generates the same CSV file as above:

from django.http import HttpResponse
from django.template import loader, Context

def some_view(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'

# The data is hard-coded here, but you could load it from a database or
# some other source.
csv_data = (
('First row', 'Foo', 'Bar', 'Baz'),
('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
)

t = loader.get_template('my_template_name.txt')
c = Context({
'data': csv_data,
})
response.write(t.render(c))
return response

The only difference between this example and the previous example is that this one uses template loading instead of the CSV module. The rest of the code – such as the content_type='text/csv' – is the same.

Then, create the template my_template_name.txt, with this template code:

{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}

This template is quite basic. It just iterates over the given data and displays a line of CSV for each row. It uses the addslashes template filter to ensure there aren’t any problems with quotes.

Other text-based formats

Notice that there isn’t very much specific to CSV here – just the specific output format. You can use either of these techniques to output any text-based format you can dream of. You can also use a similar technique to generate arbitrary binary data; see Outputting PDFs with Django for an example.

Outputting PDFs with Django

This document explains how to output PDF files dynamically using Django views. This is made possible by the excellent, open-source ReportLab Python PDF library.

The advantage of generating PDF files dynamically is that you can create customized PDFs for different purposes – say, for different users or different pieces of content.

For example, Django was used at kusports.com to generate customized, printer-friendly NCAA tournament brackets, as PDF files, for people participating in a March Madness contest.

Install ReportLab

The ReportLab library is available on PyPI. A user guide (not coincidentally, a PDF file) is also available for download. You can install ReportLab with pip:

$ pip install reportlab

Test your installation by importing it in the Python interactive interpreter:

>>> import reportlab

If that command doesn’t raise any errors, the installation worked.

Write your view

The key to generating PDFs dynamically with Django is that the ReportLab API acts on file-like objects, and Django’s HttpResponse objects are file-like objects.

Here’s a “Hello World” example:

from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)

# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")

# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response

The code and comments should be self-explanatory, but a few things deserve a mention:

- The response gets a special MIME type, application/pdf. This tells browsers that the document is a PDF file, rather than an HTML file. If you leave this off, browsers will probably interpret the output as HTML, which would result in ugly, scary gobbledygook in the browser window.

- The response gets an additional Content-Disposition header, which contains the name of the PDF file. This filename is arbitrary: Call it whatever you want. It’ll be used by browsers in the “Save as...” dialog, etc.

- The Content-Disposition header starts with 'attachment; ' in this example. This forces Web browsers to pop-up a dialog box prompting/confirming how to handle the document even if a default is set on the machine. If you leave off 'attachment;', browsers will handle the PDF using whatever program/plugin they’ve been configured to use for PDFs. Here’s what that code would look like:

response['Content-Disposition'] = 'filename="somefilename.pdf"'

- Hooking into the ReportLab API is easy: Just pass response as the first argument to canvas.Canvas. The Canvas class expects a file-like object, and HttpResponse objects fit the bill.

- Note that all subsequent PDF-generation methods are called on the PDF object (in this case, p) – not on response.

- Finally, it’s important to call showPage() and save() on the PDF file.

Note

ReportLab is not thread-safe. Some of our users have reported odd issues with building PDF-generating Django views that are accessed by many people at the same time.

Complex PDFs

If you’re creating a complex PDF document with ReportLab, consider using the io library as a temporary holding place for your PDF file. This library provides a file-like object interface that is particularly efficient. Here’s the above “Hello World” example rewritten to use io:

from io import BytesIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

buffer = BytesIO()

# Create the PDF object, using the BytesIO object as its "file."
p = canvas.Canvas(buffer)

# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")

# Close the PDF object cleanly.
p.showPage()
p.save()

# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response

Further resources

- PDFlib is another PDF-generation library that has Python bindings. To use it with Django, just use the same concepts explained in this article.

- XHTML2PDF is yet another PDF-generation library. It ships with an example of how to integrate it with Django.

- HTMLdoc is a command-line script that can convert HTML to PDF. It doesn’t have a Python interface, but you can escape out to the shell using system or popen and retrieve the output in Python.

Other formats

Notice that there isn’t a lot in these examples that’s PDF-specific – just the bits using reportlab. You can use a similar technique to generate any arbitrary format that you can find a Python library for. Also see Outputting CSV with Django for another example and some techniques you can use when generated text-based formats.

Managing static files (e.g. images, JavaScript, CSS)

Websites generally need to serve additional files such as images, JavaScript, or CSS. In Django, we refer to these files as “static files”. Django provides django.contrib.staticfiles to help you manage them.

This page describes how you can serve these static files.

Configuring static files

1. Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS.

2. In your settings file, define STATIC_URL, for example:

STATIC_URL = '/static/'

3. In your templates, either hardcode the url like /static/my_app/myexample.jpg or, preferably, use the static template tag to build the URL for the given relative path by using the configured STATICFILES_STORAGE storage (this makes it much easier when you want to switch to a content delivery network (CDN) for serving static files).

{% load staticfiles %}
<img src="{% static "my_app/myexample.jpg" %}" alt="My image"/>

4. Store your static files in a folder called static in your app. For example my_app/static/my_app/myimage.jpg.

Serving the files

In addition to these configuration steps, you’ll also need to actually serve the static files.

During development, if you use django.contrib.staticfiles, this will be done automatically by runserver when DEBUG is set to True (see django.contrib.staticfiles.views.serve()).

This method is grossly inefficient and probably insecure, so it is unsuitable for production.

See Deploying static files for proper strategies to serve static files in production environments.

Your project will probably also have static assets that aren’t tied to a particular app. In addition to using a static/ directory inside your apps, you can define a list of directories (STATICFILES_DIRS) in your settings file where Django will also look for static files. For example:

STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
'/var/www/static/',
]

See the documentation for the STATICFILES_FINDERS setting for details on how staticfiles finds your files.

Static file namespacing

Now we might be able to get away with putting our static files directly in my_app/static/ (rather than creating another my_app subdirectory), but it would actually be a bad idea. Django will use the first static file it finds whose name matches, and if you had a static file with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those static files inside another directory named for the application itself.

Serving static files during development

If you use django.contrib.staticfiles as explained above, runserver will do this automatically when DEBUG is set to True. If you don’t have django.contrib.staticfiles in INSTALLED_APPS, you can still manually serve static files using the django.contrib.staticfiles.views.serve() view.

This is not suitable for production use! For some common deployment strategies, see Deploying static files.

For example, if your STATIC_URL is defined as /static/, you can do this by adding the following snippet to your urls.py:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Note

This helper function works only in debug mode and only if the given prefix is local (e.g. /static/) and not a URL (e.g. http://static.example.com/).

Also this helper function only serves the actual STATIC_ROOT folder; it doesn’t perform static files discovery like django.contrib.staticfiles.

Serving files uploaded by a user during development

During development, you can serve user-uploaded media files from MEDIA_ROOT using the django.contrib.staticfiles.views.serve() view.

This is not suitable for production use! For some common deployment strategies, see Deploying static files.

For example, if your MEDIA_URL is defined as /media/, you can do this by adding the following snippet to your urls.py:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Note

This helper function works only in debug mode and only if the given prefix is local (e.g. /media/) and not a URL (e.g. http://media.example.com/).

Testing

When running tests that use actual HTTP requests instead of the built-in testing client (i.e. when using the built-in LiveServerTestCase) the static assets need to be served along the rest of the content so the test environment reproduces the real one as faithfully as possible, but LiveServerTestCase has only very basic static file-serving functionality: It doesn’t know about the finders feature of the staticfiles application and assumes the static content has already been collected under STATIC_ROOT.

Because of this, staticfiles ships its own django.contrib.staticfiles.testing.StaticLiveServerTestCase, a subclass of the built-in one that has the ability to transparently serve all the assets during execution of these tests in a way very similar to what we get at development time with DEBUG = True, i.e. without having to collect them using collectstatic first.

Deployment

django.contrib.staticfiles provides a convenience management command for gathering static files in a single directory so you can serve them easily.

1. Set the STATIC_ROOT setting to the directory from which you’d like to serve these files, for example:

STATIC_ROOT = "/var/www/example.com/static/"

2. Run the collectstatic management command:

$ python manage.py collectstatic

This will copy all files from your static folders into the STATIC_ROOT directory.

3. Use a web server of your choice to serve the files. Deploying static files covers some common deployment strategies for static files.

Learn more

This document has covered the basics and some common usage patterns. For complete details on all the settings, commands, template tags, and other pieces included in django.contrib.staticfiles, see the staticfiles reference.

Deploying static files

See also

For an introduction to the use of django.contrib.staticfiles, see Managing static files (e.g. images, JavaScript, CSS).

Serving static files in production

The basic outline of putting static files into production is simple: run the collectstatic command when static files change, then arrange for the collected static files directory (STATIC_ROOT) to be moved to the static file server and served. Depending on STATICFILES_STORAGE, files may need to be moved to a new location manually or the post_process method of the Storage class might take care of that.

Of course, as with all deployment tasks, the devil’s in the details. Every production setup will be a bit different, so you’ll need to adapt the basic outline to fit your needs. Below are a few common patterns that might help.

Serving the site and your static files from the same server

If you want to serve your static files from the same server that’s already serving your site, the process may look something like:

- Push your code up to the deployment server.

- On the server, run collectstatic to copy all the static files into STATIC_ROOT.

- Configure your web server to serve the files in STATIC_ROOT under the URL STATIC_URL. For example, here’s how to do this with Apache and mod_wsgi.

You’ll probably want to automate this process, especially if you’ve got multiple web servers. There’s any number of ways to do this automation, but one option that many Django developers enjoy is Fabric.

Below, and in the following sections, we’ll show off a few example fabfiles (i.e. Fabric scripts) that automate these file deployment options. The syntax of a fabfile is fairly straightforward but won’t be covered here; consult Fabric’s documentation, for a complete explanation of the syntax.

So, a fabfile to deploy static files to a couple of web servers might look something like:

from fabric.api import *

# Hosts to deploy onto
env.hosts = ['www1.example.com', 'www2.example.com']

# Where your project code lives on the server
env.project_root = '/home/www/myproject'

def deploy_static():
with cd(env.project_root):
run('./manage.py collectstatic -v0 --noinput')

Serving static files from a dedicated server

Most larger Django sites use a separate Web server – i.e., one that’s not also running Django – for serving static files. This server often runs a different type of web server – faster but less full-featured. Some common choices are:

- Nginx

- A stripped-down version of Apache

Configuring these servers is out of scope of this document; check each server’s respective documentation for instructions.

Since your static file server won’t be running Django, you’ll need to modify the deployment strategy to look something like:

- When your static files change, run collectstatic locally.

- Push your local STATIC_ROOT up to the static file server into the directory that’s being served. rsync is a common choice for this step since it only needs to transfer the bits of static files that have changed.

Here’s how this might look in a fabfile:

from fabric.api import *
from fabric.contrib import project

# Where the static files get collected locally. Your STATIC_ROOT setting.
env.local_static_root = '/path/to/static'

# Where the static files should go remotely
env.remote_static_root = '/home/www/static.example.com'

@roles('static')
def deploy_static():
local('./manage.py collectstatic')
project.rsync_project(
remote_dir=env.remote_static_root,
local_dir=env.local_static_root,
delete=True,
)

Serving static files from a cloud service or CDN

Another common tactic is to serve static files from a cloud storage provider like Amazon’s S3 and/or a CDN (content delivery network). This lets you ignore the problems of serving static files and can often make for faster-loading webpages (especially when using a CDN).

When using these services, the basic workflow would look a bit like the above, except that instead of using rsync to transfer your static files to the server you’d need to transfer the static files to the storage provider or CDN.

There’s any number of ways you might do this, but if the provider has an API a custom file storage backend will make the process incredibly simple. If you’ve written or are using a 3rd party custom storage backend, you can tell collectstatic to use it by setting STATICFILES_STORAGE to the storage engine.

For example, if you’ve written an S3 storage backend in myproject.storage.S3Storage you could use it with:

STATICFILES_STORAGE = 'myproject.storage.S3Storage'

Once that’s done, all you have to do is run collectstatic and your static files would be pushed through your storage package up to S3. If you later needed to switch to a different storage provider, it could be as simple as changing your STATICFILES_STORAGE setting.

For details on how you’d write one of these backends, see Writing a custom storage system. There are 3rd party apps available that provide storage backends for many common file storage APIs. A good starting point is the overview at djangopackages.com.

Learn more

For complete details on all the settings, commands, template tags, and other pieces included in django.contrib.staticfiles, see the staticfiles reference.

How to install Django on Windows

This document will guide you through installing Python 3.5 and Django on Windows. It also provides instructions for installing virtualenv and virtualenvwrapper, which make it easier to work on Python projects. This is meant as a beginner’s guide for users working on Django projects and does not reflect how Django should be installed when developing patches for Django itself.

The steps in this guide have been tested with Windows 7, 8, and 10. In other versions, the steps would be similar. You will need to be familiar with using the Windows command prompt.

Install Python

Django is a Python web framework, thus requiring Python to be installed on your machine. At the time of writing, Python 3.5 is the latest version.

To install Python on your machine go to https://python.org/downloads/. The website should offer you a download button for the latest Python version. Download the executable installer and run it. Check the box next to Add Python to to environment variables and then click Install Now.

After installation, open the command prompt and check that the Python version matches the version you installed by executing:

python --version

About pip

pip is a package manage for Python. It makes installing and uninstalling Python packages (such as Django!) very easy. For the rest of the installation, we’ll use pip to install Python packages from the command line.

To install pip on your machine, go to https://pip.pypa.io/en/latest/installing/, and follow the Installing with get-pip.py instructions.

Install virtualenv and virtualenvwrapper

virtualenv and virtualenvwrapper provide a dedicated environment for each Django project you create. While not mandatory, this is considered a best practice and will save you time in the future when you’re ready to deploy your project. Simply type:

pip install virtualenvwrapper-win

Then create a virtual environment for your project:

mkvirtualenv myproject

The virtual environment will be activated automatically and you’ll see “(myproject)” next to the command prompt to designate that. If you start a new command prompt, you’ll need to activate the environment again using:

workon myproject

Install Django

Django can be installed easily using pip within your virtual environment.

In the command prompt, ensure your virtual environment is active, and execute the following command:

pip install django

This will download and install the latest Django release.

After the installation has completed, you can verify your Django installation by executing django-admin --version in the command prompt.

See Get your database running for information on database installation with Django.

Common pitfalls

- If django-admin only displays the help text no matter what arguments it is given, there is probably a problem with the file association in Windows. Check if there is more than one environment variable set for running Python scripts in PATH. This usually occurs when there is more than one Python version installed.

- If you are connecting to the internet behind a proxy, there might be problem in running the command pip install django. Set the environment variables for proxy configuration in the command prompt as follows:

set http_proxy=http://username:password@proxyserver:proxyport
set https_proxy=https://username:password@proxyserver:proxyport

Writing database migrations

This document explains how to structure and write database migrations for different scenarios you might encounter. For introductory material on migrations, see the topic guide.

Data migrations and multiple databases

When using multiple databases, you may need to figure out whether or not to run a migration against a particular database. For example, you may want to only run a migration on a particular database.

In order to do that you can check the database connection’s alias inside a RunPython operation by looking at the schema_editor.connection.alias attribute:

from django.db import migrations

def forwards(apps, schema_editor):
if not schema_editor.connection.alias == 'default':
return
# Your migration code goes here

class Migration(migrations.Migration):

dependencies = [
# Dependencies to other migrations
]

operations = [
migrations.RunPython(forwards),
]

New in Django 1.8.

You can also provide hints that will be passed to the allow_migrate() method of database routers as **hints:

myapp/dbrouters.py

class MyRouter(object):

def allow_migrate(self, db, app_label, model_name=None, **hints):
if 'target_db' in hints:
return db == hints['target_db']
return True

Then, to leverage this in your migrations, do the following:

from django.db import migrations

def forwards(apps, schema_editor):
# Your migration code goes here
...

class Migration(migrations.Migration):

dependencies = [
# Dependencies to other migrations
]

operations = [
migrations.RunPython(forwards, hints={'target_db': 'default'}),
]

If your RunPython or RunSQL operation only affects one model, it’s good practice to pass model_name as a hint to make it as transparent as possible to the router. This is especially important for reusable and third-party apps.

Migrations that add unique fields

Applying a “plain” migration that adds a unique non-nullable field to a table with existing rows will raise an error because the value used to populate existing rows is generated only once, thus breaking the unique constraint.

Therefore, the following steps should be taken. In this example, we’ll add a non-nullable UUIDField with a default value. Modify the respective field according to your needs.

- Add the field on your model with default=uuid.uuid4 and unique=True arguments (choose an appropriate default for the type of the field you’re adding).

- Run the makemigrations command. This should generate a migration with an AddField operation.

- Generate two empty migration files for the same app by running makemigrations myapp --empty twice. We’ve renamed the migration files to give them meaningful names in the examples below.

- Copy the AddField operation from the auto-generated migration (the first of the three new files) to the last migration and change AddField to AlterField. For example:

0006_remove_uuid_null.py

# -*- coding: utf-8 -*-
# Generated by Django A.B on YYYY-MM-DD HH:MM
from __future__ import unicode_literals

from django.db import migrations, models
import uuid

class Migration(migrations.Migration):

dependencies = [
('myapp', '0005_populate_uuid_values'),
]

operations = [
migrations.AlterField(
model_name='mymodel',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, unique=True),
),
]

- Edit the first migration file. The generated migration class should look similar to this:

0004_add_uuid_field.py

class Migration(migrations.Migration):

dependencies = [
('myapp', '0003_auto_20150129_1705'),
]

operations = [
migrations.AddField(
model_name='mymodel',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, unique=True),
),
]

Change unique=True to null=True – this will create the intermediary null field and defer creating the unique constraint until we’ve populated unique values on all the rows.

- In the first empty migration file, add a RunPython or RunSQL operation to generate a unique value (UUID in the example) for each existing row. For example:

0005_populate_uuid_values.py

# -*- coding: utf-8 -*-
# Generated by Django A.B on YYYY-MM-DD HH:MM
from __future__ import unicode_literals

from django.db import migrations, models
import uuid

def gen_uuid(apps, schema_editor):
MyModel = apps.get_model('myapp', 'MyModel')
for row in MyModel.objects.all():
row.uuid = uuid.uuid4()
row.save()

class Migration(migrations.Migration):

dependencies = [
('myapp', '0004_add_uuid_field'),
]

operations = [
# omit reverse_code=... if you don't want the migration to be reversible.
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
]

- Now you can apply the migrations as usual with the migrate command.

Note there is a race condition if you allow objects to be created while this migration is running. Objects created after the AddField and before RunPython will have their original uuid’s overwritten.

Controlling the order of migrations

Django determines the order in which migrations should be applied not by the filename of each migration, but by building a graph using two properties on the Migration class: dependencies and run_before.

If you’ve used the makemigrations command you’ve probably already seen dependencies in action because auto-created migrations have this defined as part of their creation process.

The dependencies property is declared like this:

from django.db import migrations

class Migration(migrations.Migration):

dependencies = [
('myapp', '0123_the_previous_migration'),
]

Usually this will be enough, but from time to time you may need to ensure that your migration runs before other migrations. This is useful, for example, to make third-party apps’ migrations run after your AUTH_USER_MODEL replacement.

To achieve this, place all migrations that should depend on yours in the run_before attribute on your Migration class:

class Migration(migrations.Migration):
...

run_before = [
('third_party_app', '0001_do_awesome'),
]

Prefer using dependencies over run_before when possible. You should only use run_before if it is undesirable or impractical to specify dependencies in the migration which you want to run after the one you are writing.

Migrating data between third-party apps

You can use a data migration to move data from one third-party application to another.

If you plan to remove the old app later, you’ll need to set the dependencies property based on whether or not the old app is installed. Otherwise, you’ll have missing dependencies once you uninstall the old app. Similarly, you’ll need to catch LookupError in the apps.get_model() call that retrieves models from the old app. This approach allows you to deploy your project anywhere without first installing and then uninstalling the old app.

Here’s a sample migration:

myapp/migrations/0124_move_old_app_to_new_app.py

from django.apps import apps as global_apps
from django.db import migrations

def forwards(apps, schema_editor):
try:
OldModel = apps.get_model('old_app', 'OldModel')
except LookupError:
# The old app isn't installed.
return

NewModel = apps.get_model('new_app', 'NewModel')
NewModel.objects.bulk_create(
NewModel(new_attribute=old_object.old_attribute)
for old_object in OldModel.objects.all()
)

class Migration(migrations.Migration):
operations = [
migrations.RunPython(forwards, migrations.RunPython.noop),
]
dependencies = [
('myapp', '0123_the_previous_migration'),
('new_app', '0001_initial'),
]

if global_apps.is_installed('old_app'):
dependencies.append(('old_app', '0001_initial'))

Also consider what you want to happen when the migration is unapplied. You could either do nothing (as in the example above) or remove some or all of the data from the new application. Adjust the second argument of the RunPython operation accordingly.

Django FAQ

- FAQ: General

- Why does this project exist?

- What does “Django” mean, and how do you pronounce it?

- Is Django stable?

- Does Django scale?

- Who’s behind this?

- Which sites use Django?

- Django appears to be a MVC framework, but you call the Controller the “view”, and the View the “template”. How come you don’t use the standard names?

- <Framework X> does <feature Y> – why doesn’t Django?

- Why did you write all of Django from scratch, instead of using other Python libraries?

- Is Django a content-management-system (CMS)?

- How can I download the Django documentation to read it offline?

- Where can I find Django developers for hire?

- How do I cite Django?

- FAQ: Installation

- How do I get started?

- What are Django’s prerequisites?

- What Python version can I use with Django?

- What Python version should I use with Django?

- Should I use the stable version or development version?

- FAQ: Using Django

- Why do I get an error about importing DJANGO_SETTINGS_MODULE?

- I can’t stand your template language. Do I have to use it?

- Do I have to use your model/database layer?

- How do I use image and file fields?

- How do I make a variable available to all my templates?

- FAQ: Getting Help

- How do I do X? Why doesn’t Y work? Where can I go to get help?

- Why hasn’t my message appeared on django-users?

- Nobody on django-users answered my question! What should I do?

- I think I’ve found a bug! What should I do?

- I think I’ve found a security problem! What should I do?

- FAQ: Databases and models

- How can I see the raw SQL queries Django is running?

- Can I use Django with a pre-existing database?

- If I make changes to a model, how do I update the database?

- Do Django models support multiple-column primary keys?

- Does Django support NoSQL databases?

- How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?

- FAQ: The admin

- I can’t log in. When I enter a valid username and password, it just brings up the login page again, with no error messages.

- I can’t log in. When I enter a valid username and password, it brings up the login page again, with a “Please enter a correct username and password” error.

- How do I automatically set a field’s value to the user who last edited the object in the admin?

- How do I limit admin access so that objects can only be edited by the users who created them?

- My admin-site CSS and images showed up fine using the development server, but they’re not displaying when using mod_wsgi.

- My “list_filter” contains a ManyToManyField, but the filter doesn’t display.

- Some objects aren’t appearing in the admin.

- How can I customize the functionality of the admin interface?

- The dynamically-generated admin site is ugly! How can I change it?

- What browsers are supported for using the admin?

- FAQ: Contributing code

- How can I get started contributing code to Django?

- I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?

- When and how might I remind the core team of a patch I care about?

- But I’ve reminded you several times and you keep ignoring my patch!

- Troubleshooting

- Problems running django-admin

- Miscellaneous

FAQ: General

Why does this project exist?

Django grew from a very practical need: World Online, a newspaper Web operation, is responsible for building intensive Web applications on journalism deadlines. In the fast-paced newsroom, World Online often has only a matter of hours to take a complicated Web application from concept to public launch.

At the same time, the World Online Web developers have consistently been perfectionists when it comes to following best practices of Web development.

In fall 2003, the World Online developers (Adrian Holovaty and Simon Willison) ditched PHP and began using Python to develop its websites. As they built intensive, richly interactive sites such as Lawrence.com, they began to extract a generic Web development framework that let them build Web applications more and more quickly. They tweaked this framework constantly, adding improvements over two years.

In summer 2005, World Online decided to open-source the resulting software, Django. Django would not be possible without a whole host of open-source projects – Apache, Python, and PostgreSQL to name a few – and we’re thrilled to be able to give something back to the open-source community.

What does “Django” mean, and how do you pronounce it?

Django is named after Django Reinhardt, a jazz manouche guitarist from the 1930s to early 1950s. To this day, he’s considered one of the best guitarists of all time.

Listen to his music. You’ll like it.

Django is pronounced JANG-oh. Rhymes with FANG-oh. The “D” is silent.

We’ve also recorded an audio clip of the pronunciation.

Is Django stable?

Yes, it’s quite stable. Companies like Disqus, Instagram, Pinterest, and Mozilla have been using Django for many years. Sites built on Django have weathered traffic spikes of over 50 thousand hits per second.

Does Django scale?

Yes. Compared to development time, hardware is cheap, and so Django is designed to take advantage of as much hardware as you can throw at it.

Django uses a “shared-nothing” architecture, which means you can add hardware at any level – database servers, caching servers or Web/application servers.

The framework cleanly separates components such as its database layer and application layer. And it ships with a simple-yet-powerful cache framework.

Who’s behind this?

Django was originally developed at World Online, the Web department of a newspaper in Lawrence, Kansas, USA. Django’s now run by an international team of volunteers.

Which sites use Django?

DjangoSites.org features a constantly growing list of Django-powered sites.

Django appears to be a MVC framework, but you call the Controller the “view”, and the View the “template”. How come you don’t use the standard names?

Well, the standard names are debatable.

In our interpretation of MVC, the “view” describes the data that gets presented to the user. It’s not necessarily how the data looks, but which data is presented. The view describes which data you see, not how you see it. It’s a subtle distinction.

So, in our case, a “view” is the Python callback function for a particular URL, because that callback function describes which data is presented.

Furthermore, it’s sensible to separate content from presentation – which is where templates come in. In Django, a “view” describes which data is presented, but a view normally delegates to a template, which describes how the data is presented.

Where does the “controller” fit in, then? In Django’s case, it’s probably the framework itself: the machinery that sends a request to the appropriate view, according to the Django URL configuration.

If you’re hungry for acronyms, you might say that Django is a “MTV” framework – that is, “model”, “template”, and “view.” That breakdown makes much more sense.

At the end of the day, of course, it comes down to getting stuff done. And, regardless of how things are named, Django gets stuff done in a way that’s most logical to us.

<Framework X> does <feature Y> – why doesn’t Django?

We’re well aware that there are other awesome Web frameworks out there, and we’re not averse to borrowing ideas where appropriate. However, Django was developed precisely because we were unhappy with the status quo, so please be aware that “because <Framework X> does it” is not going to be sufficient reason to add a given feature to Django.

Why did you write all of Django from scratch, instead of using other Python libraries?

When Django was originally written a couple of years ago, Adrian and Simon spent quite a bit of time exploring the various Python Web frameworks available.

In our opinion, none of them were completely up to snuff.

We’re picky. You might even call us perfectionists. (With deadlines.)

Over time, we stumbled across open-source libraries that did things we’d already implemented. It was reassuring to see other people solving similar problems in similar ways, but it was too late to integrate outside code: We’d already written, tested and implemented our own framework bits in several production settings – and our own code met our needs delightfully.

In most cases, however, we found that existing frameworks/tools inevitably had some sort of fundamental, fatal flaw that made us squeamish. No tool fit our philosophies 100%.

Like we said: We’re picky.

We’ve documented our philosophies on the design philosophies page.

Is Django a content-management-system (CMS)?

No, Django is not a CMS, or any sort of “turnkey product” in and of itself. It’s a Web framework; it’s a programming tool that lets you build websites.

For example, it doesn’t make much sense to compare Django to something like Drupal, because Django is something you use to create things like Drupal.

Of course, Django’s automatic admin site is fantastic and timesaving – but the admin site is one module of Django the framework. Furthermore, although Django has special conveniences for building “CMS-y” apps, that doesn’t mean it’s not just as appropriate for building “non-CMS-y” apps (whatever that means!).

How can I download the Django documentation to read it offline?

The Django docs are available in the docs directory of each Django tarball release. These docs are in reST (reStructuredText) format, and each text file corresponds to a Web page on the official Django site.

Because the documentation is stored in revision control, you can browse documentation changes just like you can browse code changes.

Technically, the docs on Django’s site are generated from the latest development versions of those reST documents, so the docs on the Django site may offer more information than the docs that come with the latest Django release.

Where can I find Django developers for hire?

Consult our developers for hire page for a list of Django developers who would be happy to help you.

You might also be interested in posting a job to https://djangogigs.com/ . If you want to find Django-capable people in your local area, try https://people.djangoproject.com/ .

How do I cite Django?

It’s difficult to give an official citation format, for two reasons: citation formats can vary wildly between publications, and citation standards for software are still a matter of some debate.

For example, APA style, would dictate something like:

Django (Version 1.5) [Computer Software]. (2013). Retrieved from https://djangoproject.com.

However, the only true guide is what your publisher will accept, so get a copy of those guidelines and fill in the gaps as best you can.

If your referencing style guide requires a publisher name, use “Django Software Foundation”.

If you need a publishing location, use “Lawrence, Kansas”.

If you need a web address, use https://djangoproject.com.

If you need a name, just use “Django”, without any tagline.

If you need a publication date, use the year of release of the version you’re referencing (e.g., 2013 for v1.5)

FAQ: Installation

How do I get started?

1. Download the code.

2. Install Django (read the installation guide).

3. Walk through the tutorial.

4. Check out the rest of the documentation, and ask questions if you run into trouble.

What are Django’s prerequisites?

Django requires Python. See the table in the next question for the versions of Python that work with each version of Django. Other Python libraries may be required for some uses, but you’ll receive an error about it as they’re needed.

For a development environment – if you just want to experiment with Django – you don’t need to have a separate Web server installed; Django comes with its own lightweight development server. For a production environment, Django follows the WSGI spec, PEP 3333, which means it can run on a variety of server platforms. See Deploying Django for some popular alternatives.

If you want to use Django with a database, which is probably the case, you’ll also need a database engine. PostgreSQL is recommended, because we’re PostgreSQL fans, and MySQL, SQLite 3, and Oracle are also supported.

What Python version can I use with Django?

Django version

Python versions

1.8

2.7, 3.2 (until the end of 2016), 3.3, 3.4, 3.5

1.9, 1.10

2.7, 3.4, 3.5

For each version of Python, only the latest micro release (A.B.C) is officially supported. You can find the latest micro version for each series on the Python download page.

Typically, we will support a Python version up to and including the first Django LTS release whose security support ends after security support for that version of Python ends. For example, Python 3.3 security support ends September 2017 and Django 1.8 LTS security support ends April 2018. Therefore Django 1.8 is the last version to support Python 3.3.

What Python version should I use with Django?

As of Django 1.6, Python 3 support is considered stable and you can safely use it in production. See also Porting to Python 3. However, the community is still in the process of migrating third-party packages and applications to Python 3.

If you’re starting a new project, and the dependencies you plan to use work on Python 3, you should use Python 3. If they don’t, consider contributing to the porting efforts, or stick to Python 2.

Since newer versions of Python are often faster, have more features, and are better supported, all else being equal, we recommend that you use the latest 2.x.y or 3.x.y release.

You don’t lose anything in Django by using an older release, but you don’t take advantage of the improvements and optimizations in newer Python releases. Third-party applications for use with Django are, of course, free to set their own version requirements.

Should I use the stable version or development version?

Generally, if you’re using code in production, you should be using a stable release. The Django project publishes a full stable release every nine months or so, with bugfix updates in between. These stable releases contain the API that is covered by our backwards compatibility guarantees; if you write code against stable releases, you shouldn’t have any problems upgrading when the next official version is released.

FAQ: Using Django

Why do I get an error about importing DJANGO_SETTINGS_MODULE?

Make sure that:

- The environment variable DJANGO_SETTINGS_MODULE is set to a fully-qualified Python module (i.e. “mysite.settings”).

- Said module is on sys.path (import mysite.settings should work).

- The module doesn’t contain syntax errors (of course).

I can’t stand your template language. Do I have to use it?

We happen to think our template engine is the best thing since chunky bacon, but we recognize that choosing a template language runs close to religion. There’s nothing about Django that requires using the template language, so if you’re attached to Jinja2, Mako, or whatever, feel free to use those.

Do I have to use your model/database layer?

Nope. Just like the template system, the model/database layer is decoupled from the rest of the framework.

The one exception is: If you use a different database library, you won’t get to use Django’s automatically-generated admin site. That app is coupled to the Django database layer.

How do I use image and file fields?

Using a FileField or an ImageField in a model takes a few steps:

1. In your settings file, you’ll need to define MEDIA_ROOT as the full path to a directory where you’d like Django to store uploaded files. (For performance, these files are not stored in the database.) Define MEDIA_URL as the base public URL of that directory. Make sure that this directory is writable by the Web server’s user account.

2. Add the FileField or ImageField to your model, defining the upload_to option to specify a subdirectory of MEDIA_ROOT to use for uploaded files.

3. All that will be stored in your database is a path to the file (relative to MEDIA_ROOT). You’ll most likely want to use the convenience url attribute provided by Django. For example, if your ImageField is called mug_shot, you can get the absolute path to your image in a template with {{ object.mug_shot.url }}.

How do I make a variable available to all my templates?

Sometimes your templates just all need the same thing. A common example would be dynamically-generated menus. At first glance, it seems logical to simply add a common dictionary to the template context.

The correct solution is to use a RequestContext. Details on how to do this are here: Subclassing Context: RequestContext.

FAQ: Getting Help

How do I do X? Why doesn’t Y work? Where can I go to get help?

If this FAQ doesn’t contain an answer to your question, you might want to try the django-users mailing list. Feel free to ask any question related to installing, using, or debugging Django.

If you prefer IRC, the #django IRC channel on the Freenode IRC network is an active community of helpful individuals who may be able to solve your problem.

Why hasn’t my message appeared on django-users?

django-users has a lot of subscribers. This is good for the community, as it means many people are available to contribute answers to questions. Unfortunately, it also means that django-users is an attractive target for spammers.

In order to combat the spam problem, when you join the django-users mailing list, we manually moderate the first message you send to the list. This means that spammers get caught, but it also means that your first question to the list might take a little longer to get answered. We apologize for any inconvenience that this policy may cause.

Nobody on django-users answered my question! What should I do?

Try making your question more specific, or provide a better example of your problem.

As with most open-source mailing lists, the folks on django-users are volunteers. If nobody has answered your question, it may be because nobody knows the answer, it may be because nobody can understand the question, or it may be that everybody that can help is busy. One thing you might try is to ask the question on IRC – visit the #django IRC channel on the Freenode IRC network.

You might notice we have a second mailing list, called django-developers – but please don’t email support questions to this mailing list. This list is for discussion of the development of Django itself. Asking a tech support question there is considered quite impolite.

I think I’ve found a bug! What should I do?

Detailed instructions on how to handle a potential bug can be found in our Guide to contributing to Django.

I think I’ve found a security problem! What should I do?

If you think you’ve found a security problem with Django, please send a message to security@djangoproject.com. This is a private list only open to long-time, highly trusted Django developers, and its archives are not publicly readable.

Due to the sensitive nature of security issues, we ask that if you think you have found a security problem, please don’t send a message to one of the public mailing lists. Django has a policy for handling security issues; while a defect is outstanding, we would like to minimize any damage that could be inflicted through public knowledge of that defect.

FAQ: Databases and models

How can I see the raw SQL queries Django is running?

Make sure your Django DEBUG setting is set to True. Then, just do this:

>>> from django.db import connection
>>> connection.queries
[{'sql': 'SELECT polls_polls.id, polls_polls.question, polls_polls.pub_date FROM polls_polls',
'time': '0.002'}]

connection.queries is only available if DEBUG is True. It’s a list of dictionaries in order of query execution. Each dictionary has the following:

``sql`` -- The raw SQL statement
``time`` -- How long the statement took to execute, in seconds.

connection.queries includes all SQL statements – INSERTs, UPDATES, SELECTs, etc. Each time your app hits the database, the query will be recorded.

If you are using multiple databases, you can use the same interface on each member of the connections dictionary:

>>> from django.db import connections
>>> connections['my_db_alias'].queries

If you need to clear the query list manually at any point in your functions, just call reset_queries(), like this:

from django.db import reset_queries
reset_queries()

Can I use Django with a pre-existing database?

Yes. See Integrating with a legacy database.

If I make changes to a model, how do I update the database?

Take a look at Django’s support for schema migrations.

If you don’t mind clearing data, your project’s manage.py utility has a flush option to reset the database to the state it was in immediately after migrate was executed.

Do Django models support multiple-column primary keys?

No. Only single-column primary keys are supported.

But this isn’t an issue in practice, because there’s nothing stopping you from adding other constraints (using the unique_together model option or creating the constraint directly in your database), and enforcing the uniqueness at that level. Single-column primary keys are needed for things such as the admin interface to work; e.g., you need a simple way of being able to specify an object to edit or delete.

Does Django support NoSQL databases?

NoSQL databases are not officially supported by Django itself. There are, however, a number of side project and forks which allow NoSQL functionality in Django, like Django non-rel.

You can also take a look on the wiki page which discusses some alternatives.

How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?

We try to avoid adding special cases in the Django code to accommodate all the database-specific options such as table type, etc. If you’d like to use any of these options, create a migration with a RunSQL operation that contains ALTER TABLE statements that do what you want to do.

For example, if you’re using MySQL and want your tables to use the MyISAM table type, use the following SQL:

ALTER TABLE myapp_mytable ENGINE=MyISAM;

FAQ: The admin

I can’t log in. When I enter a valid username and password, it just brings up the login page again, with no error messages.

The login cookie isn’t being set correctly, because the domain of the cookie sent out by Django doesn’t match the domain in your browser. Try setting the SESSION_COOKIE_DOMAIN setting to match your domain. For example, if you’re going to “https://www.example.com/admin/” in your browser, set SESSION_COOKIE_DOMAIN = 'www.example.com'.

I can’t log in. When I enter a valid username and password, it brings up the login page again, with a “Please enter a correct username and password” error.

If you’re sure your username and password are correct, make sure your user account has is_active and is_staff set to True. The admin site only allows access to users with those two fields both set to True.

How do I automatically set a field’s value to the user who last edited the object in the admin?

The ModelAdmin class provides customization hooks that allow you to transform an object as it saved, using details from the request. By extracting the current user from the request, and customizing the save_model() hook, you can update an object to reflect the user that edited it. See the documentation on ModelAdmin methods for an example.

How do I limit admin access so that objects can only be edited by the users who created them?

The ModelAdmin class also provides customization hooks that allow you to control the visibility and editability of objects in the admin. Using the same trick of extracting the user from the request, the get_queryset() and has_change_permission() can be used to control the visibility and editability of objects in the admin.

My admin-site CSS and images showed up fine using the development server, but they’re not displaying when using mod_wsgi.

See serving the admin files in the “How to use Django with mod_wsgi” documentation.

My “list_filter” contains a ManyToManyField, but the filter doesn’t display.

Django won’t bother displaying the filter for a ManyToManyField if there are fewer than two related objects.

For example, if your list_filter includes sites, and there’s only one site in your database, it won’t display a “Site” filter. In that case, filtering by site would be meaningless.

Some objects aren’t appearing in the admin.

Inconsistent row counts may be caused by missing foreign key values or a foreign key field incorrectly set to null=False. If you have a record with a ForeignKey pointing to a non-existent object and that foreign key is included is list_display, the record will not be shown in the admin changelist because the Django model is declaring an integrity constraint that is not implemented at the database level.

How can I customize the functionality of the admin interface?

You’ve got several options. If you want to piggyback on top of an add/change form that Django automatically generates, you can attach arbitrary JavaScript modules to the page via the model’s class Admin js parameter. That parameter is a list of URLs, as strings, pointing to JavaScript modules that will be included within the admin form via a <script> tag.

If you want more flexibility than simply tweaking the auto-generated forms, feel free to write custom views for the admin. The admin is powered by Django itself, and you can write custom views that hook into the authentication system, check permissions and do whatever else they need to do.

If you want to customize the look-and-feel of the admin interface, read the next question.

The dynamically-generated admin site is ugly! How can I change it?

We like it, but if you don’t agree, you can modify the admin site’s presentation by editing the CSS stylesheet and/or associated image files. The site is built using semantic HTML and plenty of CSS hooks, so any changes you’d like to make should be possible by editing the stylesheet.

What browsers are supported for using the admin?

The admin provides a fully-functional experience to YUI’s A-grade browsers, with the notable exception of IE6, which is not supported.

There may be minor stylistic differences between supported browsers—for example, some browsers may not support rounded corners. These are considered acceptable variations in rendering.

FAQ: Contributing code

How can I get started contributing code to Django?

Thanks for asking! We’ve written an entire document devoted to this question. It’s titled Contributing to Django.

I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?

Don’t worry: We’re not ignoring you!

It’s important to understand there is a difference between “a ticket is being ignored” and “a ticket has not been attended to yet.” Django’s ticket system contains hundreds of open tickets, of various degrees of impact on end-user functionality, and Django’s developers have to review and prioritize.

On top of that: the people who work on Django are all volunteers. As a result, the amount of time that we have to work on the framework is limited and will vary from week to week depending on our spare time. If we’re busy, we may not be able to spend as much time on Django as we might want.

The best way to make sure tickets do not get hung up on the way to checkin is to make it dead easy, even for someone who may not be intimately familiar with that area of the code, to understand the problem and verify the fix:

- Are there clear instructions on how to reproduce the bug? If this touches a dependency (such as Pillow), a contrib module, or a specific database, are those instructions clear enough even for someone not familiar with it?

- If there are several patches attached to the ticket, is it clear what each one does, which ones can be ignored and which matter?

- Does the patch include a unit test? If not, is there a very clear explanation why not? A test expresses succinctly what the problem is, and shows that the patch actually fixes it.

If your patch stands no chance of inclusion in Django, we won’t ignore it – we’ll just close the ticket. So if your ticket is still open, it doesn’t mean we’re ignoring you; it just means we haven’t had time to look at it yet.

When and how might I remind the core team of a patch I care about?

A polite, well-timed message to the mailing list is one way to get attention. To determine the right time, you need to keep an eye on the schedule. If you post your message when the core developers are trying to hit a feature deadline or manage a planning phase, you’re not going to get the sort of attention you require. However, if you draw attention to a ticket when the core developers are paying particular attention to bugs – just before a bug fixing sprint, or in the lead up to a beta release for example – you’re much more likely to get a productive response.

Gentle IRC reminders can also work – again, strategically timed if possible. During a bug sprint would be a very good time, for example.

Another way to get traction is to pull several related tickets together. When the core developers sit down to fix a bug in an area they haven’t touched for a while, it can take a few minutes to remember all the fine details of how that area of code works. If you collect several minor bug fixes together into a similarly themed group, you make an attractive target, as the cost of coming up to speed on an area of code can be spread over multiple tickets.

Please refrain from emailing core developers personally, or repeatedly raising the same issue over and over. This sort of behavior will not gain you any additional attention – certainly not the attention that you need in order to get your pet bug addressed.

But I’ve reminded you several times and you keep ignoring my patch!

Seriously - we’re not ignoring you. If your patch stands no chance of inclusion in Django, we’ll close the ticket. For all the other tickets, we need to prioritize our efforts, which means that some tickets will be addressed before others.

One of the criteria that is used to prioritize bug fixes is the number of people that will likely be affected by a given bug. Bugs that have the potential to affect many people will generally get priority over those that are edge cases.

Another reason that bugs might be ignored for while is if the bug is a symptom of a larger problem. While we can spend time writing, testing and applying lots of little patches, sometimes the right solution is to rebuild. If a rebuild or refactor of a particular component has been proposed or is underway, you may find that bugs affecting that component will not get as much attention. Again, this is just a matter of prioritizing scarce resources. By concentrating on the rebuild, we can close all the little bugs at once, and hopefully prevent other little bugs from appearing in the future.

Whatever the reason, please keep in mind that while you may hit a particular bug regularly, it doesn’t necessarily follow that every single Django user will hit the same bug. Different users use Django in different ways, stressing different parts of the code under different conditions. When we evaluate the relative priorities, we are generally trying to consider the needs of the entire community, not just the severity for one particular user. This doesn’t mean that we think your problem is unimportant – just that in the limited time we have available, we will always err on the side of making 10 people happy rather than making 1 person happy.

Troubleshooting

This page contains some advice about errors and problems commonly encountered during the development of Django applications.

Problems running django-admin

“command not found: django-admin”

django-admin should be on your system path if you installed Django via python setup.py. If it’s not on your path, you can find it in site-packages/django/bin, where site-packages is a directory within your Python installation. Consider symlinking to django-admin from some place on your path, such as /usr/local/bin.

If django-admin doesn’t work but django-admin.py does, you’re probably using a version of Django that doesn’t match the version of this documentation. django-admin is new in Django 1.7.

Mac OS X permissions

If you’re using Mac OS X, you may see the message “permission denied” when you try to run django-admin. This is because, on Unix-based systems like OS X, a file must be marked as “executable” before it can be run as a program. To do this, open Terminal.app and navigate (using the cd command) to the directory where django-admin is installed, then run the command sudo chmod +x django-admin.

Miscellaneous

I’m getting a UnicodeDecodeError. What am I doing wrong?

This class of errors happen when a bytestring containing non-ASCII sequences is transformed into a Unicode string and the specified encoding is incorrect. The output generally looks like this:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x?? in position ?:
ordinal not in range(128)

The resolution mostly depends on the context, however here are two common pitfalls producing this error:

- Your system locale may be a default ASCII locale, like the “C” locale on UNIX-like systems (can be checked by the locale command). If it’s the case, please refer to your system documentation to learn how you can change this to a UTF-8 locale.

- You created raw bytestrings, which is easy to do on Python 2:

my_string = 'café'

Either use the u'' prefix or even better, add the from __future__ import unicode_literals line at the top of your file so that your code will be compatible with Python 3.2 which doesn’t support the u'' prefix.

Related resources:

- Unicode in Django

- https://wiki.python.org/moin/UnicodeDecodeError

API Reference

- Applications

- System check framework

- Built-in class-based views API

- Clickjacking Protection

- contrib packages

- Cross Site Request Forgery protection

- Databases

- django-admin and manage.py

- Running management commands from your code

- Django Exceptions

- File handling

- Forms

- Middleware

- Migration Operations

- Models

- Request and response objects

- SchemaEditor

- Settings

- Signals

- Templates

- TemplateResponse and SimpleTemplateResponse

- Unicode data

- django.core.urlresolvers utility functions

- django.conf.urls utility functions

- Django Utils

- Validators

- Built-in Views

Applications

Django contains a registry of installed applications that stores configuration and provides introspection. It also maintains a list of available models.

This registry is simply called apps and it’s available in django.apps:

>>> from django.apps import apps
>>> apps.get_app_config('admin').verbose_name
'Admin'

Projects and applications

The term project describes a Django web application. The project Python package is defined primarily by a settings module, but it usually contains other things. For example, when you run django-admin startproject mysite you’ll get a mysite project directory that contains a mysite Python package with settings.py, urls.py, and wsgi.py. The project package is often extended to include things like fixtures, CSS, and templates which aren’t tied to a particular application.

A project’s root directory (the one that contains manage.py) is usually the container for all of a project’s applications which aren’t installed separately.

The term application describes a Python package that provides some set of features. Applications may be reused in various projects.

Applications include some combination of models, views, templates, template tags, static files, URLs, middleware, etc. They’re generally wired into projects with the INSTALLED_APPS setting and optionally with other mechanisms such as URLconfs, the MIDDLEWARE_CLASSES setting, or template inheritance.

It is important to understand that a Django application is just a set of code that interacts with various parts of the framework. There’s no such thing as an Application object. However, there’s a few places where Django needs to interact with installed applications, mainly for configuration and also for introspection. That’s why the application registry maintains metadata in an AppConfig instance for each installed application.

There’s no restriction that a project package can’t also be considered an application and have models, etc. (which would require adding it to INSTALLED_APPS).

Configuring applications

To configure an application, subclass AppConfig and put the dotted path to that subclass in INSTALLED_APPS.

When INSTALLED_APPS simply contains the dotted path to an application module, Django checks for a default_app_config variable in that module.

If it’s defined, it’s the dotted path to the AppConfig subclass for that application.

If there is no default_app_config, Django uses the base AppConfig class.

default_app_config allows applications that predate Django 1.7 such as django.contrib.admin to opt-in to AppConfig features without requiring users to update their INSTALLED_APPS.

New applications should avoid default_app_config. Instead they should require the dotted path to the appropriate AppConfig subclass to be configured explicitly in INSTALLED_APPS.

For application authors

If you’re creating a pluggable app called “Rock ’n’ roll”, here’s how you would provide a proper name for the admin:

# rock_n_roll/apps.py

from django.apps import AppConfig

class RockNRollConfig(AppConfig):
name = 'rock_n_roll'
verbose_name = "Rock ’n’ roll"

You can make your application load this AppConfig subclass by default as follows:

# rock_n_roll/__init__.py

default_app_config = 'rock_n_roll.apps.RockNRollConfig'

That will cause RockNRollConfig to be used when INSTALLED_APPS just contains 'rock_n_roll'. This allows you to make use of AppConfig features without requiring your users to update their INSTALLED_APPS setting. Besides this use case, it’s best to avoid using default_app_config and instead specify the app config class in INSTALLED_APPS as described next.

Of course, you can also tell your users to put 'rock_n_roll.apps.RockNRollConfig' in their INSTALLED_APPS setting. You can even provide several different AppConfig subclasses with different behaviors and allow your users to choose one via their INSTALLED_APPS setting.

The recommended convention is to put the configuration class in a submodule of the application called apps. However, this isn’t enforced by Django.

You must include the name attribute for Django to determine which application this configuration applies to. You can define any attributes documented in the AppConfig API reference.

Note

If your code imports the application registry in an application’s __init__.py, the name apps will clash with the apps submodule. The best practice is to move that code to a submodule and import it. A workaround is to import the registry under a different name:

from django.apps import apps as django_apps

For application users

If you’re using “Rock ’n’ roll” in a project called anthology, but you want it to show up as “Jazz Manouche” instead, you can provide your own configuration:

# anthology/apps.py

from rock_n_roll.apps import RockNRollConfig

class JazzManoucheConfig(RockNRollConfig):
verbose_name = "Jazz Manouche"

# anthology/settings.py

INSTALLED_APPS = [
'anthology.apps.JazzManoucheConfig',
# ...
]

Again, defining project-specific configuration classes in a submodule called apps is a convention, not a requirement.

Application configuration

class AppConfig[source]

Application configuration objects store metadata for an application. Some attributes can be configured in AppConfig subclasses. Others are set by Django and read-only.

Configurable attributes

AppConfig.name

Full Python path to the application, e.g. 'django.contrib.admin'.

This attribute defines which application the configuration applies to. It must be set in all AppConfig subclasses.

It must be unique across a Django project.

AppConfig.label

Short name for the application, e.g. 'admin'

This attribute allows relabeling an application when two applications have conflicting labels. It defaults to the last component of name. It should be a valid Python identifier.

It must be unique across a Django project.

AppConfig.verbose_name

Human-readable name for the application, e.g. “Administration”.

This attribute defaults to label.title().

AppConfig.path

Filesystem path to the application directory, e.g. '/usr/lib/python3.4/dist-packages/django/contrib/admin'.

In most cases, Django can automatically detect and set this, but you can also provide an explicit override as a class attribute on your AppConfig subclass. In a few situations this is required; for instance if the app package is a namespace package with multiple paths.

Read-only attributes

AppConfig.module

Root module for the application, e.g. <module 'django.contrib.admin' from 'django/contrib/admin/__init__.pyc'>.

AppConfig.models_module

Module containing the models, e.g. <module 'django.contrib.admin.models' from 'django/contrib/admin/models.pyc'>.

It may be None if the application doesn’t contain a models module. Note that the database related signals such as pre_migrate and post_migrate are only emitted for applications that have a models module.

Methods

AppConfig.get_models()[source]

Returns an iterable of Model classes for this application.

AppConfig.get_model(model_name)[source]

Returns the Model with the given model_name. Raises LookupError if no such model exists in this application. model_name is case-insensitive.

AppConfig.ready()[source]

Subclasses can override this method to perform initialization tasks such as registering signals. It is called as soon as the registry is fully populated.

You cannot import models in modules that define application configuration classes, but you can use get_model() to access a model class by name, like this:

def ready(self):
MyModel = self.get_model('MyModel')

Warning

Although you can access model classes as described above, avoid interacting with the database in your ready() implementation. This includes model methods that execute queries (save(), delete(), manager methods etc.), and also raw SQL queries via django.db.connection. Your ready() method will run during startup of every management command. For example, even though the test database configuration is separate from the production settings, manage.py test would still execute some queries against your production database!

Note

In the usual initialization process, the ready method is only called once by Django. But in some corner cases, particularly in tests which are fiddling with installed applications, ready might be called more than once. In that case, either write idempotent methods, or put a flag on your AppConfig classes to prevent re-running code which should be executed exactly one time.

Namespace packages as apps (Python 3.3+)

Python versions 3.3 and later support Python packages without an __init__.py file. These packages are known as “namespace packages” and may be spread across multiple directories at different locations on sys.path (see PEP 420).

Django applications require a single base filesystem path where Django (depending on configuration) will search for templates, static assets, etc. Thus, namespace packages may only be Django applications if one of the following is true:

1. The namespace package actually has only a single location (i.e. is not spread across more than one directory.)

2. The AppConfig class used to configure the application has a path class attribute, which is the absolute directory path Django will use as the single base path for the application.

If neither of these conditions is met, Django will raise ImproperlyConfigured.

Application registry

apps

The application registry provides the following public API. Methods that aren’t listed below are considered private and may change without notice.

apps.ready

Boolean attribute that is set to True after the registry is fully populated and all AppConfig.ready() methods are called.

apps.get_app_configs()

Returns an iterable of AppConfig instances.

apps.get_app_config(app_label)

Returns an AppConfig for the application with the given app_label. Raises LookupError if no such application exists.

apps.is_installed(app_name)

Checks whether an application with the given name exists in the registry. app_name is the full name of the app, e.g. 'django.contrib.admin'.

apps.get_model(app_label, model_name)

Returns the Model with the given app_label and model_name. As a shortcut, this method also accepts a single argument in the form app_label.model_name. model_name is case- insensitive.

Raises LookupError if no such application or model exists. Raises ValueError when called with a single argument that doesn’t contain exactly one dot.

Initialization process

How applications are loaded

When Django starts, django.setup() is responsible for populating the application registry.

setup()[source]

Configures Django by:

- Loading the settings.

- Setting up logging.

- Initializing the application registry.

This function is called automatically:

- When running an HTTP server via Django’s WSGI support.

- When invoking a management command.

It must be called explicitly in other cases, for instance in plain Python scripts.

The application registry is initialized in three stages. At each stage, Django processes all applications in the order of INSTALLED_APPS.

1. First Django imports each item in INSTALLED_APPS.

If it’s an application configuration class, Django imports the root package of the application, defined by its name attribute. If it’s a Python package, Django creates a default application configuration.

At this stage, your code shouldn’t import any models!

In other words, your applications’ root packages and the modules that define your application configuration classes shouldn’t import any models, even indirectly.

Strictly speaking, Django allows importing models once their application configuration is loaded. However, in order to avoid needless constraints on the order of INSTALLED_APPS, it’s strongly recommended not import any models at this stage.

Once this stage completes, APIs that operate on application configurations such as get_app_config() become usable.

2. Then Django attempts to import the models submodule of each application, if there is one.

You must define or import all models in your application’s models.py or models/__init__.py. Otherwise, the application registry may not be fully populated at this point, which could cause the ORM to malfunction.

Once this stage completes, APIs that operate on models such as get_model() become usable.

3. Finally Django runs the ready() method of each application configuration.

Troubleshooting

Here are some common problems that you may encounter during initialization:

- AppRegistryNotReady This happens when importing an application configuration or a models module triggers code that depends on the app registry.

For example, ugettext() uses the app registry to look up translation catalogs in applications. To translate at import time, you need ugettext_lazy() instead. (Using ugettext() would be a bug, because the translation would happen at import time, rather than at each request depending on the active language.)

Executing database queries with the ORM at import time in models modules will also trigger this exception. The ORM cannot function properly until all models are available.

Another common culprit is django.contrib.auth.get_user_model(). Use the AUTH_USER_MODEL setting to reference the User model at import time.

This exception also happens if you forget to call django.setup() in a standalone Python script.

- ImportError: cannot import name ... This happens if the import sequence ends up in a loop.

To eliminate such problems, you should minimize dependencies between your models modules and do as little work as possible at import time. To avoid executing code at import time, you can move it into a function and cache its results. The code will be executed when you first need its results. This concept is known as “lazy evaluation”.

- django.contrib.admin automatically performs autodiscovery of admin modules in installed applications. To prevent it, change your INSTALLED_APPS to contain 'django.contrib.admin.apps.SimpleAdminConfig' instead of 'django.contrib.admin'.

System check framework

The system check framework is a set of static checks for validating Django projects. It detects common problems and provides hints for how to fix them. The framework is extensible so you can easily add your own checks.

For details on how to add your own checks and integrate them with Django’s system checks, see the System check topic guide.

API Reference

CheckMessage

class CheckMessage(level, msg, hint, obj=None, id=None)[source]

The warnings and errors raised by system checks must be instances of CheckMessage. An instance encapsulates a single reportable error or warning. It also provides context and hints applicable to the message, and a unique identifier that is used for filtering purposes.

Constructor arguments are:

level

The severity of the message. Use one of the predefined values: DEBUG, INFO, WARNING, ERROR, CRITICAL. If the level is greater or equal to ERROR, then Django will prevent management commands from executing. Messages with level lower than ERROR (i.e. warnings) are reported to the console, but can be silenced.

msg

A short (less than 80 characters) string describing the problem. The string should not contain newlines.

hint

A single-line string providing a hint for fixing the problem. If no hint can be provided, or the hint is self-evident from the error message, the hint can be omitted, or a value of None can be used.

obj

Optional. An object providing context for the message (for example, the model where the problem was discovered). The object should be a model, field, or manager or any other object that defines __str__ method (on Python 2 you need to define __unicode__ method). The method is used while reporting all messages and its result precedes the message.

id

Optional string. A unique identifier for the issue. Identifiers should follow the pattern applabel.X001, where X is one of the letters CEWID, indicating the message severity (C for criticals, E for errors and so). The number can be allocated by the application, but should be unique within that application.

There are subclasses to make creating messages with common levels easier. When using them you can omit the level argument because it is implied by the class name.

class Debug(msg, hint, obj=None, id=None)[source]

class Info(msg, hint, obj=None, id=None)[source]

class Warning(msg, hint, obj=None, id=None)[source]

class Error(msg, hint, obj=None, id=None)[source]

class Critical(msg, hint, obj=None, id=None)[source]

Builtin checks

Builtin tags

Django’s system checks are organized using the following tags:

- models: Checks governing model, field and manager definitions.

- signals: Checks on signal declarations and handler registrations.

- admin: Checks of any admin site declarations.

- compatibility: Flagging potential problems with version upgrades.

- security: Checks security related configuration.

- templates: Checks template related configuration.

- caches: Checks cache related configuration.

- urls: Checks URL configuration.

Some checks may be registered with multiple tags.

Core system checks

Models

- models.E001: <swappable> is not of the form app_label.app_name.

- models.E002: <SETTING> references <model>, which has not been installed, or is abstract.

- models.E003: The model has two many-to-many relations through the intermediate model <app_label>.<model>.

- models.E004: id can only be used as a field name if the field also sets primary_key=True.

- models.E005: The field <field name> from parent model <model> clashes with the field <field name> from parent model <model>.

- models.E006: The field clashes with the field <field name> from model <model>.

- models.E007: Field <field name> has column name <column name> that is used by another field.

- models.E008: index_together must be a list or tuple.

- models.E009: All index_together elements must be lists or tuples.

- models.E010: unique_together must be a list or tuple.

- models.E011: All unique_together elements must be lists or tuples.

- models.E012: index_together/unique_together refers to the non-existent field <field name>.

- models.E013: index_together/unique_together refers to a ManyToManyField <field name>, but ManyToManyFields are not supported for that option.

- models.E014: ordering must be a tuple or list (even if you want to order by only one field).

- models.E015: ordering refers to the non-existent field <field name>.

- models.E016: index_together/unique_together refers to field <field_name> which is not local to model <model>.

- models.E017: Proxy model <model> contains model fields.

- models.E018: Autogenerated column name too long for field <field>. Maximum length is <maximum length> for database <alias>.

- models.E019: Autogenerated column name too long for M2M field <M2M field>. Maximum length is <maximum length> for database <alias>.

- models.E020: The <model>.check() class method is currently overridden.

- models.E021: ordering and order_with_respect_to cannot be used together.

Fields

- fields.E001: Field names must not end with an underscore.

- fields.E002: Field names must not contain "__".

- fields.E003: pk is a reserved word that cannot be used as a field name.

- fields.E004: choices must be an iterable (e.g., a list or tuple).

- fields.E005: choices must be an iterable returning (actual value, human readable name) tuples.

- fields.E006: db_index must be None, True or False.

- fields.E007: Primary keys must not have null=True.

- fields.E100: AutoFields must set primary_key=True.

- fields.E110: BooleanFields do not accept null values.

- fields.E120: CharFields must define a max_length attribute.

- fields.E121: max_length must be a positive integer.

- fields.W122: max_length is ignored when used with IntegerField.

- fields.E130: DecimalFields must define a decimal_places attribute.

- fields.E131: decimal_places must be a non-negative integer.

- fields.E132: DecimalFields must define a max_digits attribute.

- fields.E133: max_digits must be a non-negative integer.

- fields.E134: max_digits must be greater or equal to decimal_places.

- fields.E140: FilePathFields must have either allow_files or allow_folders set to True.

- fields.E150: GenericIPAddressFields cannot accept blank values if null values are not allowed, as blank values are stored as nulls.

- fields.E160: The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.

- fields.W161: Fixed default value provided.

- fields.E900: IPAddressField has been removed except for support in historical migrations.

- fields.W900: IPAddressField has been deprecated. Support for it (except in historical migrations) will be removed in Django 1.9. This check appeared in Django 1.7 and 1.8.

File Fields

- fields.E200: unique is not a valid argument for a FileField.

- fields.E201: primary_key is not a valid argument for a FileField.

- fields.E210: Cannot use ImageField because Pillow is not installed.

Related Fields

- fields.E300: Field defines a relation with model <model>, which is either not installed, or is abstract.

- fields.E301: Field defines a relation with the model <model> which has been swapped out.

- fields.E302: Accessor for field <field name> clashes with field <field name>.

- fields.E303: Reverse query name for field <field name> clashes with field <field name>.

- fields.E304: Field name <field name> clashes with accessor for <field name>.

- fields.E305: Field name <field name> clashes with reverse query name for <field name>.

- fields.E306: Related name must be a valid Python identifier or end with a '+'.

- fields.E310: No subset of the fields <field1>, <field2>, ... on model <model> is unique. Add unique=True on any of those fields or add at least a subset of them to a unique_together constraint.

- fields.E311: <model> must set unique=True because it is referenced by a ForeignKey.

- fields.E320: Field specifies on_delete=SET_NULL, but cannot be null.

- fields.E321: The field specifies on_delete=SET_DEFAULT, but has no default value.

- fields.E330: ManyToManyFields cannot be unique.

- fields.E331: Field specifies a many-to-many relation through model <model>, which has not been installed.

- fields.E332: Many-to-many fields with intermediate tables must not be symmetrical.

- fields.E333: The model is used as an intermediate model by <model>, but it has more than two foreign keys to <model>, which is ambiguous. You must specify which two foreign keys Django should use via the through_fields keyword argument.

- fields.E334: The model is used as an intermediate model by <model>, but it has more than one foreign key from <model>, which is ambiguous. You must specify which foreign key Django should use via the through_fields keyword argument.

- fields.E335: The model is used as an intermediate model by <model>, but it has more than one foreign key to <model>, which is ambiguous. You must specify which foreign key Django should use via the through_fields keyword argument.

- fields.E336: The model is used as an intermediary model by <model>, but it does not have foreign key to <model> or <model>.

- fields.E337: Field specifies through_fields but does not provide the names of the two link fields that should be used for the relation through <model>.

- fields.E338: The intermediary model <through model> has no field <field name>.

- fields.E339: <model>.<field name> is not a foreign key to <model>.

- fields.W340: null has no effect on ManyToManyField.

- fields.W341: ManyToManyField does not support validators.

- fields.W342: Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.

Signals

- signals.E001: <handler> was connected to the <signal> signal with a lazy reference to the <model> sender, which has not been installed.

Backwards Compatibility

The following checks are performed to warn the user of any potential problems that might occur as a result of a version upgrade.

- 1_6.W001: Some project unit tests may not execute as expected. This check was removed in Django 1.8 due to false positives.

- 1_6.W002: BooleanField does not have a default value. This check was removed in Django 1.8 due to false positives.

- 1_7.W001: Django 1.7 changed the global defaults for the MIDDLEWARE_CLASSES. django.contrib.sessions.middleware.SessionMiddleware, django.contrib.auth.middleware.AuthenticationMiddleware, and django.contrib.messages.middleware.MessageMiddleware were removed from the defaults. If your project needs these middleware then you should configure this setting. This check was removed in Django 1.9.

- 1_8.W001: The standalone TEMPLATE_* settings were deprecated in Django 1.8 and the TEMPLATES dictionary takes precedence. You must put the values of the following settings into your defaults TEMPLATES dict: TEMPLATE_DIRS, ALLOWED_INCLUDE_ROOTS, TEMPLATE_CONTEXT_PROCESSORS, TEMPLATE_DEBUG, TEMPLATE_LOADERS, TEMPLATE_STRING_IF_INVALID.

Admin

Admin checks are all performed as part of the admin tag.

The following checks are performed on any ModelAdmin (or subclass) that is registered with the admin site:

- admin.E001: The value of raw_id_fields must be a list or tuple.

- admin.E002: The value of raw_id_fields[n] refers to <field name>, which is not an attribute of <model>.

- admin.E003: The value of raw_id_fields[n] must be a ForeignKey or ManyToManyField.

- admin.E004: The value of fields must be a list or tuple.

- admin.E005: Both fieldsets and fields are specified.

- admin.E006: The value of fields contains duplicate field(s).

- admin.E007: The value of fieldsets must be a list or tuple.

- admin.E008: The value of fieldsets[n] must be a list or tuple.

- admin.E009: The value of fieldsets[n] must be of length 2.

- admin.E010: The value of fieldsets[n][1] must be a dictionary.

- admin.E011: The value of fieldsets[n][1] must contain the key fields.

- admin.E012: There are duplicate field(s) in fieldsets[n][1].

- admin.E013: fields[n]/fieldsets[n][m] cannot include the ManyToManyField <field name>, because that field manually specifies a relationship model.

- admin.E014: The value of exclude must be a list or tuple.

- admin.E015: The value of exclude contains duplicate field(s).

- admin.E016: The value of form must inherit from BaseModelForm.

- admin.E017: The value of filter_vertical must be a list or tuple.

- admin.E018: The value of filter_horizontal must be a list or tuple.

- admin.E019: The value of filter_vertical[n]/filter_vertical[n] refers to <field name>, which is not an attribute of <model>.

- admin.E020: The value of filter_vertical[n]/filter_vertical[n] must be a ManyToManyField.

- admin.E021: The value of radio_fields must be a dictionary.

- admin.E022: The value of radio_fields refers to <field name>, which is not an attribute of <model>.

- admin.E023: The value of radio_fields refers to <field name>, which is not a ForeignKey, and does not have a choices definition.

- admin.E024: The value of radio_fields[<field name>] must be either admin.HORIZONTAL or admin.VERTICAL.

- admin.E025: The value of view_on_site must be either a callable or a boolean value.

- admin.E026: The value of prepopulated_fields must be a dictionary.

- admin.E027: The value of prepopulated_fields refers to <field name>, which is not an attribute of <model>.

- admin.E028: The value of prepopulated_fields refers to <field name>, which must not be a DateTimeField, ForeignKey or ManyToManyField.

- admin.E029: The value of prepopulated_fields[<field name>] must be a list or tuple.

- admin.E030: The value of prepopulated_fields refers to <field name>, which is not an attribute of <model>.

- admin.E031: The value of ordering must be a list or tuple.

- admin.E032: The value of ordering has the random ordering marker ?, but contains other fields as well.

- admin.E033: The value of ordering refers to <field name>, which is not an attribute of <model>.

- admin.E034: The value of readonly_fields must be a list or tuple.

- admin.E035: The value of readonly_fields[n] is not a callable, an attribute of <ModelAdmin class>, or an attribute of <model>.

ModelAdmin

The following checks are performed on any ModelAdmin that is registered with the admin site:

- admin.E101: The value of save_as must be a boolean.

- admin.E102: The value of save_on_top must be a boolean.

- admin.E103: The value of inlines must be a list or tuple.

- admin.E104: <InlineModelAdmin class> must inherit from BaseModelAdmin.

- admin.E105: <InlineModelAdmin class> must have a model attribute.

- admin.E106: The value of <InlineModelAdmin class>.model must be a Model.

- admin.E107: The value of list_display must be a list or tuple.

- admin.E108: The value of list_display[n] refers to <label>, which is not a callable, an attribute of <ModelAdmin class>, or an attribute or method on <model>.

- admin.E109: The value of list_display[n] must not be a ManyToManyField.

- admin.E110: The value of list_display_links must be a list, a tuple, or None.

- admin.E111: The value of list_display_links[n] refers to <label>, which is not defined in list_display.

- admin.E112: The value of list_filter must be a list or tuple.

- admin.E113: The value of list_filter[n] must inherit from ListFilter.

- admin.E114: The value of list_filter[n] must not inherit from FieldListFilter.

- admin.E115: The value of list_filter[n][1] must inherit from FieldListFilter.

- admin.E116: The value of list_filter[n] refers to <label>, which does not refer to a Field.

- admin.E117: The value of list_select_related must be a boolean, tuple or list.

- admin.E118: The value of list_per_page must be an integer.

- admin.E119: The value of list_max_show_all must be an integer.

- admin.E120: The value of list_editable must be a list or tuple.

- admin.E121: The value of list_editable[n] refers to <label>, which is not an attribute of <model>.

- admin.E122: The value of list_editable[n] refers to <label>, which is not contained in list_display.

- admin.E123: The value of list_editable[n] cannot be in both list_editable and list_display_links.

- admin.E124: The value of list_editable[n] refers to the first field in list_display (<label>), which cannot be used unless list_display_links is set.

- admin.E125: The value of list_editable[n] refers to <field name>, which is not editable through the admin.

- admin.E126: The value of search_fields must be a list or tuple.

- admin.E127: The value of date_hierarchy refers to <field name>, which is not an attribute of <model>.

- admin.E128: The value of date_hierarchy must be a DateField or DateTimeField.

InlineModelAdmin

The following checks are performed on any InlineModelAdmin that is registered as an inline on a ModelAdmin.

- admin.E201: Cannot exclude the field <field name>, because it is the foreign key to the parent model <app_label>.<model>.

- admin.E202: <model> has no ForeignKey to <parent model>./ <model> has more than one ForeignKey to <parent model>.

- admin.E203: The value of extra must be an integer.

- admin.E204: The value of max_num must be an integer.

- admin.E205: The value of min_num must be an integer.

- admin.E206: The value of formset must inherit from BaseModelFormSet.

GenericInlineModelAdmin

The following checks are performed on any GenericInlineModelAdmin that is registered as an inline on a ModelAdmin.

- admin.E301: 'ct_field' references <label>, which is not a field on <model>.

- admin.E302: 'ct_fk_field' references <label>, which is not a field on <model>.

- admin.E303: <model> has no GenericForeignKey.

- admin.E304: <model> has no GenericForeignKey using content type field <field name> and object ID field <field name>.

Auth

- auth.E001: REQUIRED_FIELDS must be a list or tuple.

- auth.E002: The field named as the USERNAME_FIELD for a custom user model must not be included in REQUIRED_FIELDS.

- auth.E003: <field> must be unique because it is named as the USERNAME_FIELD.

- auth.W004: <field> is named as the USERNAME_FIELD, but it is not unique.

Content Types

The following checks are performed when a model contains a GenericForeignKey or GenericRelation:

- contenttypes.E001: The GenericForeignKey object ID references the non-existent field <field>.

- contenttypes.E002: The GenericForeignKey content type references the non-existent field <field>.

- contenttypes.E003: <field> is not a ForeignKey.

- contenttypes.E004: <field> is not a ForeignKey to contenttypes.ContentType.

Security

The security checks do not make your site secure. They do not audit code, do intrusion detection, or do anything particularly complex. Rather, they help perform an automated, low-hanging-fruit checklist. They help you remember the simple things that improve your site’s security.

Some of these checks may not be appropriate for your particular deployment configuration. For instance, if you do your HTTP to HTTPS redirection in a load balancer, it’d be irritating to be constantly warned about not having enabled SECURE_SSL_REDIRECT. Use SILENCED_SYSTEM_CHECKS to silence unneeded checks.

The following checks are run if you use the check --deploy option:

- security.W001: You do not have django.middleware.security.SecurityMiddleware in your MIDDLEWARE_CLASSES so the SECURE_HSTS_SECONDS, SECURE_CONTENT_TYPE_NOSNIFF, SECURE_BROWSER_XSS_FILTER, and SECURE_SSL_REDIRECT settings will have no effect.

- security.W002: You do not have django.middleware.clickjacking.XFrameOptionsMiddleware in your MIDDLEWARE_CLASSES, so your pages will not be served with an 'x-frame-options' header. Unless there is a good reason for your site to be served in a frame, you should consider enabling this header to help prevent clickjacking attacks.

- security.W003: You don’t appear to be using Django’s built-in cross-site request forgery protection via the middleware (django.middleware.csrf.CsrfViewMiddleware is not in your MIDDLEWARE_CLASSES). Enabling the middleware is the safest approach to ensure you don’t leave any holes.

- security.W004: You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.

- security.W005: You have not set the SECURE_HSTS_INCLUDE_SUBDOMAINS setting to True. Without this, your site is potentially vulnerable to attack via an insecure connection to a subdomain. Only set this to True if you are certain that all subdomains of your domain should be served exclusively via SSL.

- security.W006: Your SECURE_CONTENT_TYPE_NOSNIFF setting is not set to True, so your pages will not be served with an 'x-content-type-options: nosniff' header. You should consider enabling this header to prevent the browser from identifying content types incorrectly.

- security.W007: Your SECURE_BROWSER_XSS_FILTER setting is not set to True, so your pages will not be served with an 'x-xss-protection: 1; mode=block' header. You should consider enabling this header to activate the browser’s XSS filtering and help prevent XSS attacks.

- security.W008: Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting to True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.

- security.W009: Your SECRET_KEY has less than 50 characters or less than 5 unique characters. Please generate a long and random SECRET_KEY, otherwise many of Django’s security-critical features will be vulnerable to attack.

- security.W010: You have django.contrib.sessions in your INSTALLED_APPS but you have not set SESSION_COOKIE_SECURE to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.

- security.W011: You have django.contrib.sessions.middleware.SessionMiddleware in your MIDDLEWARE_CLASSES, but you have not set SESSION_COOKIE_SECURE to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.

- security.W012: SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.

- security.W013: You have django.contrib.sessions in your INSTALLED_APPS, but you have not set SESSION_COOKIE_HTTPONLY to True. Using an HttpOnly session cookie makes it more difficult for cross-site scripting attacks to hijack user sessions.

- security.W014: You have django.contrib.sessions.middleware.SessionMiddleware in your MIDDLEWARE_CLASSES, but you have not set SESSION_COOKIE_HTTPONLY to True. Using an HttpOnly session cookie makes it more difficult for cross-site scripting attacks to hijack user sessions.

- security.W015: SESSION_COOKIE_HTTPONLY is not set to True. Using an HttpOnly session cookie makes it more difficult for cross-site scripting attacks to hijack user sessions.

- security.W016: CSRF_COOKIE_SECURE is not set to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.

- security.W017: CSRF_COOKIE_HTTPONLY is not set to True. Using an HttpOnly CSRF cookie makes it more difficult for cross-site scripting attacks to steal the CSRF token.

- security.W018: You should not have DEBUG set to True in deployment.

- security.W019: You have django.middleware.clickjacking.XFrameOptionsMiddleware in your MIDDLEWARE_CLASSES, but X_FRAME_OPTIONS is not set to 'DENY'. The default is 'SAMEORIGIN', but unless there is a good reason for your site to serve other parts of itself in a frame, you should change it to 'DENY'.

- security.W020: ALLOWED_HOSTS must not be empty in deployment.

Sites

The following checks are performed on any model using a CurrentSiteManager:

- sites.E001: CurrentSiteManager could not find a field named <field name>.

- sites.E002: CurrentSiteManager cannot use <field> as it is not a ForeignKey or ManyToManyField.

Database

MySQL

If you’re using MySQL, the following checks will be performed:

- mysql.E001: MySQL does not allow unique CharFields to have a max_length > 255.

Templates

The following checks verify that your TEMPLATES setting is correctly configured:

- templates.E001: You have 'APP_DIRS': True in your TEMPLATES but also specify 'loaders' in OPTIONS. Either remove APP_DIRS or remove the 'loaders' option.

Caches

The following checks verify that your CACHES setting is correctly configured:

- caches.E001: You must define a 'default' cache in your CACHES setting.

URLs

The following checks are performed on your URL configuration:

- urls.W001: Your URL pattern <pattern> uses include() with a regex ending with a $. Remove the dollar from the regex to avoid problems including URLs.

- urls.W002: Your URL pattern <pattern> has a regex beginning with a /. Remove this slash as it is unnecessary.

- urls.W003: Your URL pattern <pattern> has a name including a :. Remove the colon, to avoid ambiguous namespace references.

Built-in class-based views API

Class-based views API reference. For introductory material, see the Class-based views topic guide.

- Base views

- View

- TemplateView

- RedirectView

- Generic display views

- DetailView

- ListView

- Generic editing views

- FormView

- CreateView

- UpdateView

- DeleteView

- Generic date views

- ArchiveIndexView

- YearArchiveView

- MonthArchiveView

- WeekArchiveView

- DayArchiveView

- TodayArchiveView

- DateDetailView

- Class-based views mixins

- Simple mixins

- ContextMixin

- TemplateResponseMixin

- Single object mixins

- SingleObjectMixin

- SingleObjectTemplateResponseMixin

- Multiple object mixins

- MultipleObjectMixin

- MultipleObjectTemplateResponseMixin

- Editing mixins

- FormMixin

- ModelFormMixin

- ProcessFormView

- DeletionMixin

- Date-based mixins

- YearMixin

- MonthMixin

- DayMixin

- WeekMixin

- DateMixin

- BaseDateListView

- Class-based generic views - flattened index

- Simple generic views

- View

- TemplateView

- RedirectView

- Detail Views

- DetailView

- List Views

- ListView

- Editing views

- FormView

- CreateView

- UpdateView

- DeleteView

- Date-based views

- ArchiveIndexView

- YearArchiveView

- MonthArchiveView

- WeekArchiveView

- DayArchiveView

- TodayArchiveView

- DateDetailView

Specification

Each request served by a class-based view has an independent state; therefore, it is safe to store state variables on the instance (i.e., self.foo = 3 is a thread-safe operation).

A class-based view is deployed into a URL pattern using the as_view() classmethod:

urlpatterns = [
url(r'^view/$', MyView.as_view(size=42)),
]

Thread safety with view arguments

Arguments passed to a view are shared between every instance of a view. This means that you shouldn’t use a list, dictionary, or any other mutable object as an argument to a view. If you do and the shared object is modified, the actions of one user visiting your view could have an effect on subsequent users visiting the same view.

Arguments passed into as_view() will be assigned onto the instance that is used to service a request. Using the previous example, this means that every request on MyView is able to use self.size. Arguments must correspond to attributes that already exist on the class (return True on a hasattr check).

Base vs Generic views

Base class-based views can be thought of as parent views, which can be used by themselves or inherited from. They may not provide all the capabilities required for projects, in which case there are Mixins which extend what base views can do.

Django’s generic views are built off of those base views, and were developed as a shortcut for common usage patterns such as displaying the details of an object. They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to repeat yourself.

Most generic views require the queryset key, which is a QuerySet instance; see Making queries for more information about QuerySet objects.

Base views

The following three classes provide much of the functionality needed to create Django views. You may think of them as parent views, which can be used by themselves or inherited from. They may not provide all the capabilities required for projects, in which case there are Mixins and Generic class-based views.

Many of Django’s built-in class-based views inherit from other class-based views or various mixins. Because this inheritance chain is very important, the ancestor classes are documented under the section title of Ancestors (MRO). MRO is an acronym for Method Resolution Order.

View

class django.views.generic.base.View

The master class-based base view. All other class-based views inherit from this base class.

Method Flowchart

1. dispatch()

2. http_method_not_allowed()

3. options()

Example views.py:

from django.http import HttpResponse
from django.views.generic import View

class MyView(View):

def get(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')

Example urls.py:

from django.conf.urls import url

from myapp.views import MyView

urlpatterns = [
url(r'^mine/$', MyView.as_view(), name='my-view'),
]

Attributes

http_method_names

The list of HTTP method names that this view will accept.

Default:

['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

Methods

classmethod as_view(**initkwargs)

Returns a callable view that takes a request and returns a response:

response = MyView.as_view()(request)

New in Django 1.9.

The returned view has view_class and view_initkwargs attributes.

dispatch(request, *args, **kwargs)

The view part of the view – the method that accepts a request argument plus arguments, and returns a HTTP response.

The default implementation will inspect the HTTP method and attempt to delegate to a method that matches the HTTP method; a GET will be delegated to get(), a POST to post(), and so on.

By default, a HEAD request will be delegated to get(). If you need to handle HEAD requests in a different way than GET, you can override the head() method. See Supporting other HTTP methods for an example.

http_method_not_allowed(request, *args, **kwargs)

If the view was called with a HTTP method it doesn’t support, this method is called instead.

The default implementation returns HttpResponseNotAllowed with a list of allowed methods in plain text.

options(request, *args, **kwargs)

Handles responding to requests for the OPTIONS HTTP verb. Returns a response with the Allow header containing a list of the view’s allowed HTTP method names.

TemplateView

class django.views.generic.base.TemplateView

Renders a given template, with the context containing parameters captured in the URL.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.base.ContextMixin

- django.views.generic.base.View

Method Flowchart

1. dispatch()

2. http_method_not_allowed()

3. get_context_data()

Example views.py:

from django.views.generic.base import TemplateView

from articles.models import Article

class HomePageView(TemplateView):

template_name = "home.html"

def get_context_data(self, **kwargs):
context = super(HomePageView, self).get_context_data(**kwargs)
context['latest_articles'] = Article.objects.all()[:5]
return context

Example urls.py:

from django.conf.urls import url

from myapp.views import HomePageView

urlpatterns = [
url(r'^$', HomePageView.as_view(), name='home'),
]

Context

- Populated (through ContextMixin) with the keyword arguments captured from the URL pattern that served the view.

RedirectView

class django.views.generic.base.RedirectView

Redirects to a given URL.

The given URL may contain dictionary-style string formatting, which will be interpolated against the parameters captured in the URL. Because keyword interpolation is always done (even if no arguments are passed in), any "%" characters in the URL must be written as "%%" so that Python will convert them to a single percent sign on output.

If the given URL is None, Django will return an HttpResponseGone (410).

Ancestors (MRO)

This view inherits methods and attributes from the following view:

- django.views.generic.base.View

Method Flowchart

1. dispatch()

2. http_method_not_allowed()

3. get_redirect_url()

Example views.py:

from django.shortcuts import get_object_or_404
from django.views.generic.base import RedirectView

from articles.models import Article

class ArticleCounterRedirectView(RedirectView):

permanent = False
query_string = True
pattern_name = 'article-detail'

def get_redirect_url(self, *args, **kwargs):
article = get_object_or_404(Article, pk=kwargs['pk'])
article.update_counter()
return super(ArticleCounterRedirectView, self).get_redirect_url(*args, **kwargs)

Example urls.py:

from django.conf.urls import url
from django.views.generic.base import RedirectView

from article.views import ArticleCounterRedirectView, ArticleDetail

urlpatterns = [
url(r'^counter/(?P<pk>[0-9]+)/$', ArticleCounterRedirectView.as_view(), name='article-counter'),
url(r'^details/(?P<pk>[0-9]+)/$', ArticleDetail.as_view(), name='article-detail'),
url(r'^go-to-django/$', RedirectView.as_view(url='https://djangoproject.com'), name='go-to-django'),
]

Attributes

url

The URL to redirect to, as a string. Or None to raise a 410 (Gone) HTTP error.

pattern_name

The name of the URL pattern to redirect to. Reversing will be done using the same args and kwargs as are passed in for this view.

permanent

Whether the redirect should be permanent. The only difference here is the HTTP status code returned. If True, then the redirect will use status code 301. If False, then the redirect will use status code 302. By default, permanent is False.

Changed in Django 1.9:
The default value of the permanent attribute changed from True to False.

query_string

Whether to pass along the GET query string to the new location. If True, then the query string is appended to the URL. If False, then the query string is discarded. By default, query_string is False.

Methods

get_redirect_url(*args, **kwargs)

Constructs the target URL for redirection.

The default implementation uses url as a starting string and performs expansion of % named parameters in that string using the named groups captured in the URL.

If url is not set, get_redirect_url() tries to reverse the pattern_name using what was captured in the URL (both named and unnamed groups are used).

If requested by query_string, it will also append the query string to the generated URL. Subclasses may implement any behavior they wish, as long as the method returns a redirect-ready URL string.

Generic display views

The two following generic class-based views are designed to display data. On many projects they are typically the most commonly used views.

DetailView

class django.views.generic.detail.DetailView

While this view is executing, self.object will contain the object that the view is operating upon.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.detail.SingleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.detail.BaseDetailView

- django.views.generic.detail.SingleObjectMixin

- django.views.generic.base.View

Method Flowchart

1. dispatch()

2. http_method_not_allowed()

3. get_template_names()

4. get_slug_field()

5. get_queryset()

6. get_object()

7. get_context_object_name()

8. get_context_data()

9. get()

10. render_to_response()

Example myapp/views.py:

from django.views.generic.detail import DetailView
from django.utils import timezone

from articles.models import Article

class ArticleDetailView(DetailView):

model = Article

def get_context_data(self, **kwargs):
context = super(ArticleDetailView, self).get_context_data(**kwargs)
context['now'] = timezone.now()
return context

Example myapp/urls.py:

from django.conf.urls import url

from article.views import ArticleDetailView

urlpatterns = [
url(r'^(?P<slug>[-\w]+)/$', ArticleDetailView.as_view(), name='article-detail'),
]

Example myapp/article_detail.html:

<h1>{{ object.headline }}</h1>
<p>{{ object.content }}</p>
<p>Reporter: {{ object.reporter }}</p>
<p>Published: {{ object.pub_date|date }}</p>
<p>Date: {{ now|date }}</p>

ListView

class django.views.generic.list.ListView

A page representing a list of objects.

While this view is executing, self.object_list will contain the list of objects (usually, but not necessarily a queryset) that the view is operating upon.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.list.BaseListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.base.View

Method Flowchart

1. dispatch()

2. http_method_not_allowed()

3. get_template_names()

4. get_queryset()

5. get_context_object_name()

6. get_context_data()

7. get()

8. render_to_response()

Example views.py:

from django.views.generic.list import ListView
from django.utils import timezone

from articles.models import Article

class ArticleListView(ListView):

model = Article

def get_context_data(self, **kwargs):
context = super(ArticleListView, self).get_context_data(**kwargs)
context['now'] = timezone.now()
return context

Example myapp/urls.py:

from django.conf.urls import url

from article.views import ArticleListView

urlpatterns = [
url(r'^$', ArticleListView.as_view(), name='article-list'),
]

Example myapp/article_list.html:

<h1>Articles</h1>
<ul>
{% for article in object_list %}
<li>{{ article.pub_date|date }} - {{ article.headline }}</li>
{% empty %}
<li>No articles yet.</li>
{% endfor %}
</ul>

class django.views.generic.list.BaseListView

A base view for displaying a list of objects. It is not intended to be used directly, but rather as a parent class of the django.views.generic.list.ListView or other views representing lists of objects.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.base.View

Methods

get(request, *args, **kwargs)

Adds object_list to the context. If allow_empty is True then display an empty list. If allow_empty is False then raise a 404 error.

Generic editing views

The following views are described on this page and provide a foundation for editing content:

- django.views.generic.edit.FormView

- django.views.generic.edit.CreateView

- django.views.generic.edit.UpdateView

- django.views.generic.edit.DeleteView

Note

Some of the examples on this page assume that an Author model has been defined as follows in myapp/models.py:

from django.core.urlresolvers import reverse
from django.db import models

class Author(models.Model):
name = models.CharField(max_length=200)

def get_absolute_url(self):
return reverse('author-detail', kwargs={'pk': self.pk})

FormView

class django.views.generic.edit.FormView

A view that displays a form. On error, redisplays the form with validation errors; on success, redirects to a new URL.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.edit.BaseFormView

- django.views.generic.edit.FormMixin

- django.views.generic.edit.ProcessFormView

- django.views.generic.base.View

Example myapp/forms.py:

from django import forms

class ContactForm(forms.Form):
name = forms.CharField()
message = forms.CharField(widget=forms.Textarea)

def send_email(self):
# send email using the self.cleaned_data dictionary
pass

Example myapp/views.py:

from myapp.forms import ContactForm
from django.views.generic.edit import FormView

class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = '/thanks/'

def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form.send_email()
return super(ContactView, self).form_valid(form)

Example myapp/contact.html:

<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Send message" />
</form>

CreateView

class django.views.generic.edit.CreateView

A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.detail.SingleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.edit.BaseCreateView

- django.views.generic.edit.ModelFormMixin

- django.views.generic.edit.FormMixin

- django.views.generic.detail.SingleObjectMixin

- django.views.generic.edit.ProcessFormView

- django.views.generic.base.View

Attributes

template_name_suffix

The CreateView page displayed to a GET request uses a template_name_suffix of '_form'. For example, changing this attribute to '_create_form' for a view creating objects for the example Author model would cause the default template_name to be 'myapp/author_create_form.html'.

object

When using CreateView you have access to self.object, which is the object being created. If the object hasn’t been created yet, the value will be None.

Example myapp/views.py:

from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(CreateView):
model = Author
fields = ['name']

Example myapp/author_form.html:

<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>

UpdateView

class django.views.generic.edit.UpdateView

A view that displays a form for editing an existing object, redisplaying the form with validation errors (if there are any) and saving changes to the object. This uses a form automatically generated from the object’s model class (unless a form class is manually specified).

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.detail.SingleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.edit.BaseUpdateView

- django.views.generic.edit.ModelFormMixin

- django.views.generic.edit.FormMixin

- django.views.generic.detail.SingleObjectMixin

- django.views.generic.edit.ProcessFormView

- django.views.generic.base.View

Attributes

template_name_suffix

The UpdateView page displayed to a GET request uses a template_name_suffix of '_form'. For example, changing this attribute to '_update_form' for a view updating objects for the example Author model would cause the default template_name to be 'myapp/author_update_form.html'.

object

When using UpdateView you have access to self.object, which is the object being updated.

Example myapp/views.py:

from django.views.generic.edit import UpdateView
from myapp.models import Author

class AuthorUpdate(UpdateView):
model = Author
fields = ['name']
template_name_suffix = '_update_form'

Example myapp/author_update_form.html:

<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update" />
</form>

DeleteView

class django.views.generic.edit.DeleteView

A view that displays a confirmation page and deletes an existing object. The given object will only be deleted if the request method is POST. If this view is fetched via GET, it will display a confirmation page that should contain a form that POSTs to the same URL.

Ancestors (MRO)

This view inherits methods and attributes from the following views:

- django.views.generic.detail.SingleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.edit.BaseDeleteView

- django.views.generic.edit.DeletionMixin

- django.views.generic.detail.BaseDetailView

- django.views.generic.detail.SingleObjectMixin

- django.views.generic.base.View

Attributes

template_name_suffix

The DeleteView page displayed to a GET request uses a template_name_suffix of '_confirm_delete'. For example, changing this attribute to '_check_delete' for a view deleting objects for the example Author model would cause the default template_name to be 'myapp/author_check_delete.html'.

Example myapp/views.py:

from django.views.generic.edit import DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author

class AuthorDelete(DeleteView):
model = Author
success_url = reverse_lazy('author-list')

Example myapp/author_confirm_delete.html:

<form action="" method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>

Generic date views

Date-based generic views, provided in django.views.generic.dates, are views for displaying drilldown pages for date-based data.

Note

Some of the examples on this page assume that an Article model has been defined as follows in myapp/models.py:

from django.db import models
from django.core.urlresolvers import reverse

class Article(models.Model):
title = models.CharField(max_length=200)
pub_date = models.DateField()

def get_absolute_url(self):
return reverse('article-detail', kwargs={'pk': self.pk})

ArchiveIndexView

class ArchiveIndexView[source]

A top-level index page showing the “latest” objects, by date. Objects with a date in the future are not included unless you set allow_future to True.

Ancestors (MRO)

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseArchiveIndexView

- django.views.generic.dates.BaseDateListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.dates.DateMixin

- django.views.generic.base.View

Context

In addition to the context provided by django.views.generic.list.MultipleObjectMixin (via django.views.generic.dates.BaseDateListView), the template’s context will be:

- date_list: A QuerySet object containing all years that have objects available according to queryset, represented as datetime.datetime objects, in descending order.

Notes

- Uses a default context_object_name of latest.

- Uses a default template_name_suffix of _archive.

- Defaults to providing date_list by year, but this can be altered to month or day using the attribute date_list_period. This also applies to all subclass views.

Example myapp/urls.py:

from django.conf.urls import url
from django.views.generic.dates import ArchiveIndexView

from myapp.models import Article

urlpatterns = [
url(r'^archive/$',
ArchiveIndexView.as_view(model=Article, date_field="pub_date"),
name="article_archive"),
]

Example myapp/article_archive.html:

<ul>
{% for article in latest %}
<li>{{ article.pub_date }}: {{ article.title }}</li>
{% endfor %}
</ul>

This will output all articles.

YearArchiveView

class YearArchiveView[source]

A yearly archive page showing all available months in a given year. Objects with a date in the future are not displayed unless you set allow_future to True.

Ancestors (MRO)

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseYearArchiveView

- django.views.generic.dates.YearMixin

- django.views.generic.dates.BaseDateListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.dates.DateMixin

- django.views.generic.base.View

make_object_list

A boolean specifying whether to retrieve the full list of objects for this year and pass those to the template. If True, the list of objects will be made available to the context. If False, the None queryset will be used as the object list. By default, this is False.

get_make_object_list()

Determine if an object list will be returned as part of the context. Returns make_object_list by default.

Context

In addition to the context provided by django.views.generic.list.MultipleObjectMixin (via django.views.generic.dates.BaseDateListView), the template’s context will be:

- date_list: A QuerySet object containing all months that have objects available according to queryset, represented as datetime.datetime objects, in ascending order.

- year: A date object representing the given year.

- next_year: A date object representing the first day of the next year, according to allow_empty and allow_future.

- previous_year: A date object representing the first day of the previous year, according to allow_empty and allow_future.

Notes

- Uses a default template_name_suffix of _archive_year.

Example myapp/views.py:

from django.views.generic.dates import YearArchiveView

from myapp.models import Article

class ArticleYearArchiveView(YearArchiveView):
queryset = Article.objects.all()
date_field = "pub_date"
make_object_list = True
allow_future = True

Example myapp/urls.py:

from django.conf.urls import url

from myapp.views import ArticleYearArchiveView

urlpatterns = [
url(r'^(?P<year>[0-9]{4})/$',
ArticleYearArchiveView.as_view(),
name="article_year_archive"),
]

Example myapp/article_archive_year.html:

<ul>
{% for date in date_list %}
<li>{{ date|date }}</li>
{% endfor %}
</ul>

<div>
<h1>All Articles for {{ year|date:"Y" }}</h1>
{% for obj in object_list %}
<p>
{{ obj.title }} - {{ obj.pub_date|date:"F j, Y" }}
</p>
{% endfor %}
</div>

MonthArchiveView

class MonthArchiveView[source]

A monthly archive page showing all objects in a given month. Objects with a date in the future are not displayed unless you set allow_future to True.

Ancestors (MRO)

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseMonthArchiveView

- django.views.generic.dates.YearMixin

- django.views.generic.dates.MonthMixin

- django.views.generic.dates.BaseDateListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.dates.DateMixin

- django.views.generic.base.View

Context

In addition to the context provided by MultipleObjectMixin (via BaseDateListView), the template’s context will be:

- date_list: A QuerySet object containing all days that have objects available in the given month, according to queryset, represented as datetime.datetime objects, in ascending order.

- month: A date object representing the given month.

- next_month: A date object representing the first day of the next month, according to allow_empty and allow_future.

- previous_month: A date object representing the first day of the previous month, according to allow_empty and allow_future.

Notes

- Uses a default template_name_suffix of _archive_month.

Example myapp/views.py:

from django.views.generic.dates import MonthArchiveView

from myapp.models import Article

class ArticleMonthArchiveView(MonthArchiveView):
queryset = Article.objects.all()
date_field = "pub_date"
allow_future = True

Example myapp/urls.py:

from django.conf.urls import url

from myapp.views import ArticleMonthArchiveView

urlpatterns = [
# Example: /2012/aug/
url(r'^(?P<year>[0-9]{4})/(?P<month>[-\w]+)/$',
ArticleMonthArchiveView.as_view(),
name="archive_month"),
# Example: /2012/08/
url(r'^(?P<year>[0-9]{4})/(?P<month>[0-9]+)/$',
ArticleMonthArchiveView.as_view(month_format='%m'),
name="archive_month_numeric"),
]

Example myapp/article_archive_month.html:

<ul>
{% for article in object_list %}
<li>{{ article.pub_date|date:"F j, Y" }}: {{ article.title }}</li>
{% endfor %}
</ul>

<p>
{% if previous_month %}
Previous Month: {{ previous_month|date:"F Y" }}
{% endif %}
{% if next_month %}
Next Month: {{ next_month|date:"F Y" }}
{% endif %}
</p>

WeekArchiveView

class WeekArchiveView[source]

A weekly archive page showing all objects in a given week. Objects with a date in the future are not displayed unless you set allow_future to True.

Ancestors (MRO)

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseWeekArchiveView

- django.views.generic.dates.YearMixin

- django.views.generic.dates.WeekMixin

- django.views.generic.dates.BaseDateListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.dates.DateMixin

- django.views.generic.base.View

Context

In addition to the context provided by MultipleObjectMixin (via BaseDateListView), the template’s context will be:

- week: A date object representing the first day of the given week.

- next_week: A date object representing the first day of the next week, according to allow_empty and allow_future.

- previous_week: A date object representing the first day of the previous week, according to allow_empty and allow_future.

Notes

- Uses a default template_name_suffix of _archive_week.

- The week_format attribute is a strptime() format string used to parse the week number. The following values are supported:

- '%U': Based on the United States week system where the week begins on Sunday. This is the default value.

- '%W': Similar to '%U', except it assumes that the week begins on Monday. This is not the same as the ISO 8601 week number.

Example myapp/views.py:

from django.views.generic.dates import WeekArchiveView

from myapp.models import Article

class ArticleWeekArchiveView(WeekArchiveView):
queryset = Article.objects.all()
date_field = "pub_date"
week_format = "%W"
allow_future = True

Example myapp/urls.py:

from django.conf.urls import url

from myapp.views import ArticleWeekArchiveView

urlpatterns = [
# Example: /2012/week/23/
url(r'^(?P<year>[0-9]{4})/week/(?P<week>[0-9]+)/$',
ArticleWeekArchiveView.as_view(),
name="archive_week"),
]

Example myapp/article_archive_week.html:

<h1>Week {{ week|date:'W' }}</h1>

<ul>
{% for article in object_list %}
<li>{{ article.pub_date|date:"F j, Y" }}: {{ article.title }}</li>
{% endfor %}
</ul>

<p>
{% if previous_week %}
Previous Week: {{ previous_week|date:"W" }} of year {{ previous_week|date:"Y" }}
{% endif %}
{% if previous_week and next_week %}--{% endif %}
{% if next_week %}
Next week: {{ next_week|date:"W" }} of year {{ next_week|date:"Y" }}
{% endif %}
</p>

In this example, you are outputting the week number. Keep in mind that week numbers computed by the date template filter with the 'W' format character are not always the same as those computed by strftime() and strptime() with the '%W' format string. For year 2015, for example, week numbers output by date are higher by one compared to those output by strftime(). There isn’t an equivalent for the '%U' strftime() format string in date. Therefore, you should avoid using date to generate URLs for WeekArchiveView.

DayArchiveView

class DayArchiveView[source]

A day archive page showing all objects in a given day. Days in the future throw a 404 error, regardless of whether any objects exist for future days, unless you set allow_future to True.

Ancestors (MRO)

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseDayArchiveView

- django.views.generic.dates.YearMixin

- django.views.generic.dates.MonthMixin

- django.views.generic.dates.DayMixin

- django.views.generic.dates.BaseDateListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.dates.DateMixin

- django.views.generic.base.View

Context

In addition to the context provided by MultipleObjectMixin (via BaseDateListView), the template’s context will be:

- day: A date object representing the given day.

- next_day: A date object representing the next day, according to allow_empty and allow_future.

- previous_day: A date object representing the previous day, according to allow_empty and allow_future.

- next_month: A date object representing the first day of the next month, according to allow_empty and allow_future.

- previous_month: A date object representing the first day of the previous month, according to allow_empty and allow_future.

Notes

- Uses a default template_name_suffix of _archive_day.

Example myapp/views.py:

from django.views.generic.dates import DayArchiveView

from myapp.models import Article

class ArticleDayArchiveView(DayArchiveView):
queryset = Article.objects.all()
date_field = "pub_date"
allow_future = True

Example myapp/urls.py:

from django.conf.urls import url

from myapp.views import ArticleDayArchiveView

urlpatterns = [
# Example: /2012/nov/10/
url(r'^(?P<year>[0-9]{4})/(?P<month>[-\w]+)/(?P<day>[0-9]+)/$',
ArticleDayArchiveView.as_view(),
name="archive_day"),
]

Example myapp/article_archive_day.html:

<h1>{{ day }}</h1>

<ul>
{% for article in object_list %}
<li>{{ article.pub_date|date:"F j, Y" }}: {{ article.title }}</li>
{% endfor %}
</ul>

<p>
{% if previous_day %}
Previous Day: {{ previous_day }}
{% endif %}
{% if previous_day and next_day %}--{% endif %}
{% if next_day %}
Next Day: {{ next_day }}
{% endif %}
</p>

TodayArchiveView

class TodayArchiveView[source]

A day archive page showing all objects for today. This is exactly the same as django.views.generic.dates.DayArchiveView, except today’s date is used instead of the year/month/day arguments.

Ancestors (MRO)

- django.views.generic.list.MultipleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseTodayArchiveView

- django.views.generic.dates.BaseDayArchiveView

- django.views.generic.dates.YearMixin

- django.views.generic.dates.MonthMixin

- django.views.generic.dates.DayMixin

- django.views.generic.dates.BaseDateListView

- django.views.generic.list.MultipleObjectMixin

- django.views.generic.dates.DateMixin

- django.views.generic.base.View

Notes

- Uses a default template_name_suffix of _archive_today.

Example myapp/views.py:

from django.views.generic.dates import TodayArchiveView

from myapp.models import Article

class ArticleTodayArchiveView(TodayArchiveView):
queryset = Article.objects.all()
date_field = "pub_date"
allow_future = True

Example myapp/urls.py:

from django.conf.urls import url

from myapp.views import ArticleTodayArchiveView

urlpatterns = [
url(r'^today/$',
ArticleTodayArchiveView.as_view(),
name="archive_today"),
]

Where is the example template for TodayArchiveView?

This view uses by default the same template as the DayArchiveView, which is in the previous example. If you need a different template, set the template_name attribute to be the name of the new template.

DateDetailView

class DateDetailView[source]

A page representing an individual object. If the object has a date value in the future, the view will throw a 404 error by default, unless you set allow_future to True.

Ancestors (MRO)

- django.views.generic.detail.SingleObjectTemplateResponseMixin

- django.views.generic.base.TemplateResponseMixin

- django.views.generic.dates.BaseDateDetailView

- django.views.generic.dates.YearMixin

- django.views.generic.dates.MonthMixin

- django.views.generic.dates.DayMixin

- django.views.generic.dates.DateMixin

- django.views.generic.detail.BaseDetailView

- django.views.generic.detail.SingleObjectMixin

- django.views.generic.base.View

Context

- Includes the single object associated with the model specified in the DateDetailView.

Notes

- Uses a default template_name_suffix of _detail.

Example myapp/urls.py:

from django.conf.urls import url
from django.views.generic.dates import DateDetailView

urlpatterns = [
url(r'^(?P<year>[0-9]{4})/(?P<month>[-\w]+)/(?P<day>[0-9]+)/(?P<pk>[0-9]+)/$',
DateDetailView.as_view(model=Article, date_field="pub_date"),
name="archive_date_detail"),
]

Example myapp/article_detail.html:

<h1>{{ object.title }}</h1>

Note

All of the generic views listed above have matching Base views that only differ in that they do not include the MultipleObjectTemplateResponseMixin (for the archive views) or SingleObjectTemplateResponseMixin (for the DateDetailView):

class BaseArchiveIndexView[source]

class BaseYearArchiveView[source]

class BaseMonthArchiveView[source]

class BaseWeekArchiveView[source]

class BaseDayArchiveView[source]

class BaseTodayArchiveView[source]

class BaseDateDetailView[source]

Class-based views mixins

Class-based views API reference. For introductory material, see Using mixins with class-based views.

- Simple mixins

- Single object mixins

- Multiple object mixins

- Editing mixins

- Date-based mixins

Simple mixins

ContextMixin

class django.views.generic.base.ContextMixin

Methods

get_context_data(**kwargs)

Returns a dictionary representing the template context. The keyword arguments provided will make up the returned context. Example usage:

def get_context_data(self, **kwargs):
context = super(RandomNumberView, self).get_context_data(**kwargs)
context['number'] = random.randrange(1, 100)
return context

The template context of all class-based generic views include a view variable that points to the View instance.

Use alters_data where appropriate

Note that having the view instance in the template context may expose potentially hazardous methods to template authors. To prevent methods like this from being called in the template, set alters_data=True on those methods. For more information, read the documentation on rendering a template context.

TemplateResponseMixin

class django.views.generic.base.TemplateResponseMixin

Provides a mechanism to construct a TemplateResponse, given suitable context. The template to use is configurable and can be further customized by subclasses.

Attributes

template_name

The full name of a template to use as defined by a string. Not defining a template_name will raise a django.core.exceptions.ImproperlyConfigured exception.

template_engine

New in Django 1.8.

The NAME of a template engine to use for loading the template. template_engine is passed as the using keyword argument to response_class. Default is None, which tells Django to search for the template in all configured engines.

response_class

The response class to be returned by render_to_response method. Default is TemplateResponse. The template and context of TemplateResponse instances can be altered later (e.g. in template response middleware).

Changed in Django 1.8:
In older versions of Django, TemplateResponse used RequestContext in such a way that values from template context processors would override template variables defined in your views. For example, if you subclassed DetailView and set context_object_name to user, the django.contrib.auth.context_processors.auth context processor would overwrite your variable with the current user. Now, for consistency with the render() shortcut, values in the context provided by the class override values from context processors.

If you need custom template loading or custom context object instantiation, create a TemplateResponse subclass and assign it to response_class.

content_type

The content type to use for the response. content_type is passed as a keyword argument to response_class. Default is None – meaning that Django uses DEFAULT_CONTENT_TYPE.

Methods

render_to_response(context, **response_kwargs)

Returns a self.response_class instance.

If any keyword arguments are provided, they will be passed to the constructor of the response class.

Calls get_template_names() to obtain the list of template names that will be searched looking for an existent template.

get_template_names()

Returns a list of template names to search for when rendering the template. The first template that is found will be used.

If template_name is specified, the default implementation will return a list containing template_name (if it is specified).

Single object mixins

SingleObjectMixin

class django.views.generic.detail.SingleObjectMixin

Provides a mechanism for looking up an object associated with the current HTTP request.

Methods and Attributes

model

The model that this view will display data for. Specifying model = Foo is effectively the same as specifying queryset = Foo.objects.all(), where objects stands for Foo’s default manager.

queryset

A QuerySet that represents the objects. If provided, the value of queryset supersedes the value provided for model.

Warning

queryset is a class attribute with a mutable value so care must be taken when using it directly. Before using it, either call its all() method or retrieve it with get_queryset() which takes care of the cloning behind the scenes.

slug_field

The name of the field on the model that contains the slug. By default, slug_field is 'slug'.

slug_url_kwarg

The name of the URLConf keyword argument that contains the slug. By default, slug_url_kwarg is 'slug'.

pk_url_kwarg

The name of the URLConf keyword argument that contains the primary key. By default, pk_url_kwarg is 'pk'.

context_object_name

Designates the name of the variable to use in the context.

query_pk_and_slug

New in Django 1.8.

If True, causes get_object() to perform its lookup using both the primary key and the slug. Defaults to False.

This attribute can help mitigate insecure direct object reference attacks. When applications allow access to individual objects by a sequential primary key, an attacker could brute-force guess all URLs; thereby obtaining a list of all objects in the application. If users with access to individual objects should be prevented from obtaining this list, setting query_pk_and_slug to True will help prevent the guessing of URLs as each URL will require two correct, non-sequential arguments. Simply using a unique slug may serve the same purpose, but this scheme allows you to have non-unique slugs.

get_object(queryset=None)

Returns the single object that this view will display. If queryset is provided, that queryset will be used as the source of objects; otherwise, get_queryset() will be used. get_object() looks for a pk_url_kwarg argument in the arguments to the view; if this argument is found, this method performs a primary-key based lookup using that value. If this argument is not found, it looks for a slug_url_kwarg argument, and performs a slug lookup using the slug_field.

Changed in Django 1.8:
When query_pk_and_slug is True, get_object() will perform its lookup using both the primary key and the slug.

get_queryset()

Returns the queryset that will be used to retrieve the object that this view will display. By default, get_queryset() returns the value of the queryset attribute if it is set, otherwise it constructs a QuerySet by calling the all() method on the model attribute’s default manager.

get_context_object_name(obj)

Return the context variable name that will be used to contain the data that this view is manipulating. If context_object_name is not set, the context name will be constructed from the model_name of the model that the queryset is composed from. For example, the model Article would have context object named 'article'.

get_context_data(**kwargs)

Returns context data for displaying the list of objects.

The base implementation of this method requires that the self.object attribute be set by the view (even if None). Be sure to do this if you are using this mixin without one of the built-in views that does so.

It returns a dictionary with these contents:

- object: The object that this view is displaying (self.object).

- context_object_name: self.object will also be stored under the name returned by get_context_object_name(), which defaults to the lowercased version of the model name.

Context variables override values from template context processors

Any variables from get_context_data() take precedence over context variables from context processors. For example, if your view sets the model attribute to User, the default context object name of user would override the user variable from the django.contrib.auth.context_processors.auth() context processor. Use get_context_object_name() to avoid a clash.

get_slug_field()

Returns the name of a slug field to be used to look up by slug. By default this simply returns the value of slug_field.

SingleObjectTemplateResponseMixin

class django.views.generic.detail.SingleObjectTemplateResponseMixin

A mixin class that performs template-based response rendering for views that operate upon a single object instance. Requires that the view it is mixed with provides self.object, the object instance that the view is operating on. self.object will usually be, but is not required to be, an instance of a Django model. It may be None if the view is in the process of constructing a new instance.

Extends

- TemplateResponseMixin

Methods and Attributes

template_name_field

The field on the current object instance that can be used to determine the name of a candidate template. If either template_name_field itself or the value of the template_name_field on the current object instance is None, the object will not be used for a candidate template name.

template_name_suffix

The suffix to append to the auto-generated candidate template name. Default suffix is _detail.

get_template_names()

Returns a list of candidate template names. Returns the following list:

- the value of template_name on the view (if provided)

- the contents of the template_name_field field on the object instance that the view is operating upon (if available)

- <app_label>/<model_name><template_name_suffix>.html

Multiple object mixins

MultipleObjectMixin

class django.views.generic.list.MultipleObjectMixin

A mixin that can be used to display a list of objects.

If paginate_by is specified, Django will paginate the results returned by this. You can specify the page number in the URL in one of two ways:

- Use the page parameter in the URLconf. For example, this is what your URLconf might look like:

url(r'^objects/page(?P<page>[0-9]+)/$', PaginatedView.as_view()),

- Pass the page number via the page query-string parameter. For example, a URL would look like this:

/objects/?page=3

These values and lists are 1-based, not 0-based, so the first page would be represented as page 1.

For more on pagination, read the pagination documentation.

As a special case, you are also permitted to use last as a value for page:

/objects/?page=last

This allows you to access the final page of results without first having to determine how many pages there are.

Note that page must be either a valid page number or the value last; any other value for page will result in a 404 error.

Extends

- django.views.generic.base.ContextMixin

Methods and Attributes

allow_empty

A boolean specifying whether to display the page if no objects are available. If this is False and no objects are available, the view will raise a 404 instead of displaying an empty page. By default, this is True.

model

The model that this view will display data for. Specifying model = Foo is effectively the same as specifying queryset = Foo.objects.all(), where objects stands for Foo’s default manager.

queryset

A QuerySet that represents the objects. If provided, the value of queryset supersedes the value provided for model.

Warning

queryset is a class attribute with a mutable value so care must be taken when using it directly. Before using it, either call its all() method or retrieve it with get_queryset() which takes care of the cloning behind the scenes.

ordering

New in Django 1.8.

A string or list of strings specifying the ordering to apply to the queryset. Valid values are the same as those for order_by().

paginate_by

An integer specifying how many objects should be displayed per page. If this is given, the view will paginate objects with paginate_by objects per page. The view will expect either a page query string parameter (via request.GET) or a page variable specified in the URLconf.

paginate_orphans

An integer specifying the number of “overflow” objects the last page can contain. This extends the paginate_by limit on the last page by up to paginate_orphans, in order to keep the last page from having a very small number of objects.

page_kwarg

A string specifying the name to use for the page parameter. The view will expect this parameter to be available either as a query string parameter (via request.GET) or as a kwarg variable specified in the URLconf. Defaults to page.

paginator_class

The paginator class to be used for pagination. By default, django.core.paginator.Paginator is used. If the custom paginator class doesn’t have the same constructor interface as django.core.paginator.Paginator, you will also need to provide an implementation for get_paginator().

context_object_name

Designates the name of the variable to use in the context.

get_queryset()

Get the list of items for this view. This must be an iterable and may be a queryset (in which queryset-specific behavior will be enabled).

get_ordering()

New in Django 1.8.

Returns a string (or iterable of strings) that defines the ordering that will be applied to the queryset.

Returns ordering by default.

paginate_queryset(queryset, page_size)

Returns a 4-tuple containing (paginator, page, object_list, is_paginated).

Constructed by paginating queryset into pages of size page_size. If the request contains a page argument, either as a captured URL argument or as a GET argument, object_list will correspond to the objects from that page.

get_paginate_by(queryset)

Returns the number of items to paginate by, or None for no pagination. By default this simply returns the value of paginate_by.

get_paginator(queryset, per_page, orphans=0, allow_empty_first_page=True)

Returns an instance of the paginator to use for this view. By default, instantiates an instance of paginator_class.

get_paginate_orphans()

An integer specifying the number of “overflow” objects the last page can contain. By default this simply returns the value of paginate_orphans.

get_allow_empty()

Return a boolean specifying whether to display the page if no objects are available. If this method returns False and no objects are available, the view will raise a 404 instead of displaying an empty page. By default, this is True.

get_context_object_name(object_list)

Return the context variable name that will be used to contain the list of data that this view is manipulating. If object_list is a queryset of Django objects and context_object_name is not set, the context name will be the model_name of the model that the queryset is composed from, with postfix '_list' appended. For example, the model Article would have a context object named article_list.

get_context_data(**kwargs)

Returns context data for displaying the list of objects.

Context

- object_list: The list of objects that this view is displaying. If context_object_name is specified, that variable will also be set in the context, with the same value as object_list.

- is_paginated: A boolean representing whether the results are paginated. Specifically, this is set to False if no page size has been specified, or if the available objects do not span multiple pages.

- paginator: An instance of django.core.paginator.Paginator. If the page is not paginated, this context variable will be None.

- page_obj: An instance of django.core.paginator.Page. If the page is not paginated, this context variable will be None.

MultipleObjectTemplateResponseMixin

class django.views.generic.list.MultipleObjectTemplateResponseMixin

A mixin class that performs template-based response rendering for views that operate upon a list of object instances. Requires that the view it is mixed with provides self.object_list, the list of object instances that the view is operating on. self.object_list may be, but is not required to be, a QuerySet.

Extends

- TemplateResponseMixin

Methods and Attributes

template_name_suffix

The suffix to append to the auto-generated candidate template name. Default suffix is _list.

get_template_names()

Returns a list of candidate template names. Returns the following list:

- the value of template_name on the view (if provided)

- <app_label>/<model_name><template_name_suffix>.html

Editing mixins

The following mixins are used to construct Django’s editing views:

- django.views.generic.edit.FormMixin

- django.views.generic.edit.ModelFormMixin

- django.views.generic.edit.ProcessFormView

- django.views.generic.edit.DeletionMixin

Note

Examples of how these are combined into editing views can be found at the documentation on Generic editing views.

FormMixin

class django.views.generic.edit.FormMixin

A mixin class that provides facilities for creating and displaying forms.

Mixins

- django.views.generic.base.ContextMixin

Methods and Attributes

initial

A dictionary containing initial data for the form.

form_class

The form class to instantiate.

success_url

The URL to redirect to when the form is successfully processed.

prefix

The prefix for the generated form.

get_initial()

Retrieve initial data for the form. By default, returns a copy of initial.

get_form_class()

Retrieve the form class to instantiate. By default form_class.

get_form(form_class=None)

Instantiate an instance of form_class using get_form_kwargs(). If form_class isn’t provided get_form_class() will be used.

Changed in Django 1.8:
The form_class argument is not required anymore.

get_form_kwargs()

Build the keyword arguments required to instantiate the form.

The initial argument is set to get_initial(). If the request is a POST or PUT, the request data (request.POST and request.FILES) will also be provided.

get_prefix()

Determine the prefix for the generated form. Returns prefix by default.

get_success_url()

Determine the URL to redirect to when the form is successfully validated. Returns success_url by default.

form_valid(form)

Redirects to get_success_url().

form_invalid(form)

Renders a response, providing the invalid form as context.

get_context_data(**kwargs)

New in Django 1.9.

Calls get_form() and adds the result to the context data with the name ‘form’.

ModelFormMixin

class django.views.generic.edit.ModelFormMixin

A form mixin that works on ModelForms, rather than a standalone form.

Since this is a subclass of SingleObjectMixin, instances of this mixin have access to the model and queryset attributes, describing the type of object that the ModelForm is manipulating.

If you specify both the fields and form_class attributes, an ImproperlyConfigured exception will be raised.

Changed in Django 1.8:
Previously if both fields and form_class were specified, fields was silently ignored.

Mixins

- django.views.generic.edit.FormMixin

- django.views.generic.detail.SingleObjectMixin

Methods and Attributes

model

A model class. Can be explicitly provided, otherwise will be determined by examining self.object or queryset.

fields

A list of names of fields. This is interpreted the same way as the Meta.fields attribute of ModelForm.

This is a required attribute if you are generating the form class automatically (e.g. using model). Omitting this attribute will result in an ImproperlyConfigured exception.

Changed in Django 1.8:
Previously, omitting this attribute was allowed and resulted in a form with all fields of the model.

success_url

The URL to redirect to when the form is successfully processed.

success_url may contain dictionary string formatting, which will be interpolated against the object’s field attributes. For example, you could use success_url="/polls/{slug}/" to redirect to a URL composed out of the slug field on a model.

Changed in Django 1.8:
Support for the new brace-based Python formatting syntax has been added. The old %(slug)s placeholder syntax support has been deprecated and will be removed in Django 1.10.

get_form_class()

Retrieve the form class to instantiate. If form_class is provided, that class will be used. Otherwise, a ModelForm will be instantiated using the model associated with the queryset, or with the model, depending on which attribute is provided.

get_form_kwargs()

Add the current instance (self.object) to the standard get_form_kwargs().

get_success_url()

Determine the URL to redirect to when the form is successfully validated. Returns django.views.generic.edit.ModelFormMixin.success_url if it is provided; otherwise, attempts to use the get_absolute_url() of the object.

form_valid(form)

Saves the form instance, sets the current object for the view, and redirects to get_success_url().

form_invalid()

Renders a response, providing the invalid form as context.

ProcessFormView

class django.views.generic.edit.ProcessFormView

A mixin that provides basic HTTP GET and POST workflow.

Note

This is named ‘ProcessFormView’ and inherits directly from django.views.generic.base.View, but breaks if used independently, so it is more of a mixin.

Extends

- django.views.generic.base.View

Methods and Attributes

get(request, *args, **kwargs)

Renders a response using a context created with get_context_data().

Changed in Django 1.9:
Construction of the form was moved from this method to get_context_data().

post(request, *args, **kwargs)

Constructs a form, checks the form for validity, and handles it accordingly.

put(*args, **kwargs)

The PUT action is also handled and just passes all parameters through to post().

DeletionMixin

class django.views.generic.edit.DeletionMixin

Enables handling of the DELETE http action.

Methods and Attributes

success_url

The url to redirect to when the nominated object has been successfully deleted.

success_url may contain dictionary string formatting, which will be interpolated against the object’s field attributes. For example, you could use success_url="/parent/{parent_id}/" to redirect to a URL composed out of the parent_id field on a model.

Changed in Django 1.8:
Support for the new brace-based Python formatting syntax has been added. The old %(slug)s placeholder syntax support has been deprecated and will be removed in Django 1.10.

get_success_url()

Returns the url to redirect to when the nominated object has been successfully deleted. Returns success_url by default.

Date-based mixins

Note

All the date formatting attributes in these mixins use strftime() format characters. Do not try to use the format characters from the now template tag as they are not compatible.

YearMixin

class YearMixin[source]

A mixin that can be used to retrieve and provide parsing information for a year component of a date.

Methods and Attributes

year_format

The strftime() format to use when parsing the year. By default, this is '%Y'.

year

Optional The value for the year, as a string. By default, set to None, which means the year will be determined using other means.

get_year_format()[source]

Returns the strftime() format to use when parsing the year. Returns year_format by default.

get_year()[source]

Returns the year for which this view will display data, as a string. Tries the following sources, in order:

- The value of the YearMixin.year attribute.

- The value of the year argument captured in the URL pattern.

- The value of the year GET query argument.

Raises a 404 if no valid year specification can be found.

get_next_year(date)[source]

Returns a date object containing the first day of the year after the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

get_previous_year(date)[source]

Returns a date object containing the first day of the year before the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

MonthMixin

class MonthMixin[source]

A mixin that can be used to retrieve and provide parsing information for a month component of a date.

Methods and Attributes

month_format

The strftime() format to use when parsing the month. By default, this is '%b'.

month

Optional The value for the month, as a string. By default, set to None, which means the month will be determined using other means.

get_month_format()[source]

Returns the strftime() format to use when parsing the month. Returns month_format by default.

get_month()[source]

Returns the month for which this view will display data, as a string. Tries the following sources, in order:

- The value of the MonthMixin.month attribute.

- The value of the month argument captured in the URL pattern.

- The value of the month GET query argument.

Raises a 404 if no valid month specification can be found.

get_next_month(date)[source]

Returns a date object containing the first day of the month after the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

get_previous_month(date)[source]

Returns a date object containing the first day of the month before the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

DayMixin

class DayMixin[source]

A mixin that can be used to retrieve and provide parsing information for a day component of a date.

Methods and Attributes

day_format

The strftime() format to use when parsing the day. By default, this is '%d'.

day

Optional The value for the day, as a string. By default, set to None, which means the day will be determined using other means.

get_day_format()[source]

Returns the strftime() format to use when parsing the day. Returns day_format by default.

get_day()[source]

Returns the day for which this view will display data, as a string. Tries the following sources, in order:

- The value of the DayMixin.day attribute.

- The value of the day argument captured in the URL pattern.

- The value of the day GET query argument.

Raises a 404 if no valid day specification can be found.

get_next_day(date)[source]

Returns a date object containing the next valid day after the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

get_previous_day(date)[source]

Returns a date object containing the previous valid day. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

WeekMixin

class WeekMixin[source]

A mixin that can be used to retrieve and provide parsing information for a week component of a date.

Methods and Attributes

week_format

The strftime() format to use when parsing the week. By default, this is '%U', which means the week starts on Sunday. Set it to '%W' if your week starts on Monday.

week

Optional The value for the week, as a string. By default, set to None, which means the week will be determined using other means.

get_week_format()[source]

Returns the strftime() format to use when parsing the week. Returns week_format by default.

get_week()[source]

Returns the week for which this view will display data, as a string. Tries the following sources, in order:

- The value of the WeekMixin.week attribute.

- The value of the week argument captured in the URL pattern

- The value of the week GET query argument.

Raises a 404 if no valid week specification can be found.

get_next_week(date)[source]

Returns a date object containing the first day of the week after the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

get_prev_week(date)

Returns a date object containing the first day of the week before the date provided. This function can also return None or raise an Http404 exception, depending on the values of allow_empty and allow_future.

DateMixin

class DateMixin[source]

A mixin class providing common behavior for all date-based views.

Methods and Attributes

date_field

The name of the DateField or DateTimeField in the QuerySet’s model that the date-based archive should use to determine the list of objects to display on the page.

When time zone support is enabled and date_field is a DateTimeField, dates are assumed to be in the current time zone. Otherwise, the queryset could include objects from the previous or the next day in the end user’s time zone.

Warning

In this situation, if you have implemented per-user time zone selection, the same URL may show a different set of objects, depending on the end user’s time zone. To avoid this, you should use a DateField as the date_field attribute.

allow_future

A boolean specifying whether to include “future” objects on this page, where “future” means objects in which the field specified in date_field is greater than the current date/time. By default, this is False.

get_date_field()[source]

Returns the name of the field that contains the date data that this view will operate on. Returns date_field by default.

get_allow_future()[source]

Determine whether to include “future” objects on this page, where “future” means objects in which the field specified in date_field is greater than the current date/time. Returns allow_future by default.

BaseDateListView

class BaseDateListView[source]

A base class that provides common behavior for all date-based views. There won’t normally be a reason to instantiate BaseDateListView; instantiate one of the subclasses instead.

While this view (and its subclasses) are executing, self.object_list will contain the list of objects that the view is operating upon, and self.date_list will contain the list of dates for which data is available.

Mixins

- DateMixin

- MultipleObjectMixin

Methods and Attributes

allow_empty

A boolean specifying whether to display the page if no objects are available. If this is True and no objects are available, the view will display an empty page instead of raising a 404.

This is identical to django.views.generic.list.MultipleObjectMixin.allow_empty, except for the default value, which is False.

date_list_period

Optional A string defining the aggregation period for date_list. It must be one of 'year' (default), 'month', or 'day'.

get_dated_items()[source]

Returns a 3-tuple containing (date_list, object_list, extra_context).

date_list is the list of dates for which data is available. object_list is the list of objects. extra_context is a dictionary of context data that will be added to any context data provided by the MultipleObjectMixin.

get_dated_queryset(**lookup)[source]

Returns a queryset, filtered using the query arguments defined by lookup. Enforces any restrictions on the queryset, such as allow_empty and allow_future.

get_date_list_period()[source]

Returns the aggregation period for date_list. Returns date_list_period by default.

get_date_list(queryset, date_type=None, ordering='ASC')[source]

Returns the list of dates of type date_type for which queryset contains entries. For example, get_date_list(qs, 'year') will return the list of years for which qs has entries. If date_type isn’t provided, the result of get_date_list_period() is used. date_type and ordering are simply passed to QuerySet.dates().

Class-based generic views - flattened index

This index provides an alternate organization of the reference documentation for class-based views. For each view, the effective attributes and methods from the class tree are represented under that view. For the reference documentation organized by the class which defines the behavior, see Class-based views

Simple generic views

View

class View

Attributes (with optional accessor):

- http_method_names

Methods

- as_view()

- dispatch()

- head()

- http_method_not_allowed()

TemplateView

class TemplateView

Attributes (with optional accessor):

- content_type

- http_method_names

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- head()

- http_method_not_allowed()

- render_to_response()

RedirectView

class RedirectView

Attributes (with optional accessor):

- http_method_names

- pattern_name

- permanent

- query_string

- url [get_redirect_url()]

Methods

- as_view()

- delete()

- dispatch()

- get()

- head()

- http_method_not_allowed()

- options()

- post()

- put()

Detail Views

DetailView

class DetailView

Attributes (with optional accessor):

- content_type

- context_object_name [get_context_object_name()]

- http_method_names

- model

- pk_url_kwarg

- queryset [get_queryset()]

- response_class [render_to_response()]

- slug_field [get_slug_field()]

- slug_url_kwarg

- template_engine

- template_name [get_template_names()]

- template_name_field

- template_name_suffix

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_object()

- head()

- http_method_not_allowed()

- render_to_response()

List Views

ListView

class ListView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- content_type

- context_object_name [get_context_object_name()]

- http_method_names

- model

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_paginator()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

Editing views

FormView

class FormView

Attributes (with optional accessor):

- content_type

- form_class [get_form_class()]

- http_method_names

- initial [get_initial()]

- prefix [get_prefix()]

- response_class [render_to_response()]

- success_url [get_success_url()]

- template_engine

- template_name [get_template_names()]

Methods

- as_view()

- dispatch()

- form_invalid()

- form_valid()

- get()

- get_context_data()

- get_form()

- get_form_kwargs()

- http_method_not_allowed()

- post()

- put()

CreateView

class CreateView

Attributes (with optional accessor):

- content_type

- context_object_name [get_context_object_name()]

- fields

- form_class [get_form_class()]

- http_method_names

- initial [get_initial()]

- model

- pk_url_kwarg

- prefix [get_prefix()]

- queryset [get_queryset()]

- response_class [render_to_response()]

- slug_field [get_slug_field()]

- slug_url_kwarg

- success_url [get_success_url()]

- template_engine

- template_name [get_template_names()]

- template_name_field

- template_name_suffix

Methods

- as_view()

- dispatch()

- form_invalid()

- form_valid()

- get()

- get_context_data()

- get_form()

- get_form_kwargs()

- get_object()

- head()

- http_method_not_allowed()

- post()

- put()

- render_to_response()

UpdateView

class UpdateView

Attributes (with optional accessor):

- content_type

- context_object_name [get_context_object_name()]

- fields

- form_class [get_form_class()]

- http_method_names

- initial [get_initial()]

- model

- pk_url_kwarg

- prefix [get_prefix()]

- queryset [get_queryset()]

- response_class [render_to_response()]

- slug_field [get_slug_field()]

- slug_url_kwarg

- success_url [get_success_url()]

- template_engine

- template_name [get_template_names()]

- template_name_field

- template_name_suffix

Methods

- as_view()

- dispatch()

- form_invalid()

- form_valid()

- get()

- get_context_data()

- get_form()

- get_form_kwargs()

- get_object()

- head()

- http_method_not_allowed()

- post()

- put()

- render_to_response()

DeleteView

class DeleteView

Attributes (with optional accessor):

- content_type

- context_object_name [get_context_object_name()]

- http_method_names

- model

- pk_url_kwarg

- queryset [get_queryset()]

- response_class [render_to_response()]

- slug_field [get_slug_field()]

- slug_url_kwarg

- success_url [get_success_url()]

- template_engine

- template_name [get_template_names()]

- template_name_field

- template_name_suffix

Methods

- as_view()

- delete()

- dispatch()

- get()

- get_context_data()

- get_object()

- head()

- http_method_not_allowed()

- post()

- render_to_response()

Date-based views

ArchiveIndexView

class ArchiveIndexView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- http_method_names

- model

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_date_list()

- get_dated_items()

- get_dated_queryset()

- get_paginator()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

YearArchiveView

class YearArchiveView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- http_method_names

- make_object_list [get_make_object_list()]

- model

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

- year [get_year()]

- year_format [get_year_format()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_date_list()

- get_dated_items()

- get_dated_queryset()

- get_paginator()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

MonthArchiveView

class MonthArchiveView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- http_method_names

- model

- month [get_month()]

- month_format [get_month_format()]

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

- year [get_year()]

- year_format [get_year_format()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_date_list()

- get_dated_items()

- get_dated_queryset()

- get_next_month()

- get_paginator()

- get_previous_month()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

WeekArchiveView

class WeekArchiveView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- http_method_names

- model

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

- week [get_week()]

- week_format [get_week_format()]

- year [get_year()]

- year_format [get_year_format()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_date_list()

- get_dated_items()

- get_dated_queryset()

- get_paginator()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

DayArchiveView

class DayArchiveView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- day [get_day()]

- day_format [get_day_format()]

- http_method_names

- model

- month [get_month()]

- month_format [get_month_format()]

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

- year [get_year()]

- year_format [get_year_format()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_date_list()

- get_dated_items()

- get_dated_queryset()

- get_next_day()

- get_next_month()

- get_paginator()

- get_previous_day()

- get_previous_month()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

TodayArchiveView

class TodayArchiveView

Attributes (with optional accessor):

- allow_empty [get_allow_empty()]

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- day [get_day()]

- day_format [get_day_format()]

- http_method_names

- model

- month [get_month()]

- month_format [get_month_format()]

- ordering [get_ordering()]

- paginate_by [get_paginate_by()]

- paginate_orphans [get_paginate_orphans()]

- paginator_class

- queryset [get_queryset()]

- response_class [render_to_response()]

- template_engine

- template_name [get_template_names()]

- template_name_suffix

- year [get_year()]

- year_format [get_year_format()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_date_list()

- get_dated_items()

- get_dated_queryset()

- get_next_day()

- get_next_month()

- get_paginator()

- get_previous_day()

- get_previous_month()

- head()

- http_method_not_allowed()

- paginate_queryset()

- render_to_response()

DateDetailView

class DateDetailView

Attributes (with optional accessor):

- allow_future [get_allow_future()]

- content_type

- context_object_name [get_context_object_name()]

- date_field [get_date_field()]

- day [get_day()]

- day_format [get_day_format()]

- http_method_names

- model

- month [get_month()]

- month_format [get_month_format()]

- pk_url_kwarg

- queryset [get_queryset()]

- response_class [render_to_response()]

- slug_field [get_slug_field()]

- slug_url_kwarg

- template_engine

- template_name [get_template_names()]

- template_name_field

- template_name_suffix

- year [get_year()]

- year_format [get_year_format()]

Methods

- as_view()

- dispatch()

- get()

- get_context_data()

- get_next_day()

- get_next_month()

- get_object()

- get_previous_day()

- get_previous_month()

- head()

- http_method_not_allowed()

- render_to_response()

Clickjacking Protection

The clickjacking middleware and decorators provide easy-to-use protection against clickjacking. This type of attack occurs when a malicious site tricks a user into clicking on a concealed element of another site which they have loaded in a hidden frame or iframe.

An example of clickjacking

Suppose an online store has a page where a logged in user can click “Buy Now” to purchase an item. A user has chosen to stay logged into the store all the time for convenience. An attacker site might create an “I Like Ponies” button on one of their own pages, and load the store’s page in a transparent iframe such that the “Buy Now” button is invisibly overlaid on the “I Like Ponies” button. If the user visits the attacker’s site, clicking “I Like Ponies” will cause an inadvertent click on the “Buy Now” button and an unknowing purchase of the item.

Preventing clickjacking

Modern browsers honor the X-Frame-Options HTTP header that indicates whether or not a resource is allowed to load within a frame or iframe. If the response contains the header with a value of SAMEORIGIN then the browser will only load the resource in a frame if the request originated from the same site. If the header is set to DENY then the browser will block the resource from loading in a frame no matter which site made the request.

Django provides a few simple ways to include this header in responses from your site:

1. A simple middleware that sets the header in all responses.

2. A set of view decorators that can be used to override the middleware or to only set the header for certain views.

The X-Frame-Options HTTP header will only be set by the middleware or view decorators if it is not already present in the response.

How to use it

Setting X-Frame-Options for all responses

To set the same X-Frame-Options value for all responses in your site, put 'django.middleware.clickjacking.XFrameOptionsMiddleware' to MIDDLEWARE_CLASSES:

MIDDLEWARE_CLASSES = [
...
'django.middleware.clickjacking.XFrameOptionsMiddleware',
...
]

This middleware is enabled in the settings file generated by startproject.

By default, the middleware will set the X-Frame-Options header to SAMEORIGIN for every outgoing HttpResponse. If you want DENY instead, set the X_FRAME_OPTIONS setting:

X_FRAME_OPTIONS = 'DENY'

When using the middleware there may be some views where you do not want the X-Frame-Options header set. For those cases, you can use a view decorator that tells the middleware not to set the header:

from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt

@xframe_options_exempt
def ok_to_load_in_a_frame(request):
return HttpResponse("This page is safe to load in a frame on any site.")

Setting X-Frame-Options per view

To set the X-Frame-Options header on a per view basis, Django provides these decorators:

from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_deny
from django.views.decorators.clickjacking import xframe_options_sameorigin

@xframe_options_deny
def view_one(request):
return HttpResponse("I won't display in any frame!")

@xframe_options_sameorigin
def view_two(request):
return HttpResponse("Display in a frame if it's from the same origin as me.")

Note that you can use the decorators in conjunction with the middleware. Use of a decorator overrides the middleware.

Limitations

The X-Frame-Options header will only protect against clickjacking in a modern browser. Older browsers will quietly ignore the header and need other clickjacking prevention techniques.

Browsers that support X-Frame-Options

- Internet Explorer 8+

- Firefox 3.6.9+

- Opera 10.5+

- Safari 4+

- Chrome 4.1+

See also

A complete list of browsers supporting X-Frame-Options.

contrib packages

Django aims to follow Python’s “batteries included” philosophy. It ships with a variety of extra, optional tools that solve common Web-development problems.

This code lives in django/contrib in the Django distribution. This document gives a rundown of the packages in contrib, along with any dependencies those packages have.

Note

For most of these add-ons – specifically, the add-ons that include either models or template tags – you’ll need to add the package name (e.g., 'django.contrib.redirects') to your INSTALLED_APPS setting and re-run manage.py migrate.

- The Django admin site

- django.contrib.auth

- The contenttypes framework

- The flatpages app

- GeoDjango

- django.contrib.humanize

- The messages framework

- django.contrib.postgres

- The redirects app

- The sitemap framework

- The “sites” framework

- The staticfiles app

- The syndication feed framework

- django.contrib.webdesign

admin

The automatic Django administrative interface. For more information, see Tutorial 2 and the admin documentation.

Requires the auth and contenttypes contrib packages to be installed.

auth

Django’s authentication framework.

See User authentication in Django.

contenttypes

A light framework for hooking into “types” of content, where each installed Django model is a separate content type.

See the contenttypes documentation.

flatpages

A framework for managing simple “flat” HTML content in a database.

See the flatpages documentation.

Requires the sites contrib package to be installed as well.

gis

A world-class geospatial framework built on top of Django, that enables storage, manipulation and display of spatial data.

See the GeoDjango documentation for more.

humanize

A set of Django template filters useful for adding a “human touch” to data.

See the humanize documentation.

messages

A framework for storing and retrieving temporary cookie- or session-based messages

See the messages documentation.

postgres

A collection of PostgreSQL specific features.

See the contrib.postgres documentation.

redirects

A framework for managing redirects.

See the redirects documentation.

sessions

A framework for storing data in anonymous sessions.

See the sessions documentation.

sites

A light framework that lets you operate multiple websites off of the same database and Django installation. It gives you hooks for associating objects to one or more sites.

See the sites documentation.

sitemaps

A framework for generating Google sitemap XML files.

See the sitemaps documentation.

syndication

A framework for generating syndication feeds, in RSS and Atom, quite easily.

See the syndication documentation.

webdesign

Helpers and utilities targeted primarily at Web designers rather than Web developers.

See the Web design helpers documentation.

Other add-ons

If you have an idea for functionality to include in contrib, let us know! Code it up, and post it to the django-users mailing list.

The Django admin site

One of the most powerful parts of Django is the automatic admin interface. It reads metadata from your models to provide a quick, model-centric interface where trusted users can manage content on your site. The admin’s recommended use is limited to an organization’s internal management tool. It’s not intended for building your entire front end around.

The admin has many hooks for customization, but beware of trying to use those hooks exclusively. If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.

In this document we discuss how to activate, use, and customize Django’s admin interface.

Overview

The admin is enabled in the default project template used by startproject.

For reference, here are the requirements:

1. Add 'django.contrib.admin' to your INSTALLED_APPS setting.

2. The admin has four dependencies - django.contrib.auth, django.contrib.contenttypes, django.contrib.messages and django.contrib.sessions. If these applications are not in your INSTALLED_APPS list, add them.

3. Add django.contrib.auth.context_processors.auth and django.contrib.messages.context_processors.messages to the 'context_processors' option of the DjangoTemplates backend defined in your TEMPLATES as well as django.contrib.auth.middleware.AuthenticationMiddleware and django.contrib.messages.middleware.MessageMiddleware to MIDDLEWARE_CLASSES. (These are all active by default, so you only need to do this if you’ve manually tweaked the settings.)

4. Determine which of your application’s models should be editable in the admin interface.

5. For each of those models, optionally create a ModelAdmin class that encapsulates the customized admin functionality and options for that particular model.

6. Instantiate an AdminSite and tell it about each of your models and ModelAdmin classes.

7. Hook the AdminSite instance into your URLconf.

After you’ve taken these steps, you’ll be able to use your Django admin site by visiting the URL you hooked it into (/admin/, by default). If you need to create a user to login with, you can use the createsuperuser command.

Other topics

- Admin actions

- The Django admin documentation generator

- JavaScript customizations in the admin

See also

For information about serving the static files (images, JavaScript, and CSS) associated with the admin in production, see Serving files.

Having problems? Try FAQ: The admin.

ModelAdmin objects

class ModelAdmin[source]

The ModelAdmin class is the representation of a model in the admin interface. Usually, these are stored in a file named admin.py in your application. Let’s take a look at a very simple example of the ModelAdmin:

from django.contrib import admin
from myproject.myapp.models import Author

class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)

Do you need a ModelAdmin object at all?

In the preceding example, the ModelAdmin class doesn’t define any custom values (yet). As a result, the default admin interface will be provided. If you are happy with the default admin interface, you don’t need to define a ModelAdmin object at all – you can register the model class without providing a ModelAdmin description. The preceding example could be simplified to:

from django.contrib import admin
from myproject.myapp.models import Author

admin.site.register(Author)

The register decorator

register(*models, site=django.admin.sites.site)[source]

There is also a decorator for registering your ModelAdmin classes:

from django.contrib import admin
from .models import Author

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass

It is given one or more model classes to register with the ModelAdmin and an optional keyword argument site if you are not using the default AdminSite:

from django.contrib import admin
from .models import Author, Reader, Editor
from myproject.admin_site import custom_admin_site

@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
pass

You can’t use this decorator if you have to reference your model admin class in its __init__() method, e.g. super(PersonAdmin, self).__init__(*args, **kwargs). If you are using Python 3 and don’t have to worry about supporting Python 2, you can use super().__init__(*args, **kwargs) . Otherwise, you’ll have to use admin.site.register() instead of this decorator.

Discovery of admin files

When you put 'django.contrib.admin' in your INSTALLED_APPS setting, Django automatically looks for an admin module in each application and imports it.

class apps.AdminConfig

This is the default AppConfig class for the admin. It calls autodiscover() when Django starts.

class apps.SimpleAdminConfig

This class works like AdminConfig, except it doesn’t call autodiscover().

autodiscover()[source]

This function attempts to import an admin module in each installed application. Such modules are expected to register models with the admin.

Typically you won’t need to call this function directly as AdminConfig calls it when Django starts.

If you are using a custom AdminSite, it is common to import all of the ModelAdmin subclasses into your code and register them to the custom AdminSite. In that case, in order to disable auto-discovery, you should put 'django.contrib.admin.apps.SimpleAdminConfig' instead of 'django.contrib.admin' in your INSTALLED_APPS setting.

ModelAdmin options

The ModelAdmin is very flexible. It has several options for dealing with customizing the interface. All options are defined on the ModelAdmin subclass:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = 'pub_date'

ModelAdmin.actions

A list of actions to make available on the change list page. See Admin actions for details.

ModelAdmin.actions_on_top

ModelAdmin.actions_on_bottom

Controls where on the page the actions bar appears. By default, the admin changelist displays actions at the top of the page (actions_on_top = True; actions_on_bottom = False).

ModelAdmin.actions_selection_counter

Controls whether a selection counter is displayed next to the action dropdown. By default, the admin changelist will display it (actions_selection_counter = True).

ModelAdmin.date_hierarchy

Set date_hierarchy to the name of a DateField or DateTimeField in your model, and the change list page will include a date-based drilldown navigation by that field.

Example:

date_hierarchy = 'pub_date'

This will intelligently populate itself based on available data, e.g. if all the dates are in one month, it’ll show the day-level drill-down only.

Note

date_hierarchy uses QuerySet.datetimes() internally. Please refer to its documentation for some caveats when time zone support is enabled (USE_TZ = True).

ModelAdmin.empty_value_display

New in Django 1.9.

This attribute overrides the default display value for record’s fields that are empty (None, empty string, etc.). The default value is - (a dash). For example:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
empty_value_display = '-empty-'

You can also override empty_value_display for all admin pages with AdminSite.empty_value_display, or for specific fields like this:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title', 'view_birth_date')

def view_birth_date(self, obj):
return obj.birth_date

view_birth_date.empty_value_display = '???'

ModelAdmin.exclude

This attribute, if given, should be a list of field names to exclude from the form.

For example, let’s consider the following model:

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3)
birth_date = models.DateField(blank=True, null=True)

If you want a form for the Author model that includes only the name and title fields, you would specify fields or exclude like this:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title')

class AuthorAdmin(admin.ModelAdmin):
exclude = ('birth_date',)

Since the Author model only has three fields, name, title, and birth_date, the forms resulting from the above declarations will contain exactly the same fields.

ModelAdmin.fields

Use the fields option to make simple layout changes in the forms on the “add” and “change” pages such as showing only a subset of available fields, modifying their order, or grouping them into rows. For example, you could define a simpler version of the admin form for the django.contrib.flatpages.models.FlatPage model as follows:

class FlatPageAdmin(admin.ModelAdmin):
fields = ('url', 'title', 'content')

In the above example, only the fields url, title and content will be displayed, sequentially, in the form. fields can contain values defined in ModelAdmin.readonly_fields to be displayed as read-only.

For more complex layout needs, see the fieldsets option.

The fields option, unlike list_display, may only contain names of fields on the model or the form specified by form. It may contain callables only if they are listed in readonly_fields.

To display multiple fields on the same line, wrap those fields in their own tuple. In this example, the url and title fields will display on the same line and the content field will be displayed below them on its own line:

class FlatPageAdmin(admin.ModelAdmin):
fields = (('url', 'title'), 'content')

Note

This fields option should not be confused with the fields dictionary key that is within the fieldsets option, as described in the next section.

If neither fields nor fieldsets options are present, Django will default to displaying each field that isn’t an AutoField and has editable=True, in a single fieldset, in the same order as the fields are defined in the model.

ModelAdmin.fieldsets

Set fieldsets to control the layout of admin “add” and “change” pages.

fieldsets is a list of two-tuples, in which each two-tuple represents a <fieldset> on the admin form page. (A <fieldset> is a “section” of the form.)

The two-tuples are in the format (name, field_options), where name is a string representing the title of the fieldset and field_options is a dictionary of information about the fieldset, including a list of fields to be displayed in it.

A full example, taken from the django.contrib.flatpages.models.FlatPage model:

from django.contrib import admin

class FlatPageAdmin(admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('url', 'title', 'content', 'sites')
}),
('Advanced options', {
'classes': ('collapse',),
'fields': ('registration_required', 'template_name'),
}),
)

This results in an admin page that looks like:

If neither fieldsets nor fields options are present, Django will default to displaying each field that isn’t an AutoField and has editable=True, in a single fieldset, in the same order as the fields are defined in the model.

The field_options dictionary can have the following keys:

fields

A tuple of field names to display in this fieldset. This key is required.

Example:

{
'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
}

As with the fields option, to display multiple fields on the same line, wrap those fields in their own tuple. In this example, the first_name and last_name fields will display on the same line:

{
'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
}

fields can contain values defined in readonly_fields to be displayed as read-only.

If you add the name of a callable to fields, the same rule applies as with the fields option: the callable must be listed in readonly_fields.

classes

A list or tuple containing extra CSS classes to apply to the fieldset.

Example:

{
'classes': ('wide', 'extrapretty'),
}

Two useful classes defined by the default admin site stylesheet are collapse and wide. Fieldsets with the collapse style will be initially collapsed in the admin and replaced with a small “click to expand” link. Fieldsets with the wide style will be given extra horizontal space.

description

A string of optional extra text to be displayed at the top of each fieldset, under the heading of the fieldset. This string is not rendered for TabularInline due to its layout.

Note that this value is not HTML-escaped when it’s displayed in the admin interface. This lets you include HTML if you so desire. Alternatively you can use plain text and django.utils.html.escape() to escape any HTML special characters.

ModelAdmin.filter_horizontal

By default, a ManyToManyField is displayed in the admin site with a <select multiple>. However, multiple-select boxes can be difficult to use when selecting many items. Adding a ManyToManyField to this list will instead use a nifty unobtrusive JavaScript “filter” interface that allows searching within the options. The unselected and selected options appear in two boxes side by side. See filter_vertical to use a vertical interface.

ModelAdmin.filter_vertical

Same as filter_horizontal, but uses a vertical display of the filter interface with the box of unselected options appearing above the box of selected options.

ModelAdmin.form

By default a ModelForm is dynamically created for your model. It is used to create the form presented on both the add/change pages. You can easily provide your own ModelForm to override any default form behavior on the add/change pages. Alternatively, you can customize the default form rather than specifying an entirely new one by using the ModelAdmin.get_form() method.

For an example see the section Adding custom validation to the admin.

Note

If you define the Meta.model attribute on a ModelForm, you must also define the Meta.fields attribute (or the Meta.exclude attribute). However, since the admin has its own way of defining fields, the Meta.fields attribute will be ignored.

If the ModelForm is only going to be used for the admin, the easiest solution is to omit the Meta.model attribute, since ModelAdmin will provide the correct model to use. Alternatively, you can set fields = [] in the Meta class to satisfy the validation on the ModelForm.

Note

If your ModelForm and ModelAdmin both define an exclude option then ModelAdmin takes precedence:

from django import forms
from django.contrib import admin
from myapp.models import Person

class PersonForm(forms.ModelForm):

class Meta:
model = Person
exclude = ['name']

class PersonAdmin(admin.ModelAdmin):
exclude = ['age']
form = PersonForm

In the above example, the “age” field will be excluded but the “name” field will be included in the generated form.

ModelAdmin.formfield_overrides

This provides a quick-and-dirty way to override some of the Field options for use in the admin. formfield_overrides is a dictionary mapping a field class to a dict of arguments to pass to the field at construction time.

Since that’s a bit abstract, let’s look at a concrete example. The most common use of formfield_overrides is to add a custom widget for a certain type of field. So, imagine we’ve written a RichTextEditorWidget that we’d like to use for large text fields instead of the default <textarea>. Here’s how we’d do that:

from django.db import models
from django.contrib import admin

# Import our custom widget and our model from where they're defined
from myapp.widgets import RichTextEditorWidget
from myapp.models import MyModel

class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': RichTextEditorWidget},
}

Note that the key in the dictionary is the actual field class, not a string. The value is another dictionary; these arguments will be passed to the form field’s __init__() method. See The Forms API for details.

Warning

If you want to use a custom widget with a relation field (i.e. ForeignKey or ManyToManyField), make sure you haven’t included that field’s name in raw_id_fields or radio_fields.

formfield_overrides won’t let you change the widget on relation fields that have raw_id_fields or radio_fields set. That’s because raw_id_fields and radio_fields imply custom widgets of their own.

ModelAdmin.inlines

See InlineModelAdmin objects below as well as ModelAdmin.get_formsets_with_inlines().

ModelAdmin.list_display

Set list_display to control which fields are displayed on the change list page of the admin.

Example:

list_display = ('first_name', 'last_name')

If you don’t set list_display, the admin site will display a single column that displays the __str__() (__unicode__() on Python 2) representation of each object.

You have four possible values that can be used in list_display:

- A field of the model. For example:

class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')

- A callable that accepts one parameter for the model instance. For example:

def upper_case_name(obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'

class PersonAdmin(admin.ModelAdmin):
list_display = (upper_case_name,)

- A string representing an attribute on the ModelAdmin. This behaves same as the callable. For example:

class PersonAdmin(admin.ModelAdmin):
list_display = ('upper_case_name',)

def upper_case_name(self, obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'

- A string representing an attribute on the model. This behaves almost the same as the callable, but self in this context is the model instance. Here’s a full model example:

from django.db import models
from django.contrib import admin

class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()

def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'

class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')

A few special cases to note about list_display:

- If the field is a ForeignKey, Django will display the __str__() (__unicode__() on Python 2) of the related object.

- ManyToManyField fields aren’t supported, because that would entail executing a separate SQL statement for each row in the table. If you want to do this nonetheless, give your model a custom method, and add that method’s name to list_display. (See below for more on custom methods in list_display.)

- If the field is a BooleanField or NullBooleanField, Django will display a pretty “on” or “off” icon instead of True or False.

- If the string given is a method of the model, ModelAdmin or a callable, Django will HTML-escape the output by default. To escape user input and allow your own unescaped tags, use format_html().

Here’s a full example model:

from django.db import models
from django.contrib import admin
from django.utils.html import format_html

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)

def colored_name(self):
return format_html(
'<span style="color: #{};">{} {}</span>',
self.color_code,
self.first_name,
self.last_name,
)

class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'colored_name')

Deprecated since version 1.9: In older versions, you could add an allow_tags attribute to the method to prevent auto-escaping. This attribute is deprecated as it’s safer to use format_html(), format_html_join(), or mark_safe() instead.

- If the value of a field is None, an empty string, or an iterable without elements, Django will display - (a dash). You can override this with AdminSite.empty_value_display:

from django.contrib import admin

admin.site.empty_value_display = '(None)'

You can also use ModelAdmin.empty_value_display:

class PersonAdmin(admin.ModelAdmin):
empty_value_display = 'unknown'

Or on a field level:

class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'birth_date_view')

def birth_date_view(self, obj):
return obj.birth_date

birth_date_view.empty_value_display = 'unknown'

New in Django 1.9:
The ability to customize empty_value_display was added.

- If the string given is a method of the model, ModelAdmin or a callable that returns True or False Django will display a pretty “on” or “off” icon if you give the method a boolean attribute whose value is True.

Here’s a full example model:

from django.db import models
from django.contrib import admin

class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField()

def born_in_fifties(self):
return self.birthday.strftime('%Y')[:3] == '195'
born_in_fifties.boolean = True

class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'born_in_fifties')

- The __str__() (__unicode__() on Python 2) method is just as valid in list_display as any other model method, so it’s perfectly OK to do this:

list_display = ('__str__', 'some_other_field')

- Usually, elements of list_display that aren’t actual database fields can’t be used in sorting (because Django does all the sorting at the database level).

However, if an element of list_display represents a certain database field, you can indicate this fact by setting the admin_order_field attribute of the item.

For example:

from django.db import models
from django.contrib import admin
from django.utils.html import format_html

class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)

def colored_first_name(self):
return format_html(
'<span style="color: #{};">{}</span>',
self.color_code,
self.first_name,
)

colored_first_name.admin_order_field = 'first_name'

class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')

The above will tell Django to order by the first_name field when trying to sort by colored_first_name in the admin.

To indicate descending order with admin_order_field you can use a hyphen prefix on the field name. Using the above example, this would look like:

colored_first_name.admin_order_field = '-first_name'

admin_order_field supports query lookups to sort by values on related models. This example includes an “author first name” column in the list display and allows sorting it by first name:

class Blog(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(Person, on_delete=models.CASCADE)

class BlogAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'author_first_name')

def author_first_name(self, obj):
return obj.author.first_name

author_first_name.admin_order_field = 'author__first_name'

- Elements of list_display can also be properties. Please note however, that due to the way properties work in Python, setting short_description on a property is only possible when using the property() function and not with the @property decorator.

For example:

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)

def my_property(self):
return self.first_name + ' ' + self.last_name
my_property.short_description = "Full name of the person"

full_name = property(my_property)

class PersonAdmin(admin.ModelAdmin):
list_display = ('full_name',)

- The field names in list_display will also appear as CSS classes in the HTML output, in the form of column-<field_name> on each <th> element. This can be used to set column widths in a CSS file for example.

- Django will try to interpret every element of list_display in this order:

- A field of the model.

- A callable.

- A string representing a ModelAdmin attribute.

- A string representing a model attribute.

For example if you have first_name as a model field and as a ModelAdmin attribute, the model field will be used.

ModelAdmin.list_display_links

Use list_display_links to control if and which fields in list_display should be linked to the “change” page for an object.

By default, the change list page will link the first column – the first field specified in list_display – to the change page for each item. But list_display_links lets you change this:

- Set it to None to get no links at all.

- Set it to a list or tuple of fields (in the same format as list_display) whose columns you want converted to links.

You can specify one or many fields. As long as the fields appear in list_display, Django doesn’t care how many (or how few) fields are linked. The only requirement is that if you want to use list_display_links in this fashion, you must define list_display.

In this example, the first_name and last_name fields will be linked on the change list page:

class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'birthday')
list_display_links = ('first_name', 'last_name')

In this example, the change list page grid will have no links:

class AuditEntryAdmin(admin.ModelAdmin):
list_display = ('timestamp', 'message')
list_display_links = None

ModelAdmin.list_editable

Set list_editable to a list of field names on the model which will allow editing on the change list page. That is, fields listed in list_editable will be displayed as form widgets on the change list page, allowing users to edit and save multiple rows at once.

Note

list_editable interacts with a couple of other options in particular ways; you should note the following rules:

- Any field in list_editable must also be in list_display. You can’t edit a field that’s not displayed!

- The same field can’t be listed in both list_editable and list_display_links – a field can’t be both a form and a link.

You’ll get a validation error if either of these rules are broken.

ModelAdmin.list_filter

Set list_filter to activate filters in the right sidebar of the change list page of the admin, as illustrated in the following screenshot:

list_filter should be a list or tuple of elements, where each element should be of one of the following types:

- a field name, where the specified field should be either a BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey or ManyToManyField, for example:

class PersonAdmin(admin.ModelAdmin):
list_filter = ('is_staff', 'company')

Field names in list_filter can also span relations using the __ lookup, for example:

class PersonAdmin(admin.UserAdmin):
list_filter = ('company__name',)

- a class inheriting from django.contrib.admin.SimpleListFilter, which you need to provide the title and parameter_name attributes to and override the lookups and queryset methods, e.g.:

from datetime import date

from django.contrib import admin
from django.utils.translation import ugettext_lazy as _

class DecadeBornListFilter(admin.SimpleListFilter):
# Human-readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _('decade born')

# Parameter for the filter that will be used in the URL query.
parameter_name = 'decade'

def lookups(self, request, model_admin):
"""
Returns a list of tuples. The first element in each
tuple is the coded value for the option that will
appear in the URL query. The second element is the
human-readable name for the option that will appear
in the right sidebar.
"""
return (
('80s', _('in the eighties')),
('90s', _('in the nineties')),
)

def queryset(self, request, queryset):
"""
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
"""
# Compare the requested value (either '80s' or '90s')
# to decide how to filter the queryset.
if self.value() == '80s':
return queryset.filter(birthday__gte=date(1980, 1, 1),
birthday__lte=date(1989, 12, 31))
if self.value() == '90s':
return queryset.filter(birthday__gte=date(1990, 1, 1),
birthday__lte=date(1999, 12, 31))

class PersonAdmin(admin.ModelAdmin):
list_filter = (DecadeBornListFilter,)

Note

As a convenience, the HttpRequest object is passed to the lookups and queryset methods, for example:

class AuthDecadeBornListFilter(DecadeBornListFilter):

def lookups(self, request, model_admin):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter, self).lookups(request, model_admin)

def queryset(self, request, queryset):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter, self).queryset(request, queryset)

Also as a convenience, the ModelAdmin object is passed to the lookups method, for example if you want to base the lookups on the available data:

class AdvancedDecadeBornListFilter(DecadeBornListFilter):

def lookups(self, request, model_admin):
"""
Only show the lookups if there actually is
anyone born in the corresponding decades.
"""
qs = model_admin.get_queryset(request)
if qs.filter(birthday__gte=date(1980, 1, 1),
birthday__lte=date(1989, 12, 31)).exists():
yield ('80s', _('in the eighties'))
if qs.filter(birthday__gte=date(1990, 1, 1),
birthday__lte=date(1999, 12, 31)).exists():
yield ('90s', _('in the nineties'))

- a tuple, where the first element is a field name and the second element is a class inheriting from django.contrib.admin.FieldListFilter, for example:

class PersonAdmin(admin.ModelAdmin):
list_filter = (
('is_staff', admin.BooleanFieldListFilter),
)

New in Django 1.8.

You can now limit the choices of a related model to the objects involved in that relation using RelatedOnlyFieldListFilter:

class BookAdmin(admin.ModelAdmin):
list_filter = (
('author', admin.RelatedOnlyFieldListFilter),
)

Assuming author is a ForeignKey to a User model, this will limit the list_filter choices to the users who have written a book instead of listing all users.

Note

The FieldListFilter API is considered internal and might be changed.

It is possible to specify a custom template for rendering a list filter:

class FilterWithCustomTemplate(admin.SimpleListFilter):
template = "custom_template.html"

See the default template provided by django (admin/filter.html) for a concrete example.

ModelAdmin.list_max_show_all

Set list_max_show_all to control how many items can appear on a “Show all” admin change list page. The admin will display a “Show all” link on the change list only if the total result count is less than or equal to this setting. By default, this is set to 200.

ModelAdmin.list_per_page

Set list_per_page to control how many items appear on each paginated admin change list page. By default, this is set to 100.

ModelAdmin.list_select_related

Set list_select_related to tell Django to use select_related() in retrieving the list of objects on the admin change list page. This can save you a bunch of database queries.

The value should be either a boolean, a list or a tuple. Default is False.

When value is True, select_related() will always be called. When value is set to False, Django will look at list_display and call select_related() if any ForeignKey is present.

If you need more fine-grained control, use a tuple (or list) as value for list_select_related. Empty tuple will prevent Django from calling select_related at all. Any other tuple will be passed directly to select_related as parameters. For example:

class ArticleAdmin(admin.ModelAdmin):
list_select_related = ('author', 'category')

will call select_related('author', 'category').

If you need to specify a dynamic value based on the request, you can implement a get_list_select_related() method.

ModelAdmin.ordering

Set ordering to specify how lists of objects should be ordered in the Django admin views. This should be a list or tuple in the same format as a model’s ordering parameter.

If this isn’t provided, the Django admin will use the model’s default ordering.

If you need to specify a dynamic order (for example depending on user or language) you can implement a get_ordering() method.

ModelAdmin.paginator

The paginator class to be used for pagination. By default, django.core.paginator.Paginator is used. If the custom paginator class doesn’t have the same constructor interface as django.core.paginator.Paginator, you will also need to provide an implementation for ModelAdmin.get_paginator().

ModelAdmin.prepopulated_fields

Set prepopulated_fields to a dictionary mapping field names to the fields it should prepopulate from:

class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}

When set, the given fields will use a bit of JavaScript to populate from the fields assigned. The main use for this functionality is to automatically generate the value for SlugField fields from one or more other fields. The generated value is produced by concatenating the values of the source fields, and then by transforming that result into a valid slug (e.g. substituting dashes for spaces).

prepopulated_fields doesn’t accept DateTimeField, ForeignKey, nor ManyToManyField fields.

ModelAdmin.preserve_filters

The admin now preserves filters on the list view after creating, editing or deleting an object. You can restore the previous behavior of clearing filters by setting this attribute to False.

ModelAdmin.radio_fields

By default, Django’s admin uses a select-box interface (<select>) for fields that are ForeignKey or have choices set. If a field is present in radio_fields, Django will use a radio-button interface instead. Assuming group is a ForeignKey on the Person model:

class PersonAdmin(admin.ModelAdmin):
radio_fields = {"group": admin.VERTICAL}

You have the choice of using HORIZONTAL or VERTICAL from the django.contrib.admin module.

Don’t include a field in radio_fields unless it’s a ForeignKey or has choices set.

ModelAdmin.raw_id_fields

By default, Django’s admin uses a select-box interface (<select>) for fields that are ForeignKey. Sometimes you don’t want to incur the overhead of having to select all the related instances to display in the drop-down.

raw_id_fields is a list of fields you would like to change into an Input widget for either a ForeignKey or ManyToManyField:

class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ("newspaper",)

The raw_id_fields Input widget should contain a primary key if the field is a ForeignKey or a comma separated list of values if the field is a ManyToManyField. The raw_id_fields widget shows a magnifying glass button next to the field which allows users to search for and select a value:

ModelAdmin.readonly_fields

By default the admin shows all fields as editable. Any fields in this option (which should be a list or tuple) will display its data as-is and non-editable; they are also excluded from the ModelForm used for creating and editing. Note that when specifying ModelAdmin.fields or ModelAdmin.fieldsets the read-only fields must be present to be shown (they are ignored otherwise).

If readonly_fields is used without defining explicit ordering through ModelAdmin.fields or ModelAdmin.fieldsets they will be added last after all editable fields.

A read-only field can not only display data from a model’s field, it can also display the output of a model’s method or a method of the ModelAdmin class itself. This is very similar to the way ModelAdmin.list_display behaves. This provides an easy way to use the admin interface to provide feedback on the status of the objects being edited, for example:

from django.contrib import admin
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe

class PersonAdmin(admin.ModelAdmin):
readonly_fields = ('address_report',)

def address_report(self, instance):
# assuming get_full_address() returns a list of strings
# for each line of the address and you want to separate each
# line by a linebreak
return format_html_join(
mark_safe('<br/>'),
'{}',
((line,) for line in instance.get_full_address()),
) or mark_safe("<span class='errors'>I can't determine this address.</span>")

# short_description functions like a model field's verbose_name
address_report.short_description = "Address"

ModelAdmin.save_as

Set save_as to enable a “save as new” feature on admin change forms.

Normally, objects have three save options: “Save”, “Save and continue editing”, and “Save and add another”. If save_as is True, “Save and add another” will be replaced by a “Save as new” button that creates a new object (with a new ID) rather than updating the existing object.

By default, save_as is set to False.

ModelAdmin.save_on_top

Set save_on_top to add save buttons across the top of your admin change forms.

Normally, the save buttons appear only at the bottom of the forms. If you set save_on_top, the buttons will appear both on the top and the bottom.

By default, save_on_top is set to False.

ModelAdmin.search_fields

Set search_fields to enable a search box on the admin change list page. This should be set to a list of field names that will be searched whenever somebody submits a search query in that text box.

These fields should be some kind of text field, such as CharField or TextField. You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API “follow” notation:

search_fields = ['foreign_key__related_fieldname']

For example, if you have a blog entry with an author, the following definition would enable searching blog entries by the email address of the author:

search_fields = ['user__email']

When somebody does a search in the admin search box, Django splits the search query into words and returns all objects that contain each of the words, case insensitive, where each word must be in at least one of search_fields. For example, if search_fields is set to ['first_name', 'last_name'] and a user searches for john lennon, Django will do the equivalent of this SQL WHERE clause:

WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

For faster and/or more restrictive searches, prefix the field name with an operator:

^

Use the ‘^’ operator to match starting at the beginning of the field. For example, if search_fields is set to ['^first_name', '^last_name'] and a user searches for john lennon, Django will do the equivalent of this SQL WHERE clause:

WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')

This query is more efficient than the normal '%john%' query, because the database only needs to check the beginning of a column’s data, rather than seeking through the entire column’s data. Plus, if the column has an index on it, some databases may be able to use the index for this query, even though it’s a LIKE query.

=

Use the ‘=’ operator for case-insensitive exact matching. For example, if search_fields is set to ['=first_name', '=last_name'] and a user searches for john lennon, Django will do the equivalent of this SQL WHERE clause:

WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')

Note that the query input is split by spaces, so, following this example, it’s currently not possible to search for all records in which first_name is exactly 'john winston' (containing a space).

@

Using the ‘@’ operator to perform a full text match. This is like the default search method but uses an index. Currently this is only available for MySQL.

If you need to customize search you can use ModelAdmin.get_search_results() to provide additional or alternate search behavior.

ModelAdmin.show_full_result_count

New in Django 1.8.

Set show_full_result_count to control whether the full count of objects should be displayed on a filtered admin page (e.g. 99 results (103 total)). If this option is set to False, a text like 99 results (Show all) is displayed instead.

The default of show_full_result_count=True generates a query to perform a full count on the table which can be expensive if the table contains a large number of rows.

ModelAdmin.view_on_site

Set view_on_site to control whether or not to display the “View on site” link. This link should bring you to a URL where you can display the saved object.

This value can be either a boolean flag or a callable. If True (the default), the object’s get_absolute_url() method will be used to generate the url.

If your model has a get_absolute_url() method but you don’t want the “View on site” button to appear, you only need to set view_on_site to False:

from django.contrib import admin

class PersonAdmin(admin.ModelAdmin):
view_on_site = False

In case it is a callable, it accepts the model instance as a parameter. For example:

from django.contrib import admin
from django.core.urlresolvers import reverse

class PersonAdmin(admin.ModelAdmin):
def view_on_site(self, obj):
url = reverse('person-detail', kwargs={'slug': obj.slug})
return 'https://example.com' + url

Custom template options

The Overriding admin templates section describes how to override or extend the default admin templates. Use the following options to override the default templates used by the ModelAdmin views:

ModelAdmin.add_form_template

Path to a custom template, used by add_view().

ModelAdmin.change_form_template

Path to a custom template, used by change_view().

ModelAdmin.change_list_template

Path to a custom template, used by changelist_view().

ModelAdmin.delete_confirmation_template

Path to a custom template, used by delete_view() for displaying a confirmation page when deleting one or more objects.

ModelAdmin.delete_selected_confirmation_template

Path to a custom template, used by the delete_selected action method for displaying a confirmation page when deleting one or more objects. See the actions documentation.

ModelAdmin.object_history_template

Path to a custom template, used by history_view().

ModelAdmin methods

Warning

ModelAdmin.save_model() and ModelAdmin.delete_model() must save/delete the object, they are not for veto purposes, rather they allow you to perform extra operations.

ModelAdmin.save_model(request, obj, form, change)[source]

The save_model method is given the HttpRequest, a model instance, a ModelForm instance and a boolean value based on whether it is adding or changing the object. Here you can do any pre- or post-save operations.

For example to attach request.user to the object prior to saving:

from django.contrib import admin

class ArticleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
obj.save()

ModelAdmin.delete_model(request, obj)[source]

The delete_model method is given the HttpRequest and a model instance. Use this method to do pre- or post-delete operations.

ModelAdmin.save_formset(request, form, formset, change)[source]

The save_formset method is given the HttpRequest, the parent ModelForm instance and a boolean value based on whether it is adding or changing the parent object.

For example, to attach request.user to each changed formset model instance:

class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for obj in formset.deleted_objects:
obj.delete()
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()

See also Saving objects in the formset.

ModelAdmin.get_ordering(request)

The get_ordering method takes a request as parameter and is expected to return a list or tuple for ordering similar to the ordering attribute. For example:

class PersonAdmin(admin.ModelAdmin):

def get_ordering(self, request):
if request.user.is_superuser:
return ['name', 'rank']
else:
return ['name']

ModelAdmin.get_search_results(request, queryset, search_term)[source]

The get_search_results method modifies the list of objects displayed into those that match the provided search term. It accepts the request, a queryset that applies the current filters, and the user-provided search term. It returns a tuple containing a queryset modified to implement the search, and a boolean indicating if the results may contain duplicates.

The default implementation searches the fields named in ModelAdmin.search_fields.

This method may be overridden with your own custom search method. For example, you might wish to search by an integer field, or use an external tool such as Solr or Haystack. You must establish if the queryset changes implemented by your search method may introduce duplicates into the results, and return True in the second element of the return value.

For example, to search by name and age, you could use:

class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'age')
search_fields = ('name',)

def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super(PersonAdmin, self).get_search_results(request, queryset, search_term)
try:
search_term_as_int = int(search_term)
except ValueError:
pass
else:
queryset |= self.model.objects.filter(age=search_term_as_int)
return queryset, use_distinct

This implementation is more efficient than search_fields = ('name', '=age') which results in a string comparison for the numeric field, for example ... OR UPPER("polls_choice"."votes"::text) = UPPER('4') on PostgreSQL.

ModelAdmin.save_related(request, form, formsets, change)[source]

The save_related method is given the HttpRequest, the parent ModelForm instance, the list of inline formsets and a boolean value based on whether the parent is being added or changed. Here you can do any pre- or post-save operations for objects related to the parent. Note that at this point the parent object and its form have already been saved.

ModelAdmin.get_readonly_fields(request, obj=None)

The get_readonly_fields method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list or tuple of field names that will be displayed as read-only, as described above in the ModelAdmin.readonly_fields section.

ModelAdmin.get_prepopulated_fields(request, obj=None)

The get_prepopulated_fields method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a dictionary, as described above in the ModelAdmin.prepopulated_fields section.

ModelAdmin.get_list_display(request)[source]

The get_list_display method is given the HttpRequest and is expected to return a list or tuple of field names that will be displayed on the changelist view as described above in the ModelAdmin.list_display section.

ModelAdmin.get_list_display_links(request, list_display)[source]

The get_list_display_links method is given the HttpRequest and the list or tuple returned by ModelAdmin.get_list_display(). It is expected to return either None or a list or tuple of field names on the changelist that will be linked to the change view, as described in the ModelAdmin.list_display_links section.

ModelAdmin.get_fields(request, obj=None)[source]

The get_fields method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list of fields, as described above in the ModelAdmin.fields section.

ModelAdmin.get_fieldsets(request, obj=None)

The get_fieldsets method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list of two-tuples, in which each two-tuple represents a <fieldset> on the admin form page, as described above in the ModelAdmin.fieldsets section.

ModelAdmin.get_list_filter(request)[source]

The get_list_filter method is given the HttpRequest and is expected to return the same kind of sequence type as for the list_filter attribute.

ModelAdmin.get_list_select_related(request)[source]

New in Django 1.9.

The get_list_select_related method is given the HttpRequest and should return a boolean or list as ModelAdmin.list_select_related does.

ModelAdmin.get_search_fields(request)[source]

The get_search_fields method is given the HttpRequest and is expected to return the same kind of sequence type as for the search_fields attribute.

ModelAdmin.get_inline_instances(request, obj=None)[source]

The get_inline_instances method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list or tuple of InlineModelAdmin objects, as described below in the InlineModelAdmin section. For example, the following would return inlines without the default filtering based on add, change, and delete permissions:

class MyModelAdmin(admin.ModelAdmin):
inlines = (MyInline,)

def get_inline_instances(self, request, obj=None):
return [inline(self.model, self.admin_site) for inline in self.inlines]

If you override this method, make sure that the returned inlines are instances of the classes defined in inlines or you might encounter a “Bad Request” error when adding related objects.

ModelAdmin.get_urls()[source]

The get_urls method on a ModelAdmin returns the URLs to be used for that ModelAdmin in the same way as a URLconf. Therefore you can extend them as documented in URL dispatcher:

class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.my_view),
]
return my_urls + urls

def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)

If you want to use the admin layout, extend from admin/base_site.html:

{% extends "admin/base_site.html" %}
{% block content %}
...
{% endblock %}

Note

Notice that the custom patterns are included before the regular admin URLs: the admin URL patterns are very permissive and will match nearly anything, so you’ll usually want to prepend your custom URLs to the built-in ones.

In this example, my_view will be accessed at /admin/myapp/mymodel/my_view/ (assuming the admin URLs are included at /admin/.)

However, the self.my_view function registered above suffers from two problems:

- It will not perform any permission checks, so it will be accessible to the general public.

- It will not provide any header details to prevent caching. This means if the page retrieves data from the database, and caching middleware is active, the page could show outdated information.

Since this is usually not what you want, Django provides a convenience wrapper to check permissions and mark the view as non-cacheable. This wrapper is AdminSite.admin_view() (i.e. self.admin_site.admin_view inside a ModelAdmin instance); use it like so:

class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.admin_site.admin_view(self.my_view))
]
return my_urls + urls

Notice the wrapped view in the fifth line above:

url(r'^my_view/$', self.admin_site.admin_view(self.my_view))

This wrapping will protect self.my_view from unauthorized access and will apply the django.views.decorators.cache.never_cache() decorator to make sure it is not cached if the cache middleware is active.

If the page is cacheable, but you still want the permission check to be performed, you can pass a cacheable=True argument to AdminSite.admin_view():

url(r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))

New in Django 1.9.

ModelAdmin views have model_admin attributes. Other AdminSite views have admin_site attributes.

ModelAdmin.get_form(request, obj=None, **kwargs)[source]

Returns a ModelForm class for use in the admin add and change views, see add_view() and change_view().

The base implementation uses modelform_factory() to subclass form, modified by attributes such as fields and exclude. So, for example, if you wanted to offer additional fields to superusers, you could swap in a different base form like so:

class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
kwargs['form'] = MySuperuserForm
return super(MyModelAdmin, self).get_form(request, obj, **kwargs)

You may also simply return a custom ModelForm class directly.

ModelAdmin.get_formsets_with_inlines(request, obj=None)[source]

Yields (FormSet, InlineModelAdmin) pairs for use in admin add and change views.

For example if you wanted to display a particular inline only in the change view, you could override get_formsets_with_inlines as follows:

class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInline, SomeOtherInline]

def get_formsets_with_inlines(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if isinstance(inline, MyInline) and obj is None:
continue
yield inline.get_formset(request, obj), inline

ModelAdmin.formfield_for_foreignkey(db_field, request, **kwargs)

The formfield_for_foreignkey method on a ModelAdmin allows you to override the default formfield for a foreign keys field. For example, to return a subset of objects for this foreign key field based on the user:

class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "car":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

This uses the HttpRequest instance to filter the Car foreign key field to only display the cars owned by the User instance.

ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)

Like the formfield_for_foreignkey method, the formfield_for_manytomany method can be overridden to change the default formfield for a many to many field. For example, if an owner can own multiple cars and cars can belong to multiple owners – a many to many relationship – you could filter the Car foreign key field to only display the cars owned by the User:

class MyModelAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "cars":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

ModelAdmin.formfield_for_choice_field(db_field, request, **kwargs)

Like the formfield_for_foreignkey and formfield_for_manytomany methods, the formfield_for_choice_field method can be overridden to change the default formfield for a field that has declared choices. For example, if the choices available to a superuser should be different than those available to regular staff, you could proceed as follows:

class MyModelAdmin(admin.ModelAdmin):
def formfield_for_choice_field(self, db_field, request, **kwargs):
if db_field.name == "status":
kwargs['choices'] = (
('accepted', 'Accepted'),
('denied', 'Denied'),
)
if request.user.is_superuser:
kwargs['choices'] += (('ready', 'Ready for deployment'),)
return super(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs)

Note

Any choices attribute set on the formfield will be limited to the form field only. If the corresponding field on the model has choices set, the choices provided to the form must be a valid subset of those choices, otherwise the form submission will fail with a ValidationError when the model itself is validated before saving.

ModelAdmin.get_changelist(request, **kwargs)[source]

Returns the Changelist class to be used for listing. By default, django.contrib.admin.views.main.ChangeList is used. By inheriting this class you can change the behavior of the listing.

ModelAdmin.get_changelist_form(request, **kwargs)[source]

Returns a ModelForm class for use in the Formset on the changelist page. To use a custom form, for example:

from django import forms

class MyForm(forms.ModelForm):
pass

class MyModelAdmin(admin.ModelAdmin):
def get_changelist_form(self, request, **kwargs):
return MyForm

Note

If you define the Meta.model attribute on a ModelForm, you must also define the Meta.fields attribute (or the Meta.exclude attribute). However, ModelAdmin ignores this value, overriding it with the ModelAdmin.list_editable attribute. The easiest solution is to omit the Meta.model attribute, since ModelAdmin will provide the correct model to use.

ModelAdmin.get_changelist_formset(request, **kwargs)[source]

Returns a ModelFormSet class for use on the changelist page if list_editable is used. To use a custom formset, for example:

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
pass

class MyModelAdmin(admin.ModelAdmin):
def get_changelist_formset(self, request, **kwargs):
kwargs['formset'] = MyAdminFormSet
return super(MyModelAdmin, self).get_changelist_formset(request, **kwargs)

ModelAdmin.has_add_permission(request)

Should return True if adding an object is permitted, False otherwise.

ModelAdmin.has_change_permission(request, obj=None)

Should return True if editing obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether editing of objects of this type is permitted in general (e.g., False will be interpreted as meaning that the current user is not permitted to edit any object of this type).

ModelAdmin.has_delete_permission(request, obj=None)

Should return True if deleting obj is permitted, False otherwise. If obj is None, should return True or False to indicate whether deleting objects of this type is permitted in general (e.g., False will be interpreted as meaning that the current user is not permitted to delete any object of this type).

ModelAdmin.has_module_permission(request)

New in Django 1.8.

Should return True if displaying the module on the admin index page and accessing the module’s index page is permitted, False otherwise. Uses User.has_module_perms() by default. Overriding it does not restrict access to the add, change or delete views, has_add_permission(), has_change_permission(), and has_delete_permission() should be used for that.

ModelAdmin.get_queryset(request)

The get_queryset method on a ModelAdmin returns a QuerySet of all model instances that can be edited by the admin site. One use case for overriding this method is to show objects owned by the logged-in user:

class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(MyModelAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)

ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False)[source]

Sends a message to the user using the django.contrib.messages backend. See the custom ModelAdmin example.

Keyword arguments allow you to change the message level, add extra CSS tags, or fail silently if the contrib.messages framework is not installed. These keyword arguments match those for django.contrib.messages.add_message(), see that function’s documentation for more details. One difference is that the level may be passed as a string label in addition to integer/constant.

ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)[source]

Returns an instance of the paginator to use for this view. By default, instantiates an instance of paginator.

ModelAdmin.response_add(request, obj, post_url_continue=None)[source]

Determines the HttpResponse for the add_view() stage.

response_add is called after the admin form is submitted and just after the object and all the related instances have been created and saved. You can override it to change the default behavior after the object has been created.

ModelAdmin.response_change(request, obj)[source]

Determines the HttpResponse for the change_view() stage.

response_change is called after the admin form is submitted and just after the object and all the related instances have been saved. You can override it to change the default behavior after the object has been changed.

ModelAdmin.response_delete(request, obj_display, obj_id)[source]

Determines the HttpResponse for the delete_view() stage.

response_delete is called after the object has been deleted. You can override it to change the default behavior after the object has been deleted.

obj_display is a string with the name of the deleted object.

obj_id is the serialized identifier used to retrieve the object to be deleted.

New in Django 1.8:
The obj_id parameter was added.

ModelAdmin.get_changeform_initial_data(request)[source]

A hook for the initial data on admin change forms. By default, fields are given initial values from GET parameters. For instance, ?name=initial_value will set the name field’s initial value to be initial_value.

This method should return a dictionary in the form {'fieldname': 'fieldval'}:

def get_changeform_initial_data(self, request):
return {'name': 'custom_initial_value'}

Other methods

ModelAdmin.add_view(request, form_url='', extra_context=None)[source]

Django view for the model instance addition page. See note below.

ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)[source]

Django view for the model instance editing page. See note below.

ModelAdmin.changelist_view(request, extra_context=None)[source]

Django view for the model instances change list/actions page. See note below.

ModelAdmin.delete_view(request, object_id, extra_context=None)[source]

Django view for the model instance(s) deletion confirmation page. See note below.

ModelAdmin.history_view(request, object_id, extra_context=None)[source]

Django view for the page that shows the modification history for a given model instance.

Unlike the hook-type ModelAdmin methods detailed in the previous section, these five methods are in reality designed to be invoked as Django views from the admin application URL dispatching handler to render the pages that deal with model instances CRUD operations. As a result, completely overriding these methods will significantly change the behavior of the admin application.

One common reason for overriding these methods is to augment the context data that is provided to the template that renders the view. In the following example, the change view is overridden so that the rendered template is provided some extra mapping data that would not otherwise be available:

class MyModelAdmin(admin.ModelAdmin):

# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'

def get_osm_info(self):
# ...
pass

def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['osm_data'] = self.get_osm_info()
return super(MyModelAdmin, self).change_view(
request, object_id, form_url, extra_context=extra_context,
)

These views return TemplateResponse instances which allow you to easily customize the response data before rendering. For more details, see the TemplateResponse documentation.

ModelAdmin asset definitions

There are times where you would like add a bit of CSS and/or JavaScript to the add/change views. This can be accomplished by using a Media inner class on your ModelAdmin:

class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)

The staticfiles app prepends STATIC_URL (or MEDIA_URL if STATIC_URL is None) to any asset paths. The same rules apply as regular asset definitions on forms.

jQuery

Django admin JavaScript makes use of the jQuery library.

To avoid conflicts with user-supplied scripts or libraries, Django’s jQuery (version 2.1.4) is namespaced as django.jQuery. If you want to use jQuery in your own admin JavaScript without including a second copy, you can use the django.jQuery object on changelist and add/edit views.

Changed in Django 1.8:
The embedded jQuery has been upgraded from 1.9.1 to 1.11.2.

Changed in Django 1.9:
The embedded jQuery has been upgraded from 1.11.2 to 2.1.4. This drops support for Internet Explorer 8 and below. You can restore support by including your own version of jQuery 1.X.

The ModelAdmin class requires jQuery by default, so there is no need to add jQuery to your ModelAdmin’s list of media resources unless you have a specific need. For example, if you require the jQuery library to be in the global namespace (for example when using third-party jQuery plugins) or if you need a newer version of jQuery, you will have to include your own copy.

Django provides both uncompressed and ‘minified’ versions of jQuery, as jquery.js and jquery.min.js respectively.

ModelAdmin and InlineModelAdmin have a media property that returns a list of Media objects which store paths to the JavaScript files for the forms and/or formsets. If DEBUG is True it will return the uncompressed versions of the various JavaScript files, including jquery.js; if not, it will return the ‘minified’ versions.

Adding custom validation to the admin

Adding custom validation of data in the admin is quite easy. The automatic admin interface reuses django.forms, and the ModelAdmin class gives you the ability define your own form:

class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm

MyArticleAdminForm can be defined anywhere as long as you import where needed. Now within your form you can add your own custom validation for any field:

class MyArticleAdminForm(forms.ModelForm):
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]

It is important you use a ModelForm here otherwise things can break. See the forms documentation on custom validation and, more specifically, the model form validation notes for more information.

InlineModelAdmin objects

class InlineModelAdmin

class TabularInline[source]

class StackedInline[source]

The admin interface has the ability to edit models on the same page as a parent model. These are called inlines. Suppose you have these two models:

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)

class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)

You can edit the books authored by an author on the author page. You add inlines to a model by specifying them in a ModelAdmin.inlines:

from django.contrib import admin

class BookInline(admin.TabularInline):
model = Book

class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]

Django provides two subclasses of InlineModelAdmin and they are:

- TabularInline

- StackedInline

The difference between these two is merely the template used to render them.

InlineModelAdmin options

InlineModelAdmin shares many of the same features as ModelAdmin, and adds some of its own (the shared features are actually defined in the BaseModelAdmin superclass). The shared features are:

- form

- fieldsets

- fields

- formfield_overrides

- exclude

- filter_horizontal

- filter_vertical

- ordering

- prepopulated_fields

- get_queryset()

- radio_fields

- readonly_fields

- raw_id_fields

- formfield_for_choice_field()

- formfield_for_foreignkey()

- formfield_for_manytomany()

- has_add_permission()

- has_change_permission()

- has_delete_permission()

- has_module_permission()

The InlineModelAdmin class adds:

InlineModelAdmin.model

The model which the inline is using. This is required.

InlineModelAdmin.fk_name

The name of the foreign key on the model. In most cases this will be dealt with automatically, but fk_name must be specified explicitly if there are more than one foreign key to the same parent model.

InlineModelAdmin.formset

This defaults to BaseInlineFormSet. Using your own formset can give you many possibilities of customization. Inlines are built around model formsets.

InlineModelAdmin.form

The value for form defaults to ModelForm. This is what is passed through to inlineformset_factory() when creating the formset for this inline.

Warning

When writing custom validation for InlineModelAdmin forms, be cautious of writing validation that relies on features of the parent model. If the parent model fails to validate, it may be left in an inconsistent state as described in the warning in Validation on a ModelForm.

InlineModelAdmin.extra

This controls the number of extra forms the formset will display in addition to the initial forms. See the formsets documentation for more information.

For users with JavaScript-enabled browsers, an “Add another” link is provided to enable any number of additional inlines to be added in addition to those provided as a result of the extra argument.

The dynamic link will not appear if the number of currently displayed forms exceeds max_num, or if the user does not have JavaScript enabled.

InlineModelAdmin.get_extra() also allows you to customize the number of extra forms.

InlineModelAdmin.max_num

This controls the maximum number of forms to show in the inline. This doesn’t directly correlate to the number of objects, but can if the value is small enough. See Limiting the number of editable objects for more information.

InlineModelAdmin.get_max_num() also allows you to customize the maximum number of extra forms.

InlineModelAdmin.min_num

This controls the minimum number of forms to show in the inline. See modelformset_factory() for more information.

InlineModelAdmin.get_min_num() also allows you to customize the minimum number of displayed forms.

InlineModelAdmin.raw_id_fields

By default, Django’s admin uses a select-box interface (<select>) for fields that are ForeignKey. Sometimes you don’t want to incur the overhead of having to select all the related instances to display in the drop-down.

raw_id_fields is a list of fields you would like to change into an Input widget for either a ForeignKey or ManyToManyField:

class BookInline(admin.TabularInline):
model = Book
raw_id_fields = ("pages",)

InlineModelAdmin.template

The template used to render the inline on the page.

InlineModelAdmin.verbose_name

An override to the verbose_name found in the model’s inner Meta class.

InlineModelAdmin.verbose_name_plural

An override to the verbose_name_plural found in the model’s inner Meta class.

InlineModelAdmin.can_delete

Specifies whether or not inline objects can be deleted in the inline. Defaults to True.

InlineModelAdmin.show_change_link

New in Django 1.8.

Specifies whether or not inline objects that can be changed in the admin have a link to the change form. Defaults to False.

InlineModelAdmin.get_formset(request, obj=None, **kwargs)

Returns a BaseInlineFormSet class for use in admin add/change views. See the example for ModelAdmin.get_formsets_with_inlines.

InlineModelAdmin.get_extra(request, obj=None, **kwargs)

Returns the number of extra inline forms to use. By default, returns the InlineModelAdmin.extra attribute.

Override this method to programmatically determine the number of extra inline forms. For example, this may be based on the model instance (passed as the keyword argument obj):

class BinaryTreeAdmin(admin.TabularInline):
model = BinaryTree

def get_extra(self, request, obj=None, **kwargs):
extra = 2
if obj:
return extra - obj.binarytree_set.count()
return extra

InlineModelAdmin.get_max_num(request, obj=None, **kwargs)

Returns the maximum number of extra inline forms to use. By default, returns the InlineModelAdmin.max_num attribute.

Override this method to programmatically determine the maximum number of inline forms. For example, this may be based on the model instance (passed as the keyword argument obj):

class BinaryTreeAdmin(admin.TabularInline):
model = BinaryTree

def get_max_num(self, request, obj=None, **kwargs):
max_num = 10
if obj.parent:
return max_num - 5
return max_num

InlineModelAdmin.get_min_num(request, obj=None, **kwargs)

Returns the minimum number of inline forms to use. By default, returns the InlineModelAdmin.min_num attribute.

Override this method to programmatically determine the minimum number of inline forms. For example, this may be based on the model instance (passed as the keyword argument obj).

Working with a model with two or more foreign keys to the same parent model

It is sometimes possible to have more than one foreign key to the same model. Take this model for instance:

from django.db import models

class Friendship(models.Model):
to_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="friends")
from_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="from_friends")

If you wanted to display an inline on the Person admin add/change pages you need to explicitly define the foreign key since it is unable to do so automatically:

from django.contrib import admin
from myapp.models import Friendship

class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"

class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]

Working with many-to-many models

By default, admin widgets for many-to-many relations will be displayed on whichever model contains the actual reference to the ManyToManyField. Depending on your ModelAdmin definition, each many-to-many field in your model will be represented by a standard HTML <select multiple>, a horizontal or vertical filter, or a raw_id_admin widget. However, it is also possible to replace these widgets with inlines.

Suppose we have the following models:

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=128)

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, related_name='groups')

If you want to display many-to-many relations using an inline, you can do so by defining an InlineModelAdmin object for the relationship:

from django.contrib import admin

class MembershipInline(admin.TabularInline):
model = Group.members.through

class PersonAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]

class GroupAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
exclude = ('members',)

There are two features worth noting in this example.

Firstly - the MembershipInline class references Group.members.through. The through attribute is a reference to the model that manages the many-to-many relation. This model is automatically created by Django when you define a many-to-many field.

Secondly, the GroupAdmin must manually exclude the members field. Django displays an admin widget for a many-to-many field on the model that defines the relation (in this case, Group). If you want to use an inline model to represent the many-to-many relationship, you must tell Django’s admin to not display this widget - otherwise you will end up with two widgets on your admin page for managing the relation.

Note that when using this technique the m2m_changed signals aren’t triggered. This is because as far as the admin is concerned, through is just a model with two foreign key fields rather than a many-to-many relation.

In all other respects, the InlineModelAdmin is exactly the same as any other. You can customize the appearance using any of the normal ModelAdmin properties.

Working with many-to-many intermediary models

When you specify an intermediary model using the through argument to a ManyToManyField, the admin will not display a widget by default. This is because each instance of that intermediary model requires more information than could be displayed in a single widget, and the layout required for multiple widgets will vary depending on the intermediate model.

However, we still want to be able to edit that information inline. Fortunately, this is easy to do with inline admin models. Suppose we have the following models:

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=128)

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)

The first step in displaying this intermediate model in the admin is to define an inline class for the Membership model:

class MembershipInline(admin.TabularInline):
model = Membership
extra = 1

This simple example uses the default InlineModelAdmin values for the Membership model, and limits the extra add forms to one. This could be customized using any of the options available to InlineModelAdmin classes.

Now create admin views for the Person and Group models:

class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)

class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)

Finally, register your Person and Group models with the admin site:

admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)

Now your admin site is set up to edit Membership objects inline from either the Person or the Group detail pages.

Using generic relations as an inline

It is possible to use an inline with generically related objects. Let’s say you have the following models:

from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey

class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")

class Product(models.Model):
name = models.CharField(max_length=100)

If you want to allow editing and creating an Image instance on the Product, add/change views you can use GenericTabularInline or GenericStackedInline (both subclasses of GenericInlineModelAdmin) provided by admin. They implement tabular and stacked visual layouts for the forms representing the inline objects, respectively, just like their non-generic counterparts. They behave just like any other inline. In your admin.py for this example app:

from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline

from myproject.myapp.models import Image, Product

class ImageInline(GenericTabularInline):
model = Image

class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]

admin.site.register(Product, ProductAdmin)

See the contenttypes documentation for more specific information.

Overriding admin templates

It is relatively easy to override many of the templates which the admin module uses to generate the various pages of an admin site. You can even override a few of these templates for a specific app, or a specific model.

Set up your projects admin template directories

The admin template files are located in the contrib/admin/templates/admin directory.

In order to override one or more of them, first create an admin directory in your project’s templates directory. This can be any of the directories you specified in the DIRS option of the DjangoTemplates backend in the TEMPLATES setting. If you have customized the 'loaders' option, be sure 'django.template.loaders.filesystem.Loader' appears before 'django.template.loaders.app_directories.Loader' so that your custom templates will be found by the template loading system before those that are included with django.contrib.admin.

Within this admin directory, create sub-directories named after your app. Within these app subdirectories create sub-directories named after your models. Note, that the admin app will lowercase the model name when looking for the directory, so make sure you name the directory in all lowercase if you are going to run your app on a case-sensitive filesystem.

To override an admin template for a specific app, copy and edit the template from the django/contrib/admin/templates/admin directory, and save it to one of the directories you just created.

For example, if we wanted to add a tool to the change list view for all the models in an app named my_app, we would copy contrib/admin/templates/admin/change_list.html to the templates/admin/my_app/ directory of our project, and make any necessary changes.

If we wanted to add a tool to the change list view for only a specific model named ‘Page’, we would copy that same file to the templates/admin/my_app/page directory of our project.

Overriding vs. replacing an admin template

Because of the modular design of the admin templates, it is usually neither necessary nor advisable to replace an entire template. It is almost always better to override only the section of the template which you need to change.

To continue the example above, we want to add a new link next to the History tool for the Page model. After looking at change_form.html we determine that we only need to override the object-tools-items block. Therefore here is our new change_form.html :

{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
<li>
<a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% trans "History" %}</a>
</li>
<li>
<a href="mylink/" class="historylink">My Link</a>
</li>
{% if has_absolute_url %}
<li>
<a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% trans "View on site" %}</a>
</li>
{% endif %}
{% endblock %}

And that’s it! If we placed this file in the templates/admin/my_app directory, our link would appear on the change form for all models within my_app.

Templates which may be overridden per app or model

Not every template in contrib/admin/templates/admin may be overridden per app or per model. The following can:

- app_index.html

- change_form.html

- change_list.html

- delete_confirmation.html

- object_history.html

For those templates that cannot be overridden in this way, you may still override them for your entire project. Just place the new version in your templates/admin directory. This is particularly useful to create custom 404 and 500 pages.

Note

Some of the admin templates, such as change_list_results.html are used to render custom inclusion tags. These may be overridden, but in such cases you are probably better off creating your own version of the tag in question and giving it a different name. That way you can use it selectively.

Root and login templates

If you wish to change the index, login or logout templates, you are better off creating your own AdminSite instance (see below), and changing the AdminSite.index_template , AdminSite.login_template or AdminSite.logout_template properties.

AdminSite objects

class AdminSite(name='admin')[source]

A Django administrative site is represented by an instance of django.contrib.admin.sites.AdminSite; by default, an instance of this class is created as django.contrib.admin.site and you can register your models and ModelAdmin instances with it.

When constructing an instance of an AdminSite, you can provide a unique instance name using the name argument to the constructor. This instance name is used to identify the instance, especially when reversing admin URLs. If no instance name is provided, a default instance name of admin will be used. See Customizing the AdminSite class for an example of customizing the AdminSite class.

AdminSite attributes

Templates can override or extend base admin templates as described in Overriding admin templates.

AdminSite.site_header

The text to put at the top of each admin page, as an <h1> (a string). By default, this is “Django administration”.

AdminSite.site_title

The text to put at the end of each admin page’s <title> (a string). By default, this is “Django site admin”.

AdminSite.site_url

New in Django 1.8.

The URL for the “View site” link at the top of each admin page. By default, site_url is /. Set it to None to remove the link.

AdminSite.index_title

The text to put at the top of the admin index page (a string). By default, this is “Site administration”.

AdminSite.index_template

Path to a custom template that will be used by the admin site main index view.

AdminSite.app_index_template

Path to a custom template that will be used by the admin site app index view.

AdminSite.empty_value_display

New in Django 1.9.

The string to use for displaying empty values in the admin site’s change list. Defaults to a dash. The value can also be overridden on a per ModelAdmin basis and on a custom field within a ModelAdmin by setting an empty_value_display attribute on the field. See ModelAdmin.empty_value_display for examples.

AdminSite.login_template

Path to a custom template that will be used by the admin site login view.

AdminSite.login_form

Subclass of AuthenticationForm that will be used by the admin site login view.

AdminSite.logout_template

Path to a custom template that will be used by the admin site logout view.

AdminSite.password_change_template

Path to a custom template that will be used by the admin site password change view.

AdminSite.password_change_done_template

Path to a custom template that will be used by the admin site password change done view.

AdminSite methods

AdminSite.each_context(request)[source]

Returns a dictionary of variables to put in the template context for every page in the admin site.

Includes the following variables and values by default:

- site_header: AdminSite.site_header

- site_title: AdminSite.site_title

- site_url: AdminSite.site_url

- has_permission: AdminSite.has_permission()

- available_apps: a list of applications from the application registry available for the current user. Each entry in the list is a dict representing an application with the following keys:

- app_label: the application label

- app_url: the URL of the application index in the admin

- has_module_perms: a boolean indicating if displaying and accessing of the module’s index page is permitted for the current user

- models: a list of the models available in the application

Each model is a dict with the following keys:

- object_name: class name of the model

- name: plural name of the model

- perms: a dict tracking add, change, and delete permissions

- admin_url: admin changelist URL for the model

- add_url: admin URL to add a new model instance

Changed in Django 1.8:
The request argument and the has_permission variable were added.

Changed in Django 1.9:
The available_apps variable was added.

AdminSite.has_permission(request)[source]

Returns True if the user for the given HttpRequest has permission to view at least one page in the admin site. Defaults to requiring both User.is_active and User.is_staff to be True.

Hooking AdminSite instances into your URLconf

The last step in setting up the Django admin is to hook your AdminSite instance into your URLconf. Do this by pointing a given URL at the AdminSite.urls method. It is not necessary to use include().

In this example, we register the default AdminSite instance django.contrib.admin.site at the URL /admin/

# urls.py
from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
url(r'^admin/', admin.site.urls),
]

Changed in Django 1.9:
In previous versions, you would pass admin.site.urls to include().

Customizing the AdminSite class

If you’d like to set up your own admin site with custom behavior, you’re free to subclass AdminSite and override or add anything you like. Then, simply create an instance of your AdminSite subclass (the same way you’d instantiate any other Python class) and register your models and ModelAdmin subclasses with it instead of with the default site. Finally, update myproject/urls.py to reference your AdminSite subclass.

myapp/admin.py

from django.contrib.admin import AdminSite

from .models import MyModel

class MyAdminSite(AdminSite):
site_header = 'Monty Python administration'

admin_site = MyAdminSite(name='myadmin')
admin_site.register(MyModel)

myproject/urls.py

from django.conf.urls import url

from myapp.admin import admin_site

urlpatterns = [
url(r'^myadmin/', admin_site.urls),
]

Note that you may not want autodiscovery of admin modules when using your own AdminSite instance since you will likely be importing all the per-app admin modules in your myproject.admin module. This means you need to put 'django.contrib.admin.apps.SimpleAdminConfig' instead of 'django.contrib.admin' in your INSTALLED_APPS setting.

Multiple admin sites in the same URLconf

It’s easy to create multiple instances of the admin site on the same Django-powered website. Just create multiple instances of AdminSite and root each one at a different URL.

In this example, the URLs /basic-admin/ and /advanced-admin/ feature separate versions of the admin site – using the AdminSite instances myproject.admin.basic_site and myproject.admin.advanced_site, respectively:

# urls.py
from django.conf.urls import url
from myproject.admin import basic_site, advanced_site

urlpatterns = [
url(r'^basic-admin/', basic_site.urls),
url(r'^advanced-admin/', advanced_site.urls),
]

AdminSite instances take a single argument to their constructor, their name, which can be anything you like. This argument becomes the prefix to the URL names for the purposes of reversing them. This is only necessary if you are using more than one AdminSite.

Adding views to admin sites

Just like ModelAdmin, AdminSite provides a get_urls() method that can be overridden to define additional views for the site. To add a new view to your admin site, extend the base get_urls() method to include a pattern for your new view.

Note

Any view you render that uses the admin templates, or extends the base admin template, should set request.current_app before rendering the template. It should be set to either self.name if your view is on an AdminSite or self.admin_site.name if your view is on a ModelAdmin.

Changed in Django 1.8:
In previous versions of Django, you had to provide the current_app argument to RequestContext or Context when rendering the template.

Adding a password-reset feature

You can add a password-reset feature to the admin site by adding a few lines to your URLconf. Specifically, add these four patterns:

from django.contrib.auth import views as auth_views

url(r'^admin/password_reset/$', auth_views.password_reset, name='admin_password_reset'),
url(r'^admin/password_reset/done/$', auth_views.password_reset_done, name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$', auth_views.password_reset_confirm, name='password_reset_confirm'),
url(r'^reset/done/$', auth_views.password_reset_complete, name='password_reset_complete'),

(This assumes you’ve added the admin at admin/ and requires that you put the URLs starting with ^admin/ before the line that includes the admin app itself).

The presence of the admin_password_reset named URL will cause a “forgotten your password?” link to appear on the default admin log-in page under the password box.

LogEntry objects

class models.LogEntry

The LogEntry class tracks additions, changes, and deletions of objects done through the admin interface.

LogEntry attributes

LogEntry.action_time

The date and time of the action.

LogEntry.user

The user (an AUTH_USER_MODEL instance) who performed the action.

LogEntry.content_type

The ContentType of the modified object.

LogEntry.object_id

The textual representation of the modified object’s primary key.

LogEntry.object_repr

The object`s repr() after the modification.

LogEntry.action_flag

The type of action logged: ADDITION, CHANGE, DELETION.

For example, to get a list of all additions done through the admin:

from django.contrib.admin.models import LogEntry, ADDITION

LogEntry.objects.filter(action_flag=ADDITION)

LogEntry.change_message

The detailed description of the modification. In the case of an edit, for example, the message contains a list of the edited fields.

LogEntry methods

LogEntry.get_edited_object()

A shortcut that returns the referenced object.

Reversing admin URLs

When an AdminSite is deployed, the views provided by that site are accessible using Django’s URL reversing system.

The AdminSite provides the following named URL patterns:

Page

URL name

Parameters

Index

index

Logout

logout

Password change

password_change

Password change done

password_change_done

i18n JavaScript

jsi18n

Application index page

app_list

app_label

Redirect to object’s page

view_on_site

content_type_id, object_id

Each ModelAdmin instance provides an additional set of named URLs:

Page

URL name

Parameters

Changelist

{{ app_label }}_{{ model_name }}_changelist

Add

{{ app_label }}_{{ model_name }}_add

History

{{ app_label }}_{{ model_name }}_history

object_id

Delete

{{ app_label }}_{{ model_name }}_delete

object_id

Change

{{ app_label }}_{{ model_name }}_change

object_id

The UserAdmin provides a named URL:

Page

URL name

Parameters

Password change

auth_user_password_change

user_id

These named URLs are registered with the application namespace admin, and with an instance namespace corresponding to the name of the Site instance.

So - if you wanted to get a reference to the Change view for a particular Choice object (from the polls application) in the default admin, you would call:

>>> from django.core import urlresolvers
>>> c = Choice.objects.get(...)
>>> change_url = urlresolvers.reverse('admin:polls_choice_change', args=(c.id,))

This will find the first registered instance of the admin application (whatever the instance name), and resolve to the view for changing poll.Choice instances in that instance.

If you want to find a URL in a specific admin instance, provide the name of that instance as a current_app hint to the reverse call. For example, if you specifically wanted the admin view from the admin instance named custom, you would need to call:

>>> change_url = urlresolvers.reverse('admin:polls_choice_change',
...                                   args=(c.id,), current_app='custom')

For more details, see the documentation on reversing namespaced URLs.

To allow easier reversing of the admin urls in templates, Django provides an admin_urlname filter which takes an action as argument:

{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

The action in the examples above match the last part of the URL names for ModelAdmin instances described above. The opts variable can be any object which has an app_label and model_name attributes and is usually supplied by the admin views for the current model.

The staff_member_required decorator

staff_member_required(redirect_field_name='next', login_url='admin:login')[source]

This decorator is used on the admin views that require authorization. A view decorated with this function will having the following behavior:

- If the user is logged in, is a staff member (User.is_staff=True), and is active (User.is_active=True), execute the view normally.

- Otherwise, the request will be redirected to the URL specified by the login_url parameter, with the originally requested path in a query string variable specified by redirect_field_name. For example: /admin/login/?next=/admin/polls/question/3/.

Example usage:

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
def my_view(request):
...

Admin actions

The basic workflow of Django’s admin is, in a nutshell, “select an object, then change it.” This works well for a majority of use cases. However, if you need to make the same change to many objects at once, this workflow can be quite tedious.

In these cases, Django’s admin lets you write and register “actions” – simple functions that get called with a list of objects selected on the change list page.

If you look at any change list in the admin, you’ll see this feature in action; Django ships with a “delete selected objects” action available to all models. For example, here’s the user module from Django’s built-in django.contrib.auth app:

Warning

The “delete selected objects” action uses QuerySet.delete() for efficiency reasons, which has an important caveat: your model’s delete() method will not be called.

If you wish to override this behavior, simply write a custom action which accomplishes deletion in your preferred manner – for example, by calling Model.delete() for each of the selected items.

For more background on bulk deletion, see the documentation on object deletion.

Read on to find out how to add your own actions to this list.

Writing actions

The easiest way to explain actions is by example, so let’s dive in.

A common use case for admin actions is the bulk updating of a model. Imagine a simple news application with an Article model:

from django.db import models

STATUS_CHOICES = (
('d', 'Draft'),
('p', 'Published'),
('w', 'Withdrawn'),
)

class Article(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
status = models.CharField(max_length=1, choices=STATUS_CHOICES)

def __str__(self):              # __unicode__ on Python 2
return self.title

A common task we might perform with a model like this is to update an article’s status from “draft” to “published”. We could easily do this in the admin one article at a time, but if we wanted to bulk-publish a group of articles, it’d be tedious. So, let’s write an action that lets us change an article’s status to “published.”

Writing action functions

First, we’ll need to write a function that gets called when the action is triggered from the admin. Action functions are just regular functions that take three arguments:

- The current ModelAdmin

- An HttpRequest representing the current request,

- A QuerySet containing the set of objects selected by the user.

Our publish-these-articles function won’t need the ModelAdmin or the request object, but we will use the queryset:

def make_published(modeladmin, request, queryset):
queryset.update(status='p')

Note

For the best performance, we’re using the queryset’s update method. Other types of actions might need to deal with each object individually; in these cases we’d just iterate over the queryset:

for obj in queryset:
do_something_with(obj)

That’s actually all there is to writing an action! However, we’ll take one more optional-but-useful step and give the action a “nice” title in the admin. By default, this action would appear in the action list as “Make published” – the function name, with underscores replaced by spaces. That’s fine, but we can provide a better, more human-friendly name by giving the make_published function a short_description attribute:

def make_published(modeladmin, request, queryset):
queryset.update(status='p')
make_published.short_description = "Mark selected stories as published"

Note

This might look familiar; the admin’s list_display option uses the same technique to provide human-readable descriptions for callback functions registered there, too.

Adding actions to the ModelAdmin

Next, we’ll need to inform our ModelAdmin of the action. This works just like any other configuration option. So, the complete admin.py with the action and its registration would look like:

from django.contrib import admin
from myapp.models import Article

def make_published(modeladmin, request, queryset):
queryset.update(status='p')
make_published.short_description = "Mark selected stories as published"

class ArticleAdmin(admin.ModelAdmin):
list_display = ['title', 'status']
ordering = ['title']
actions = [make_published]

admin.site.register(Article, ArticleAdmin)

That code will give us an admin change list that looks something like this:

That’s really all there is to it! If you’re itching to write your own actions, you now know enough to get started. The rest of this document just covers more advanced techniques.

Handling errors in actions

If there are foreseeable error conditions that may occur while running your action, you should gracefully inform the user of the problem. This means handling exceptions and using django.contrib.admin.ModelAdmin.message_user() to display a user friendly description of the problem in the response.

Advanced action techniques

There’s a couple of extra options and possibilities you can exploit for more advanced options.

Actions as ModelAdmin methods

The example above shows the make_published action defined as a simple function. That’s perfectly fine, but it’s not perfect from a code design point of view: since the action is tightly coupled to the Article object, it makes sense to hook the action to the ArticleAdmin object itself.

That’s easy enough to do:

class ArticleAdmin(admin.ModelAdmin):
...

actions = ['make_published']

def make_published(self, request, queryset):
queryset.update(status='p')
make_published.short_description = "Mark selected stories as published"

Notice first that we’ve moved make_published into a method and renamed the modeladmin parameter to self, and second that we’ve now put the string 'make_published' in actions instead of a direct function reference. This tells the ModelAdmin to look up the action as a method.

Defining actions as methods gives the action more straightforward, idiomatic access to the ModelAdmin itself, allowing the action to call any of the methods provided by the admin.

For example, we can use self to flash a message to the user informing her that the action was successful:

class ArticleAdmin(admin.ModelAdmin):
...

def make_published(self, request, queryset):
rows_updated = queryset.update(status='p')
if rows_updated == 1:
message_bit = "1 story was"
else:
message_bit = "%s stories were" % rows_updated
self.message_user(request, "%s successfully marked as published." % message_bit)

This make the action match what the admin itself does after successfully performing an action:

Actions that provide intermediate pages

By default, after an action is performed the user is simply redirected back to the original change list page. However, some actions, especially more complex ones, will need to return intermediate pages. For example, the built-in delete action asks for confirmation before deleting the selected objects.

To provide an intermediary page, simply return an HttpResponse (or subclass) from your action. For example, you might write a simple export function that uses Django’s serialization functions to dump some selected objects as JSON:

from django.http import HttpResponse
from django.core import serializers

def export_as_json(modeladmin, request, queryset):
response = HttpResponse(content_type="application/json")
serializers.serialize("json", queryset, stream=response)
return response

Generally, something like the above isn’t considered a great idea. Most of the time, the best practice will be to return an HttpResponseRedirect and redirect the user to a view you’ve written, passing the list of selected objects in the GET query string. This allows you to provide complex interaction logic on the intermediary pages. For example, if you wanted to provide a more complete export function, you’d want to let the user choose a format, and possibly a list of fields to include in the export. The best thing to do would be to write a small action that simply redirects to your custom export view:

from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponseRedirect

def export_selected_objects(modeladmin, request, queryset):
selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
ct = ContentType.objects.get_for_model(queryset.model)
return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected)))

As you can see, the action is the simple part; all the complex logic would belong in your export view. This would need to deal with objects of any type, hence the business with the ContentType.

Writing this view is left as an exercise to the reader.

Making actions available site-wide

AdminSite.add_action(action, name=None)[source]

Some actions are best if they’re made available to any object in the admin site – the export action defined above would be a good candidate. You can make an action globally available using AdminSite.add_action(). For example:

from django.contrib import admin

admin.site.add_action(export_selected_objects)

This makes the export_selected_objects action globally available as an action named “export_selected_objects”. You can explicitly give the action a name – good if you later want to programmatically remove the action – by passing a second argument to AdminSite.add_action():

admin.site.add_action(export_selected_objects, 'export_selected')

Disabling actions

Sometimes you need to disable certain actions – especially those registered site-wide – for particular objects. There’s a few ways you can disable actions:

Disabling a site-wide action

AdminSite.disable_action(name)[source]

If you need to disable a site-wide action you can call AdminSite.disable_action().

For example, you can use this method to remove the built-in “delete selected objects” action:

admin.site.disable_action('delete_selected')

Once you’ve done the above, that action will no longer be available site-wide.

If, however, you need to re-enable a globally-disabled action for one particular model, simply list it explicitly in your ModelAdmin.actions list:

# Globally disable delete selected
admin.site.disable_action('delete_selected')

# This ModelAdmin will not have delete_selected available
class SomeModelAdmin(admin.ModelAdmin):
actions = ['some_other_action']
...

# This one will
class AnotherModelAdmin(admin.ModelAdmin):
actions = ['delete_selected', 'a_third_action']
...

Disabling all actions for a particular ModelAdmin

If you want no bulk actions available for a given ModelAdmin, simply set ModelAdmin.actions to None:

class MyModelAdmin(admin.ModelAdmin):
actions = None

This tells the ModelAdmin to not display or allow any actions, including any site-wide actions.

Conditionally enabling or disabling actions

ModelAdmin.get_actions(request)[source]

Finally, you can conditionally enable or disable actions on a per-request (and hence per-user basis) by overriding ModelAdmin.get_actions().

This returns a dictionary of actions allowed. The keys are action names, and the values are (function, name, short_description) tuples.

Most of the time you’ll use this method to conditionally remove actions from the list gathered by the superclass. For example, if I only wanted users whose names begin with ‘J’ to be able to delete objects in bulk, I could do the following:

class MyModelAdmin(admin.ModelAdmin):
...

def get_actions(self, request):
actions = super(MyModelAdmin, self).get_actions(request)
if request.user.username[0].upper() != 'J':
if 'delete_selected' in actions:
del actions['delete_selected']
return actions

The Django admin documentation generator

Django’s admindocs app pulls documentation from the docstrings of models, views, template tags, and template filters for any app in INSTALLED_APPS and makes that documentation available from the Django admin.

Overview

To activate the admindocs, you will need to do the following:

- Add django.contrib.admindocs to your INSTALLED_APPS.

- Add url(r'^admin/doc/', include('django.contrib.admindocs.urls')) to your urlpatterns. Make sure it’s included before the r'^admin/' entry, so that requests to /admin/doc/ don’t get handled by the latter entry.

- Install the docutils Python module (http://docutils.sf.net/).

- Optional: Using the admindocs bookmarklets requires django.contrib.admindocs.middleware.XViewMiddleware to be installed.

Once those steps are complete, you can start browsing the documentation by going to your admin interface and clicking the “Documentation” link in the upper right of the page.

Documentation helpers

The following special markup can be used in your docstrings to easily create hyperlinks to other components:

Django Component

reStructuredText roles

Models

:model:`app_label.ModelName`

Views

:view:`app_label.view_name`

Template tags

:tag:`tagname`

Template filters

:filter:`filtername`

Templates

:template:`path/to/template.html`

Model reference

The models section of the admindocs page describes each model in the system along with all the fields and methods available on it. Relationships to other models appear as hyperlinks. Descriptions are pulled from help_text attributes on fields or from docstrings on model methods.

Changed in Django 1.9:
The models section of the admindocs now describes methods that take arguments as well. In previous versions it was restricted to methods without arguments.

A model with useful documentation might look like this:

class BlogEntry(models.Model):
"""
Stores a single blog entry, related to :model:`blog.Blog` and
:model:`auth.User`.
"""
slug = models.SlugField(help_text="A short label, generally used in URLs.")
author = models.ForeignKey(
User,
models.SET_NULL,
blank=True, null=True,
)
blog = models.ForeignKey(Blog, models.CASCADE)
...

def publish(self):
"""Makes the blog entry live on the site."""
...

View reference

Each URL in your site has a separate entry in the admindocs page, and clicking on a given URL will show you the corresponding view. Helpful things you can document in your view function docstrings include:

- A short description of what the view does.

- The context, or a list of variables available in the view’s template.

- The name of the template or templates that are used for that view.

For example:

from django.shortcuts import render

from myapp.models import MyModel

def my_view(request, slug):
"""
Display an individual :model:`myapp.MyModel`.

**Context**

``mymodel``
An instance of :model:`myapp.MyModel`.

**Template:**

:template:`myapp/my_template.html`
"""
context = {'mymodel': MyModel.objects.get(slug=slug)}
return render(request, 'myapp/my_template.html', context)

Template tags and filters reference

The tags and filters admindocs sections describe all the tags and filters that come with Django (in fact, the built-in tag reference and built-in filter reference documentation come directly from those pages). Any tags or filters that you create or are added by a third-party app will show up in these sections as well.

Template reference

While admindocs does not include a place to document templates by themselves, if you use the :template:`path/to/template.html` syntax in a docstring the resulting page will verify the path of that template with Django’s template loaders. This can be a handy way to check if the specified template exists and to show where on the filesystem that template is stored.

Included Bookmarklets

One bookmarklet is available from the admindocs page:

Documentation for this page

Jumps you from any page to the documentation for the view that generates that page.

Using this bookmarklet requires that XViewMiddleware is installed and that you are logged into the Django admin as a User with is_staff set to True.

JavaScript customizations in the admin

Inline form events

New in Django 1.9.

You may want to execute some JavaScript when an inline form is added or removed in the admin change form. The formset:added and formset:removed jQuery events allow this. The event handler is passed three arguments:

- event is the jQuery event.

- $row is the newly added (or removed) row.

- formsetName is the formset the row belongs to.

The event is fired using the django.jQuery namespace.

In your custom change_form.html template, extend the admin_change_form_document_ready block and add the event listener code:

{% extends 'admin/change_form.html' %}

{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript">
(function($) {
$(document).on('formset:added', function(event, $row, formsetName) {
if (formsetName == 'author_set') {
// Do something
}
});

$(document).on('formset:removed', function(event, $row, formsetName) {
// Row removed
});
})(django.jQuery);
</script>
{% endblock %}

Two points to keep in mind:

- The JavaScript code must go in a template block if you are inheriting admin/change_form.html or it won’t be rendered in the final HTML.

- {{ block.super }} is added because Django’s admin_change_form_document_ready block contains JavaScript code to handle various operations in the change form and we need that to be rendered too.

Sometimes you’ll need to work with jQuery plugins that are not registered in the django.jQuery namespace. To do that, simply change how the code listens for events. Instead of wrapping the listener in the django.jQuery namespace, just listen to the event triggered from there. For example:

{% extends 'admin/change_form.html' %}

{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript">
django.jQuery(document).on('formset:added', function(event, $row, formsetName) {
// Row added
});

django.jQuery(document).on('formset:removed', function(event, $row, formsetName) {
// Row removed
});
</script>
{% endblock %}

django.contrib.auth

This document provides API reference material for the components of Django’s authentication system. For more details on the usage of these components or how to customize authentication and authorization see the authentication topic guide.

User model

Fields

class models.User

User objects have the following fields:

username

Required. 30 characters or fewer. Usernames may contain alphanumeric, _, @, +, . and - characters.

first_name

Optional. 30 characters or fewer.

last_name

Optional. 30 characters or fewer.

email

Optional. Email address.

password

Required. A hash of, and metadata about, the password. (Django doesn’t store the raw password.) Raw passwords can be arbitrarily long and can contain any character. See the password documentation.

groups

Many-to-many relationship to Group

user_permissions

Many-to-many relationship to Permission

is_staff

Boolean. Designates whether this user can access the admin site.

is_active

Boolean. Designates whether this user account should be considered active. We recommend that you set this flag to False instead of deleting accounts; that way, if your applications have any foreign keys to users, the foreign keys won’t break.

This doesn’t necessarily control whether or not the user can log in. Authentication backends aren’t required to check for the is_active flag, and the default backends do not. If you want to reject a login based on is_active being False, it’s up to you to check that in your own login view or a custom authentication backend. However, the AuthenticationForm used by the login() view (which is the default) does perform this check, as do the permission-checking methods such as has_perm() and the authentication in the Django admin. All of those functions/methods will return False for inactive users.

is_superuser

Boolean. Designates that this user has all permissions without explicitly assigning them.

last_login

A datetime of the user’s last login.

Changed in Django 1.8:
This field will be null if the user has never logged in. Previously it was set to the current date/time by default.

date_joined

A datetime designating when the account was created. Is set to the current date/time by default when the account is created.

Methods

class models.User

get_username()

Returns the username for the user. Since the User model can be swapped out, you should use this method instead of referencing the username attribute directly.

is_anonymous()

Always returns False. This is a way of differentiating User and AnonymousUser objects. Generally, you should prefer using is_authenticated() to this method.

is_authenticated()

Always returns True (as opposed to AnonymousUser.is_authenticated() which always returns False). This is a way to tell if the user has been authenticated. This does not imply any permissions, and doesn’t check if the user is active or has a valid session. Even though normally you will call this method on request.user to find out whether it has been populated by the AuthenticationMiddleware (representing the currently logged-in user), you should know this method returns True for any User instance.

get_full_name()

Returns the first_name plus the last_name, with a space in between.

get_short_name()

Returns the first_name.

set_password(raw_password)

Sets the user’s password to the given raw string, taking care of the password hashing. Doesn’t save the User object.

When the raw_password is None, the password will be set to an unusable password, as if set_unusable_password() were used.

check_password(raw_password)

Returns True if the given raw string is the correct password for the user. (This takes care of the password hashing in making the comparison.)

set_unusable_password()

Marks the user as having no password set. This isn’t the same as having a blank string for a password. check_password() for this user will never return True. Doesn’t save the User object.

You may need this if authentication for your application takes place against an existing external source such as an LDAP directory.

has_usable_password()

Returns False if set_unusable_password() has been called for this user.

get_group_permissions(obj=None)

Returns a set of permission strings that the user has, through their groups.

If obj is passed in, only returns the group permissions for this specific object.

get_all_permissions(obj=None)

Returns a set of permission strings that the user has, both through group and user permissions.

If obj is passed in, only returns the permissions for this specific object.

has_perm(perm, obj=None)

Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>". (see documentation on permissions). If the user is inactive, this method will always return False.

If obj is passed in, this method won’t check for a permission for the model, but for this specific object.

has_perms(perm_list, obj=None)

Returns True if the user has each of the specified permissions, where each perm is in the format "<app label>.<permission codename>". If the user is inactive, this method will always return False.

If obj is passed in, this method won’t check for permissions for the model, but for the specific object.

has_module_perms(package_name)

Returns True if the user has any permissions in the given package (the Django app label). If the user is inactive, this method will always return False.

email_user(subject, message, from_email=None, **kwargs)

Sends an email to the user. If from_email is None, Django uses the DEFAULT_FROM_EMAIL. Any **kwargs are passed to the underlying send_mail() call.

Manager methods

class models.UserManager

The User model has a custom manager that has the following helper methods (in addition to the methods provided by BaseUserManager):

create_user(username, email=None, password=None, **extra_fields)

Creates, saves and returns a User.

The username and password are set as given. The domain portion of email is automatically converted to lowercase, and the returned User object will have is_active set to True.

If no password is provided, set_unusable_password() will be called.

The extra_fields keyword arguments are passed through to the User’s __init__ method to allow setting arbitrary fields on a custom User model.

See Creating users for example usage.

create_superuser(username, email, password, **extra_fields)

Same as create_user(), but sets is_staff and is_superuser to True.

AnonymousUser object

class models.AnonymousUser

django.contrib.auth.models.AnonymousUser is a class that implements the django.contrib.auth.models.User interface, with these differences:

- id is always None.

- username is always the empty string.

- get_username() always returns the empty string.

- is_staff and is_superuser are always False.

- is_active is always False.

- groups and user_permissions are always empty.

- is_anonymous() returns True instead of False.

- is_authenticated() returns False instead of True.

- set_password(), check_password(), save() and delete() raise NotImplementedError.

New in Django 1.8:
AnonymousUser.get_username() has been added to better mirror django.contrib.auth.models.User.

In practice, you probably won’t need to use AnonymousUser objects on your own, but they’re used by Web requests, as explained in the next section.

Permission model

class models.Permission

Fields

Permission objects have the following fields:

class models.Permission

name

Required. 255 characters or fewer. Example: 'Can vote'.

Changed in Django 1.8:
The max_length increased from 50 to 255 characters.

content_type

Required. A reference to the django_content_type database table, which contains a record for each installed model.

codename

Required. 100 characters or fewer. Example: 'can_vote'.

Methods

Permission objects have the standard data-access methods like any other Django model.

Group model

class models.Group

Fields

Group objects have the following fields:

class models.Group

name

Required. 80 characters or fewer. Any characters are permitted. Example: 'Awesome Users'.

permissions

Many-to-many field to Permission:

group.permissions = [permission_list]
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()

Login and logout signals

The auth framework uses the following signals that can be used for notification when a user logs in or out.

user_logged_in()

Sent when a user logs in successfully.

Arguments sent with this signal:

sender

The class of the user that just logged in.

request

The current HttpRequest instance.

user

The user instance that just logged in.

user_logged_out()

Sent when the logout method is called.

sender

As above: the class of the user that just logged out or None if the user was not authenticated.

request

The current HttpRequest instance.

user

The user instance that just logged out or None if the user was not authenticated.

user_login_failed()

Sent when the user failed to login successfully

sender

The name of the module used for authentication.

credentials

A dictionary of keyword arguments containing the user credentials that were passed to authenticate() or your own custom authentication backend. Credentials matching a set of ‘sensitive’ patterns, (including password) will not be sent in the clear as part of the signal.

Authentication backends

This section details the authentication backends that come with Django. For information on how to use them and how to write your own authentication backends, see the Other authentication sources section of the User authentication guide.

Available authentication backends

The following backends are available in django.contrib.auth.backends:

class ModelBackend

This is the default authentication backend used by Django. It authenticates using credentials consisting of a user identifier and password. For Django’s default user model, the user identifier is the username, for custom user models it is the field specified by USERNAME_FIELD (see Customizing Users and authentication).

It also handles the default permissions model as defined for User and PermissionsMixin.

has_perm(), get_all_permissions(), get_user_permissions(), and get_group_permissions() allow an object to be passed as a parameter for object-specific permissions, but this backend does not implement them other than returning an empty set of permissions if obj is not None.

authenticate(username=None, password=None, **kwargs)

Tries to authenticate username with password by calling User.check_password. If no username is provided, it tries to fetch a username from kwargs using the key CustomUser.USERNAME_FIELD. Returns an authenticated user or None.

get_user_permissions(user_obj, obj=None)

New in Django 1.8.

Returns the set of permission strings the user_obj has from their own user permissions. Returns an empty set if is_anonymous() or is_active is False.

get_group_permissions(user_obj, obj=None)

Returns the set of permission strings the user_obj has from the permissions of the groups they belong. Returns an empty set if is_anonymous() or is_active is False.

get_all_permissions(user_obj, obj=None)

Returns the set of permission strings the user_obj has, including both user permissions and group permissions. Returns an empty set if is_anonymous() or is_active is False.

has_perm(user_obj, perm, obj=None)

Uses get_all_permissions() to check if user_obj has the permission string perm. Returns False if the user is not is_active.

has_module_perms(self, user_obj, app_label)

Returns whether the user_obj has any permissions on the app app_label.

class RemoteUserBackend

Use this backend to take advantage of external-to-Django-handled authentication. It authenticates using usernames passed in request.META['REMOTE_USER']. See the Authenticating against REMOTE_USER documentation.

If you need more control, you can create your own authentication backend that inherits from this class and override these attributes or methods:

RemoteUserBackend.create_unknown_user

True or False. Determines whether or not a User object is created if not already in the database. Defaults to True.

RemoteUserBackend.authenticate(remote_user)

The username passed as remote_user is considered trusted. This method simply returns the User object with the given username, creating a new User object if create_unknown_user is True.

Returns None if create_unknown_user is False and a User object with the given username is not found in the database.

RemoteUserBackend.clean_username(username)

Performs any cleaning on the username (e.g. stripping LDAP DN information) prior to using it to get or create a User object. Returns the cleaned username.

RemoteUserBackend.configure_user(user)

Configures a newly created user. This method is called immediately after a new user is created, and can be used to perform custom setup actions, such as setting the user’s groups based on attributes in an LDAP directory. Returns the user object.

The contenttypes framework

Django includes a contenttypes application that can track all of the models installed in your Django-powered project, providing a high-level, generic interface for working with your models.

Overview

At the heart of the contenttypes application is the ContentType model, which lives at django.contrib.contenttypes.models.ContentType. Instances of ContentType represent and store information about the models installed in your project, and new instances of ContentType are automatically created whenever new models are installed.

Instances of ContentType have methods for returning the model classes they represent and for querying objects from those models. ContentType also has a custom manager that adds methods for working with ContentType and for obtaining instances of ContentType for a particular model.

Relations between your models and ContentType can also be used to enable “generic” relationships between an instance of one of your models and instances of any model you have installed.

Installing the contenttypes framework

The contenttypes framework is included in the default INSTALLED_APPS list created by django-admin startproject, but if you’ve removed it or if you manually set up your INSTALLED_APPS list, you can enable it by adding 'django.contrib.contenttypes' to your INSTALLED_APPS setting.

It’s generally a good idea to have the contenttypes framework installed; several of Django’s other bundled applications require it:

- The admin application uses it to log the history of each object added or changed through the admin interface.

- Django’s authentication framework uses it to tie user permissions to specific models.

The ContentType model

class ContentType

Each instance of ContentType has two fields which, taken together, uniquely describe an installed model:

app_label

The name of the application the model is part of. This is taken from the app_label attribute of the model, and includes only the last part of the application’s Python import path; “django.contrib.contenttypes”, for example, becomes an app_label of “contenttypes”.

model

The name of the model class.

Additionally, the following property is available:

name

The human-readable name of the content type. This is taken from the verbose_name attribute of the model.

Changed in Django 1.8:
Before Django 1.8, the name property was a real field on the ContentType model.

Let’s look at an example to see how this works. If you already have the contenttypes application installed, and then add the sites application to your INSTALLED_APPS setting and run manage.py migrate to install it, the model django.contrib.sites.models.Site will be installed into your database. Along with it a new instance of ContentType will be created with the following values:

- app_label will be set to 'sites' (the last part of the Python path “django.contrib.sites”).

- model will be set to 'site'.

Methods on ContentType instances

Each ContentType instance has methods that allow you to get from a ContentType instance to the model it represents, or to retrieve objects from that model:

ContentType.get_object_for_this_type(**kwargs)

Takes a set of valid lookup arguments for the model the ContentType represents, and does a get() lookup on that model, returning the corresponding object.

ContentType.model_class()

Returns the model class represented by this ContentType instance.

For example, we could look up the ContentType for the User model:

>>> from django.contrib.contenttypes.models import ContentType
>>> ContentType.objects.get(app_label="auth", model="user")
<ContentType: user>

And then use it to query for a particular User, or to get access to the User model class:

>>> user_type.model_class()
<class 'django.contrib.auth.models.User'>
>>> user_type.get_object_for_this_type(username='Guido')
<User: Guido>

Together, get_object_for_this_type() and model_class() enable two extremely important use cases:

1. Using these methods, you can write high-level generic code that performs queries on any installed model – instead of importing and using a single specific model class, you can pass an app_label and model into a ContentType lookup at runtime, and then work with the model class or retrieve objects from it.

2. You can relate another model to ContentType as a way of tying instances of it to particular model classes, and use these methods to get access to those model classes.

Several of Django’s bundled applications make use of the latter technique. For example, the permissions system in Django’s authentication framework uses a Permission model with a foreign key to ContentType; this lets Permission represent concepts like “can add blog entry” or “can delete news story”.

The ContentTypeManager

class ContentTypeManager

ContentType also has a custom manager, ContentTypeManager, which adds the following methods:

clear_cache()

Clears an internal cache used by ContentType to keep track of models for which it has created ContentType instances. You probably won’t ever need to call this method yourself; Django will call it automatically when it’s needed.

get_for_id(id)

Lookup a ContentType by ID. Since this method uses the same shared cache as get_for_model(), it’s preferred to use this method over the usual ContentType.objects.get(pk=id)

get_for_model(model, for_concrete_model=True)

Takes either a model class or an instance of a model, and returns the ContentType instance representing that model. for_concrete_model=False allows fetching the ContentType of a proxy model.

get_for_models(*models, for_concrete_models=True)

Takes a variadic number of model classes, and returns a dictionary mapping the model classes to the ContentType instances representing them. for_concrete_models=False allows fetching the ContentType of proxy models.

get_by_natural_key(app_label, model)

Returns the ContentType instance uniquely identified by the given application label and model name. The primary purpose of this method is to allow ContentType objects to be referenced via a natural key during deserialization.

The get_for_model() method is especially useful when you know you need to work with a ContentType but don’t want to go to the trouble of obtaining the model’s metadata to perform a manual lookup:

>>> from django.contrib.auth.models import User
>>> ContentType.objects.get_for_model(User)
<ContentType: user>

Generic relations

Adding a foreign key from one of your own models to ContentType allows your model to effectively tie itself to another model class, as in the example of the Permission model above. But it’s possible to go one step further and use ContentType to enable truly generic (sometimes called “polymorphic”) relationships between models.

A simple example is a tagging system, which might look like this:

from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')

def __str__(self):              # __unicode__ on Python 2
return self.tag

A normal ForeignKey can only “point to” one other model, which means that if the TaggedItem model used a ForeignKey it would have to choose one and only one model to store tags for. The contenttypes application provides a special field type (GenericForeignKey) which works around this and allows the relationship to be with any model:

class GenericForeignKey

There are three parts to setting up a GenericForeignKey:

1. Give your model a ForeignKey to ContentType. The usual name for this field is “content_type”.

2. Give your model a field that can store primary key values from the models you’ll be relating to. For most models, this means a PositiveIntegerField. The usual name for this field is “object_id”.

3. Give your model a GenericForeignKey, and pass it the names of the two fields described above. If these fields are named “content_type” and “object_id”, you can omit this – those are the default field names GenericForeignKey will look for.

for_concrete_model

If False, the field will be able to reference proxy models. Default is True. This mirrors the for_concrete_model argument to get_for_model().

Primary key type compatibility

The “object_id” field doesn’t have to be the same type as the primary key fields on the related models, but their primary key values must be coercible to the same type as the “object_id” field by its get_db_prep_value() method.

For example, if you want to allow generic relations to models with either IntegerField or CharField primary key fields, you can use CharField for the “object_id” field on your model since integers can be coerced to strings by get_db_prep_value().

For maximum flexibility you can use a TextField which doesn’t have a maximum length defined, however this may incur significant performance penalties depending on your database backend.

There is no one-size-fits-all solution for which field type is best. You should evaluate the models you expect to be pointing to and determine which solution will be most effective for your use case.

Serializing references to ContentType objects

If you’re serializing data (for example, when generating fixtures) from a model that implements generic relations, you should probably be using a natural key to uniquely identify related ContentType objects. See natural keys and dumpdata --natural-foreign for more information.

This will enable an API similar to the one used for a normal ForeignKey; each TaggedItem will have a content_object field that returns the object it’s related to, and you can also assign to that field or use it when creating a TaggedItem:

>>> from django.contrib.auth.models import User
>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> t.save()
>>> t.content_object
<User: Guido>

Due to the way GenericForeignKey is implemented, you cannot use such fields directly with filters (filter() and exclude(), for example) via the database API. Because a GenericForeignKey isn’t a normal field object, these examples will not work:

# This will fail
>>> TaggedItem.objects.filter(content_object=guido)
# This will also fail
>>> TaggedItem.objects.get(content_object=guido)

Likewise, GenericForeignKeys does not appear in ModelForms.

Reverse generic relations

class GenericRelation

related_query_name

The relation on the related object back to this object doesn’t exist by default. Setting related_query_name creates a relation from the related object back to this one. This allows querying and filtering from the related object.

If you know which models you’ll be using most often, you can also add a “reverse” generic relationship to enable an additional API. For example:

from django.db import models
from django.contrib.contenttypes.fields import GenericRelation

class Bookmark(models.Model):
url = models.URLField()
tags = GenericRelation(TaggedItem)

Bookmark instances will each have a tags attribute, which can be used to retrieve their associated TaggedItems:

>>> b = Bookmark(url='https://www.djangoproject.com/')
>>> b.save()
>>> t1 = TaggedItem(content_object=b, tag='django')
>>> t1.save()
>>> t2 = TaggedItem(content_object=b, tag='python')
>>> t2.save()
>>> b.tags.all()
[<TaggedItem: django>, <TaggedItem: python>]

Defining GenericRelation with related_query_name set allows querying from the related object:

tags = GenericRelation(TaggedItem, related_query_name='bookmarks')

This enables filtering, ordering, and other query operations on Bookmark from TaggedItem:

>>> # Get all tags belonging to bookmarks containing `django` in the url
>>> TaggedItem.objects.filter(bookmarks__url__contains='django')
[<TaggedItem: django>, <TaggedItem: python>]

Of course, if you don’t add the reverse relationship, you can do the same types of lookups manually:

>>> b = Bookmark.objects.get(url='https://www.djangoproject.com/')
>>> bookmark_type = ContentType.objects.get_for_model(b)
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, object_id=b.id)
[<TaggedItem: django>, <TaggedItem: python>]

Just as GenericForeignKey accepts the names of the content-type and object-ID fields as arguments, so too does GenericRelation; if the model which has the generic foreign key is using non-default names for those fields, you must pass the names of the fields when setting up a GenericRelation to it. For example, if the TaggedItem model referred to above used fields named content_type_fk and object_primary_key to create its generic foreign key, then a GenericRelation back to it would need to be defined like so:

tags = GenericRelation(
TaggedItem,
content_type_field='content_type_fk',
object_id_field='object_primary_key',
)

Note also, that if you delete an object that has a GenericRelation, any objects which have a GenericForeignKey pointing at it will be deleted as well. In the example above, this means that if a Bookmark object were deleted, any TaggedItem objects pointing at it would be deleted at the same time.

Unlike ForeignKey, GenericForeignKey does not accept an on_delete argument to customize this behavior; if desired, you can avoid the cascade-deletion simply by not using GenericRelation, and alternate behavior can be provided via the pre_delete signal.

Generic relations and aggregation

Django’s database aggregation API works with a GenericRelation. For example, you can find out how many tags all the bookmarks have:

>>> Bookmark.objects.aggregate(Count('tags'))
{'tags__count': 3}

Generic relation in forms

The django.contrib.contenttypes.forms module provides:

- BaseGenericInlineFormSet

- A formset factory, generic_inlineformset_factory(), for use with GenericForeignKey.

class BaseGenericInlineFormSet

generic_inlineformset_factory(model, form=ModelForm, formset=BaseGenericInlineFormSet, ct_field="content_type", fk_field="object_id", fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, validate_max=False, for_concrete_model=True, min_num=None, validate_min=False)

Returns a GenericInlineFormSet using modelformset_factory().

You must provide ct_field and fk_field if they are different from the defaults, content_type and object_id respectively. Other parameters are similar to those documented in modelformset_factory() and inlineformset_factory().

The for_concrete_model argument corresponds to the for_concrete_model argument on GenericForeignKey.

Generic relations in admin

The django.contrib.contenttypes.admin module provides GenericTabularInline and GenericStackedInline (subclasses of GenericInlineModelAdmin)

These classes and functions enable the use of generic relations in forms and the admin. See the model formset and admin documentation for more information.

class GenericInlineModelAdmin

The GenericInlineModelAdmin class inherits all properties from an InlineModelAdmin class. However, it adds a couple of its own for working with the generic relation:

ct_field

The name of the ContentType foreign key field on the model. Defaults to content_type.

ct_fk_field

The name of the integer field that represents the ID of the related object. Defaults to object_id.

class GenericTabularInline

class GenericStackedInline

Subclasses of GenericInlineModelAdmin with stacked and tabular layouts, respectively.

The flatpages app

Django comes with an optional “flatpages” application. It lets you store simple “flat” HTML content in a database and handles the management for you via Django’s admin interface and a Python API.

A flatpage is a simple object with a URL, title and content. Use it for one-off, special-case pages, such as “About” or “Privacy Policy” pages, that you want to store in a database but for which you don’t want to develop a custom Django application.

A flatpage can use a custom template or a default, systemwide flatpage template. It can be associated with one, or multiple, sites.

The content field may optionally be left blank if you prefer to put your content in a custom template.

Here are some examples of flatpages on Django-powered sites:

- http://www.lawrence.com/about/contact/

- http://www2.ljworld.com/site/rules/

Installation

To install the flatpages app, follow these steps:

1. Install the sites framework by adding 'django.contrib.sites' to your INSTALLED_APPS setting, if it’s not already in there.

Also make sure you’ve correctly set SITE_ID to the ID of the site the settings file represents. This will usually be 1 (i.e. SITE_ID = 1, but if you’re using the sites framework to manage multiple sites, it could be the ID of a different site.

2. Add 'django.contrib.flatpages' to your INSTALLED_APPS setting.

Then either:

3. Add an entry in your URLconf. For example:

urlpatterns = [
url(r'^pages/', include('django.contrib.flatpages.urls')),
]

or:

3. Add 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' to your MIDDLEWARE_CLASSES setting.

4. Run the command manage.py migrate.

How it works

manage.py migrate creates two tables in your database: django_flatpage and django_flatpage_sites. django_flatpage is a simple lookup table that simply maps a URL to a title and bunch of text content. django_flatpage_sites associates a flatpage with a site.

Using the URLconf

There are several ways to include the flat pages in your URLconf. You can dedicate a particular path to flat pages:

urlpatterns = [
url(r'^pages/', include('django.contrib.flatpages.urls')),
]

You can also set it up as a “catchall” pattern. In this case, it is important to place the pattern at the end of the other urlpatterns:

from django.contrib.flatpages import views

# Your other patterns here
urlpatterns += [
url(r'^(?P<url>.*/)$', views.flatpage),
]

Warning

If you set APPEND_SLASH to False, you must remove the slash in the catchall pattern or flatpages without a trailing slash will not be matched.

Another common setup is to use flat pages for a limited set of known pages and to hard code the urls, so you can reference them with the url template tag:

from django.contrib.flatpages import views

urlpatterns += [
url(r'^about-us/$', views.flatpage, {'url': '/about-us/'}, name='about'),
url(r'^license/$', views.flatpage, {'url': '/license/'}, name='license'),
]

Using the middleware

The FlatpageFallbackMiddleware can do all of the work.

class FlatpageFallbackMiddleware

Each time any Django application raises a 404 error, this middleware checks the flatpages database for the requested URL as a last resort. Specifically, it checks for a flatpage with the given URL with a site ID that corresponds to the SITE_ID setting.

If it finds a match, it follows this algorithm:

- If the flatpage has a custom template, it loads that template. Otherwise, it loads the template flatpages/default.html.

- It passes that template a single context variable, flatpage, which is the flatpage object. It uses RequestContext in rendering the template.

The middleware will only add a trailing slash and redirect (by looking at the APPEND_SLASH setting) if the resulting URL refers to a valid flatpage. Redirects are permanent (301 status code).

If it doesn’t find a match, the request continues to be processed as usual.

The middleware only gets activated for 404s – not for 500s or responses of any other status code.

Flatpages will not apply view middleware

Because the FlatpageFallbackMiddleware is applied only after URL resolution has failed and produced a 404, the response it returns will not apply any view middleware methods. Only requests which are successfully routed to a view via normal URL resolution apply view middleware.

Note that the order of MIDDLEWARE_CLASSES matters. Generally, you can put FlatpageFallbackMiddleware at the end of the list. This means it will run first when processing the response, and ensures that any other response-processing middlewares see the real flatpage response rather than the 404.

For more on middleware, read the middleware docs.

Ensure that your 404 template works

Note that the FlatpageFallbackMiddleware only steps in once another view has successfully produced a 404 response. If another view or middleware class attempts to produce a 404 but ends up raising an exception instead, the response will become an HTTP 500 (“Internal Server Error”) and the FlatpageFallbackMiddleware will not attempt to serve a flat page.

How to add, change and delete flatpages

Via the admin interface

If you’ve activated the automatic Django admin interface, you should see a “Flatpages” section on the admin index page. Edit flatpages as you edit any other object in the system.

The FlatPage model has an enable_comments field that isn’t used by contrib.flatpages, but that could be useful for your project or third-party apps. It doesn’t appear in the admin interface, but you can add it by registering a custom ModelAdmin for FlatPage:

from django.contrib import admin
from django.contrib.flatpages.admin import FlatPageAdmin
from django.contrib.flatpages.models import FlatPage
from django.utils.translation import ugettext_lazy as _

# Define a new FlatPageAdmin
class FlatPageAdmin(FlatPageAdmin):
fieldsets = (
(None, {'fields': ('url', 'title', 'content', 'sites')}),
(_('Advanced options'), {
'classes': ('collapse', ),
'fields': (
'enable_comments',
'registration_required',
'template_name',
),
}),
)

# Re-register FlatPageAdmin
admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin)

Changed in Django 1.9:
The enable_comments field was removed from FlatPageAdmin.

Via the Python API

class FlatPage

Flatpages are represented by a standard Django model, which lives in django/contrib/flatpages/models.py. You can access flatpage objects via the Django database API.

Check for duplicate flatpage URLs.

If you add or modify flatpages via your own code, you will likely want to check for duplicate flatpage URLs within the same site. The flatpage form used in the admin performs this validation check, and can be imported from django.contrib.flatpages.forms.FlatpageForm and used in your own views.

Flatpage templates

By default, flatpages are rendered via the template flatpages/default.html, but you can override that for a particular flatpage: in the admin, a collapsed fieldset titled “Advanced options” (clicking will expand it) contains a field for specifying a template name. If you’re creating a flat page via the Python API you can simply set the template name as the field template_name on the FlatPage object.

Creating the flatpages/default.html template is your responsibility; in your template directory, just create a flatpages directory containing a file default.html.

Flatpage templates are passed a single context variable, flatpage, which is the flatpage object.

Here’s a sample flatpages/default.html template:

<!DOCTYPE html>
<html>
<head>
<title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content }}
</body>
</html>

Since you’re already entering raw HTML into the admin page for a flatpage, both flatpage.title and flatpage.content are marked as not requiring automatic HTML escaping in the template.

Getting a list of FlatPage objects in your templates

The flatpages app provides a template tag that allows you to iterate over all of the available flatpages on the current site.

Like all custom template tags, you’ll need to load its custom tag library before you can use it. After loading the library, you can retrieve all current flatpages via the get_flatpages tag:

{% load flatpages %}
{% get_flatpages as flatpages %}
<ul>
{% for page in flatpages %}
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
{% endfor %}
</ul>

Displaying registration_required flatpages

By default, the get_flatpages templatetag will only show flatpages that are marked registration_required = False. If you want to display registration-protected flatpages, you need to specify an authenticated user using a for clause.

For example:

{% get_flatpages for someuser as about_pages %}

If you provide an anonymous user, get_flatpages will behave the same as if you hadn’t provided a user – i.e., it will only show you public flatpages.

Limiting flatpages by base URL

An optional argument, starts_with, can be applied to limit the returned pages to those beginning with a particular base URL. This argument may be passed as a string, or as a variable to be resolved from the context.

For example:

{% get_flatpages '/about/' as about_pages %}
{% get_flatpages about_prefix as about_pages %}
{% get_flatpages '/about/' for someuser as about_pages %}

Integrating with django.contrib.sitemaps

class FlatPageSitemap[source]

The sitemaps.FlatPageSitemap class looks at all publicly visible flatpages defined for the current SITE_ID (see the sites documentation) and creates an entry in the sitemap. These entries include only the location attribute – not lastmod, changefreq or priority.

Changed in Django 1.8:
This class is available from django.contrib.sitemaps.FlatPageSitemap in older version of Django.

Example

Here’s an example of a URLconf using FlatPageSitemap:

from django.conf.urls import url
from django.contrib.flatpages.sitemaps import FlatPageSitemap
from django.contrib.sitemaps.views import sitemap

urlpatterns = [
# ...

# the sitemap
url(r'^sitemap\.xml$', sitemap,
{'sitemaps': {'flatpages': FlatPageSitemap}},
name='django.contrib.sitemaps.views.sitemap'),
]

GeoDjango

GeoDjango intends to be a world-class geographic Web framework. Its goal is to make it as easy as possible to build GIS Web applications and harness the power of spatially enabled data.

- GeoDjango Tutorial

- Introduction

- Setting Up

- Geographic Data

- Geographic Models

- Importing Spatial Data

- Spatial Queries

- Putting your data on the map

- GeoDjango Installation

- Overview

- Requirements

- Installation

- Troubleshooting

- Platform-specific instructions

- GeoDjango Model API

- Spatial Field Types

- Spatial Field Options

- Geometry Field Options

- GeoManager

- GeoDjango Database API

- Spatial Backends

- Creating and Saving Models with Geometry Fields

- Creating and Saving Models with Raster Fields

- Spatial Lookups

- Distance Queries

- Compatibility Tables

- GeoDjango Forms API

- Field arguments

- Form field classes

- Form widgets

- GeoQuerySet API Reference

- Spatial Lookups

- Distance Lookups

- GeoQuerySet Methods

- Spatial Aggregates

- Geographic Database Functions

- Area

- AsGeoJSON

- AsGML

- AsKML

- AsSVG

- BoundingCircle

- Centroid

- Difference

- Distance

- Envelope

- ForceRHR

- GeoHash

- Intersection

- Length

- MemSize

- NumGeometries

- NumPoints

- Perimeter

- PointOnSurface

- Reverse

- Scale

- SnapToGrid

- SymDifference

- Transform

- Translate

- Union

- Measurement Objects

- Example

- Supported units

- Measurement API

- GEOS API

- Background

- Tutorial

- Geometry Objects

- Geometry Collections

- Prepared Geometries

- Geometry Factories

- I/O Objects

- Settings

- Exceptions

- GDAL API

- Overview

- Vector Data Source Objects

- OGR Geometries

- Coordinate System Objects

- Raster Data Objects

- Settings

- Geolocation with GeoIP

- Example

- GeoIP Settings

- GeoIP API

- GeoIP Methods

- Geolocation with GeoIP2

- Example

- GeoIP Settings

- GeoIP API

- GeoIP Methods

- GeoDjango Utilities

- LayerMapping data import utility

- OGR Inspection

- GeoJSON Serializer

- GeoDjango Management Commands

- inspectdb

- ogrinspect

- GeoDjango’s admin site

- GeoModelAdmin

- OSMGeoAdmin

- Geographic Feeds

- Example

- API Reference

- Geographic Sitemaps

- Example

- Reference

- Testing GeoDjango apps

- PostGIS

- GeoDjango tests

- Deploying GeoDjango

GeoDjango Tutorial

Introduction

GeoDjango is an included contrib module for Django that turns it into a world-class geographic Web framework. GeoDjango strives to make it as simple as possible to create geographic Web applications, like location-based services. Its features include:

- Django model fields for OGC geometries and raster data.

- Extensions to Django’s ORM for querying and manipulating spatial data.

- Loosely-coupled, high-level Python interfaces for GIS geometry and raster operations and data manipulation in different formats.

- Editing geometry fields from the admin.

This tutorial assumes familiarity with Django; thus, if you’re brand new to Django, please read through the regular tutorial to familiarize yourself with Django first.

Note

GeoDjango has additional requirements beyond what Django requires – please consult the installation documentation for more details.

This tutorial will guide you through the creation of a geographic web application for viewing the world borders. [1] Some of the code used in this tutorial is taken from and/or inspired by the GeoDjango basic apps project. [2]

Note

Proceed through the tutorial sections sequentially for step-by-step instructions.

Setting Up

Create a Spatial Database

Typically no special setup is required, so you can create a database as you would for any other project. We provide some tips for selected databases:

- Installing PostGIS

- Installing Spatialite

Create a New Project

Use the standard django-admin script to create a project called geodjango:

$ django-admin startproject geodjango

This will initialize a new project. Now, create a world Django application within the geodjango project:

$ cd geodjango
$ python manage.py startapp world

Configure settings.py

The geodjango project settings are stored in the geodjango/settings.py file. Edit the database connection settings to match your setup:

DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'geodjango',
'USER': 'geo',
},
}

In addition, modify the INSTALLED_APPS setting to include django.contrib.admin, django.contrib.gis, and world (your newly created application):

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
'world',
]

Geographic Data

World Borders

The world borders data is available in this zip file. Create a data directory in the world application, download the world borders data, and unzip. On GNU/Linux platforms, use the following commands:

$ mkdir world/data
$ cd world/data
$ wget http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
$ unzip TM_WORLD_BORDERS-0.3.zip
$ cd ../..

The world borders ZIP file contains a set of data files collectively known as an ESRI Shapefile, one of the most popular geospatial data formats. When unzipped, the world borders dataset includes files with the following extensions:

- .shp: Holds the vector data for the world borders geometries.

- .shx: Spatial index file for geometries stored in the .shp.

- .dbf: Database file for holding non-geometric attribute data (e.g., integer and character fields).

- .prj: Contains the spatial reference information for the geographic data stored in the shapefile.

Use ogrinfo to examine spatial data

The GDAL ogrinfo utility allows examining the metadata of shapefiles or other vector data sources:

$ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
using driver `ESRI Shapefile' successful.
1: TM_WORLD_BORDERS-0.3 (Polygon)

ogrinfo tells us that the shapefile has one layer, and that this layer contains polygon data. To find out more, we’ll specify the layer name and use the -so option to get only the important summary information:

$ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
using driver `ESRI Shapefile' successful.

Layer name: TM_WORLD_BORDERS-0.3
Geometry: Polygon
Feature Count: 246
Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
Layer SRS WKT:
GEOGCS["GCS_WGS_1984",
DATUM["WGS_1984",
SPHEROID["WGS_1984",6378137.0,298.257223563]],
PRIMEM["Greenwich",0.0],
UNIT["Degree",0.0174532925199433]]
FIPS: String (2.0)
ISO2: String (2.0)
ISO3: String (3.0)
UN: Integer (3.0)
NAME: String (50.0)
AREA: Integer (7.0)
POP2005: Integer (10.0)
REGION: Integer (3.0)
SUBREGION: Integer (3.0)
LON: Real (8.3)
LAT: Real (7.3)

This detailed summary information tells us the number of features in the layer (246), the geographic bounds of the data, the spatial reference system (“SRS WKT”), as well as type information for each attribute field. For example, FIPS: String (2.0) indicates that the FIPS character field has a maximum length of 2. Similarly, LON: Real (8.3) is a floating-point field that holds a maximum of 8 digits up to three decimal places.

Geographic Models

Defining a Geographic Model

Now that you’ve examined your dataset using ogrinfo, create a GeoDjango model to represent this data:

from django.contrib.gis.db import models

class WorldBorder(models.Model):
# Regular Django fields corresponding to the attributes in the
# world borders shapefile.
name = models.CharField(max_length=50)
area = models.IntegerField()
pop2005 = models.IntegerField('Population 2005')
fips = models.CharField('FIPS Code', max_length=2)
iso2 = models.CharField('2 Digit ISO', max_length=2)
iso3 = models.CharField('3 Digit ISO', max_length=3)
un = models.IntegerField('United Nations Code')
region = models.IntegerField('Region Code')
subregion = models.IntegerField('Sub-Region Code')
lon = models.FloatField()
lat = models.FloatField()

# GeoDjango-specific: a geometry field (MultiPolygonField)
mpoly = models.MultiPolygonField()

# Returns the string representation of the model.
def __str__(self):              # __unicode__ on Python 2
return self.name

Note that the models module is imported from django.contrib.gis.db.

The default spatial reference system for geometry fields is WGS84 (meaning the SRID is 4326) – in other words, the field coordinates are in longitude, latitude pairs in units of degrees. To use a different coordinate system, set the SRID of the geometry field with the srid argument. Use an integer representing the coordinate system’s EPSG code.

Run migrate

After defining your model, you need to sync it with the database. First, create a database migration:

$ python manage.py makemigrations
Migrations for 'world':
0001_initial.py:
- Create model WorldBorder

Let’s look at the SQL that will generate the table for the WorldBorder model:

$ python manage.py sqlmigrate world 0001

This command should produce the following output:

BEGIN;
--
-- Create model WorldBorder
--
CREATE TABLE "world_worldborder" (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar(50) NOT NULL,
"area" integer NOT NULL,
"pop2005" integer NOT NULL,
"fips" varchar(2) NOT NULL,
"iso2" varchar(2) NOT NULL,
"iso3" varchar(3) NOT NULL,
"un" integer NOT NULL,
"region" integer NOT NULL,
"subregion" integer NOT NULL,
"lon" double precision NOT NULL,
"lat" double precision NOT NULL
"mpoly" geometry(MULTIPOLYGON,4326) NOT NULL
)
;
CREATE INDEX "world_worldborder_mpoly_id" ON "world_worldborder" USING GIST ( "mpoly" );
COMMIT;

If this looks correct, run migrate to create this table in the database:

$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, world, contenttypes, auth, sessions
Running migrations:
...
Applying world.0001_initial... OK

Importing Spatial Data

This section will show you how to import the world borders shapefile into the database via GeoDjango models using the LayerMapping data import utility.

There are many different ways to import data into a spatial database – besides the tools included within GeoDjango, you may also use the following:

- ogr2ogr: A command-line utility included with GDAL that can import many vector data formats into PostGIS, MySQL, and Oracle databases.

- shp2pgsql: This utility included with PostGIS imports ESRI shapefiles into PostGIS.

GDAL Interface

Earlier, you used ogrinfo to examine the contents of the world borders shapefile. GeoDjango also includes a Pythonic interface to GDAL’s powerful OGR library that can work with all the vector data sources that OGR supports.

First, invoke the Django shell:

$ python manage.py shell

If you downloaded the World Borders data earlier in the tutorial, then you can determine its path using Python’s built-in os module:

>>> import os
>>> import world
>>> world_shp = os.path.abspath(os.path.join(os.path.dirname(world.__file__),
...                             'data', 'TM_WORLD_BORDERS-0.3.shp'))

Now, open the world borders shapefile using GeoDjango’s DataSource interface:

>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource(world_shp)
>>> print(ds)
/ ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile)

Data source objects can have different layers of geospatial features; however, shapefiles are only allowed to have one layer:

>>> print(len(ds))
1
>>> lyr = ds[0]
>>> print(lyr)
TM_WORLD_BORDERS-0.3

You can see the layer’s geometry type and how many features it contains:

>>> print(lyr.geom_type)
Polygon
>>> print(len(lyr))
246

Note

Unfortunately, the shapefile data format does not allow for greater specificity with regards to geometry types. This shapefile, like many others, actually includes MultiPolygon geometries, not Polygons. It’s important to use a more general field type in models: a GeoDjango MultiPolygonField will accept a Polygon geometry, but a PolygonField will not accept a MultiPolygon type geometry. This is why the WorldBorder model defined above uses a MultiPolygonField.

The Layer may also have a spatial reference system associated with it. If it does, the srs attribute will return a SpatialReference object:

>>> srs = lyr.srs
>>> print(srs)
GEOGCS["GCS_WGS_1984",
DATUM["WGS_1984",
SPHEROID["WGS_1984",6378137.0,298.257223563]],
PRIMEM["Greenwich",0.0],
UNIT["Degree",0.0174532925199433]]
>>> srs.proj4 # PROJ.4 representation
'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '

This shapefile is in the popular WGS84 spatial reference system – in other words, the data uses longitude, latitude pairs in units of degrees.

In addition, shapefiles also support attribute fields that may contain additional data. Here are the fields on the World Borders layer:

>>> print(lyr.fields)
['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT']

The following code will let you examine the OGR types (e.g. integer or string) associated with each of the fields:

>>> [fld.__name__ for fld in lyr.field_types]
['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal']

You can iterate over each feature in the layer and extract information from both the feature’s geometry (accessed via the geom attribute) as well as the feature’s attribute fields (whose values are accessed via get() method):

>>> for feat in lyr:
...    print(feat.get('NAME'), feat.geom.num_points)
...
Guernsey 18
Jersey 26
South Georgia South Sandwich Islands 338
Taiwan 363

Layer objects may be sliced:

>>> lyr[0:2]
[<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>]

And individual features may be retrieved by their feature ID:

>>> feat = lyr[234]
>>> print(feat.get('NAME'))
San Marino

Boundary geometries may be exported as WKT and GeoJSON:

>>> geom = feat.geom
>>> print(geom.wkt)
POLYGON ((12.415798 43.957954,12.450554 ...
>>> print(geom.json)
{ "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...

LayerMapping

To import the data, use a LayerMapping in a Python script. Create a file called load.py inside the world application, with the following code:

import os
from django.contrib.gis.utils import LayerMapping
from .models import WorldBorder

world_mapping = {
'fips' : 'FIPS',
'iso2' : 'ISO2',
'iso3' : 'ISO3',
'un' : 'UN',
'name' : 'NAME',
'area' : 'AREA',
'pop2005' : 'POP2005',
'region' : 'REGION',
'subregion' : 'SUBREGION',
'lon' : 'LON',
'lat' : 'LAT',
'mpoly' : 'MULTIPOLYGON',
}

world_shp = os.path.abspath(
os.path.join(os.path.dirname(__file__), 'data', 'TM_WORLD_BORDERS-0.3.shp'),
)

def run(verbose=True):
lm = LayerMapping(
WorldBorder, world_shp, world_mapping,
transform=False, encoding='iso-8859-1',
)
lm.save(strict=True, verbose=verbose)

A few notes about what’s going on:

- Each key in the world_mapping dictionary corresponds to a field in the WorldBorder model. The value is the name of the shapefile field that data will be loaded from.

- The key mpoly for the geometry field is MULTIPOLYGON, the geometry type GeoDjango will import the field as. Even simple polygons in the shapefile will automatically be converted into collections prior to insertion into the database.

- The path to the shapefile is not absolute – in other words, if you move the world application (with data subdirectory) to a different location, the script will still work.

- The transform keyword is set to False because the data in the shapefile does not need to be converted – it’s already in WGS84 (SRID=4326).

- The encoding keyword is set to the character encoding of the string values in the shapefile. This ensures that string values are read and saved correctly from their original encoding system.

Afterwards, invoke the Django shell from the geodjango project directory:

$ python manage.py shell

Next, import the load module, call the run routine, and watch LayerMapping do the work:

>>> from world import load
>>> load.run()

Try ogrinspect

Now that you’ve seen how to define geographic models and import data with the LayerMapping data import utility, it’s possible to further automate this process with use of the ogrinspect management command. The ogrinspect command introspects a GDAL-supported vector data source (e.g., a shapefile) and generates a model definition and LayerMapping dictionary automatically.

The general usage of the command goes as follows:

$ python manage.py ogrinspect [options] <data_source> <model_name> [options]

data_source is the path to the GDAL-supported data source and model_name is the name to use for the model. Command-line options may be used to further define how the model is generated.

For example, the following command nearly reproduces the WorldBorder model and mapping dictionary created above, automatically:

$ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorder \
--srid=4326 --mapping --multi

A few notes about the command-line options given above:

- The --srid=4326 option sets the SRID for the geographic field.

- The --mapping option tells ogrinspect to also generate a mapping dictionary for use with LayerMapping.

- The --multi option is specified so that the geographic field is a MultiPolygonField instead of just a PolygonField.

The command produces the following output, which may be copied directly into the models.py of a GeoDjango application:

# This is an auto-generated Django model module created by ogrinspect.
from django.contrib.gis.db import models

class WorldBorder(models.Model):
fips = models.CharField(max_length=2)
iso2 = models.CharField(max_length=2)
iso3 = models.CharField(max_length=3)
un = models.IntegerField()
name = models.CharField(max_length=50)
area = models.IntegerField()
pop2005 = models.IntegerField()
region = models.IntegerField()
subregion = models.IntegerField()
lon = models.FloatField()
lat = models.FloatField()
geom = models.MultiPolygonField(srid=4326)

# Auto-generated `LayerMapping` dictionary for WorldBorder model
worldborders_mapping = {
'fips' : 'FIPS',
'iso2' : 'ISO2',
'iso3' : 'ISO3',
'un' : 'UN',
'name' : 'NAME',
'area' : 'AREA',
'pop2005' : 'POP2005',
'region' : 'REGION',
'subregion' : 'SUBREGION',
'lon' : 'LON',
'lat' : 'LAT',
'geom' : 'MULTIPOLYGON',
}

Spatial Queries

Spatial Lookups

GeoDjango adds spatial lookups to the Django ORM. For example, you can find the country in the WorldBorder table that contains a particular point. First, fire up the management shell:

$ python manage.py shell

Now, define a point of interest [3]:

>>> pnt_wkt = 'POINT(-95.3385 29.7245)'

The pnt_wkt string represents the point at -95.3385 degrees longitude, 29.7245 degrees latitude. The geometry is in a format known as Well Known Text (WKT), a standard issued by the Open Geospatial Consortium (OGC). [4] Import the WorldBorder model, and perform a contains lookup using the pnt_wkt as the parameter:

>>> from world.models import WorldBorder
>>> qs = WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
>>> qs
[<WorldBorder: United States>]

Here, you retrieved a QuerySet with only one model: the border of the United States (exactly what you would expect).

Similarly, you may also use a GEOS geometry object. Here, you can combine the intersects spatial lookup with the get method to retrieve only the WorldBorder instance for San Marino instead of a queryset:

>>> from django.contrib.gis.geos import Point
>>> pnt = Point(12.4604, 43.9420)
>>> sm = WorldBorder.objects.get(mpoly__intersects=pnt)
>>> sm
<WorldBorder: San Marino>

The contains and intersects lookups are just a subset of the available queries – the GeoDjango Database API documentation has more.

Automatic Spatial Transformations

When doing spatial queries, GeoDjango automatically transforms geometries if they’re in a different coordinate system. In the following example, coordinates will be expressed in EPSG SRID 32140, a coordinate system specific to south Texas only and in units of meters, not degrees:

>>> from django.contrib.gis.geos import Point, GEOSGeometry
>>> pnt = Point(954158.1, 4215137.1, srid=32140)

Note that pnt may also be constructed with EWKT, an “extended” form of WKT that includes the SRID:

>>> pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)')

GeoDjango’s ORM will automatically wrap geometry values in transformation SQL, allowing the developer to work at a higher level of abstraction:

>>> qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
>>> print(qs.query) # Generating the SQL
SELECT "world_worldborder"."id", "world_worldborder"."name", "world_worldborder"."area",
"world_worldborder"."pop2005", "world_worldborder"."fips", "world_worldborder"."iso2",
"world_worldborder"."iso3", "world_worldborder"."un", "world_worldborder"."region",
"world_worldborder"."subregion", "world_worldborder"."lon", "world_worldborder"."lat",
"world_worldborder"."mpoly" FROM "world_worldborder"
WHERE ST_Intersects("world_worldborder"."mpoly", ST_Transform(%s, 4326))
>>> qs # printing evaluates the queryset
[<WorldBorder: United States>]

Raw queries

When using raw queries, you should generally wrap your geometry fields with the asText() SQL function (or ST_AsText for PostGIS) so that the field value will be recognized by GEOS:

City.objects.raw('SELECT id, name, asText(point) from myapp_city')

This is not absolutely required by PostGIS, but generally you should only use raw queries when you know exactly what you are doing.

Lazy Geometries

GeoDjango loads geometries in a standardized textual representation. When the geometry field is first accessed, GeoDjango creates a GEOS geometry object <ref-geos>, exposing powerful functionality, such as serialization properties for popular geospatial formats:

>>> sm = WorldBorder.objects.get(name='San Marino')
>>> sm.mpoly
<MultiPolygon object at 0x24c6798>
>>> sm.mpoly.wkt # WKT
MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
>>> sm.mpoly.wkb # WKB (as Python binary buffer)
<read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
>>> sm.mpoly.geojson # GeoJSON (requires GDAL)
'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...

This includes access to all of the advanced geometric operations provided by the GEOS library:

>>> pnt = Point(12.4604, 43.9420)
>>> sm.mpoly.contains(pnt)
True
>>> pnt.contains(sm.mpoly)
False

Geographic annotations

GeoDjango also offers a set of geographic annotations to compute distances and several other operations (intersection, difference, etc.). See the Geographic Database Functions documentation.

Putting your data on the map

Geographic Admin

GeoDjango extends Django’s admin application with support for editing geometry fields.

Basics

GeoDjango also supplements the Django admin by allowing users to create and modify geometries on a JavaScript slippy map (powered by OpenLayers).

Let’s dive right in. Create a file called admin.py inside the world application with the following code:

from django.contrib.gis import admin
from .models import WorldBorder

admin.site.register(WorldBorder, admin.GeoModelAdmin)

Next, edit your urls.py in the geodjango application folder as follows:

from django.conf.urls import url, include
from django.contrib.gis import admin

urlpatterns = [
url(r'^admin/', admin.site.urls),
]

Create an admin user:

$ python manage.py createsuperuser

Next, start up the Django development server:

$ python manage.py runserver

Finally, browse to http://localhost:8000/admin/, and log in with the user you just created. Browse to any of the WorldBorder entries – the borders may be edited by clicking on a polygon and dragging the vertexes to the desired position.

OSMGeoAdmin

With the OSMGeoAdmin, GeoDjango uses a Open Street Map layer in the admin. This provides more context (including street and thoroughfare details) than available with the GeoModelAdmin (which uses the Vector Map Level 0 WMS dataset hosted at OSGeo).

First, there are some important requirements:

- OSMGeoAdmin requires that GDAL is installed.

- The PROJ.4 datum shifting files must be installed (see the PROJ.4 installation instructions for more details).

If you meet this requirement, then just substitute the OSMGeoAdmin option class in your admin.py file:

admin.site.register(WorldBorder, admin.OSMGeoAdmin)

Footnotes

[1]

Special thanks to Bjørn Sandvik of thematicmapping.org for providing and maintaining this dataset.

[2]

GeoDjango basic apps was written by Dane Springmeyer, Josh Livni, and Christopher Schmidt.

[3]

This point is the University of Houston Law Center.

[4]

Open Geospatial Consortium, Inc., OpenGIS Simple Feature Specification For SQL.

GeoDjango Installation

Overview

In general, GeoDjango installation requires:

1. Python and Django

2. Spatial database

3. Installing Geospatial libraries

Details for each of the requirements and installation instructions are provided in the sections below. In addition, platform-specific instructions are available for:

- Mac OS X

- Windows

Use the Source

Because GeoDjango takes advantage of the latest in the open source geospatial software technology, recent versions of the libraries are necessary. If binary packages aren’t available for your platform, installation from source may be required. When compiling the libraries from source, please follow the directions closely, especially if you’re a beginner.

Requirements

Python and Django

Because GeoDjango is included with Django, please refer to Django’s installation instructions for details on how to install.

Spatial database

PostgreSQL (with PostGIS), MySQL (mostly with MyISAM engine), Oracle, and SQLite (with SpatiaLite) are the spatial databases currently supported.

Note

PostGIS is recommended, because it is the most mature and feature-rich open source spatial database.

The geospatial libraries required for a GeoDjango installation depends on the spatial database used. The following lists the library requirements, supported versions, and any notes for each of the supported database backends:

Database

Library Requirements

Supported Versions

Notes

PostgreSQL

GEOS, PROJ.4, PostGIS

9.1+

Requires PostGIS.

MySQL

GEOS

5.5+

Not OGC-compliant; limited functionality.

Oracle

GEOS

11.2+

XE not supported.

SQLite

GEOS, GDAL, PROJ.4, SpatiaLite

3.6.+

Requires SpatiaLite 2.4+, pysqlite2 2.5+

See also this comparison matrix on the OSGeo Wiki for PostgreSQL/PostGIS/GEOS/GDAL possible combinations.

Installation

Geospatial libraries

- Installing Geospatial libraries

Database installation

- Installing PostGIS

- Installing Spatialite

Add django.contrib.gis to INSTALLED_APPS

Like other Django contrib applications, you will only need to add django.contrib.gis to INSTALLED_APPS in your settings. This is so that the gis templates can be located – if not done, then features such as the geographic admin or KML sitemaps will not function properly.

Troubleshooting

If you can’t find the solution to your problem here then participate in the community! You can:

- Join the #geodjango IRC channel on Freenode. Please be patient and polite – while you may not get an immediate response, someone will attempt to answer your question as soon as they see it.

- Ask your question on the GeoDjango mailing list.

- File a ticket on the Django trac if you think there’s a bug. Make sure to provide a complete description of the problem, versions used, and specify the component as “GIS”.

Library environment settings

By far, the most common problem when installing GeoDjango is that the external shared libraries (e.g., for GEOS and GDAL) cannot be located. [1] Typically, the cause of this problem is that the operating system isn’t aware of the directory where the libraries built from source were installed.

In general, the library path may be set on a per-user basis by setting an environment variable, or by configuring the library path for the entire system.

LD_LIBRARY_PATH environment variable

A user may set this environment variable to customize the library paths they want to use. The typical library directory for software built from source is /usr/local/lib. Thus, /usr/local/lib needs to be included in the LD_LIBRARY_PATH variable. For example, the user could place the following in their bash profile:

export LD_LIBRARY_PATH=/usr/local/lib

Setting system library path

On GNU/Linux systems, there is typically a file in /etc/ld.so.conf, which may include additional paths from files in another directory, such as /etc/ld.so.conf.d. As the root user, add the custom library path (like /usr/local/lib) on a new line in ld.so.conf. This is one example of how to do so:

$ sudo echo /usr/local/lib >> /etc/ld.so.conf
$ sudo ldconfig

For OpenSolaris users, the system library path may be modified using the crle utility. Run crle with no options to see the current configuration and use crle -l to set with the new library path. Be very careful when modifying the system library path:

# crle -l $OLD_PATH:/usr/local/lib

Install binutils

GeoDjango uses the find_library function (from the ctypes.util Python module) to discover libraries. The find_library routine uses a program called objdump (part of the binutils package) to verify a shared library on GNU/Linux systems. Thus, if binutils is not installed on your Linux system then Python’s ctypes may not be able to find your library even if your library path is set correctly and geospatial libraries were built perfectly.

The binutils package may be installed on Debian and Ubuntu systems using the following command:

$ sudo apt-get install binutils

Similarly, on Red Hat and CentOS systems:

$ sudo yum install binutils

Platform-specific instructions

Mac OS X

Because of the variety of packaging systems available for OS X, users have several different options for installing GeoDjango. These options are:

- Postgres.app (easiest and recommended)

- Homebrew

- KyngChaos packages

- Fink

- MacPorts

- Building from source

This section also includes instructions for installing an upgraded version of Python from packages provided by the Python Software Foundation, however, this is not required.

Python

Although OS X comes with Python installed, users can use framework installers provided by the Python Software Foundation. An advantage to using the installer is that OS X’s Python will remain “pristine” for internal operating system use.

Note

You will need to modify the PATH environment variable in your .profile file so that the new version of Python is used when python is entered at the command-line:

export PATH=/Library/Frameworks/Python.framework/Versions/Current/bin:$PATH

Postgres.app

Postgres.app is a standalone PostgreSQL server that includes the PostGIS extension. You will also need to install gdal and libgeoip with Homebrew.

After installing Postgres.app, add the following to your .bash_profile so you can run the package’s programs from the command-line. Replace X.Y with the version of PostgreSQL in the Postgres.app you installed:

export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/X.Y/bin

You can check if the path is set up correctly by typing which psql at a terminal prompt.

Homebrew

Homebrew provides “recipes” for building binaries and packages from source. It provides recipes for the GeoDjango prerequisites on Macintosh computers running OS X. Because Homebrew still builds the software from source, the Apple Developer Tools are required.

Summary:

$ brew install postgresql
$ brew install postgis
$ brew install gdal
$ brew install libgeoip

KyngChaos packages

William Kyngesburye provides a number of geospatial library binary packages that make it simple to get GeoDjango installed on OS X without compiling them from source. However, the Apple Developer Tools are still necessary for compiling the Python database adapters psycopg2 (for PostGIS) and pysqlite2 (for SpatiaLite).

Note

SpatiaLite users should consult the Mac OS X-specific instructions section after installing the packages for additional instructions.

Download the framework packages for:

- UnixImageIO

- PROJ

- GEOS

- SQLite3 (includes the SpatiaLite library)

- GDAL

Install the packages in the order they are listed above, as the GDAL and SQLite packages require the packages listed before them.

Afterwards, you can also install the KyngChaos binary packages for PostgreSQL and PostGIS.

After installing the binary packages, you’ll want to add the following to your .profile to be able to run the package programs from the command-line:

export PATH=/Library/Frameworks/UnixImageIO.framework/Programs:$PATH
export PATH=/Library/Frameworks/PROJ.framework/Programs:$PATH
export PATH=/Library/Frameworks/GEOS.framework/Programs:$PATH
export PATH=/Library/Frameworks/SQLite3.framework/Programs:$PATH
export PATH=/Library/Frameworks/GDAL.framework/Programs:$PATH
export PATH=/usr/local/pgsql/bin:$PATH

psycopg2

After you’ve installed the KyngChaos binaries and modified your PATH, as described above, psycopg2 may be installed using the following command:

$ pip install psycopg2

Note

If you don’t have pip, follow the installation instructions to install it.

Fink

Kurt Schwehr has been gracious enough to create GeoDjango packages for users of the Fink package system. Different packages are available (starting with “django-gis”), depending on which version of Python you want to use.

MacPorts

MacPorts may be used to install GeoDjango prerequisites on Macintosh computers running OS X. Because MacPorts still builds the software from source, the Apple Developer Tools are required.

Summary:

$ sudo port install postgresql93-server
$ sudo port install geos
$ sudo port install proj
$ sudo port install postgis
$ sudo port install gdal +geos
$ sudo port install libgeoip

Note

You will also have to modify the PATH in your .profile so that the MacPorts programs are accessible from the command-line:

export PATH=/opt/local/bin:/opt/local/lib/postgresql93/bin

In addition, add the DYLD_FALLBACK_LIBRARY_PATH setting so that the libraries can be found by Python:

export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql93

Windows

Proceed through the following sections sequentially in order to install GeoDjango on Windows.

Note

These instructions assume that you are using 32-bit versions of all programs. While 64-bit versions of Python and PostgreSQL 9.x are available, 64-bit versions of spatial libraries, like GEOS and GDAL, are not yet provided by the OSGeo4W installer.

Python

First, download the latest Python 2.7 installer from the Python website. Next, run the installer and keep the defaults – for example, keep ‘Install for all users’ checked and the installation path set as C:\Python27.

Note

You may already have a version of Python installed in C:\python as ESRI products sometimes install a copy there. You should still install a fresh version of Python 2.7.

PostgreSQL

First, download the latest PostgreSQL 9.x installer from the EnterpriseDB website. After downloading, simply run the installer, follow the on-screen directions, and keep the default options unless you know the consequences of changing them.

Note

The PostgreSQL installer creates both a new Windows user to be the ‘postgres service account’ and a postgres database superuser You will be prompted once to set the password for both accounts – make sure to remember it!

When the installer completes, it will ask to launch the Application Stack Builder (ASB) on exit – keep this checked, as it is necessary to install PostGIS.

Note

If installed successfully, the PostgreSQL server will run in the background each time the system as started as a Windows service. A PostgreSQL 9.x start menu group will created and contains shortcuts for the ASB as well as the ‘SQL Shell’, which will launch a psql command window.

PostGIS

From within the Application Stack Builder (to run outside of the installer, Start ‣ Programs ‣ PostgreSQL 9.x), select PostgreSQL Database Server 9.x on port 5432 from the drop down menu. Next, expand the Categories ‣ Spatial Extensions menu tree and select PostGIS X.Y for PostgreSQL 9.x.

After clicking next, you will be prompted to select your mirror, PostGIS will be downloaded, and the PostGIS installer will begin. Select only the default options during install (e.g., do not uncheck the option to create a default PostGIS database).

Note

You will be prompted to enter your postgres database superuser password in the ‘Database Connection Information’ dialog.

psycopg2

The psycopg2 Python module provides the interface between Python and the PostgreSQL database. Download the latest Windows installer for your version of Python and PostgreSQL and run using the default settings. [2]

OSGeo4W

The OSGeo4W installer makes it simple to install the PROJ.4, GDAL, and GEOS libraries required by GeoDjango. First, download the OSGeo4W installer, and run it. Select Express Web-GIS Install and click next. In the ‘Select Packages’ list, ensure that GDAL is selected; MapServer and Apache are also enabled by default, but are not required by GeoDjango and may be unchecked safely. After clicking next, the packages will be automatically downloaded and installed, after which you may exit the installer.

Modify Windows environment

In order to use GeoDjango, you will need to add your Python and OSGeo4W directories to your Windows system Path, as well as create GDAL_DATA and PROJ_LIB environment variables. The following set of commands, executable with cmd.exe, will set this up:

set OSGEO4W_ROOT=C:\OSGeo4W
set PYTHON_ROOT=C:\Python27
set GDAL_DATA=%OSGEO4W_ROOT%\share\gdal
set PROJ_LIB=%OSGEO4W_ROOT%\share\proj
set PATH=%PATH%;%PYTHON_ROOT%;%OSGEO4W_ROOT%\bin
reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /t REG_EXPAND_SZ /f /d "%PATH%"
reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v GDAL_DATA /t REG_EXPAND_SZ /f /d "%GDAL_DATA%"
reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PROJ_LIB /t REG_EXPAND_SZ /f /d "%PROJ_LIB%"

For your convenience, these commands are available in the executable batch script, geodjango_setup.bat.

Note

Administrator privileges are required to execute these commands. To do this, right-click on geodjango_setup.bat and select Run as administrator. You need to log out and log back in again for the settings to take effect.

Note

If you customized the Python or OSGeo4W installation directories, then you will need to modify the OSGEO4W_ROOT and/or PYTHON_ROOT variables accordingly.

Install Django and set up database

Finally, install Django on your system.

Footnotes

[1]

GeoDjango uses the find_library() routine from ctypes.util to locate shared libraries.

[2]

The psycopg2 Windows installers are packaged and maintained by Jason Erickson.

Installing Geospatial libraries

GeoDjango uses and/or provides interfaces for the following open source geospatial libraries:

Program

Description

Required

Supported Versions

GEOS

Geometry Engine Open Source

Yes

3.4, 3.3, 3.2

PROJ.4

Cartographic Projections library

Yes (PostgreSQL and SQLite only)

4.9, 4.8, 4.7, 4.6, 4.5, 4.4

GDAL

Geospatial Data Abstraction Library

Yes (SQLite only)

2.0, 1.11, 1.10, 1.9, 1.8, 1.7

GeoIP

IP-based geolocation library

No

1.4

PostGIS

Spatial extensions for PostgreSQL

Yes (PostgreSQL only)

2.1, 2.0

SpatiaLite

Spatial extensions for SQLite

Yes (SQLite only)

4.3, 4.2, 4.1, 4.0, 3.0, 2.4

Note that older or more recent versions of these libraries may also work totally fine with GeoDjango. Your mileage may vary.

Install GDAL

While GDAL is technically not required, it is recommended. Important features of GeoDjango (including the LayerMapping data import utility, geometry reprojection, and the geographic admin) depend on its functionality.

Note

The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used independently of Django. In other words, no database or settings file required – just import them as normal from django.contrib.gis.

On Debian/Ubuntu, you are advised to install the following packages which will install, directly or by dependency, the required geospatial libraries:

$ sudo apt-get install binutils libproj-dev gdal-bin

Optional packages to consider:

- libgeoip1: for GeoIP support

- gdal-bin: for GDAL command line programs like ogr2ogr

- python-gdal for GDAL’s own Python bindings – includes interfaces for raster manipulation

Please also consult platform-specific instructions if you are on Mac OS X or Windows.

Building from source

When installing from source on UNIX and GNU/Linux systems, please follow the installation instructions carefully, and install the libraries in the given order. If using MySQL or Oracle as the spatial database, only GEOS is required.

Note

On Linux platforms, it may be necessary to run the ldconfig command after installing each library. For example:

$ sudo make install
$ sudo ldconfig

Note

OS X users are required to install Apple Developer Tools in order to compile software from source. This is typically included on your OS X installation DVDs.

GEOS

GEOS is a C++ library for performing geometric operations, and is the default internal geometry representation used by GeoDjango (it’s behind the “lazy” geometries). Specifically, the C API library is called (e.g., libgeos_c.so) directly from Python using ctypes.

First, download GEOS 3.4.2 from the GEOS website and untar the source archive:

$ wget http://download.osgeo.org/geos/geos-3.4.2.tar.bz2
$ tar xjf geos-3.4.2.tar.bz2

Next, change into the directory where GEOS was unpacked, run the configure script, compile, and install:

$ cd geos-3.4.2
$ ./configure
$ make
$ sudo make install
$ cd ..

Troubleshooting

Can’t find GEOS library

When GeoDjango can’t find GEOS, this error is raised:

ImportError: Could not find the GEOS library (tried "geos_c"). Try setting GEOS_LIBRARY_PATH in your settings.

The most common solution is to properly configure your Library environment settings or set GEOS_LIBRARY_PATH in your settings.

If using a binary package of GEOS (e.g., on Ubuntu), you may need to Install binutils.

GEOS_LIBRARY_PATH

If your GEOS library is in a non-standard location, or you don’t want to modify the system’s library path then the GEOS_LIBRARY_PATH setting may be added to your Django settings file with the full path to the GEOS C library. For example:

GEOS_LIBRARY_PATH = '/home/bob/local/lib/libgeos_c.so'

Note

The setting must be the full path to the C shared library; in other words you want to use libgeos_c.so, not libgeos.so.

See also My logs are filled with GEOS-related errors.

PROJ.4

PROJ.4 is a library for converting geospatial data to different coordinate reference systems.

First, download the PROJ.4 source code and datum shifting files [1]:

$ wget http://download.osgeo.org/proj/proj-4.9.1.tar.gz
$ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.tar.gz

Next, untar the source code archive, and extract the datum shifting files in the nad subdirectory. This must be done prior to configuration:

$ tar xzf proj-4.9.1.tar.gz
$ cd proj-4.9.1/nad
$ tar xzf ../../proj-datumgrid-1.5.tar.gz
$ cd ..

Finally, configure, make and install PROJ.4:

$ ./configure
$ make
$ sudo make install
$ cd ..

GDAL

GDAL is an excellent open source geospatial library that has support for reading most vector and raster spatial data formats. Currently, GeoDjango only supports GDAL’s vector data capabilities [2]. GEOS and PROJ.4 should be installed prior to building GDAL.

First download the latest GDAL release version and untar the archive:

$ wget http://download.osgeo.org/gdal/1.11.2/gdal-1.11.2.tar.gz
$ tar xzf gdal-1.11.2.tar.gz
$ cd gdal-1.11.2

Configure, make and install:

$ ./configure
$ make # Go get some coffee, this takes a while.
$ sudo make install
$ cd ..

Note

Because GeoDjango has its own Python interface, the preceding instructions do not build GDAL’s own Python bindings. The bindings may be built by adding the --with-python flag when running configure. See GDAL/OGR In Python for more information on GDAL’s bindings.

If you have any problems, please see the troubleshooting section below for suggestions and solutions.

Troubleshooting

Can’t find GDAL library

When GeoDjango can’t find the GDAL library, the HAS_GDAL flag will be false:

>>> from django.contrib.gis import gdal
>>> gdal.HAS_GDAL
False

The solution is to properly configure your Library environment settings or set GDAL_LIBRARY_PATH in your settings.

GDAL_LIBRARY_PATH

If your GDAL library is in a non-standard location, or you don’t want to modify the system’s library path then the GDAL_LIBRARY_PATH setting may be added to your Django settings file with the full path to the GDAL library. For example:

GDAL_LIBRARY_PATH = '/home/sue/local/lib/libgdal.so'

Footnotes

[1]

The datum shifting files are needed for converting data to and from certain projections. For example, the PROJ.4 string for the Google projection (900913 or 3857) requires the null grid file only included in the extra datum shifting files. It is easier to install the shifting files now, then to have debug a problem caused by their absence later.

[2]

Specifically, GeoDjango provides support for the OGR library, a component of GDAL.

Installing PostGIS

PostGIS adds geographic object support to PostgreSQL, turning it into a spatial database. GEOS, PROJ.4 and GDAL should be installed prior to building PostGIS. You might also need additional libraries, see PostGIS requirements.

Note

The psycopg2 module is required for use as the database adapter when using GeoDjango with PostGIS.

On Debian/Ubuntu, you are advised to install the following packages: postgresql-x.x, postgresql-x.x-postgis, postgresql-server-dev-x.x, python-psycopg2 (x.x matching the PostgreSQL version you want to install). Please also consult platform-specific instructions if you are on Mac OS X or Windows.

Building from source

First download the source archive, and extract:

$ wget http://download.osgeo.org/postgis/source/postgis-2.1.5.tar.gz
$ tar xzf postgis-2.1.5.tar.gz
$ cd postgis-2.1.5

Next, configure, make and install PostGIS:

$ ./configure

Finally, make and install:

$ make
$ sudo make install
$ cd ..

Note

GeoDjango does not automatically create a spatial database. Please consult the section on Creating a spatial database for more information.

Post-installation

Creating a spatial database

PostGIS 2 includes an extension for Postgres 9.1+ that can be used to enable spatial functionality:

$ createdb  <db name>
$ psql <db name>
> CREATE EXTENSION postgis;

The database user must be a superuser in order to run CREATE EXTENSION postgis;.

GeoDjango does not currently leverage any PostGIS topology functionality. If you plan to use those features at some point, you can also install the postgis_topology extension by issuing CREATE EXTENSION postgis_topology;.

Changed in Django 1.8:
The CREATE EXTENSION postgis command is now automatically run during the migrate process. You can still create it manually if you wish.

Managing the database

To administer the database, you can either use the pgAdmin III program (Start ‣ PostgreSQL 9.x ‣ pgAdmin III) or the SQL Shell (Start ‣ PostgreSQL 9.x ‣ SQL Shell). For example, to create a geodjango spatial database and user, the following may be executed from the SQL Shell as the postgres user:

postgres# CREATE USER geodjango PASSWORD 'my_passwd';
postgres# CREATE DATABASE geodjango OWNER geodjango;

Installing Spatialite

SpatiaLite adds spatial support to SQLite, turning it into a full-featured spatial database.

First, check if you can install Spatialite from system packages or binaries.

For example, on Debian-based distributions, try to install the spatialite-bin package. For distributions that package SpatiaLite 4.2+, install libsqlite3-mod-spatialite.

For Mac OS X, follow the instructions below.

For Windows, you may find binaries on the Gaia-SINS home page.

In any case, you should always be able to install from source.

SPATIALITE_LIBRARY_PATH setting required for SpatiaLite 4.2+

If you’re using SpatiaLite 4.2+, you must put this in your settings:

SPATIALITE_LIBRARY_PATH = 'mod_spatialite'

Installing from source

GEOS and PROJ.4 should be installed prior to building SpatiaLite.

SQLite

Check first if SQLite is compiled with the R*Tree module. Run the sqlite3 command line interface and enter the following query:

sqlite> CREATE VIRTUAL TABLE testrtree USING rtree(id,minX,maxX,minY,maxY);

If you obtain an error, you will have to recompile SQLite from source. Otherwise, just skip this section.

To install from sources, download the latest amalgamation source archive from the SQLite download page, and extract:

$ wget https://sqlite.org/sqlite-amalgamation-3.6.23.1.tar.gz
$ tar xzf sqlite-amalgamation-3.6.23.1.tar.gz
$ cd sqlite-3.6.23.1

Next, run the configure script – however the CFLAGS environment variable needs to be customized so that SQLite knows to build the R*Tree module:

$ CFLAGS="-DSQLITE_ENABLE_RTREE=1" ./configure
$ make
$ sudo make install
$ cd ..

SpatiaLite library (libspatialite)

Get the latest SpatiaLite library source bundle from the download page:

$ wget http://www.gaia-gis.it/gaia-sins/libspatialite-sources/libspatialite-4.1.0.tar.gz
$ tar xaf libspatialite-4.1.0.tar.gz
$ cd libspatialite-4.1.0
$ ./configure
$ make
$ sudo make install

Note

For Mac OS X users building from source, the SpatiaLite library and tools need to have their target configured:

$ ./configure --target=macosx

Mac OS X-specific instructions

To install the SpatiaLite library and tools, Mac OS X users can choose between KyngChaos packages and Homebrew.

KyngChaos

First, follow the instructions in the KyngChaos packages section.

When creating a SpatiaLite database, the spatialite program is required. However, instead of attempting to compile the SpatiaLite tools from source, download the SpatiaLite Binaries for OS X, and install spatialite in a location available in your PATH. For example:

$ curl -O http://www.gaia-gis.it/spatialite/spatialite-tools-osx-x86-2.3.1.tar.gz
$ tar xzf spatialite-tools-osx-x86-2.3.1.tar.gz
$ cd spatialite-tools-osx-x86-2.3.1/bin
$ sudo cp spatialite /Library/Frameworks/SQLite3.framework/Programs

Finally, for GeoDjango to be able to find the KyngChaos SpatiaLite library, add the following to your settings.py:

SPATIALITE_LIBRARY_PATH='/Library/Frameworks/SQLite3.framework/SQLite3'

Homebrew

Homebrew handles all the SpatiaLite related packages on your behalf, including SQLite3, SpatiaLite, PROJ, and GEOS. Install them like this:

$ brew update
$ brew install spatialite-tools
$ brew install gdal

Finally, for GeoDjango to be able to find the SpatiaLite library, add the following to your settings.py:

SPATIALITE_LIBRARY_PATH='/usr/local/lib/mod_spatialite.dylib'

GeoDjango Model API

This document explores the details of the GeoDjango Model API. Throughout this section, we’ll be using the following geographic model of a ZIP code and of a Digital Elevation Model as our examples:

from django.contrib.gis.db import models

class Zipcode(models.Model):
code = models.CharField(max_length=5)
poly = models.PolygonField()

class Elevation(models.Model):
name = models.CharField(max_length=100)
rast = models.RasterField()

Spatial Field Types

Spatial fields consist of a series of geometry field types and one raster field type. Each of the geometry field types correspond to the OpenGIS Simple Features specification [1]. There is no such standard for raster data.

GeometryField

class GeometryField

PointField

class PointField

LineStringField

class LineStringField

PolygonField

class PolygonField

MultiPointField

class MultiPointField

MultiLineStringField

class MultiLineStringField

MultiPolygonField

class MultiPolygonField

GeometryCollectionField

class GeometryCollectionField

RasterField

New in Django 1.9.

class RasterField

RasterField is currently only implemented for the PostGIS backend.

Spatial Field Options

Changed in Django 1.9:
The geometry field options srid and spatial_index are now shared by GeometryField and RasterField through the BaseSpatialField.

In addition to the regular Field options available for Django model fields, spatial fields have the following additional options. All are optional.

srid

BaseSpatialField.srid

Sets the SRID [2] (Spatial Reference System Identity) of the geometry field to the given value. Defaults to 4326 (also known as WGS84, units are in degrees of longitude and latitude).

Selecting an SRID

Choosing an appropriate SRID for your model is an important decision that the developer should consider carefully. The SRID is an integer specifier that corresponds to the projection system that will be used to interpret the data in the spatial database. [3] Projection systems give the context to the coordinates that specify a location. Although the details of geodesy are beyond the scope of this documentation, the general problem is that the earth is spherical and representations of the earth (e.g., paper maps, Web maps) are not.

Most people are familiar with using latitude and longitude to reference a location on the earth’s surface. However, latitude and longitude are angles, not distances. In other words, while the shortest path between two points on a flat surface is a straight line, the shortest path between two points on a curved surface (such as the earth) is an arc of a great circle. [4] Thus, additional computation is required to obtain distances in planar units (e.g., kilometers and miles). Using a geographic coordinate system may introduce complications for the developer later on. For example, Spatialite does not have the capability to perform distance calculations between geometries using geographic coordinate systems, e.g. constructing a query to find all points within 5 miles of a county boundary stored as WGS84. [5]

Portions of the earth’s surface may projected onto a two-dimensional, or Cartesian, plane. Projected coordinate systems are especially convenient for region-specific applications, e.g., if you know that your database will only cover geometries in North Kansas, then you may consider using projection system specific to that region. Moreover, projected coordinate systems are defined in Cartesian units (such as meters or feet), easing distance calculations.

Note

If you wish to perform arbitrary distance queries using non-point geometries in WGS84 in PostGIS and you want decent performance, enable the GeometryField.geography keyword so that geography database type is used instead.

Additional Resources:

- spatialreference.org: A Django-powered database of spatial reference systems.

- The State Plane Coordinate System: A website covering the various projection systems used in the United States. Much of the U.S. spatial data encountered will be in one of these coordinate systems rather than in a geographic coordinate system such as WGS84.

spatial_index

BaseSpatialField.spatial_index

Defaults to True. Creates a spatial index for the given geometry field.

Note

This is different from the db_index field option because spatial indexes are created in a different manner than regular database indexes. Specifically, spatial indexes are typically created using a variant of the R-Tree, while regular database indexes typically use B-Trees.

Geometry Field Options

There are additional options available for Geometry fields. All the following options are optional.

dim

GeometryField.dim

This option may be used for customizing the coordinate dimension of the geometry field. By default, it is set to 2, for representing two-dimensional geometries. For spatial backends that support it, it may be set to 3 for three-dimensional support.

Note

At this time 3D support is limited to the PostGIS spatial backend.

geography

GeometryField.geography

If set to True, this option will create a database column of type geography, rather than geometry. Please refer to the geography type section below for more details.

Note

Geography support is limited to PostGIS and will force the SRID to be 4326.

Geography Type

The geography type provides native support for spatial features represented with geographic coordinates (e.g., WGS84 longitude/latitude). [6] Unlike the plane used by a geometry type, the geography type uses a spherical representation of its data. Distance and measurement operations performed on a geography column automatically employ great circle arc calculations and return linear units. In other words, when ST_Distance is called on two geographies, a value in meters is returned (as opposed to degrees if called on a geometry column in WGS84).

Because geography calculations involve more mathematics, only a subset of the PostGIS spatial lookups are available for the geography type. Practically, this means that in addition to the distance lookups only the following additional spatial lookups are available for geography columns:

- bboverlaps

- coveredby

- covers

- intersects

For more information, the PostGIS documentation contains a helpful section on determining when to use geography data type over geometry data type.

GeoManager

class GeoManager

The GeoManager is required in order to use the legacy GeoQuerySet Methods.

Deprecated since version 1.9: All GeoQuerySet methods have been deprecated and replaced by equivalent database functions. As soon as the legacy methods have been replaced in your code, you should be able to remove the special GeoManager from your GIS-enabled classes.

Changed in Django 1.9:
In older versions, the manager was required to conduct geographic queries. Without it, all geographic filters failed.

GeoManager was required even if the model did not have a geographic field itself, e.g., in the case of a ForeignKey relation to a model with a geographic field. For example, if we had an Address model with a ForeignKey to our Zipcode model:

from django.contrib.gis.db import models

class Address(models.Model):
num = models.IntegerField()
street = models.CharField(max_length=100)
city = models.CharField(max_length=100)
state = models.CharField(max_length=2)
zipcode = models.ForeignKey(Zipcode, on_delete=models.CASCADE)
objects = models.GeoManager()

The geographic manager was needed to do spatial queries on related Zipcode objects, for example:

qs = Address.objects.filter(zipcode__poly__contains='POINT(-104.590948 38.319914)')

Footnotes

[1]

OpenGIS Consortium, Inc., Simple Feature Specification For SQL.

[2]

See id. at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems).

[3]

Typically, SRID integer corresponds to an EPSG (European Petroleum Survey Group) identifier. However, it may also be associated with custom projections defined in spatial database’s spatial reference systems table.

[4]

Terry A. Slocum, Robert B. McMaster, Fritz C. Kessler, & Hugh H. Howard, Thematic Cartography and Geographic Visualization (Prentice Hall, 2nd edition), at Ch. 7.1.3.

[5]

This limitation does not apply to PostGIS.

[6]

Please refer to the PostGIS Geography Type documentation for more details.

GeoDjango Database API

Spatial Backends

GeoDjango currently provides the following spatial database backends:

- django.contrib.gis.db.backends.postgis

- django.contrib.gis.db.backends.mysql

- django.contrib.gis.db.backends.oracle

- django.contrib.gis.db.backends.spatialite

MySQL Spatial Limitations

MySQL’s spatial extensions only support bounding box operations (what MySQL calls minimum bounding rectangles, or MBR). Specifically, MySQL does not conform to the OGC standard:

Currently, MySQL does not implement these functions [Contains, Crosses, Disjoint, Intersects, Overlaps, Touches, Within] according to the specification. Those that are implemented return the same result as the corresponding MBR-based functions.

In other words, while spatial lookups such as contains are available in GeoDjango when using MySQL, the results returned are really equivalent to what would be returned when using bbcontains on a different spatial backend.

Warning

True spatial indexes (R-trees) are only supported with MyISAM tables on MySQL. [5] In other words, when using MySQL spatial extensions you have to choose between fast spatial lookups and the integrity of your data – MyISAM tables do not support transactions or foreign key constraints.

Raster Support

RasterField is currently only implemented for the PostGIS backend. Spatial queries (such as lookups and distance) are not yet available for raster fields.

Creating and Saving Models with Geometry Fields

Here is an example of how to create a geometry object (assuming the Zipcode model):

>>> from zipcode.models import Zipcode
>>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z.save()

GEOSGeometry objects may also be used to save geometric models:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z = Zipcode(code=77096, poly=poly)
>>> z.save()

Moreover, if the GEOSGeometry is in a different coordinate system (has a different SRID value) than that of the field, then it will be implicitly transformed into the SRID of the model’s field, using the spatial database’s transform procedure:

>>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084)  # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
>>> z = Zipcode(code=78212, poly=poly_3084)
>>> z.save()
>>> from django.db import connection
>>> print(connection.queries[-1]['sql']) # printing the last SQL statement executed (requires DEBUG=True)
INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))

Thus, geometry parameters may be passed in using the GEOSGeometry object, WKT (Well Known Text [1]), HEXEWKB (PostGIS specific – a WKB geometry in hexadecimal [2]), and GeoJSON [3] (requires GDAL). Essentially, if the input is not a GEOSGeometry object, the geometry field will attempt to create a GEOSGeometry instance from the input.

For more information creating GEOSGeometry objects, refer to the GEOS tutorial.

Creating and Saving Models with Raster Fields

New in Django 1.9.

When creating raster models, the raster field will implicitly convert the input into a GDALRaster using lazy-evaluation. The raster field will therefore accept any input that is accepted by the GDALRaster constructor.

Here is an example of how to create a raster object from a raster file volcano.tif (assuming the Elevation model):

>>> from elevation.models import Elevation
>>> dem = Elevation(name='Volcano', rast='/path/to/raster/volcano.tif')
>>> dem.save()

GDALRaster objects may also be used to save raster models:

>>> from django.contrib.gis.gdal import GDALRaster
>>> rast = GDALRaster({'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
...                    'scale': [0.1, -0.1], 'bands': [{"data": range(100)}]})
>>> dem = Elevation(name='Canyon', rast=rast)
>>> dem.save()

Note that this equivalent to:

>>> dem = Elevation.objects.create(
...     name='Canyon',
...     rast={'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
...           'scale': [0.1, -0.1], 'bands': [{"data": range(100)}]},
... )

Spatial Lookups

GeoDjango’s lookup types may be used with any manager method like filter(), exclude(), etc. However, the lookup types unique to GeoDjango are only available on geometry fields. Filters on ‘normal’ fields (e.g. CharField) may be chained with those on geographic fields. Thus, geographic queries take the following general form (assuming the Zipcode model used in the GeoDjango Model API):

>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Zipcode.objects.exclude(...)

For example:

>>> qs = Zipcode.objects.filter(poly__contains=pnt)

In this case, poly is the geographic field, contains is the spatial lookup type, and pnt is the parameter (which may be a GEOSGeometry object or a string of GeoJSON , WKT, or HEXEWKB).

A complete reference can be found in the spatial lookup reference.

Distance Queries

Introduction

Distance calculations with spatial data is tricky because, unfortunately, the Earth is not flat. Some distance queries with fields in a geographic coordinate system may have to be expressed differently because of limitations in PostGIS. Please see the Selecting an SRID section in the GeoDjango Model API documentation for more details.

Distance Lookups

Availability: PostGIS, Oracle, SpatiaLite

The following distance lookups are available:

- distance_lt

- distance_lte

- distance_gt

- distance_gte

- dwithin

Note

For measuring, rather than querying on distances, use the Distance function.

Distance lookups take a tuple parameter comprising:

1. A geometry to base calculations from; and

2. A number or Distance object containing the distance.

If a Distance object is used, it may be expressed in any units (the SQL generated will use units converted to those of the field); otherwise, numeric parameters are assumed to be in the units of the field.

Note

In PostGIS, ST_Distance_Sphere does not limit the geometry types geographic distance queries are performed with. [4] However, these queries may take a long time, as great-circle distances must be calculated on the fly for every row in the query. This is because the spatial index on traditional geometry fields cannot be used.

For much better performance on WGS84 distance queries, consider using geography columns in your database instead because they are able to use their spatial index in distance queries. You can tell GeoDjango to use a geography column by setting geography=True in your field definition.

For example, let’s say we have a SouthTexasCity model (from the GeoDjango distance tests ) on a projected coordinate system valid for cities in southern Texas:

from django.contrib.gis.db import models

class SouthTexasCity(models.Model):
name = models.CharField(max_length=30)
# A projected coordinate system (only valid for South Texas!)
# is used, units are in meters.
point = models.PointField(srid=32140)

Then distance queries may be performed as follows:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
>>> from geoapp.models import SouthTexasCity
# Distances will be calculated from this point, which does not have to be projected.
>>> pnt = GEOSGeometry('POINT(-96.876369 29.905320)', srid=4326)
# If numeric parameter, units of field (meters in this case) are assumed.
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
# Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit)
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))

Compatibility Tables

Spatial Lookups

The following table provides a summary of what spatial lookups are available for each spatial database backend.

Lookup Type

PostGIS

Oracle

MySQL [6]

SpatiaLite

bbcontains

X

X

X

bboverlaps

X

X

X

contained

X

X

X

contains

X

X

X

X

contains_properly

X

coveredby

X

X

covers

X

X

crosses

X

X

disjoint

X

X

X

X

distance_gt

X

X

X

distance_gte

X

X

X

distance_lt

X

X

X

distance_lte

X

X

X

dwithin

X

X

equals

X

X

X

X

exact

X

X

X

X

intersects

X

X

X

X

overlaps

X

X

X

X

relate

X

X

X

same_as

X

X

X

X

touches

X

X

X

X

within

X

X

X

X

left

X

right

X

overlaps_left

X

overlaps_right

X

overlaps_above

X

overlaps_below

X

strictly_above

X

strictly_below

X

Database functions

The following table provides a summary of what geography-specific database functions are available on each spatial backend.

Function

PostGIS

Oracle

MySQL

SpatiaLite

Area

X

X

X

X

AsGeoJSON

X

X

AsGML

X

X

X

AsKML

X

X

AsSVG

X

X

BoundingCircle

X

Centroid

X

X

X

X

Difference

X

X

X

Distance

X

X

X (≥ 5.6.1)

X

Envelope

X

X

X

ForceRHR

X

GeoHash

X

Intersection

X

X

X

Length

X

X

X

X

MemSize

X

NumGeometries

X

X

X

X

NumPoints

X

X

X

X

Perimeter

X

X

X (≥ 4.0)

PointOnSurface

X

X

X

Reverse

X

X

X (≥ 4.0)

Scale

X

X

SnapToGrid

X

X (≥ 3.1)

SymDifference

X

X

X

Transform

X

X

X

Translate

X

X

Union

X

X

X (≥ 5.6.1)

X

Aggregate Functions

The following table provides a summary of what GIS-specific aggregate functions are available on each spatial backend. Please note that MySQL does not support any of these aggregates, and is thus excluded from the table.

Aggregate

PostGIS

Oracle

SpatiaLite

Collect

X

(from v3.0)

Extent

X

X

(from v3.0)

Extent3D

X

MakeLine

X

Union

X

X

X

Footnotes

[1]

See Open Geospatial Consortium, Inc., OpenGIS Simple Feature Specification For SQL, Document 99-049 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry).

[2]

See PostGIS EWKB, EWKT and Canonical Forms, PostGIS documentation at Ch. 4.1.2.

[3]

See Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, The GeoJSON Format Specification, Revision 1.0 (June 16, 2008).

[4]

See PostGIS documentation on ST_distance_sphere.

[5]

See Creating Spatial Indexes in the MySQL Reference Manual:

For MyISAM tables, SPATIAL INDEX creates an R-tree index. For storage engines that support nonspatial indexing of spatial columns, the engine creates a B-tree index. A B-tree index on spatial values will be useful for exact-value lookups, but not for range scans.

[6]

Refer MySQL Spatial Limitations section for more details.

GeoDjango Forms API

GeoDjango provides some specialized form fields and widgets in order to visually display and edit geolocalized data on a map. By default, they use OpenLayers-powered maps, with a base WMS layer provided by Metacarta.

Field arguments

In addition to the regular form field arguments, GeoDjango form fields take the following optional arguments.

srid

Field.srid

This is the SRID code that the field value should be transformed to. For example, if the map widget SRID is different from the SRID more generally used by your application or database, the field will automatically convert input values into that SRID.

geom_type

Field.geom_type

You generally shouldn’t have to set or change that attribute which should be setup depending on the field class. It matches the OpenGIS standard geometry name.

Form field classes

GeometryField

class GeometryField[source]

PointField

class PointField[source]

LineStringField

class LineStringField[source]

PolygonField

class PolygonField[source]

MultiPointField

class MultiPointField[source]

MultiLineStringField

class MultiLineStringField[source]

MultiPolygonField

class MultiPolygonField[source]

GeometryCollectionField

class GeometryCollectionField[source]

Form widgets

GeoDjango form widgets allow you to display and edit geographic data on a visual map. Note that none of the currently available widgets supports 3D geometries, hence geometry fields will fallback using a simple Textarea widget for such data.

Widget attributes

GeoDjango widgets are template-based, so their attributes are mostly different from other Django widget attributes.

BaseGeometryWidget.geom_type

The OpenGIS geometry type, generally set by the form field.

BaseGeometryWidget.map_height

BaseGeometryWidget.map_width

Height and width of the widget map (default is 400x600).

BaseGeometryWidget.map_srid

SRID code used by the map (default is 4326).

BaseGeometryWidget.display_raw

Boolean value specifying if a textarea input showing the serialized representation of the current geometry is visible, mainly for debugging purposes (default is False).

BaseGeometryWidget.supports_3d

Indicates if the widget supports edition of 3D data (default is False).

BaseGeometryWidget.template_name

The template used to render the map widget.

You can pass widget attributes in the same manner that for any other Django widget. For example:

from django.contrib.gis import forms

class MyGeoForm(forms.Form):
point = forms.PointField(widget=
forms.OSMWidget(attrs={'map_width': 800, 'map_height': 500}))

Widget classes

BaseGeometryWidget

class BaseGeometryWidget

This is an abstract base widget containing the logic needed by subclasses. You cannot directly use this widget for a geometry field. Note that the rendering of GeoDjango widgets is based on a template, identified by the template_name class attribute.

OpenLayersWidget

class OpenLayersWidget

This is the default widget used by all GeoDjango form fields. template_name is gis/openlayers.html.

OpenLayersWidget and OSMWidget use the openlayers.js file hosted on the openlayers.org website. This works for basic usage during development, but isn’t appropriate for a production deployment as openlayers.org/api/ has no guaranteed uptime and runs on a slow server. You are therefore advised to subclass these widgets in order to specify your own version of the openlayers.js file in the js property of the inner Media class (see Assets as a static definition). You can host a copy of openlayers.js tailored to your needs on your own server or refer to a copy from a content-delivery network like https://cdnjs.com/. This will also allow you to serve the JavaScript file(s) using the https protocol if needed.

OSMWidget

class OSMWidget

This widget uses an OpenStreetMap base layer (Mapnik) to display geographic objects on. template_name is gis/openlayers-osm.html.

The OpenLayersWidget note about JavaScript file hosting above also applies here. See also this FAQ answer about https access to map tiles.

GeoQuerySet API Reference

class GeoQuerySet(model=None)

Spatial Lookups

The spatial lookups in this section are available for GeometryField.

For an introduction, see the spatial lookups introduction. For an overview of what lookups are compatible with a particular spatial backend, refer to the spatial lookup compatibility table.

bbcontains

Availability: PostGIS, MySQL, SpatiaLite

Tests if the geometry field’s bounding box completely contains the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__bbcontains=geom)

Backend

SQL Equivalent

PostGIS

poly ~ geom

MySQL

MBRContains(poly, geom)

SpatiaLite

MbrContains(poly, geom)

bboverlaps

Availability: PostGIS, MySQL, SpatiaLite

Tests if the geometry field’s bounding box overlaps the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__bboverlaps=geom)

Backend

SQL Equivalent

PostGIS

poly && geom

MySQL

MBROverlaps(poly, geom)

SpatiaLite

MbrOverlaps(poly, geom)

contained

Availability: PostGIS, MySQL, SpatiaLite

Tests if the geometry field’s bounding box is completely contained by the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__contained=geom)

Backend

SQL Equivalent

PostGIS

poly @ geom

MySQL

MBRWithin(poly, geom)

SpatiaLite

MbrWithin(poly, geom)

contains

Availability: PostGIS, Oracle, MySQL, SpatiaLite

Tests if the geometry field spatially contains the lookup geometry.

Example:

Zipcode.objects.filter(poly__contains=geom)

Backend

SQL Equivalent

PostGIS

ST_Contains(poly, geom)

Oracle

SDO_CONTAINS(poly, geom)

MySQL

MBRContains(poly, geom)

SpatiaLite

Contains(poly, geom)

contains_properly

Availability: PostGIS

Returns true if the lookup geometry intersects the interior of the geometry field, but not the boundary (or exterior). [4]

Example:

Zipcode.objects.filter(poly__contains_properly=geom)

Backend

SQL Equivalent

PostGIS

ST_ContainsProperly(poly, geom)

coveredby

Availability: PostGIS, Oracle

Tests if no point in the geometry field is outside the lookup geometry. [3]

Example:

Zipcode.objects.filter(poly__coveredby=geom)

Backend

SQL Equivalent

PostGIS

ST_CoveredBy(poly, geom)

Oracle

SDO_COVEREDBY(poly, geom)

covers

Availability: PostGIS, Oracle

Tests if no point in the lookup geometry is outside the geometry field. [3]

Example:

Zipcode.objects.filter(poly__covers=geom)

Backend

SQL Equivalent

PostGIS

ST_Covers(poly, geom)

Oracle

SDO_COVERS(poly, geom)

crosses

Availability: PostGIS, SpatiaLite

Tests if the geometry field spatially crosses the lookup geometry.

Example:

Zipcode.objects.filter(poly__crosses=geom)

Backend

SQL Equivalent

PostGIS

ST_Crosses(poly, geom)

SpatiaLite

Crosses(poly, geom)

disjoint

Availability: PostGIS, Oracle, MySQL, SpatiaLite

Tests if the geometry field is spatially disjoint from the lookup geometry.

Example:

Zipcode.objects.filter(poly__disjoint=geom)

Backend

SQL Equivalent

PostGIS

ST_Disjoint(poly, geom)

Oracle

SDO_GEOM.RELATE(poly, 'DISJOINT', geom, 0.05)

MySQL

MBRDisjoint(poly, geom)

SpatiaLite

Disjoint(poly, geom)

equals

Availability: PostGIS, Oracle, MySQL, SpatiaLite

exact, same_as

Availability: PostGIS, Oracle, MySQL, SpatiaLite

intersects

Availability: PostGIS, Oracle, MySQL, SpatiaLite

Tests if the geometry field spatially intersects the lookup geometry.

Example:

Zipcode.objects.filter(poly__intersects=geom)

Backend

SQL Equivalent

PostGIS

ST_Intersects(poly, geom)

Oracle

SDO_OVERLAPBDYINTERSECT(poly, geom)

MySQL

MBRIntersects(poly, geom)

SpatiaLite

Intersects(poly, geom)

overlaps

Availability: PostGIS, Oracle, MySQL, SpatiaLite

relate

Availability: PostGIS, Oracle, SpatiaLite

Tests if the geometry field is spatially related to the lookup geometry by the values given in the given pattern. This lookup requires a tuple parameter, (geom, pattern); the form of pattern will depend on the spatial backend:

PostGIS & SpatiaLite

On these spatial backends the intersection pattern is a string comprising nine characters, which define intersections between the interior, boundary, and exterior of the geometry field and the lookup geometry. The intersection pattern matrix may only use the following characters: 1, 2, T, F, or *. This lookup type allows users to “fine tune” a specific geometric relationship consistent with the DE-9IM model. [1]

Example:

# A tuple lookup parameter is used to specify the geometry and
# the intersection pattern (the pattern here is for 'contains').
Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*'))

PostGIS SQL equivalent:

SELECT ... WHERE ST_Relate(poly, geom, 'T*T***FF*')

SpatiaLite SQL equivalent:

SELECT ... WHERE Relate(poly, geom, 'T*T***FF*')

Oracle

Here the relation pattern is comprised of at least one of the nine relation strings: TOUCH, OVERLAPBDYDISJOINT, OVERLAPBDYINTERSECT, EQUAL, INSIDE, COVEREDBY, CONTAINS, COVERS, ON, and ANYINTERACT. Multiple strings may be combined with the logical Boolean operator OR, for example, 'inside+touch'. [2] The relation strings are case-insensitive.

Example:

Zipcode.objects.filter(poly__relate=(geom, 'anyinteract'))

Oracle SQL equivalent:

SELECT ... WHERE SDO_RELATE(poly, geom, 'anyinteract')

touches

Availability: PostGIS, Oracle, MySQL, SpatiaLite

Tests if the geometry field spatially touches the lookup geometry.

Example:

Zipcode.objects.filter(poly__touches=geom)

Backend

SQL Equivalent

PostGIS

ST_Touches(poly, geom)

MySQL

MBRTouches(poly, geom)

Oracle

SDO_TOUCH(poly, geom)

SpatiaLite

Touches(poly, geom)

within

Availability: PostGIS, Oracle, MySQL, SpatiaLite

Tests if the geometry field is spatially within the lookup geometry.

Example:

Zipcode.objects.filter(poly__within=geom)

Backend

SQL Equivalent

PostGIS

ST_Within(poly, geom)

MySQL

MBRWithin(poly, geom)

Oracle

SDO_INSIDE(poly, geom)

SpatiaLite

Within(poly, geom)

left

Availability: PostGIS

Tests if the geometry field’s bounding box is strictly to the left of the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__left=geom)

PostGIS equivalent:

SELECT ... WHERE poly << geom

right

Availability: PostGIS

Tests if the geometry field’s bounding box is strictly to the right of the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__right=geom)

PostGIS equivalent:

SELECT ... WHERE poly >> geom

overlaps_left

Availability: PostGIS

Tests if the geometry field’s bounding box overlaps or is to the left of the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__overlaps_left=geom)

PostGIS equivalent:

SELECT ... WHERE poly &< geom

overlaps_right

Availability: PostGIS

Tests if the geometry field’s bounding box overlaps or is to the right of the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__overlaps_right=geom)

PostGIS equivalent:

SELECT ... WHERE poly &> geom

overlaps_above

Availability: PostGIS

Tests if the geometry field’s bounding box overlaps or is above the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__overlaps_above=geom)

PostGIS equivalent:

SELECT ... WHERE poly |&> geom

overlaps_below

Availability: PostGIS

Tests if the geometry field’s bounding box overlaps or is below the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__overlaps_below=geom)

PostGIS equivalent:

SELECT ... WHERE poly &<| geom

strictly_above

Availability: PostGIS

Tests if the geometry field’s bounding box is strictly above the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__strictly_above=geom)

PostGIS equivalent:

SELECT ... WHERE poly |>> geom

strictly_below

Availability: PostGIS

Tests if the geometry field’s bounding box is strictly below the lookup geometry’s bounding box.

Example:

Zipcode.objects.filter(poly__strictly_below=geom)

PostGIS equivalent:

SELECT ... WHERE poly <<| geom

Distance Lookups

Availability: PostGIS, Oracle, SpatiaLite

For an overview on performing distance queries, please refer to the distance queries introduction.

Distance lookups take the following form:

<field>__<distance lookup>=(<geometry>, <distance value>[, 'spheroid'])

The value passed into a distance lookup is a tuple; the first two values are mandatory, and are the geometry to calculate distances to, and a distance value (either a number in units of the field or a Distance object). On every distance lookup but dwithin, an optional third element, 'spheroid', may be included to tell GeoDjango to use the more accurate spheroid distance calculation functions on fields with a geodetic coordinate system (e.g., ST_Distance_Spheroid would be used instead of ST_Distance_Sphere). The simpler ST_Distance function is used with projected coordinate systems.

distance_gt

Returns models where the distance to the geometry field from the lookup geometry is greater than the given distance value.

Example:

Zipcode.objects.filter(poly__distance_gt=(geom, D(m=5)))

Backend

SQL Equivalent

PostGIS

ST_Distance/ST_Distance_Sphere(poly, geom) > 5

Oracle

SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) > 5

SpatiaLite

Distance(poly, geom) > 5

distance_gte

Returns models where the distance to the geometry field from the lookup geometry is greater than or equal to the given distance value.

Example:

Zipcode.objects.filter(poly__distance_gte=(geom, D(m=5)))

Backend

SQL Equivalent

PostGIS

ST_Distance/ST_Distance_Sphere(poly, geom) >= 5

Oracle

SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) >= 5

SpatiaLite

Distance(poly, geom) >= 5

distance_lt

Returns models where the distance to the geometry field from the lookup geometry is less than the given distance value.

Example:

Zipcode.objects.filter(poly__distance_lt=(geom, D(m=5)))

Backend

SQL Equivalent

PostGIS

ST_Distance/ST_Distance_Sphere(poly, geom) < 5

Oracle

SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) < 5

SpatiaLite

Distance(poly, geom) < 5

distance_lte

Returns models where the distance to the geometry field from the lookup geometry is less than or equal to the given distance value.

Example:

Zipcode.objects.filter(poly__distance_lte=(geom, D(m=5)))

Backend

SQL Equivalent

PostGIS

ST_Distance/ST_Distance_Sphere(poly, geom) <= 5

Oracle

SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) <= 5

SpatiaLite

Distance(poly, geom) <= 5

dwithin

Returns models where the distance to the geometry field from the lookup geometry are within the given distance from one another. Note that you can only provide Distance objects if the targeted geometries are in a projected system. For geographic geometries, you should use units of the geometry field (e.g. degrees for WGS84) .

Example:

Zipcode.objects.filter(poly__dwithin=(geom, D(m=5)))

Backend

SQL Equivalent

PostGIS

ST_DWithin(poly, geom, 5)

Oracle

SDO_WITHIN_DISTANCE(poly, geom, 5)

Note

This lookup is not available on SpatiaLite.

GeoQuerySet Methods

Deprecated since version 1.9: Using GeoQuerySet methods is now deprecated in favor of the new Geographic Database Functions. Albeit a little more verbose, they are much more powerful in how it is possible to combine them to build more complex queries.

GeoQuerySet methods specify that a spatial operation be performed on each spatial operation on each geographic field in the queryset and store its output in a new attribute on the model (which is generally the name of the GeoQuerySet method).

There are also aggregate GeoQuerySet methods which return a single value instead of a queryset. This section will describe the API and availability of every GeoQuerySet method available in GeoDjango.

Note

What methods are available depend on your spatial backend. See the compatibility table for more details.

With a few exceptions, the following keyword arguments may be used with all GeoQuerySet methods:

Keyword Argument

Description

field_name

By default, GeoQuerySet methods use the first geographic field encountered in the model. This keyword should be used to specify another geographic field (e.g., field_name='point2') when there are multiple geographic fields in a model.

On PostGIS, the field_name keyword may also be used on geometry fields in models that are related via a ForeignKey relation (e.g., field_name='related__point').

model_att

By default, GeoQuerySet methods typically attach their output in an attribute with the same name as the GeoQuerySet method. Setting this keyword with the desired attribute name will override this default behavior. For example, qs = Zipcode.objects.centroid(model_att='c') will attach the centroid of the Zipcode geometry field in a c attribute on every model rather than in a centroid attribute.

This keyword is required if a method name clashes with an existing GeoQuerySet method – if you wanted to use the area() method on model with a PolygonField named area, for example.

Measurement

Availability: PostGIS, Oracle, SpatiaLite

area

GeoQuerySet.area(**kwargs)

Deprecated since version 1.9: Use the Area function instead.

Returns the area of the geographic field in an area attribute on each element of this GeoQuerySet.

distance

GeoQuerySet.distance(geom, **kwargs)

Deprecated since version 1.9: Use the Distance function instead.

This method takes a geometry as a parameter, and attaches a distance attribute to every model in the returned queryset that contains the distance (as a Distance object) to the given geometry.

In the following example (taken from the GeoDjango distance tests), the distance from the Tasmanian city of Hobart to every other PointField in the AustraliaCity queryset is calculated:

>>> pnt = AustraliaCity.objects.get(name='Hobart').point
>>> for city in AustraliaCity.objects.distance(pnt): print(city.name, city.distance)
Wollongong 990071.220408 m
Shellharbour 972804.613941 m
Thirroul 1002334.36351 m
Mittagong 975691.632637 m
Batemans Bay 834342.185561 m
Canberra 598140.268959 m
Melbourne 575337.765042 m
Sydney 1056978.87363 m
Hobart 0.0 m
Adelaide 1162031.83522 m
Hillsdale 1049200.46122 m

Note

Because the distance attribute is a Distance object, you can easily express the value in the units of your choice. For example, city.distance.mi is the distance value in miles and city.distance.km is the distance value in kilometers. See Measurement Objects for usage details and the list of Supported units.

length

GeoQuerySet.length(**kwargs)

Deprecated since version 1.9: Use the Length function instead.

Returns the length of the geometry field in a length attribute (a Distance object) on each model in the queryset.

perimeter

GeoQuerySet.perimeter(**kwargs)

Deprecated since version 1.9: Use the Perimeter function instead.

Returns the perimeter of the geometry field in a perimeter attribute (a Distance object) on each model in the queryset.

Geometry Relationships

The following methods take no arguments, and attach geometry objects each element of the GeoQuerySet that is the result of relationship function evaluated on the geometry field.

centroid

GeoQuerySet.centroid(**kwargs)

Deprecated since version 1.9: Use the Centroid function instead.

Availability: PostGIS, Oracle, SpatiaLite

Returns the centroid value for the geographic field in a centroid attribute on each element of the GeoQuerySet.

envelope

GeoQuerySet.envelope(**kwargs)

Deprecated since version 1.9: Use the Envelope function instead.

Availability: PostGIS, SpatiaLite

Returns a geometry representing the bounding box of the geometry field in an envelope attribute on each element of the GeoQuerySet.

point_on_surface

GeoQuerySet.point_on_surface(**kwargs)

Deprecated since version 1.9: Use the PointOnSurface function instead.

Availability: PostGIS, Oracle, SpatiaLite

Returns a Point geometry guaranteed to lie on the surface of the geometry field in a point_on_surface attribute on each element of the queryset; otherwise sets with None.

Geometry Editors

force_rhr

GeoQuerySet.force_rhr(**kwargs)

Deprecated since version 1.9: Use the ForceRHR function instead.

Availability: PostGIS

Returns a modified version of the polygon/multipolygon in which all of the vertices follow the Right-Hand-Rule, and attaches as a force_rhr attribute on each element of the queryset.

reverse_geom

GeoQuerySet.reverse_geom(**kwargs)

Deprecated since version 1.9: Use the Reverse function instead.

Availability: PostGIS, Oracle

Reverse the coordinate order of the geometry field, and attaches as a reverse attribute on each element of the queryset.

scale

GeoQuerySet.scale(x, y, z=0.0, **kwargs)

Deprecated since version 1.9: Use the Scale function instead.

Availability: PostGIS, SpatiaLite

snap_to_grid

GeoQuerySet.snap_to_grid(*args, **kwargs)

Deprecated since version 1.9: Use the SnapToGrid function instead.

Snap all points of the input geometry to the grid. How the geometry is snapped to the grid depends on how many numeric (either float, integer, or long) arguments are given.

Number of Arguments

Description

1

A single size to snap bot the X and Y grids to.

2

X and Y sizes to snap the grid to.

4

X, Y sizes and the corresponding X, Y origins.

transform

GeoQuerySet.transform(srid=4326, **kwargs)

Deprecated since version 1.9: Use the Transform function instead.

Availability: PostGIS, Oracle, SpatiaLite

The transform method transforms the geometry field of a model to the spatial reference system specified by the srid parameter. If no srid is given, then 4326 (WGS84) is used by default.

Note

Unlike other GeoQuerySet methods, transform stores its output “in-place”. In other words, no new attribute for the transformed geometry is placed on the models.

Note

What spatial reference system an integer SRID corresponds to may depend on the spatial database used. In other words, the SRID numbers used for Oracle are not necessarily the same as those used by PostGIS.

Example:

>>> qs = Zipcode.objects.all().transform() # Transforms to WGS84
>>> qs = Zipcode.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central"
>>> print(qs[0].poly.srid)
32140
>>> print(qs[0].poly)
POLYGON ((234055.1698884720099159 4937796.9232223574072123 ...

translate

GeoQuerySet.translate(x, y, z=0.0, **kwargs)

Deprecated since version 1.9: Use the Translate function instead.

Availability: PostGIS, SpatiaLite

Translates the geometry field to a new location using the given numeric parameters as offsets.

Geometry Operations

Availability: PostGIS, Oracle, SpatiaLite

The following methods all take a geometry as a parameter and attach a geometry to each element of the GeoQuerySet that is the result of the operation.

difference

GeoQuerySet.difference(geom)

Deprecated since version 1.9: Use the Difference function instead.

Returns the spatial difference of the geographic field with the given geometry in a difference attribute on each element of the GeoQuerySet.

intersection

GeoQuerySet.intersection(geom)

Deprecated since version 1.9: Use the Intersection function instead.

Returns the spatial intersection of the geographic field with the given geometry in an intersection attribute on each element of the GeoQuerySet.

sym_difference

GeoQuerySet.sym_difference(geom)

Deprecated since version 1.9: Use the SymDifference function instead.

Returns the symmetric difference of the geographic field with the given geometry in a sym_difference attribute on each element of the GeoQuerySet.

union

GeoQuerySet.union(geom)

Deprecated since version 1.9: Use the Union function instead.

Returns the union of the geographic field with the given geometry in an union attribute on each element of the GeoQuerySet.

Geometry Output

The following GeoQuerySet methods will return an attribute that has the value of the geometry field in each model converted to the requested output format.

geohash

GeoQuerySet.geohash(precision=20, **kwargs)

Deprecated since version 1.9: Use the GeoHash function instead.

Attaches a geohash attribute to every model the queryset containing the GeoHash representation of the geometry.

geojson

GeoQuerySet.geojson(**kwargs)

Deprecated since version 1.9: Use the AsGeoJSON function instead.

Availability: PostGIS, SpatiaLite

Attaches a geojson attribute to every model in the queryset that contains the GeoJSON representation of the geometry.

Keyword Argument

Description

precision

It may be used to specify the number of significant digits for the coordinates in the GeoJSON representation – the default value is 8.

crs

Set this to True if you want the coordinate reference system to be included in the returned GeoJSON.

bbox

Set this to True if you want the bounding box to be included in the returned GeoJSON.

gml

GeoQuerySet.gml(**kwargs)

Deprecated since version 1.9: Use the AsGML function instead.

Availability: PostGIS, Oracle, SpatiaLite

Attaches a gml attribute to every model in the queryset that contains the Geographic Markup Language (GML) representation of the geometry.

Example:

>>> qs = Zipcode.objects.all().gml()
>>> print(qs[0].gml)
<gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ...  -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon>

Keyword Argument

Description

precision

This keyword is for PostGIS only. It may be used to specify the number of significant digits for the coordinates in the GML representation – the default value is 8.

version

This keyword is for PostGIS only. It may be used to specify the GML version used, and may only be values of 2 or 3. The default value is 2.

kml

GeoQuerySet.kml(**kwargs)

Deprecated since version 1.9: Use the AsKML function instead.

Availability: PostGIS, SpatiaLite

Attaches a kml attribute to every model in the queryset that contains the Keyhole Markup Language (KML) representation of the geometry fields. It should be noted that the contents of the KML are transformed to WGS84 if necessary.

Example:

>>> qs = Zipcode.objects.all().kml()
>>> print(qs[0].kml)
<Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ... -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon>

Keyword Argument

Description

precision

This keyword may be used to specify the number of significant digits for the coordinates in the KML representation – the default value is 8.

svg

GeoQuerySet.svg(**kwargs)

Deprecated since version 1.9: Use the AsSVG function instead.

Availability: PostGIS, SpatiaLite

Attaches a svg attribute to every model in the queryset that contains the Scalable Vector Graphics (SVG) path data of the geometry fields.

Keyword Argument

Description

relative

If set to True, the path data will be implemented in terms of relative moves. Defaults to False, meaning that absolute moves are used instead.

precision

This keyword may be used to specify the number of significant digits for the coordinates in the SVG representation – the default value is 8.

Miscellaneous

mem_size

GeoQuerySet.mem_size(**kwargs)

Deprecated since version 1.9: Use the MemSize function instead.

Availability: PostGIS

Returns the memory size (number of bytes) that the geometry field takes in a mem_size attribute on each element of the GeoQuerySet.

num_geom

GeoQuerySet.num_geom(**kwargs)

Deprecated since version 1.9: Use the NumGeometries function instead.

Availability: PostGIS, Oracle, SpatiaLite

Returns the number of geometries in a num_geom attribute on each element of the GeoQuerySet if the geometry field is a collection (e.g., a GEOMETRYCOLLECTION or MULTI* field); otherwise sets with None.

num_points

GeoQuerySet.num_points(**kwargs)

Deprecated since version 1.9: Use the NumPoints function instead.

Availability: PostGIS, Oracle, SpatiaLite

Returns the number of points in the first linestring in the geometry field in a num_points attribute on each element of the GeoQuerySet; otherwise sets with None.

Spatial Aggregates

Aggregate Methods

Deprecated since version 1.8: Aggregate methods are now deprecated. Prefer using their function-based equivalents.

collect

GeoQuerySet.collect(**kwargs)

Deprecated since version 1.8: Use the Collect aggregate instead.

Shortcut for aggregate(Collect(<field>)).

extent

GeoQuerySet.extent(**kwargs)

Deprecated since version 1.8: Use the Extent aggregate instead.

Shortcut for aggregate(Extent(<field>)).

extent3d

GeoQuerySet.extent3d(**kwargs)

Deprecated since version 1.8: Use the Extent aggregate instead.

Shortcut for aggregate(Extent3D(<field>)).

make_line

GeoQuerySet.make_line(**kwargs)

Deprecated since version 1.8: Use the MakeLine aggregate instead.

Shortcut for aggregate(MakeLine(<field>)).

unionagg

GeoQuerySet.unionagg(**kwargs)

Deprecated since version 1.8: Use the Union aggregate instead.

Shortcut for aggregate(Union(<field>)).

Aggregate Functions

Django provides some GIS-specific aggregate functions. For details on how to use these aggregate functions, see the topic guide on aggregation.

Keyword Argument

Description

tolerance

This keyword is for Oracle only. It is for the tolerance value used by the SDOAGGRTYPE procedure; the Oracle documentation has more details.

Example:

>>> from django.contrib.gis.db.models import Extent, Union
>>> WorldBorder.objects.aggregate(Extent('mpoly'), Union('mpoly'))

Collect

class Collect(geo_field)

Availability: PostGIS, Spatialite (≥3.0)

Returns a GEOMETRYCOLLECTION or a MULTI geometry object from the geometry column. This is analogous to a simplified version of the Union aggregate, except it can be several orders of magnitude faster than performing a union because it simply rolls up geometries into a collection or multi object, not caring about dissolving boundaries.

Extent

class Extent(geo_field)

Availability: PostGIS, Oracle, Spatialite (≥3.0)

Returns the extent of all geo_field in the QuerySet as a four-tuple, comprising the lower left coordinate and the upper right coordinate.

Example:

>>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(Extent('poly'))
>>> print(qs['poly__extent'])
(-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)

Extent3D

class Extent3D(geo_field)

Availability: PostGIS

Returns the 3D extent of all geo_field in the QuerySet as a six-tuple, comprising the lower left coordinate and upper right coordinate (each with x, y, and z coordinates).

Example:

>>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(Extent3D('poly'))
>>> print(qs['poly__extent3d'])
(-96.8016128540039, 29.7633724212646, 0, -95.3631439208984, 32.782058715820, 0)

MakeLine

class MakeLine(geo_field)

Availability: PostGIS

Returns a LineString constructed from the point field geometries in the QuerySet. Currently, ordering the queryset has no effect.

Example:

>>> print(City.objects.filter(name__in=('Houston', 'Dallas')
...      ).aggregate(MakeLine('poly'))['poly__makeline']
LINESTRING (-95.3631510000000020 29.7633739999999989, -96.8016109999999941 32.7820570000000018)

Union

class Union(geo_field)

Availability: PostGIS, Oracle, SpatiaLite

This method returns a GEOSGeometry object comprising the union of every geometry in the queryset. Please note that use of Union is processor intensive and may take a significant amount of time on large querysets.

Note

If the computation time for using this method is too expensive, consider using Collect instead.

Example:

>>> u = Zipcode.objects.aggregate(Union(poly))  # This may take a long time.
>>> u = Zipcode.objects.filter(poly__within=bbox).aggregate(Union(poly))  # A more sensible approach.

Footnotes

[1]

See OpenGIS Simple Feature Specification For SQL, at Ch. 2.1.13.2, p. 2-13 (The Dimensionally Extended Nine-Intersection Model).

[2]

See SDO_RELATE documentation, from Ch. 11 of the Oracle Spatial User’s Guide and Manual.

[3]

(1, 2) For an explanation of this routine, read Quirks of the “Contains” Spatial Predicate by Martin Davis (a PostGIS developer).

[4]

Refer to the PostGIS ST_ContainsProperly documentation for more details.

Geographic Database Functions

New in Django 1.9.

The functions documented on this page allow users to access geographic database functions to be used in annotations, aggregations, or filters in Django.

Example:

>>> from django.contrib.gis.db.models.functions import Length
>>> Track.objects.annotate(length=Length('line')).filter(length__gt=100)

Not all backends support all functions, so refer to the documentation of each function to see if your database backend supports the function you want to use. If you call a geographic function on a backend that doesn’t support it, you’ll get a NotImplementedError exception.

Function’s summary:

Measurement

Relationships

Operations

Editors

Output format

Miscellaneous

Area

BoundingCircle

Difference

ForceRHR

AsGeoJSON

MemSize

Distance

Centroid

Intersection

Reverse

AsGML

NumGeometries

Length

Envelope

SymDifference

Scale

AsKML

NumPoints

Perimeter

PointOnSurface

Union

SnapToGrid

Transform

Translate

AsSVG

GeoHash

Area

class Area(expression, **extra)

Availability: MySQL, Oracle, PostGIS, SpatiaLite

Accepts a single geographic field or expression and returns the area of the field as an Area measure. On MySQL, a raw float value is returned, as it’s not possible to automatically determine the unit of the field.

AsGeoJSON

class AsGeoJSON(expression, bbox=False, crs=False, precision=8, **extra)

Availability: PostGIS, SpatiaLite (≥ 3.0)

Accepts a single geographic field or expression and returns a GeoJSON representation of the geometry. Note that the result is not a complete GeoJSON structure but only the geometry key content of a GeoJSON structure. See also GeoJSON Serializer.

Example:

>>> City.objects.annotate(json=AsGeoJSON('point')).get(name='Chicago').json
{"type":"Point","coordinates":[-87.65018,41.85039]}

Keyword Argument

Description

bbox

Set this to True if you want the bounding box to be included in the returned GeoJSON.

crs

Set this to True if you want the coordinate reference system to be included in the returned GeoJSON.

precision

It may be used to specify the number of significant digits for the coordinates in the GeoJSON representation – the default value is 8.

AsGML

class AsGML(expression, version=2, precision=8, **extra)

Availability: Oracle, PostGIS, SpatiaLite (≥ 2.4.0-RC4)

Accepts a single geographic field or expression and returns a Geographic Markup Language (GML) representation of the geometry.

Example:

>>> qs = Zipcode.objects.annotate(gml=AsGML('poly'))
>>> print(qs[0].gml)
<gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ...
-147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon>

Keyword Argument

Description

precision

Not used on Oracle. It may be used to specify the number of significant digits for the coordinates in the GML representation – the default value is 8.

version

Not used on Oracle. It may be used to specify the GML version used, and may only be values of 2 or 3. The default value is 2.

AsKML

class AsKML(expression, precision=8, **extra)

Availability: PostGIS, SpatiaLite (≥ 2.4.0-RC4)

Accepts a single geographic field or expression and returns a Keyhole Markup Language (KML) representation of the geometry.

Example:

>>> qs = Zipcode.objects.annotate(kml=AsKML('poly'))
>>> print(qs[0].kml)
<Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ...
-103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon>

Keyword Argument

Description

precision

This keyword may be used to specify the number of significant digits for the coordinates in the KML representation – the default value is 8.

AsSVG

class AsSVG(expression, relative=False, precision=8, **extra)

Availability: PostGIS, SpatiaLite

Accepts a single geographic field or expression and returns a Scalable Vector Graphics (SVG) representation of the geometry.

Keyword Argument

Description

relative

If set to True, the path data will be implemented in terms of relative moves. Defaults to False, meaning that absolute moves are used instead.

precision

This keyword may be used to specify the number of significant digits for the coordinates in the SVG representation – the default value is 8.

BoundingCircle

class BoundingCircle(expression, num_seg=48, **extra)

Availability: PostGIS

Accepts a single geographic field or expression and returns the smallest circle polygon that can fully contain the geometry.

Centroid

class Centroid(expression, **extra)

Availability: MySQL, PostGIS, Oracle, SpatiaLite

Accepts a single geographic field or expression and returns the centroid value of the geometry.

Difference

class Difference(expr1, expr2, **extra)

Availability: PostGIS, Oracle, SpatiaLite

Accepts two geographic fields or expressions and returns the geometric difference, that is the part of geometry A that does not intersect with geometry B.

Distance

class Distance(expr1, expr2, spheroid=None, **extra)

Availability: MySQL (≥ 5.6.1), PostGIS, Oracle, SpatiaLite

Accepts two geographic fields or expressions and returns the distance between them, as a Distance object. On MySQL, a raw float value is returned, as it’s not possible to automatically determine the unit of the field.

On backends that support distance calculation on geodetic coordinates, the proper backend function is automatically chosen depending on the SRID value of the geometries (e.g. ST_Distance_Sphere on PostGIS).

When distances are calculated with geodetic (angular) coordinates, as is the case with the default WGS84 (4326) SRID, you can set the spheroid keyword argument to decide if the calculation should be based on a simple sphere (less accurate, less resource-intensive) or on a spheroid (more accurate, more resource-intensive).

In the following example, the distance from the city of Hobart to every other PointField in the AustraliaCity queryset is calculated:

>>> from django.contrib.gis.db.models.functions import Distance
>>> pnt = AustraliaCity.objects.get(name='Hobart').point
>>> for city in AustraliaCity.objects.annotate(distance=Distance('point', pnt)):
...     print(city.name, city.distance)
Wollongong 990071.220408 m
Shellharbour 972804.613941 m
Thirroul 1002334.36351 m
...

Note

Because the distance attribute is a Distance object, you can easily express the value in the units of your choice. For example, city.distance.mi is the distance value in miles and city.distance.km is the distance value in kilometers. See Measurement Objects for usage details and the list of Supported units.

Envelope

class Envelope(expression, **extra)

Availability: MySQL, PostGIS, SpatiaLite

Accepts a single geographic field or expression and returns the geometry representing the bounding box of the geometry.

ForceRHR

class ForceRHR(expression, **extra)

Availability: PostGIS

Accepts a single geographic field or expression and returns a modified version of the polygon/multipolygon in which all of the vertices follow the right-hand rule.

GeoHash

class GeoHash(expression, **extra)

Availability: PostGIS

Accepts a single geographic field or expression and returns a GeoHash representation of the geometry.

Intersection

class Intersection(expr1, expr2, **extra)

Availability: PostGIS, Oracle, SpatiaLite

Accepts two geographic fields or expressions and returns the geometric intersection between them.

Length

class Length(expression, spheroid=True, **extra)

Availability: MySQL, Oracle, PostGIS, SpatiaLite

Accepts a single geographic linestring or multilinestring field or expression and returns its length as an Distance measure. On MySQL, a raw float value is returned, as it’s not possible to automatically determine the unit of the field.

On PostGIS and SpatiaLite, when the coordinates are geodetic (angular), you can specify if the calculation should be based on a simple sphere (less accurate, less resource-intensive) or on a spheroid (more accurate, more resource-intensive) with the spheroid keyword argument.

MemSize

class MemSize(expression, **extra)

Availability: PostGIS

Accepts a single geographic field or expression and returns the memory size (number of bytes) that the geometry field takes.

NumGeometries

class NumGeometries(expression, **extra)

Availability: MySQL, PostGIS, Oracle, SpatiaLite

Accepts a single geographic field or expression and returns the number of geometries if the geometry field is a collection (e.g., a GEOMETRYCOLLECTION or MULTI* field); otherwise returns None.

NumPoints

class NumPoints(expression, **extra)

Availability: MySQL, PostGIS, Oracle, SpatiaLite

Accepts a single geographic field or expression and returns the number of points in the first linestring in the geometry field; otherwise returns None.

Perimeter

class Perimeter(expression, **extra)

Availability: PostGIS, Oracle, SpatiaLite (≥ 4.0)

Accepts a single geographic field or expression and returns the perimeter of the geometry field as a Distance object. On MySQL, a raw float value is returned, as it’s not possible to automatically determine the unit of the field.

PointOnSurface

class PointOnSurface(expression, **extra)

Availability: PostGIS, Oracle, SpatiaLite

Accepts a single geographic field or expression and returns a Point geometry guaranteed to lie on the surface of the field; otherwise returns None.

Reverse

class Reverse(expression, **extra)

Availability: PostGIS, Oracle, SpatiaLite (≥ 4.0)

Accepts a single geographic field or expression and returns a geometry with reversed coordinates.

Scale

class Scale(expression, x, y, z=0.0, **extra)

Availability: PostGIS, SpatiaLite

Accepts a single geographic field or expression and returns a geometry with scaled coordinates by multiplying them with the x, y, and optionally z parameters.

SnapToGrid

class SnapToGrid(expression, *args, **extra)

Availability: PostGIS, SpatiaLite (≥ 3.1)

Accepts a single geographic field or expression and returns a geometry with all points snapped to the given grid. How the geometry is snapped to the grid depends on how many numeric (either float, integer, or long) arguments are given.

Number of Arguments

Description

1

A single size to snap both the X and Y grids to.

2

X and Y sizes to snap the grid to.

4

X, Y sizes and the corresponding X, Y origins.

SymDifference

class SymDifference(expr1, expr2, **extra)

Availability: PostGIS, Oracle, SpatiaLite

Accepts two geographic fields or expressions and returns the geometric symmetric difference (union without the intersection) between the given parameters.

Transform

class Transform(expression, srid, **extra)

Availability: PostGIS, Oracle, SpatiaLite

Accepts a geographic field or expression and a SRID integer code, and returns the transformed geometry to the spatial reference system specified by the srid parameter.

Note

What spatial reference system an integer SRID corresponds to may depend on the spatial database used. In other words, the SRID numbers used for Oracle are not necessarily the same as those used by PostGIS.

Translate

class Translate(expression, x, y, z=0.0, **extra)

Availability: PostGIS, SpatiaLite

Accepts a single geographic field or expression and returns a geometry with its coordinates offset by the x, y, and optionally z numeric parameters.

Union

class Union(expr1, expr2, **extra)

Availability: MySQL (≥ 5.6.1), PostGIS, Oracle, SpatiaLite

Accepts two geographic fields or expressions and returns the union of both geometries.

Measurement Objects

The django.contrib.gis.measure module contains objects that allow for convenient representation of distance and area units of measure. [1] Specifically, it implements two objects, Distance and Area – both of which may be accessed via the D and A convenience aliases, respectively.

Example

Distance objects may be instantiated using a keyword argument indicating the context of the units. In the example below, two different distance objects are instantiated in units of kilometers (km) and miles (mi):

>>> from django.contrib.gis.measure import Distance, D
>>> d1 = Distance(km=5)
>>> print(d1)
5.0 km
>>> d2 = D(mi=5) # `D` is an alias for `Distance`
>>> print(d2)
5.0 mi

Conversions are easy, just access the preferred unit attribute to get a converted distance quantity:

>>> print(d1.mi) # Converting 5 kilometers to miles
3.10685596119
>>> print(d2.km) # Converting 5 miles to kilometers
8.04672

Moreover, arithmetic operations may be performed between the distance objects:

>>> print(d1 + d2) # Adding 5 miles to 5 kilometers
13.04672 km
>>> print(d2 - d1) # Subtracting 5 kilometers from 5 miles
1.89314403881 mi

Two Distance objects multiplied together will yield an Area object, which uses squared units of measure:

>>> a = d1 * d2 # Returns an Area object.
>>> print(a)
40.2336 sq_km

To determine what the attribute abbreviation of a unit is, the unit_attname class method may be used:

>>> print(Distance.unit_attname('US Survey Foot'))
survey_ft
>>> print(Distance.unit_attname('centimeter'))
cm

Supported units

Unit Attribute

Full name or alias(es)

km

Kilometre, Kilometer

mi

Mile

m

Meter, Metre

yd

Yard

ft

Foot, Foot (International)

survey_ft

U.S. Foot, US survey foot

inch

Inches

cm

Centimeter

mm

Millimetre, Millimeter

um

Micrometer, Micrometre

british_ft

British foot (Sears 1922)

british_yd

British yard (Sears 1922)

british_chain_sears

British chain (Sears 1922)

indian_yd

Indian yard, Yard (Indian)

sears_yd

Yard (Sears)

clarke_ft

Clarke’s Foot

chain

Chain

chain_benoit

Chain (Benoit)

chain_sears

Chain (Sears)

british_chain_benoit

British chain (Benoit 1895 B)

british_chain_sears_truncated

British chain (Sears 1922 truncated)

gold_coast_ft

Gold Coast foot

link

Link

link_benoit

Link (Benoit)

link_sears

Link (Sears)

clarke_link

Clarke’s link

fathom

Fathom

rod

Rod

nm

Nautical Mile

nm_uk

Nautical Mile (UK)

german_m

German legal metre

Note

Area attributes are the same as Distance attributes, except they are prefixed with sq_ (area units are square in nature). For example, Area(sq_m=2) creates an Area object representing two square meters.

Measurement API

Distance

class Distance(**kwargs)[source]

To initialize a distance object, pass in a keyword corresponding to the desired unit attribute name set with desired value. For example, the following creates a distance object representing 5 miles:

>>> dist = Distance(mi=5)

__getattr__(unit_att)

Returns the distance value in units corresponding to the given unit attribute. For example:

>>> print(dist.km)
8.04672

classmethod unit_attname(unit_name)

Returns the distance unit attribute name for the given full unit name. For example:

>>> Distance.unit_attname('Mile')
'mi'

class D

Alias for Distance class.

Area

class Area(**kwargs)[source]

To initialize an area object, pass in a keyword corresponding to the desired unit attribute name set with desired value. For example, the following creates an area object representing 5 square miles:

>>> a = Area(sq_mi=5)

__getattr__(unit_att)

Returns the area value in units corresponding to the given unit attribute. For example:

>>> print(a.sq_km)
12.949940551680001

classmethod unit_attname(unit_name)

Returns the area unit attribute name for the given full unit name. For example:

>>> Area.unit_attname('Kilometer')
'sq_km'

class A

Alias for Area class.

Footnotes

[1]

Robert Coup is the initial author of the measure objects, and was inspired by Brian Beck’s work in geopy and Geoff Biggs’ PhD work on dimensioned units for robotics.

GEOS API

Background

What is GEOS?

GEOS stands for Geometry Engine - Open Source, and is a C++ library, ported from the Java Topology Suite. GEOS implements the OpenGIS Simple Features for SQL spatial predicate functions and spatial operators. GEOS, now an OSGeo project, was initially developed and maintained by Refractions Research of Victoria, Canada.

Features

GeoDjango implements a high-level Python wrapper for the GEOS library, its features include:

- A BSD-licensed interface to the GEOS geometry routines, implemented purely in Python using ctypes.

- Loosely-coupled to GeoDjango. For example, GEOSGeometry objects may be used outside of a Django project/application. In other words, no need to have DJANGO_SETTINGS_MODULE set or use a database, etc.

- Mutability: GEOSGeometry objects may be modified.

- Cross-platform and tested; compatible with Windows, Linux, Solaris, and Mac OS X platforms.

Tutorial

This section contains a brief introduction and tutorial to using GEOSGeometry objects.

Creating a Geometry

GEOSGeometry objects may be created in a few ways. The first is to simply instantiate the object on some spatial input – the following are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> pnt = GEOSGeometry('POINT(5 23)') # WKT
>>> pnt = GEOSGeometry('010100000000000000000014400000000000003740') # HEX
>>> pnt = GEOSGeometry(buffer('\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@'))
>>> pnt = GEOSGeometry('{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }') # GeoJSON

Another option is to use the constructor for the specific geometry type that you wish to create. For example, a Point object may be created by passing in the X and Y coordinates into its constructor:

>>> from django.contrib.gis.geos import Point
>>> pnt = Point(5, 23)

All these constructors take the keyword argument srid. For example:

>>> from django.contrib.gis.geos import GEOSGeometry, LineString, Point
>>> print(GEOSGeometry('POINT (0 0)', srid=4326))
SRID=4326;POINT (0.0000000000000000 0.0000000000000000)
>>> print(LineString((0, 0), (1, 1), srid=4326))
SRID=4326;LINESTRING (0.0000000000000000 0.0000000000000000, 1.0000000000000000 1.0000000000000000)
>>> print(Point(0, 0, srid=32140))
SRID=32140;POINT (0.0000000000000000 0.0000000000000000)

Finally, there is the fromfile() factory method which returns a GEOSGeometry object from a file:

>>> from django.contrib.gis.geos import fromfile
>>> pnt = fromfile('/path/to/pnt.wkt')
>>> pnt = fromfile(open('/path/to/pnt.wkt'))

My logs are filled with GEOS-related errors

You find many TypeError or AttributeError exceptions filling your Web server’s log files. This generally means that you are creating GEOS objects at the top level of some of your Python modules. Then, due to a race condition in the garbage collector, your module is garbage collected before the GEOS object. To prevent this, create GEOSGeometry objects inside the local scope of your functions/methods.

Geometries are Pythonic

GEOSGeometry objects are ‘Pythonic’, in other words components may be accessed, modified, and iterated over using standard Python conventions. For example, you can iterate over the coordinates in a Point:

>>> pnt = Point(5, 23)
>>> [coord for coord in pnt]
[5.0, 23.0]

With any geometry object, the GEOSGeometry.coords property may be used to get the geometry coordinates as a Python tuple:

>>> pnt.coords
(5.0, 23.0)

You can get/set geometry components using standard Python indexing techniques. However, what is returned depends on the geometry type of the object. For example, indexing on a LineString returns a coordinate tuple:

>>> from django.contrib.gis.geos import LineString
>>> line = LineString((0, 0), (0, 50), (50, 50), (50, 0), (0, 0))
>>> line[0]
(0.0, 0.0)
>>> line[-2]
(50.0, 0.0)

Whereas indexing on a Polygon will return the ring (a LinearRing object) corresponding to the index:

>>> from django.contrib.gis.geos import Polygon
>>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) )
>>> poly[0]
<LinearRing object at 0x1044395b0>
>>> poly[0][-2] # second-to-last coordinate of external ring
(50.0, 0.0)

In addition, coordinates/components of the geometry may added or modified, just like a Python list:

>>> line[0] = (1.0, 1.0)
>>> line.pop()
(0.0, 0.0)
>>> line.append((1.0, 1.0))
>>> line.coords
((1.0, 1.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (1.0, 1.0))

Geometries support set-like operators:

>>> from django.contrib.gis.geos import LineString
>>> ls1 = LineString((0, 0), (2, 2))
>>> ls2 = LineString((1, 1), (3, 3))
>>> print(ls1 | ls2)  # equivalent to `ls1.union(ls2)`
MULTILINESTRING ((0 0, 1 1), (1 1, 2 2), (2 2, 3 3))
>>> print(ls1 & ls2)  # equivalent to `ls1.intersection(ls2)`
LINESTRING (1 1, 2 2)
>>> print(ls1 - ls2)  # equivalent to `ls1.difference(ls2)`
LINESTRING(0 0, 1 1)
>>> print(ls1 ^ ls2)  # equivalent to `ls1.sym_difference(ls2)`
MULTILINESTRING ((0 0, 1 1), (2 2, 3 3))

Equality operator doesn’t check spatial equality

The GEOSGeometry equality operator uses equals_exact(), not equals(), i.e. it requires the compared geometries to have the same coordinates in the same positions:

>>> from django.contrib.gis.geos import LineString
>>> ls1 = LineString((0, 0), (1, 1))
>>> ls2 = LineString((1, 1), (0, 0))
>>> ls1.equals(ls2)
True
>>> ls1 == ls2
False

Geometry Objects

GEOSGeometry

class GEOSGeometry(geo_input, srid=None)[source]

Parameters:

- geo_input – Geometry input value (string or buffer)

- srid (int) – spatial reference identifier

This is the base class for all GEOS geometry objects. It initializes on the given geo_input argument, and then assumes the proper geometry subclass (e.g., GEOSGeometry('POINT(1 1)') will create a Point object).

The following input formats, along with their corresponding Python types, are accepted:

Format

Input Type

WKT / EWKT

str or unicode

HEX / HEXEWKB

str or unicode

WKB / EWKB

buffer

GeoJSON (requires GDAL)

str or unicode

Note

The new 3D/4D WKT notation with an intermediary Z or M (like POINT Z (3, 4, 5)) is only supported with GEOS 3.3.0 or later.

Properties

GEOSGeometry.coords

Returns the coordinates of the geometry as a tuple.

GEOSGeometry.dims

Returns the dimension of the geometry:

- 0 for Points and MultiPoints

- 1 for LineStrings and MultiLineStrings

- 2 for Polygons and MultiPolygons

- -1 for empty GeometryCollections

- the maximum dimension of its elements for non-empty GeometryCollections

GEOSGeometry.empty

Returns whether or not the set of points in the geometry is empty.

GEOSGeometry.geom_type

Returns a string corresponding to the type of geometry. For example:

>>> pnt = GEOSGeometry('POINT(5 23)')
>>> pnt.geom_type
'Point'

GEOSGeometry.geom_typeid

Returns the GEOS geometry type identification number. The following table shows the value for each geometry type:

Geometry

ID

Point

0

LineString

1

LinearRing

2

Polygon

3

MultiPoint

4

MultiLineString

5

MultiPolygon

6

GeometryCollection

7

GEOSGeometry.num_coords

Returns the number of coordinates in the geometry.

GEOSGeometry.num_geom

Returns the number of geometries in this geometry. In other words, will return 1 on anything but geometry collections.

GEOSGeometry.hasz

Returns a boolean indicating whether the geometry is three-dimensional.

GEOSGeometry.ring

Returns a boolean indicating whether the geometry is a LinearRing.

GEOSGeometry.simple

Returns a boolean indicating whether the geometry is ‘simple’. A geometry is simple if and only if it does not intersect itself (except at boundary points). For example, a LineString object is not simple if it intersects itself. Thus, LinearRing and Polygon objects are always simple because they do cannot intersect themselves, by definition.

GEOSGeometry.valid

Returns a boolean indicating whether the geometry is valid.

GEOSGeometry.valid_reason

Returns a string describing the reason why a geometry is invalid.

GEOSGeometry.srid

Property that may be used to retrieve or set the SRID associated with the geometry. For example:

>>> pnt = Point(5, 23)
>>> print(pnt.srid)
None
>>> pnt.srid = 4326
>>> pnt.srid
4326

Output Properties

The properties in this section export the GEOSGeometry object into a different. This output may be in the form of a string, buffer, or even another object.

GEOSGeometry.ewkt

Returns the “extended” Well-Known Text of the geometry. This representation is specific to PostGIS and is a superset of the OGC WKT standard. [1] Essentially the SRID is prepended to the WKT representation, for example SRID=4326;POINT(5 23).

Note

The output from this property does not include the 3dm, 3dz, and 4d information that PostGIS supports in its EWKT representations.

GEOSGeometry.hex

Returns the WKB of this Geometry in hexadecimal form. Please note that the SRID value is not included in this representation because it is not a part of the OGC specification (use the GEOSGeometry.hexewkb property instead).

GEOSGeometry.hexewkb

Returns the EWKB of this Geometry in hexadecimal form. This is an extension of the WKB specification that includes the SRID value that are a part of this geometry.

GEOSGeometry.json

Returns the GeoJSON representation of the geometry. Note that the result is not a complete GeoJSON structure but only the geometry key content of a GeoJSON structure. See also GeoJSON Serializer.

GEOSGeometry.geojson

Alias for GEOSGeometry.json.

GEOSGeometry.kml

Returns a KML (Keyhole Markup Language) representation of the geometry. This should only be used for geometries with an SRID of 4326 (WGS84), but this restriction is not enforced.

GEOSGeometry.ogr

Returns an OGRGeometry object corresponding to the GEOS geometry.

Note

Requires GDAL.

GEOSGeometry.wkb

Returns the WKB (Well-Known Binary) representation of this Geometry as a Python buffer. SRID value is not included, use the GEOSGeometry.ewkb property instead.

GEOSGeometry.ewkb

Return the EWKB representation of this Geometry as a Python buffer. This is an extension of the WKB specification that includes any SRID value that are a part of this geometry.

GEOSGeometry.wkt

Returns the Well-Known Text of the geometry (an OGC standard).

Spatial Predicate Methods

All of the following spatial predicate methods take another GEOSGeometry instance (other) as a parameter, and return a boolean.

GEOSGeometry.contains(other)[source]

Returns True if other.within(this) returns True.

GEOSGeometry.crosses(other)[source]

Returns True if the DE-9IM intersection matrix for the two Geometries is T*T****** (for a point and a curve,a point and an area or a line and an area) 0******** (for two curves).

GEOSGeometry.disjoint(other)[source]

Returns True if the DE-9IM intersection matrix for the two geometries is FF*FF****.

GEOSGeometry.equals(other)[source]

Returns True if the DE-9IM intersection matrix for the two geometries is T*F**FFF*.

GEOSGeometry.equals_exact(other, tolerance=0)[source]

Returns true if the two geometries are exactly equal, up to a specified tolerance. The tolerance value should be a floating point number representing the error tolerance in the comparison, e.g., poly1.equals_exact(poly2, 0.001) will compare equality to within one thousandth of a unit.

GEOSGeometry.intersects(other)[source]

Returns True if GEOSGeometry.disjoint() is False.

GEOSGeometry.overlaps(other)[source]

Returns true if the DE-9IM intersection matrix for the two geometries is T*T***T** (for two points or two surfaces) 1*T***T** (for two curves).

GEOSGeometry.relate_pattern(other, pattern)[source]

Returns True if the elements in the DE-9IM intersection matrix for this geometry and the other matches the given pattern – a string of nine characters from the alphabet: {T, F, *, 0}.

GEOSGeometry.touches(other)[source]

Returns True if the DE-9IM intersection matrix for the two geometries is FT*******, F**T***** or F***T****.

GEOSGeometry.within(other)[source]

Returns True if the DE-9IM intersection matrix for the two geometries is T*F**F***.

Topological Methods

GEOSGeometry.buffer(width, quadsegs=8)[source]

Returns a GEOSGeometry that represents all points whose distance from this geometry is less than or equal to the given width. The optional quadsegs keyword sets the number of segments used to approximate a quarter circle (defaults is 8).

GEOSGeometry.difference(other)[source]

Returns a GEOSGeometry representing the points making up this geometry that do not make up other.

GEOSGeometry.interpolate(distance)

GEOSGeometry.interpolate_normalized(distance)

Given a distance (float), returns the point (or closest point) within the geometry (LineString or MultiLineString) at that distance. The normalized version takes the distance as a float between 0 (origin) and 1 (endpoint).

Reverse of GEOSGeometry.project().

GEOSGeometry.intersection(other)[source]

Returns a GEOSGeometry representing the points shared by this geometry and other.

GEOSGeometry.project(point)

GEOSGeometry.project_normalized(point)

Returns the distance (float) from the origin of the geometry (LineString or MultiLineString) to the point projected on the geometry (that is to a point of the line the closest to the given point). The normalized version returns the distance as a float between 0 (origin) and 1 (endpoint).

Reverse of GEOSGeometry.interpolate().

GEOSGeometry.relate(other)[source]

Returns the DE-9IM intersection matrix (a string) representing the topological relationship between this geometry and the other.

GEOSGeometry.simplify(tolerance=0.0, preserve_topology=False)[source]

Returns a new GEOSGeometry, simplified to the specified tolerance using the Douglas-Peucker algorithm. A higher tolerance value implies fewer points in the output. If no tolerance is provided, it defaults to 0.

By default, this function does not preserve topology. For example, Polygon objects can be split, be collapsed into lines, or disappear. Polygon holes can be created or disappear, and lines may cross. By specifying preserve_topology=True, the result will have the same dimension and number of components as the input; this is significantly slower, however.

GEOSGeometry.sym_difference(other)[source]

Returns a GEOSGeometry combining the points in this geometry not in other, and the points in other not in this geometry.

GEOSGeometry.union(other)[source]

Returns a GEOSGeometry representing all the points in this geometry and the other.

Topological Properties

GEOSGeometry.boundary

Returns the boundary as a newly allocated Geometry object.

GEOSGeometry.centroid

Returns a Point object representing the geometric center of the geometry. The point is not guaranteed to be on the interior of the geometry.

GEOSGeometry.convex_hull

Returns the smallest Polygon that contains all the points in the geometry.

GEOSGeometry.envelope

Returns a Polygon that represents the bounding envelope of this geometry. Note that it can also return a Point if the input geometry is a point.

GEOSGeometry.point_on_surface

Computes and returns a Point guaranteed to be on the interior of this geometry.

Other Properties & Methods

GEOSGeometry.area

This property returns the area of the Geometry.

GEOSGeometry.extent

This property returns the extent of this geometry as a 4-tuple, consisting of (xmin, ymin, xmax, ymax).

GEOSGeometry.clone()[source]

This method returns a GEOSGeometry that is a clone of the original.

GEOSGeometry.distance(geom)[source]

Returns the distance between the closest points on this geometry and the given geom (another GEOSGeometry object).

Note

GEOS distance calculations are linear – in other words, GEOS does not perform a spherical calculation even if the SRID specifies a geographic coordinate system.

GEOSGeometry.length

Returns the length of this geometry (e.g., 0 for a Point, the length of a LineString, or the circumference of a Polygon).

GEOSGeometry.prepared

Returns a GEOS PreparedGeometry for the contents of this geometry. PreparedGeometry objects are optimized for the contains, intersects, covers, crosses, disjoint, overlaps, touches and within operations. Refer to the Prepared Geometries documentation for more information.

GEOSGeometry.srs

Returns a SpatialReference object corresponding to the SRID of the geometry or None.

Note

Requires GDAL.

GEOSGeometry.transform(ct, clone=False)[source]

Transforms the geometry according to the given coordinate transformation parameter (ct), which may be an integer SRID, spatial reference WKT string, a PROJ.4 string, a SpatialReference object, or a CoordTransform object. By default, the geometry is transformed in-place and nothing is returned. However if the clone keyword is set, then the geometry is not modified and a transformed clone of the geometry is returned instead.

Note

Requires GDAL. Raises GEOSException if GDAL is not available or if the geometry’s SRID is None or less than 0.

Point

class Point(x, y, z=None, srid=None)[source]

Point objects are instantiated using arguments that represent the component coordinates of the point or with a single sequence coordinates. For example, the following are equivalent:

>>> pnt = Point(5, 23)
>>> pnt = Point([5, 23])

LineString

class LineString(*args, **kwargs)[source]

LineString objects are instantiated using arguments that are either a sequence of coordinates or Point objects. For example, the following are equivalent:

>>> ls = LineString((0, 0), (1, 1))
>>> ls = LineString(Point(0, 0), Point(1, 1))

In addition, LineString objects may also be created by passing in a single sequence of coordinate or Point objects:

>>> ls = LineString( ((0, 0), (1, 1)) )
>>> ls = LineString( [Point(0, 0), Point(1, 1)] )

LinearRing

class LinearRing(*args, **kwargs)[source]

LinearRing objects are constructed in the exact same way as LineString objects, however the coordinates must be closed, in other words, the first coordinates must be the same as the last coordinates. For example:

>>> ls = LinearRing((0, 0), (0, 1), (1, 1), (0, 0))

Notice that (0, 0) is the first and last coordinate – if they were not equal, an error would be raised.

Polygon

class Polygon(*args, **kwargs)[source]

Polygon objects may be instantiated by passing in one or more parameters that represent the rings of the polygon. The parameters must either be LinearRing instances, or a sequence that may be used to construct a LinearRing:

>>> ext_coords = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))
>>> int_coords = ((0.4, 0.4), (0.4, 0.6), (0.6, 0.6), (0.6, 0.4), (0.4, 0.4))
>>> poly = Polygon(ext_coords, int_coords)
>>> poly = Polygon(LinearRing(ext_coords), LinearRing(int_coords))

classmethod from_bbox(bbox)[source]

Returns a polygon object from the given bounding-box, a 4-tuple comprising (xmin, ymin, xmax, ymax).

num_interior_rings

Returns the number of interior rings in this geometry.

Comparing Polygons

Note that it is possible to compare Polygon objects directly with < or >, but as the comparison is made through Polygon’s LineString, it does not mean much (but is consistent and quick). You can always force the comparison with the area property:

>>> if poly_1.area > poly_2.area:
>>>     pass

Geometry Collections

MultiPoint

class MultiPoint(*args, **kwargs)[source]

MultiPoint objects may be instantiated by passing in one or more Point objects as arguments, or a single sequence of Point objects:

>>> mp = MultiPoint(Point(0, 0), Point(1, 1))
>>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) )

MultiLineString

class MultiLineString(*args, **kwargs)[source]

MultiLineString objects may be instantiated by passing in one or more LineString objects as arguments, or a single sequence of LineString objects:

>>> ls1 = LineString((0, 0), (1, 1))
>>> ls2 = LineString((2, 2), (3, 3))
>>> mls = MultiLineString(ls1, ls2)
>>> mls = MultiLineString([ls1, ls2])

merged

Returns a LineString representing the line merge of all the components in this MultiLineString.

MultiPolygon

class MultiPolygon(*args, **kwargs)[source]

MultiPolygon objects may be instantiated by passing one or more Polygon objects as arguments, or a single sequence of Polygon objects:

>>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
>>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) )
>>> mp = MultiPolygon(p1, p2)
>>> mp = MultiPolygon([p1, p2])

cascaded_union

Returns a Polygon that is the union of all of the component polygons in this collection. The algorithm employed is significantly more efficient (faster) than trying to union the geometries together individually. [2]

GeometryCollection

class GeometryCollection(*args, **kwargs)[source]

GeometryCollection objects may be instantiated by passing in one or more other GEOSGeometry as arguments, or a single sequence of GEOSGeometry objects:

>>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
>>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)
>>> gc = GeometryCollection((Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly))

Prepared Geometries

In order to obtain a prepared geometry, just access the GEOSGeometry.prepared property. Once you have a PreparedGeometry instance its spatial predicate methods, listed below, may be used with other GEOSGeometry objects. An operation with a prepared geometry can be orders of magnitude faster – the more complex the geometry that is prepared, the larger the speedup in the operation. For more information, please consult the GEOS wiki page on prepared geometries.

For example:

>>> from django.contrib.gis.geos import Point, Polygon
>>> poly = Polygon.from_bbox((0, 0, 5, 5))
>>> prep_poly = poly.prepared
>>> prep_poly.contains(Point(2.5, 2.5))
True

PreparedGeometry

class PreparedGeometry

All methods on PreparedGeometry take an other argument, which must be a GEOSGeometry instance.

contains(other)

contains_properly(other)

covers(other)

crosses(other)

Note

GEOS 3.3 is required to use this predicate.

disjoint(other)

Note

GEOS 3.3 is required to use this predicate.

intersects(other)

overlaps(other)

Note

GEOS 3.3 is required to use this predicate.

touches(other)

Note

GEOS 3.3 is required to use this predicate.

within(other)

Note

GEOS 3.3 is required to use this predicate.

Geometry Factories

fromfile(file_h)[source]

Parameters:

file_h (a Python file object or a string path to the file) – input file that contains spatial data

Return type:

a GEOSGeometry corresponding to the spatial data in the file

Example:

>>> from django.contrib.gis.geos import fromfile
>>> g = fromfile('/home/bob/geom.wkt')

fromstr(string, srid=None)[source]

Parameters:

- string (string) – string that contains spatial data

- srid (int) – spatial reference identifier

Return type:

a GEOSGeometry corresponding to the spatial data in the string

fromstr(string, srid) is equivalent to GEOSGeometry(string, srid).

Example:

>>> from django.contrib.gis.geos import fromstr
>>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)

I/O Objects

Reader Objects

The reader I/O classes simply return a GEOSGeometry instance from the WKB and/or WKT input given to their read(geom) method.

class WKBReader[source]

Example:

>>> from django.contrib.gis.geos import WKBReader
>>> wkb_r = WKBReader()
>>> wkb_r.read('0101000000000000000000F03F000000000000F03F')
<Point object at 0x103a88910>

class WKTReader[source]

Example:

>>> from django.contrib.gis.geos import WKTReader
>>> wkt_r = WKTReader()
>>> wkt_r.read('POINT(1 1)')
<Point object at 0x103a88b50>

Writer Objects

All writer objects have a write(geom) method that returns either the WKB or WKT of the given geometry. In addition, WKBWriter objects also have properties that may be used to change the byte order, and or include the SRID value (in other words, EWKB).

class WKBWriter[source]

WKBWriter provides the most control over its output. By default it returns OGC-compliant WKB when its write method is called. However, it has properties that allow for the creation of EWKB, a superset of the WKB standard that includes additional information.

WKBWriter.write(geom)[source]

Returns the WKB of the given geometry as a Python buffer object. Example:

>>> from django.contrib.gis.geos import Point, WKBWriter
>>> pnt = Point(1, 1)
>>> wkb_w = WKBWriter()
>>> wkb_w.write(pnt)
<read-only buffer for 0x103a898f0, size -1, offset 0 at 0x103a89930>

WKBWriter.write_hex(geom)[source]

Returns WKB of the geometry in hexadecimal. Example:

>>> from django.contrib.gis.geos import Point, WKBWriter
>>> pnt = Point(1, 1)
>>> wkb_w = WKBWriter()
>>> wkb_w.write_hex(pnt)
'0101000000000000000000F03F000000000000F03F'

WKBWriter.byteorder

This property may be set to change the byte-order of the geometry representation.

Byteorder Value

Description

0

Big Endian (e.g., compatible with RISC systems)

1

Little Endian (e.g., compatible with x86 systems)

Example:

>>> from django.contrib.gis.geos import Point, WKBWriter
>>> wkb_w = WKBWriter()
>>> pnt = Point(1, 1)
>>> wkb_w.write_hex(pnt)
'0101000000000000000000F03F000000000000F03F'
>>> wkb_w.byteorder = 0
'00000000013FF00000000000003FF0000000000000'

WKBWriter.outdim

This property may be set to change the output dimension of the geometry representation. In other words, if you have a 3D geometry then set to 3 so that the Z value is included in the WKB.

Outdim Value

Description

2

The default, output 2D WKB.

3

Output 3D WKB.

Example:

>>> from django.contrib.gis.geos import Point, WKBWriter
>>> wkb_w = WKBWriter()
>>> wkb_w.outdim
2
>>> pnt = Point(1, 1, 1)
>>> wkb_w.write_hex(pnt) # By default, no Z value included:
'0101000000000000000000F03F000000000000F03F'
>>> wkb_w.outdim = 3 # Tell writer to include Z values
>>> wkb_w.write_hex(pnt)
'0101000080000000000000F03F000000000000F03F000000000000F03F'

WKBWriter.srid

Set this property with a boolean to indicate whether the SRID of the geometry should be included with the WKB representation. Example:

>>> from django.contrib.gis.geos import Point, WKBWriter
>>> wkb_w = WKBWriter()
>>> pnt = Point(1, 1, srid=4326)
>>> wkb_w.write_hex(pnt) # By default, no SRID included:
'0101000000000000000000F03F000000000000F03F'
>>> wkb_w.srid = True # Tell writer to include SRID
>>> wkb_w.write_hex(pnt)
'0101000020E6100000000000000000F03F000000000000F03F'

class WKTWriter[source]

WKTWriter.write(geom)[source]

Returns the WKT of the given geometry. Example:

>>> from django.contrib.gis.geos import Point, WKTWriter
>>> pnt = Point(1, 1)
>>> wkt_w = WKTWriter()
>>> wkt_w.write(pnt)
'POINT (1.0000000000000000 1.0000000000000000)'

Footnotes

[1]

See PostGIS EWKB, EWKT and Canonical Forms, PostGIS documentation at Ch. 4.1.2.

[2]

For more information, read Paul Ramsey’s blog post about (Much) Faster Unions in PostGIS 1.4 and Martin Davis’ blog post on Fast polygon merging in JTS using Cascaded Union.

Settings

GEOS_LIBRARY_PATH

A string specifying the location of the GEOS C library. Typically, this setting is only used if the GEOS C library is in a non-standard location (e.g., /home/bob/lib/libgeos_c.so).

Note

The setting must be the full path to the C shared library; in other words you want to use libgeos_c.so, not libgeos.so.

Exceptions

exception GEOSException[source]

The base GEOS exception, indicates a GEOS-related error.

GDAL API

GDAL stands for Geospatial Data Abstraction Library, and is a veritable “Swiss army knife” of GIS data functionality. A subset of GDAL is the OGR Simple Features Library, which specializes in reading and writing vector geographic data in a variety of standard formats.

GeoDjango provides a high-level Python interface for some of the capabilities of OGR, including the reading and coordinate transformation of vector spatial data and minimal support for GDAL’s features with respect to raster (image) data.

Note

Although the module is named gdal, GeoDjango only supports some of the capabilities of OGR and GDAL’s raster features at this time.

Overview

Sample Data

The GDAL/OGR tools described here are designed to help you read in your geospatial data, in order for most of them to be useful you have to have some data to work with. If you’re starting out and don’t yet have any data of your own to use, GeoDjango tests contain a number of simple data sets that you can use for testing. You can download them here:

$ wget https://raw.githubusercontent.com/django/django/master/tests/gis_tests/data/cities/cities.{shp,prj,shx,dbf}
$ wget https://raw.githubusercontent.com/django/django/master/tests/gis_tests/data/rasters/raster.tif

Vector Data Source Objects

DataSource

DataSource is a wrapper for the OGR data source object that supports reading data from a variety of OGR-supported geospatial file formats and data sources using a simple, consistent interface. Each data source is represented by a DataSource object which contains one or more layers of data. Each layer, represented by a Layer object, contains some number of geographic features (Feature), information about the type of features contained in that layer (e.g. points, polygons, etc.), as well as the names and types of any additional fields (Field) of data that may be associated with each feature in that layer.

class DataSource(ds_input, encoding='utf-8')

The constructor for DataSource only requires one parameter: the path of the file you want to read. However, OGR also supports a variety of more complex data sources, including databases, that may be accessed by passing a special name string instead of a path. For more information, see the OGR Vector Formats documentation. The name property of a DataSource instance gives the OGR name of the underlying data source that it is using.

The optional encoding parameter allows you to specify a non-standard encoding of the strings in the source. This is typically useful when you obtain DjangoUnicodeDecodeError exceptions while reading field values.

Once you’ve created your DataSource, you can find out how many layers of data it contains by accessing the layer_count property, or (equivalently) by using the len() function. For information on accessing the layers of data themselves, see the next section:

>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource('/path/to/your/cities.shp')
>>> ds.name
'/path/to/your/cities.shp'
>>> ds.layer_count                  # This file only contains one layer
1

layer_count

Returns the number of layers in the data source.

name

Returns the name of the data source.

Layer

class Layer

Layer is a wrapper for a layer of data in a DataSource object. You never create a Layer object directly. Instead, you retrieve them from a DataSource object, which is essentially a standard Python container of Layer objects. For example, you can access a specific layer by its index (e.g. ds[0] to access the first layer), or you can iterate over all the layers in the container in a for loop. The Layer itself acts as a container for geometric features.

Typically, all the features in a given layer have the same geometry type. The geom_type property of a layer is an OGRGeomType that identifies the feature type. We can use it to print out some basic information about each layer in a DataSource:

>>> for layer in ds:
...     print('Layer "%s": %i %ss' % (layer.name, len(layer), layer.geom_type.name))
...
Layer "cities": 3 Points

The example output is from the cities data source, loaded above, which evidently contains one layer, called "cities", which contains three point features. For simplicity, the examples below assume that you’ve stored that layer in the variable layer:

>>> layer = ds[0]

name

Returns the name of this layer in the data source.

>>> layer.name
'cities'

num_feat

Returns the number of features in the layer. Same as len(layer):

>>> layer.num_feat
3

geom_type

Returns the geometry type of the layer, as an OGRGeomType object:

>>> layer.geom_type.name
'Point'

num_fields

Returns the number of fields in the layer, i.e the number of fields of data associated with each feature in the layer:

>>> layer.num_fields
4

fields

Returns a list of the names of each of the fields in this layer:

>>> layer.fields
['Name', 'Population', 'Density', 'Created']

Returns a list of the data types of each of the fields in this layer. These are subclasses of Field, discussed below:

>>> [ft.__name__ for ft in layer.field_types]
['OFTString', 'OFTReal', 'OFTReal', 'OFTDate']

field_widths

Returns a list of the maximum field widths for each of the fields in this layer:

>>> layer.field_widths
[80, 11, 24, 10]

field_precisions

Returns a list of the numeric precisions for each of the fields in this layer. This is meaningless (and set to zero) for non-numeric fields:

>>> layer.field_precisions
[0, 0, 15, 0]

extent

Returns the spatial extent of this layer, as an Envelope object:

>>> layer.extent.tuple
(-104.609252, 29.763374, -95.23506, 38.971823)

srs

Property that returns the SpatialReference associated with this layer:

>>> print(layer.srs)
GEOGCS["GCS_WGS_1984",
DATUM["WGS_1984",
SPHEROID["WGS_1984",6378137,298.257223563]],
PRIMEM["Greenwich",0],
UNIT["Degree",0.017453292519943295]]

If the Layer has no spatial reference information associated with it, None is returned.

spatial_filter

Property that may be used to retrieve or set a spatial filter for this layer. A spatial filter can only be set with an OGRGeometry instance, a 4-tuple extent, or None. When set with something other than None, only features that intersect the filter will be returned when iterating over the layer:

>>> print(layer.spatial_filter)
None
>>> print(len(layer))
3
>>> [feat.get('Name') for feat in layer]
['Pueblo', 'Lawrence', 'Houston']
>>> ks_extent = (-102.051, 36.99, -94.59, 40.00) # Extent for state of Kansas
>>> layer.spatial_filter = ks_extent
>>> len(layer)
1
>>> [feat.get('Name') for feat in layer]
['Lawrence']
>>> layer.spatial_filter = None
>>> len(layer)
3

get_fields()

A method that returns a list of the values of a given field for each feature in the layer:

>>> layer.get_fields('Name')
['Pueblo', 'Lawrence', 'Houston']

get_geoms(geos=False)

A method that returns a list containing the geometry of each feature in the layer. If the optional argument geos is set to True then the geometries are converted to GEOSGeometry objects. Otherwise, they are returned as OGRGeometry objects:

>>> [pt.tuple for pt in layer.get_geoms()]
[(-104.609252, 38.255001), (-95.23506, 38.971823), (-95.363151, 29.763374)]

test_capability(capability)

Returns a boolean indicating whether this layer supports the given capability (a string). Examples of valid capability strings include: 'RandomRead', 'SequentialWrite', 'RandomWrite', 'FastSpatialFilter', 'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions', 'DeleteFeature', and 'FastSetNextByIndex'.

Feature

class Feature

Feature wraps an OGR feature. You never create a Feature object directly. Instead, you retrieve them from a Layer object. Each feature consists of a geometry and a set of fields containing additional properties. The geometry of a field is accessible via its geom property, which returns an OGRGeometry object. A Feature behaves like a standard Python container for its fields, which it returns as Field objects: you can access a field directly by its index or name, or you can iterate over a feature’s fields, e.g. in a for loop.

geom

Returns the geometry for this feature, as an OGRGeometry object:

>>> city.geom.tuple
(-104.609252, 38.255001)

get

A method that returns the value of the given field (specified by name) for this feature, not a Field wrapper object:

>>> city.get('Population')
102121

geom_type

Returns the type of geometry for this feature, as an OGRGeomType object. This will be the same for all features in a given layer, and is equivalent to the Layer.geom_type property of the Layer object the feature came from.

num_fields

Returns the number of fields of data associated with the feature. This will be the same for all features in a given layer, and is equivalent to the Layer.num_fields property of the Layer object the feature came from.

fields

Returns a list of the names of the fields of data associated with the feature. This will be the same for all features in a given layer, and is equivalent to the Layer.fields property of the Layer object the feature came from.

fid

Returns the feature identifier within the layer:

>>> city.fid
0

layer_name

Returns the name of the Layer that the feature came from. This will be the same for all features in a given layer:

>>> city.layer_name
'cities'

index

A method that returns the index of the given field name. This will be the same for all features in a given layer:

>>> city.index('Population')
1

Field

class Field

name

Returns the name of this field:

>>> city['Name'].name
'Name'

type

Returns the OGR type of this field, as an integer. The FIELD_CLASSES dictionary maps these values onto subclasses of Field:

>>> city['Density'].type
2

type_name

Returns a string with the name of the data type of this field:

>>> city['Name'].type_name
'String'

value

Returns the value of this field. The Field class itself returns the value as a string, but each subclass returns the value in the most appropriate form:

>>> city['Population'].value
102121

width

Returns the width of this field:

>>> city['Name'].width
80

precision

Returns the numeric precision of this field. This is meaningless (and set to zero) for non-numeric fields:

>>> city['Density'].precision
15

as_double()

Returns the value of the field as a double (float):

>>> city['Density'].as_double()
874.7

as_int()

Returns the value of the field as an integer:

>>> city['Population'].as_int()
102121

as_string()

Returns the value of the field as a string:

>>> city['Name'].as_string()
'Pueblo'

as_datetime()

Returns the value of the field as a tuple of date and time components:

>>> city['Created'].as_datetime()
(c_long(1999), c_long(5), c_long(23), c_long(0), c_long(0), c_long(0), c_long(0))

Driver

class Driver(dr_input)

The Driver class is used internally to wrap an OGR DataSource driver.

driver_count

Returns the number of OGR vector drivers currently registered.

OGR Geometries

OGRGeometry

OGRGeometry objects share similar functionality with GEOSGeometry objects, and are thin wrappers around OGR’s internal geometry representation. Thus, they allow for more efficient access to data when using DataSource. Unlike its GEOS counterpart, OGRGeometry supports spatial reference systems and coordinate transformation:

>>> from django.contrib.gis.gdal import OGRGeometry
>>> polygon = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))')

class OGRGeometry(geom_input, srs=None)

This object is a wrapper for the OGR Geometry class. These objects are instantiated directly from the given geom_input parameter, which may be a string containing WKT, HEX, GeoJSON, a buffer containing WKB data, or an OGRGeomType object. These objects are also returned from the Feature.geom attribute, when reading vector data from Layer (which is in turn a part of a DataSource).

classmethod from_bbox(bbox)

Constructs a Polygon from the given bounding-box (a 4-tuple).

__len__()

Returns the number of points in a LineString, the number of rings in a Polygon, or the number of geometries in a GeometryCollection. Not applicable to other geometry types.

__iter__()

Iterates over the points in a LineString, the rings in a Polygon, or the geometries in a GeometryCollection. Not applicable to other geometry types.

__getitem__()

Returns the point at the specified index for a LineString, the interior ring at the specified index for a Polygon, or the geometry at the specified index in a GeometryCollection. Not applicable to other geometry types.

dimension

Returns the number of coordinated dimensions of the geometry, i.e. 0 for points, 1 for lines, and so forth:

>> polygon.dimension
2

coord_dim

Returns or sets the coordinate dimension of this geometry. For example, the value would be 2 for two-dimensional geometries.

geom_count

Returns the number of elements in this geometry:

>>> polygon.geom_count
1

point_count

Returns the number of points used to describe this geometry:

>>> polygon.point_count
4

num_points

Alias for point_count.

num_coords

Alias for point_count.

geom_type

Returns the type of this geometry, as an OGRGeomType object.

geom_name

Returns the name of the type of this geometry:

>>> polygon.geom_name
'POLYGON'

area

Returns the area of this geometry, or 0 for geometries that do not contain an area:

>>> polygon.area
25.0

envelope

Returns the envelope of this geometry, as an Envelope object.

extent

Returns the envelope of this geometry as a 4-tuple, instead of as an Envelope object:

>>> point.extent
(0.0, 0.0, 5.0, 5.0)

srs

This property controls the spatial reference for this geometry, or None if no spatial reference system has been assigned to it. If assigned, accessing this property returns a SpatialReference object. It may be set with another SpatialReference object, or any input that SpatialReference accepts. Example:

>>> city.geom.srs.name
'GCS_WGS_1984'

srid

Returns or sets the spatial reference identifier corresponding to SpatialReference of this geometry. Returns None if there is no spatial reference information associated with this geometry, or if an SRID cannot be determined.

geos

Returns a GEOSGeometry object corresponding to this geometry.

gml

Returns a string representation of this geometry in GML format:

>>> OGRGeometry('POINT(1 2)').gml
'<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>'

hex

Returns a string representation of this geometry in HEX WKB format:

>>> OGRGeometry('POINT(1 2)').hex
'0101000000000000000000F03F0000000000000040'

json

Returns a string representation of this geometry in JSON format:

>>> OGRGeometry('POINT(1 2)').json
'{ "type": "Point", "coordinates": [ 1.000000, 2.000000 ] }'

kml

Returns a string representation of this geometry in KML format.

wkb_size

Returns the size of the WKB buffer needed to hold a WKB representation of this geometry:

>>> OGRGeometry('POINT(1 2)').wkb_size
21

wkb

Returns a buffer containing a WKB representation of this geometry.

wkt

Returns a string representation of this geometry in WKT format.

ewkt

Returns the EWKT representation of this geometry.

clone()

Returns a new OGRGeometry clone of this geometry object.

close_rings()

If there are any rings within this geometry that have not been closed, this routine will do so by adding the starting point to the end:

>>> triangle = OGRGeometry('LINEARRING (0 0,0 1,1 0)')
>>> triangle.close_rings()
>>> triangle.wkt
'LINEARRING (0 0,0 1,1 0,0 0)'

transform(coord_trans, clone=False)

Transforms this geometry to a different spatial reference system. May take a CoordTransform object, a SpatialReference object, or any other input accepted by SpatialReference (including spatial reference WKT and PROJ.4 strings, or an integer SRID). By default nothing is returned and the geometry is transformed in-place. However, if the clone keyword is set to True then a transformed clone of this geometry is returned instead.

intersects(other)

Returns True if this geometry intersects the other, otherwise returns False.

equals(other)

Returns True if this geometry is equivalent to the other, otherwise returns False.

disjoint(other)

Returns True if this geometry is spatially disjoint to (i.e. does not intersect) the other, otherwise returns False.

touches(other)

Returns True if this geometry touches the other, otherwise returns False.

crosses(other)

Returns True if this geometry crosses the other, otherwise returns False.

within(other)

Returns True if this geometry is contained within the other, otherwise returns False.

contains(other)

Returns True if this geometry contains the other, otherwise returns False.

overlaps(other)

Returns True if this geometry overlaps the other, otherwise returns False.

boundary()

The boundary of this geometry, as a new OGRGeometry object.

convex_hull

The smallest convex polygon that contains this geometry, as a new OGRGeometry object.

difference()

Returns the region consisting of the difference of this geometry and the other, as a new OGRGeometry object.

intersection()

Returns the region consisting of the intersection of this geometry and the other, as a new OGRGeometry object.

sym_difference()

Returns the region consisting of the symmetric difference of this geometry and the other, as a new OGRGeometry object.

union()

Returns the region consisting of the union of this geometry and the other, as a new OGRGeometry object.

tuple

Returns the coordinates of a point geometry as a tuple, the coordinates of a line geometry as a tuple of tuples, and so forth:

>>> OGRGeometry('POINT (1 2)').tuple
(1.0, 2.0)
>>> OGRGeometry('LINESTRING (1 2,3 4)').tuple
((1.0, 2.0), (3.0, 4.0))

coords

An alias for tuple.

class Point

x

Returns the X coordinate of this point:

>>> OGRGeometry('POINT (1 2)').x
1.0

y

Returns the Y coordinate of this point:

>>> OGRGeometry('POINT (1 2)').y
2.0

z

Returns the Z coordinate of this point, or None if the point does not have a Z coordinate:

>>> OGRGeometry('POINT (1 2 3)').z
3.0

class LineString

x

Returns a list of X coordinates in this line:

>>> OGRGeometry('LINESTRING (1 2,3 4)').x
[1.0, 3.0]

y

Returns a list of Y coordinates in this line:

>>> OGRGeometry('LINESTRING (1 2,3 4)').y
[2.0, 4.0]

z

Returns a list of Z coordinates in this line, or None if the line does not have Z coordinates:

>>> OGRGeometry('LINESTRING (1 2 3,4 5 6)').z
[3.0, 6.0]

class Polygon

shell

Returns the shell or exterior ring of this polygon, as a LinearRing geometry.

exterior_ring

An alias for shell.

centroid

Returns a Point representing the centroid of this polygon.

class GeometryCollection

add(geom)

Adds a geometry to this geometry collection. Not applicable to other geometry types.

OGRGeomType

class OGRGeomType(type_input)[source]

This class allows for the representation of an OGR geometry type in any of several ways:

>>> from django.contrib.gis.gdal import OGRGeomType
>>> gt1 = OGRGeomType(3)             # Using an integer for the type
>>> gt2 = OGRGeomType('Polygon')     # Using a string
>>> gt3 = OGRGeomType('POLYGON')     # It's case-insensitive
>>> print(gt1 == 3, gt1 == 'Polygon') # Equivalence works w/non-OGRGeomType objects
True True

name

Returns a short-hand string form of the OGR Geometry type:

>>> gt1.name
'Polygon'

num

Returns the number corresponding to the OGR geometry type:

>>> gt1.num
3

django

Returns the Django field type (a subclass of GeometryField) to use for storing this OGR type, or None if there is no appropriate Django type:

>>> gt1.django
'PolygonField'

Envelope

class Envelope(*args)[source]

Represents an OGR Envelope structure that contains the minimum and maximum X, Y coordinates for a rectangle bounding box. The naming of the variables is compatible with the OGR Envelope C structure.

min_x

The value of the minimum X coordinate.

min_y

The value of the maximum X coordinate.

max_x

The value of the minimum Y coordinate.

max_y

The value of the maximum Y coordinate.

ur

The upper-right coordinate, as a tuple.

ll

The lower-left coordinate, as a tuple.

tuple

A tuple representing the envelope.

wkt

A string representing this envelope as a polygon in WKT format.

expand_to_include(*args)[source]

Coordinate System Objects

SpatialReference

class SpatialReference(srs_input)

Spatial reference objects are initialized on the given srs_input, which may be one of the following:

- OGC Well Known Text (WKT) (a string)

- EPSG code (integer or string)

- PROJ.4 string

- A shorthand string for well-known standards ('WGS84', 'WGS72', 'NAD27', 'NAD83')

Example:

>>> wgs84 = SpatialReference('WGS84') # shorthand string
>>> wgs84 = SpatialReference(4326) # EPSG code
>>> wgs84 = SpatialReference('EPSG:4326') # EPSG string
>>> proj4 = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '
>>> wgs84 = SpatialReference(proj4) # PROJ.4 string
>>> wgs84 = SpatialReference("""GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]]""") # OGC WKT

__getitem__(target)

Returns the value of the given string attribute node, None if the node doesn’t exist. Can also take a tuple as a parameter, (target, child), where child is the index of the attribute in the WKT. For example:

>>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]')
>>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326
>>> print(srs['GEOGCS'])
WGS 84
>>> print(srs['DATUM'])
WGS_1984
>>> print(srs['AUTHORITY'])
EPSG
>>> print(srs['AUTHORITY', 1]) # The authority value
4326
>>> print(srs['TOWGS84', 4]) # the fourth value in this wkt
0
>>> print(srs['UNIT|AUTHORITY']) # For the units authority, have to use the pipe symbol.
EPSG
>>> print(srs['UNIT|AUTHORITY', 1]) # The authority value for the units
9122

attr_value(target, index=0)

The attribute value for the given target node (e.g. 'PROJCS'). The index keyword specifies an index of the child node to return.

auth_name(target)

Returns the authority name for the given string target node.

auth_code(target)

Returns the authority code for the given string target node.

clone()

Returns a clone of this spatial reference object.

identify_epsg()

This method inspects the WKT of this SpatialReference, and will add EPSG authority nodes where an EPSG identifier is applicable.

from_esri()

Morphs this SpatialReference from ESRI’s format to EPSG

to_esri()

Morphs this SpatialReference to ESRI’s format.

validate()

Checks to see if the given spatial reference is valid, if not an exception will be raised.

import_epsg(epsg)

Import spatial reference from EPSG code.

import_proj(proj)

Import spatial reference from PROJ.4 string.

import_user_input(user_input)

import_wkt(wkt)

Import spatial reference from WKT.

import_xml(xml)

Import spatial reference from XML.

name

Returns the name of this Spatial Reference.

srid

Returns the SRID of top-level authority, or None if undefined.

linear_name

Returns the name of the linear units.

linear_units

Returns the value of the linear units.

angular_name

Returns the name of the angular units.”

angular_units

Returns the value of the angular units.

units

Returns a 2-tuple of the units value and the units name, and will automatically determines whether to return the linear or angular units.

ellipsoid

Returns a tuple of the ellipsoid parameters for this spatial reference: (semimajor axis, semiminor axis, and inverse flattening)

semi_major

Returns the semi major axis of the ellipsoid for this spatial reference.

semi_minor

Returns the semi minor axis of the ellipsoid for this spatial reference.

inverse_flattening

Returns the inverse flattening of the ellipsoid for this spatial reference.

geographic

Returns True if this spatial reference is geographic (root node is GEOGCS).

local

Returns True if this spatial reference is local (root node is LOCAL_CS).

projected

Returns True if this spatial reference is a projected coordinate system (root node is PROJCS).

wkt

Returns the WKT representation of this spatial reference.

pretty_wkt

Returns the ‘pretty’ representation of the WKT.

proj

Returns the PROJ.4 representation for this spatial reference.

proj4

Alias for SpatialReference.proj.

xml

Returns the XML representation of this spatial reference.

CoordTransform

class CoordTransform(source, target)

Represents a coordinate system transform. It is initialized with two SpatialReference, representing the source and target coordinate systems, respectively. These objects should be used when performing the same coordinate transformation repeatedly on different geometries:

>>> ct = CoordTransform(SpatialReference('WGS84'), SpatialReference('NAD83'))
>>> for feat in layer:
...     geom = feat.geom # getting clone of feature geometry
...     geom.transform(ct) # transforming

Raster Data Objects

New in Django 1.8.

GDALRaster

GDALRaster is a wrapper for the GDAL raster source object that supports reading data from a variety of GDAL-supported geospatial file formats and data sources using a simple, consistent interface. Each data source is represented by a GDALRaster object which contains one or more layers of data named bands. Each band, represented by a GDALBand object, contains georeferenced image data. For example, an RGB image is represented as three bands: one for red, one for green, and one for blue.

Note

For raster data there is no difference between a raster instance and its data source. Unlike for the Geometry objects, GDALRaster objects are always a data source. Temporary rasters can be instantiated in memory using the corresponding driver, but they will be of the same class as file-based raster sources.

class GDALRaster(ds_input, write=False)

The constructor for GDALRaster accepts two parameters. The first parameter defines the raster source, it is either a path to a file or spatial data with values defining the properties of a new raster (such as size and name). If the input is a file path, the second parameter specifies if the raster should be opened with write access. If the input is raw data, the parameters width, height, and srid are required. The following example shows how rasters can be created from different input sources (using the sample data from the GeoDjango tests, see also the Sample Data section):

>>> from django.contrib.gis.gdal import GDALRaster
>>> rst = GDALRaster('/path/to/your/raster.tif', write=False)
>>> rst.name
'/path/to/your/raster.tif'
>>> rst.width, rst.height            # This file has 163 x 174 pixels
(163, 174)
>>> rst = GDALRaster({'srid': 4326, 'width': 1, 'height': 2, 'datatype': 1
...                   'bands': [{'data': [0, 1]}]}) # Creates in-memory raster
>>> rst.srs.srid
4326
>>> rst.width, rst.height
(1, 2)
>>> rst.bands[0].data()
array([[0, 1]], dtype=int8)

Changed in Django 1.9:
GDALRaster objects can now be instantiated directly from raw data. Setters have been added for the following properties: srs, geotransform, origin, scale, and skew.

name

The name of the source which is equivalent to the input file path or the name provided upon instantiation.

>>> GDALRaster({'width': 10, 'height': 10, 'name': 'myraster', 'srid': 4326}).name
'myraster'

driver

The name of the GDAL driver used to handle the input file. For GDALRasters created from a file, the driver type is detected automatically. The creation of rasters from scratch is a in-memory raster by default ('MEM'), but can be altered as needed. For instance, use GTiff for a GeoTiff file. For a list of file types, see also the GDAL Raster Formats list.

An in-memory raster is created through the following example:

>>> GDALRaster({'width': 10, 'height': 10, 'srid': 4326}).driver.name
'MEM'

A file based GeoTiff raster is created through the following example:

>>> import tempfile
>>> rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
>>> rst = GDALRaster({'driver': 'GTiff', 'name': rstfile.name, 'srid': 4326,
...                   'width': 255, 'height': 255, 'nr_of_bands': 1})
>>> rst.name
'/tmp/tmp7x9H4J.tif'           # The exact filename will be different on your computer
>>> rst.driver.name
'GTiff'

width

The width of the source in pixels (X-axis).

>>> GDALRaster({'width': 10, 'height': 20, 'srid': 4326}).width
10

height

The height of the source in pixels (Y-axis).

>>> GDALRaster({'width': 10, 'height': 20, 'srid': 4326}).height
20

srs

The spatial reference system of the raster, as a SpatialReference instance. The SRS can be changed by setting it to an other SpatialReference or providing any input that is accepted by the SpatialReference constructor.

>>> rst = GDALRaster({'width': 10, 'height': 20, 'srid': 4326})
>>> rst.srs.srid
4326
>>> rst.srs = 3086
>>> rst.srs.srid
3086

geotransform

The affine transformation matrix used to georeference the source, as a tuple of six coefficients which map pixel/line coordinates into georeferenced space using the following relationship:

Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)

The same values can be retrieved by accessing the origin (indices 0 and 3), scale (indices 1 and 5) and skew (indices 2 and 4) properties.

The default is [0.0, 1.0, 0.0, 0.0, 0.0, -1.0].

>>> rst = GDALRaster({'width': 10, 'height': 20, 'srid': 4326})
>>> rst.geotransform
[0.0, 1.0, 0.0, 0.0, 0.0, -1.0]

origin

Coordinates of the top left origin of the raster in the spatial reference system of the source, as a point object with x and y members.

>>> rst = GDALRaster({'width': 10, 'height': 20, 'srid': 4326})
>>> rst.origin
[0.0, 0.0]
>>> rst.origin.x = 1
>>> rst.origin
[1.0, 0.0]

scale

Pixel width and height used for georeferencing the raster, as a as a point object with x and y members. See geotransform for more information.

>>> rst = GDALRaster({'width': 10, 'height': 20, 'srid': 4326})
>>> rst.scale
[1.0, -1.0]
>>> rst.scale.x = 2
>>> rst.scale
[2.0, -1.0]

skew

Skew coefficients used to georeference the raster, as a point object with x and y members. In case of north up images, these coefficients are both 0.

>>> rst = GDALRaster({'width': 10, 'height': 20, 'srid': 4326})
>>> rst.skew
[0.0, 0.0]
>>> rst.skew.x = 3
>>> rst.skew
[3.0, 0.0]

extent

Extent (boundary values) of the raster source, as a 4-tuple (xmin, ymin, xmax, ymax) in the spatial reference system of the source.

>>> rst = GDALRaster({'width': 10, 'height': 20, 'srid': 4326})
>>> rst.extent
(0.0, -20.0, 10.0, 0.0)
>>> rst.origin.x = 100
>>> rst.extent
(100.0, -20.0, 110.0, 0.0)

bands

List of all bands of the source, as GDALBand instances.

>>> rst = GDALRaster({"width": 1, "height": 2, 'srid': 4326,
...                   "bands": [{"data": [0, 1]}, {"data": [2, 3]}]})
>>> len(rst.bands)
2
>>> rst.bands[1].data()
array([[ 2.,  3.]], dtype=float32)

warp(ds_input, resampling='NearestNeighbour', max_error=0.0)

New in Django 1.9.

Returns a warped version of this raster.

The warping parameters can be specified through the ds_input argument. The use of ds_input is analogous to the corresponding argument of the class constructor. It is a dictionary with the characteristics of the target raster. Allowed dictionary key values are width, height, SRID, origin, scale, skew, datatype, driver, and name (filename).

By default, the warp functions keeps most parameters equal to the values of the original source raster, so only parameters that should be changed need to be specified. Note that this includes the driver, so for file-based rasters the warp function will create a new raster on disk.

The only parameter that is set differently from the source raster is the name. The default value of the the raster name is the name of the source raster appended with '_copy' + source_driver_name. For file-based rasters it is recommended to provide the file path of the target raster.

The resampling algorithm used for warping can be specified with the resampling argument. The default is NearestNeighbor, and the other allowed values are Bilinear, Cubic, CubicSpline, Lanczos, Average, and Mode.

The max_error argument can be used to specify the maximum error measured in input pixels that is allowed in approximating the transformation. The default is 0.0 for exact calculations.

For users familiar with GDAL, this function has a similar functionality to the gdalwarp command-line utility.

For example, the warp function can be used for aggregating a raster to the double of its original pixel scale:

>>> rst = GDALRaster({
...     "width": 6, "height": 6, "srid": 3086,
...     "origin": [500000, 400000],
...     "scale": [100, -100],
...     "bands": [{"data": range(36), "nodata_value": 99}]
... })
>>> target = rst.warp({"scale": [200, -200], "width": 3, "height": 3})
>>> target.bands[0].data()
array([[  7.,   9.,  11.],
[ 19.,  21.,  23.],
[ 31.,  33.,  35.]], dtype=float32)

transform(srid, driver=None, name=None, resampling='NearestNeighbour', max_error=0.0)

New in Django 1.9.

Returns a transformed version of this raster with the specified SRID.

This function transforms the current raster into a new spatial reference system that can be specified with an srid. It calculates the bounds and scale of the current raster in the new spatial reference system and warps the raster using the warp function.

By default, the driver of the source raster is used and the name of the raster is the original name appended with '_copy' + source_driver_name. A different driver or name can be specified with the driver and name arguments.

The default resampling algorithm is NearestNeighbour but can be changed using the resampling argument. The default maximum allowed error for resampling is 0.0 and can be changed using the max_error argument. Consult the warp documentation for detail on those arguments.

>>> rst = GDALRaster({
...     "width": 6, "height": 6, "srid": 3086,
...     "origin": [500000, 400000],
...     "scale": [100, -100],
...     "bands": [{"data": range(36), "nodata_value": 99}]
... })
>>> target = rst.transform(4326)
>>> target.origin
[-82.98492744885776, 27.601924753080144]

GDALBand

class GDALBand

GDALBand instances are not created explicitly, but rather obtained from a GDALRaster object, through its bands attribute. The GDALBands contain the actual pixel values of the raster.

description

The name or description of the band, if any.

width

The width of the band in pixels (X-axis).

height

The height of the band in pixels (Y-axis).

pixel_count

New in Django 1.9.

The total number of pixels in this band. Is equal to width * height.

min

The minimum pixel value of the band (excluding the “no data” value).

max

The maximum pixel value of the band (excluding the “no data” value).

nodata_value

The “no data” value for a band is generally a special marker value used to mark pixels that are not valid data. Such pixels should generally not be displayed, nor contribute to analysis operations.

Changed in Django 1.9:
This property can now be set as well.

datatype(as_string=False)

The data type contained in the band, as an integer constant between 0 (Unknown) and 11. If as_string is True, the data type is returned as a string with the following possible values: GDT_Unknown, GDT_Byte, GDT_UInt16, GDT_Int16, GDT_UInt32, GDT_Int32, GDT_Float32, GDT_Float64, GDT_CInt16, GDT_CInt32, GDT_CFloat32, and GDT_CFloat64.

data(data=None, offset=None, size=None)

New in Django 1.9.

The accessor to the pixel values of the GDALBand. Returns the complete data array if no parameters are provided. A subset of the pixel array can be requested by specifying an offset and block size as tuples.

If NumPy is available, the data is returned as NumPy array. For performance reasons, it is highly recommended to use NumPy.

Data is written to the GDALBand if the data parameter is provided. The input can be of one of the following types - packed string, buffer, list, array, and NumPy array. The number of items in the input must correspond to the total number of pixels in the band, or to the number of pixels for a specific block of pixel values if the offset and size parameters are provided.

For example:

>>> rst = GDALRaster({'width': 4, 'height': 4, 'srid': 4326, 'datatype': 1, 'nr_of_bands': 1})
>>> bnd = rst.bands[0]
>>> bnd.data(range(16))
>>> bnd.data()
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11],
[12, 13, 14, 15]], dtype=int8)
>>> bnd.data(offset=(1, 1), size=(2, 2))
array([[ 5,  6],
[ 9, 10]], dtype=int8)
>>> bnd.data(data=[-1, -2, -3, -4], offset=(1, 1), size=(2, 2))
>>> bnd.data()
array([[ 0,  1,  2,  3],
[ 4, -1, -2,  7],
[ 8, -3, -4, 11],
[12, 13, 14, 15]], dtype=int8)
>>> bnd.data(data='\x9d\xa8\xb3\xbe', offset=(1, 1), size=(2, 2))
>>> bnd.data()
array([[  0,   1,   2,   3],
[  4, -99, -88,   7],
[  8, -77, -66,  11],
[ 12,  13,  14,  15]], dtype=int8)

Settings

GDAL_LIBRARY_PATH

A string specifying the location of the GDAL library. Typically, this setting is only used if the GDAL library is in a non-standard location (e.g., /home/john/lib/libgdal.so).

Geolocation with GeoIP

Deprecated since version 1.9: This module is deprecated in favor of django.contrib.gis.geoip2, which supports IPv6 and the GeoLite2 database format.

The GeoIP object is a ctypes wrapper for the MaxMind GeoIP C API. [1]

In order to perform IP-based geolocation, the GeoIP object requires the GeoIP C library and either the GeoIP Country or City datasets in binary format (the CSV files will not work!). These datasets may be downloaded from MaxMind. Grab the GeoLiteCountry/GeoIP.dat.gz and GeoLiteCity.dat.gz files and unzip them in a directory corresponding to what you set GEOIP_PATH with in your settings. See the example and reference below for more details.

Example

Assuming you have the GeoIP C library installed, here is an example of its usage:

>>> from django.contrib.gis.geoip import GeoIP
>>> g = GeoIP()
>>> g.country('google.com')
{'country_code': 'US', 'country_name': 'United States'}
>>> g.city('72.14.207.99')
{'area_code': 650,
'city': 'Mountain View',
'country_code': 'US',
'country_code3': 'USA',
'country_name': 'United States',
'dma_code': 807,
'latitude': 37.419200897216797,
'longitude': -122.05740356445312,
'postal_code': '94043',
'region': 'CA'}
>>> g.lat_lon('salon.com')
(37.789798736572266, -122.39420318603516)
>>> g.lon_lat('uh.edu')
(-95.415199279785156, 29.77549934387207)
>>> g.geos('24.124.1.80').wkt
'POINT (-95.2087020874023438 39.0392990112304688)'

GeoIP Settings

GEOIP_PATH

A string specifying the directory where the GeoIP data files are located. This setting is required unless manually specified with path keyword when initializing the GeoIP object.

GEOIP_LIBRARY_PATH

A string specifying the location of the GeoIP C library. Typically, this setting is only used if the GeoIP C library is in a non-standard location (e.g., /home/sue/lib/libGeoIP.so).

GEOIP_COUNTRY

The basename to use for the GeoIP country data file. Defaults to 'GeoIP.dat'.

GEOIP_CITY

The basename to use for the GeoIP city data file. Defaults to 'GeoLiteCity.dat'.

GeoIP API

class GeoIP(path=None, cache=0, country=None, city=None)

The GeoIP object does not require any parameters to use the default settings. However, at the very least the GEOIP_PATH setting should be set with the path of the location of your GeoIP data sets. The following initialization keywords may be used to customize any of the defaults.

Keyword Arguments

Description

path

Base directory to where GeoIP data is located or the full path to where the city or country data files (.dat) are located. Assumes that both the city and country data sets are located in this directory; overrides the GEOIP_PATH settings attribute.

cache

The cache settings when opening up the GeoIP datasets, and may be an integer in (0, 1, 2, 4) corresponding to the GEOIP_STANDARD, GEOIP_MEMORY_CACHE, GEOIP_CHECK_CACHE, and GEOIP_INDEX_CACHE GeoIPOptions C API settings, respectively. Defaults to 0 (GEOIP_STANDARD).

country

The name of the GeoIP country data file. Defaults to GeoIP.dat. Setting this keyword overrides the GEOIP_COUNTRY settings attribute.

city

The name of the GeoIP city data file. Defaults to GeoLiteCity.dat. Setting this keyword overrides the GEOIP_CITY settings attribute.

GeoIP Methods

Querying

All the following querying routines may take either a string IP address or a fully qualified domain name (FQDN). For example, both '205.186.163.125' and 'djangoproject.com' would be valid query parameters.

GeoIP.city(query)

Returns a dictionary of city information for the given query. Some of the values in the dictionary may be undefined (None).

GeoIP.country(query)

Returns a dictionary with the country code and country for the given query.

GeoIP.country_code(query)

Returns only the country code corresponding to the query.

GeoIP.country_name(query)

Returns only the country name corresponding to the query.

Coordinate Retrieval

GeoIP.coords(query)

Returns a coordinate tuple of (longitude, latitude).

GeoIP.lon_lat(query)

Returns a coordinate tuple of (longitude, latitude).

GeoIP.lat_lon(query)

Returns a coordinate tuple of (latitude, longitude),

GeoIP.geos(query)

Returns a django.contrib.gis.geos.Point object corresponding to the query.

Database Information

GeoIP.country_info

This property returns information about the GeoIP country database.

GeoIP.city_info

This property returns information about the GeoIP city database.

GeoIP.info

This property returns information about all GeoIP databases (both city and country), and the version of the GeoIP C library (if supported).

GeoIP-Python API compatibility methods

These methods exist to ease compatibility with any code using MaxMind’s existing Python API.

classmethod GeoIP.open(path, cache)

This classmethod instantiates the GeoIP object from the given database path and given cache setting.

GeoIP.region_by_addr(query)

GeoIP.region_by_name(query)

GeoIP.record_by_addr(query)

GeoIP.record_by_name(query)

GeoIP.country_code_by_addr(query)

GeoIP.country_code_by_name(query)

GeoIP.country_name_by_addr(query)

GeoIP.country_name_by_name(query)

Footnotes

[1]

GeoIP(R) is a registered trademark of MaxMind, LLC of Boston, Massachusetts.

Geolocation with GeoIP2

New in Django 1.9.

The GeoIP2 object is a wrapper for the MaxMind geoip2 Python library. [1]

In order to perform IP-based geolocation, the GeoIP2 object requires the geoip2 Python library and the GeoIP Country and/or City datasets in binary format (the CSV files will not work!). Grab the GeoLite2-Country.mmdb.gz and GeoLite2-City.mmdb.gz files and unzip them in a directory corresponding to the GEOIP_PATH setting.

Additionally, it is recommended to install the libmaxminddb C library, so that geoip2 can leverage the C library’s faster speed.

Example

Here is an example of its usage:

>>> from django.contrib.gis.geoip2 import GeoIP2
>>> g = GeoIP2()
>>> g.country('google.com')
{'country_code': 'US', 'country_name': 'United States'}
>>> g.city('72.14.207.99')
{'city': 'Mountain View',
'country_code': 'US',
'country_name': 'United States',
'dma_code': 807,
'latitude': 37.419200897216797,
'longitude': -122.05740356445312,
'postal_code': '94043',
'region': 'CA'}
>>> g.lat_lon('salon.com')
(39.0437, -77.4875)
>>> g.lon_lat('uh.edu')
(-95.4342, 29.834)
>>> g.geos('24.124.1.80').wkt
'POINT (-97.0000000000000000 38.0000000000000000)'

GeoIP Settings

GEOIP_PATH

A string specifying the directory where the GeoIP data files are located. This setting is required unless manually specified with path keyword when initializing the GeoIP2 object.

GEOIP_COUNTRY

The basename to use for the GeoIP country data file. Defaults to 'GeoLite2-Country.mmdb'.

GEOIP_CITY

The basename to use for the GeoIP city data file. Defaults to 'GeoLite2-City.mmdb'.

GeoIP API

class GeoIP2(path=None, cache=0, country=None, city=None)

The GeoIP object does not require any parameters to use the default settings. However, at the very least the GEOIP_PATH setting should be set with the path of the location of your GeoIP datasets. The following initialization keywords may be used to customize any of the defaults.

Keyword Arguments

Description

path

Base directory to where GeoIP data is located or the full path to where the city or country data files (.mmdb) are located. Assumes that both the city and country datasets are located in this directory; overrides the GEOIP_PATH setting.

cache

The cache settings when opening up the GeoIP datasets. May be an integer in (0, 1, 2, 4, 8) corresponding to the MODE_AUTO, MODE_MMAP_EXT, MODE_MMAP, and GEOIP_INDEX_CACHE MODE_MEMORY C API settings, respectively. Defaults to 0 (MODE_AUTO).

country

The name of the GeoIP country data file. Defaults to GeoLite2-Country.mmdb. Setting this keyword overrides the GEOIP_COUNTRY setting.

city

The name of the GeoIP city data file. Defaults to GeoLite2-City.mmdb. Setting this keyword overrides the GEOIP_CITY setting.

GeoIP Methods

Instantiating

classmethod GeoIP2.open(path, cache)

This classmethod instantiates the GeoIP object from the given database path and given cache setting.

Querying

All the following querying routines may take either a string IP address or a fully qualified domain name (FQDN). For example, both '205.186.163.125' and 'djangoproject.com' would be valid query parameters.

GeoIP2.city(query)

Returns a dictionary of city information for the given query. Some of the values in the dictionary may be undefined (None).

GeoIP2.country(query)

Returns a dictionary with the country code and country for the given query.

GeoIP2.country_code(query)

Returns the country code corresponding to the query.

GeoIP2.country_name(query)

Returns the country name corresponding to the query.

Coordinate Retrieval

GeoIP2.coords(query)

Returns a coordinate tuple of (longitude, latitude).

GeoIP2.lon_lat(query)

Returns a coordinate tuple of (longitude, latitude).

GeoIP2.lat_lon(query)

Returns a coordinate tuple of (latitude, longitude),

GeoIP2.geos(query)

Returns a Point object corresponding to the query.

Footnotes

[1]

GeoIP(R) is a registered trademark of MaxMind, Inc.

GeoDjango Utilities

The django.contrib.gis.utils module contains various utilities that are useful in creating geospatial Web applications.

- LayerMapping data import utility

- Example

- LayerMapping API

- Troubleshooting

- OGR Inspection

- ogrinspect

- mapping

- GeoJSON Serializer

LayerMapping data import utility

The LayerMapping class provides a way to map the contents of vector spatial data files (e.g. shapefiles) into GeoDjango models.

This utility grew out of the author’s personal needs to eliminate the code repetition that went into pulling geometries and fields out of a vector layer, converting to another coordinate system (e.g. WGS84), and then inserting into a GeoDjango model.

Note

Use of LayerMapping requires GDAL.

Warning

GIS data sources, like shapefiles, may be very large. If you find that LayerMapping is using too much memory, set DEBUG to False in your settings. When DEBUG is set to True, Django automatically logs every SQL query – thus, when SQL statements contain geometries, it is easy to consume more memory than is typical.

Example

1. You need a GDAL-supported data source, like a shapefile (here we’re using a simple polygon shapefile, test_poly.shp, with three features):

>>> from django.contrib.gis.gdal import DataSource
>>> ds = DataSource('test_poly.shp')
>>> layer = ds[0]
>>> print(layer.fields) # Exploring the fields in the layer, we only want the 'str' field.
['float', 'int', 'str']
>>> print(len(layer)) # getting the number of features in the layer (should be 3)
3
>>> print(layer.geom_type) # Should be 'Polygon'
Polygon
>>> print(layer.srs) # WGS84 in WKT
GEOGCS["GCS_WGS_1984",
DATUM["WGS_1984",
SPHEROID["WGS_1984",6378137,298.257223563]],
PRIMEM["Greenwich",0],
UNIT["Degree",0.017453292519943295]]

2. Now we define our corresponding Django model (make sure to use migrate):

from django.contrib.gis.db import models

class TestGeo(models.Model):
name = models.CharField(max_length=25) # corresponds to the 'str' field
poly = models.PolygonField(srid=4269) # we want our model in a different SRID

def __str__(self):              # __unicode__ on Python 2
return 'Name: %s' % self.name

3. Use LayerMapping to extract all the features and place them in the database:

>>> from django.contrib.gis.utils import LayerMapping
>>> from geoapp.models import TestGeo
>>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field.
'poly' : 'POLYGON', # For geometry fields use OGC name.
} # The mapping is a dictionary
>>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping)
>>> lm.save(verbose=True) # Save the layermap, imports the data.
Saved: Name: 1
Saved: Name: 2
Saved: Name: 3

Here, LayerMapping just transformed the three geometries from the shapefile in their original spatial reference system (WGS84) to the spatial reference system of the GeoDjango model (NAD83). If no spatial reference system is defined for the layer, use the source_srs keyword with a SpatialReference object to specify one.

LayerMapping API

class LayerMapping(model, data_source, mapping, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default')

The following are the arguments and keywords that may be used during instantiation of LayerMapping objects.

Argument

Description

model

The geographic model, not an instance.

data_source

The path to the OGR-supported data source file (e.g., a shapefile). Also accepts django.contrib.gis.gdal.DataSource instances.

mapping

A dictionary: keys are strings corresponding to the model field, and values correspond to string field names for the OGR feature, or if the model field is a geographic then it should correspond to the OGR geometry type, e.g., 'POINT', 'LINESTRING', 'POLYGON'.

Keyword Arguments

layer

The index of the layer to use from the Data Source (defaults to 0)

source_srs

Use this to specify the source SRS manually (for example, some shapefiles don’t come with a '.prj' file). An integer SRID, WKT or PROJ.4 strings, and django.contrib.gis.gdal.SpatialReference objects are accepted.

encoding

Specifies the character set encoding of the strings in the OGR data source. For example, 'latin-1', 'utf-8', and 'cp437' are all valid encoding parameters.

transaction_mode

May be 'commit_on_success' (default) or 'autocommit'.

transform

Setting this to False will disable coordinate transformations. In other words, geometries will be inserted into the database unmodified from their original state in the data source.

unique

Setting this to the name, or a tuple of names, from the given model will create models unique only to the given name(s). Geometries from each feature will be added into the collection associated with the unique model. Forces the transaction mode to be 'autocommit'.

using

Sets the database to use when importing spatial data. Default is 'default'.

save() Keyword Arguments

LayerMapping.save(verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False)

The save() method also accepts keywords. These keywords are used for controlling output logging, error handling, and for importing specific feature ranges.

Save Keyword Arguments

Description

fid_range

May be set with a slice or tuple of (begin, end) feature ID’s to map from the data source. In other words, this keyword enables the user to selectively import a subset range of features in the geographic data source.

progress

When this keyword is set, status information will be printed giving the number of features processed and successfully saved. By default, progress information will be printed every 1000 features processed, however, this default may be overridden by setting this keyword with an integer for the desired interval.

silent

By default, non-fatal error notifications are printed to sys.stdout, but this keyword may be set to disable these notifications.

step

If set with an integer, transactions will occur at every step interval. For example, if step=1000, a commit would occur after the 1,000th feature, the 2,000th feature etc.

stream

Status information will be written to this file handle. Defaults to using sys.stdout, but any object with a write method is supported.

strict

Execution of the model mapping will cease upon the first error encountered. The default value (False) behavior is to attempt to continue.

verbose

If set, information will be printed subsequent to each model save executed on the database.

Troubleshooting

Running out of memory

As noted in the warning at the top of this section, Django stores all SQL queries when DEBUG=True. Set DEBUG=False in your settings, and this should stop excessive memory use when running LayerMapping scripts.

MySQL: max_allowed_packet error

If you encounter the following error when using LayerMapping and MySQL:

OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes")

Then the solution is to increase the value of the max_allowed_packet setting in your MySQL configuration. For example, the default value may be something low like one megabyte – the setting may be modified in MySQL’s configuration file (my.cnf) in the [mysqld] section:

max_allowed_packet = 10M

OGR Inspection

ogrinspect

ogrinspect(data_source, model_name, **kwargs)

mapping

mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False)

GeoJSON Serializer

New in Django 1.8.

GeoDjango provides a specific serializer for the GeoJSON format. See Serializing Django objects for more information on serialization.

The GDAL library is required if any of the serialized geometries need coordinate transformations (that is if the geometry’s spatial reference system differs from the srid serializer option).

Changed in Django 1.9:
The GeoJSON serializer no longer needs GDAL if all geometries are in the same coordinate system as the srid serializer option.

The geojson serializer is not meant for round-tripping data, as it has no deserializer equivalent. For example, you cannot use loaddata to reload the output produced by this serializer. If you plan to reload the outputted data, use the plain json serializer instead.

In addition to the options of the json serializer, the geojson serializer accepts the following additional option when it is called by serializers.serialize():

- geometry_field: A string containing the name of a geometry field to use for the geometry key of the GeoJSON feature. This is only needed when you have a model with more than one geometry field and you don’t want to use the first defined geometry field (by default, the first geometry field is picked).

- srid: The SRID to use for the geometry content. Defaults to 4326 (WGS 84).

The fields option can be used to limit fields that will be present in the properties key, as it works with all other serializers.

Example:

from django.core.serializers import serialize
from my_app.models import City

serialize('geojson', City.objects.all(),
geometry_field='point',
fields=('name',))

Would output:

{
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {'name': 'EPSG:4326'}
},
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-87.650175, 41.850385]
},
'properties': {
'name': 'Chicago'
}
}
]
}

GeoDjango Management Commands

inspectdb

django-admin inspectdb

When django.contrib.gis is in your INSTALLED_APPS, the inspectdb management command is overridden with one from GeoDjango. The overridden command is spatially-aware, and places geometry fields in the auto-generated model definition, where appropriate.

ogrinspect

django-admin ogrinspect data_source model_name

The ogrinspect management command will inspect the given OGR-compatible DataSource (e.g., a shapefile) and will output a GeoDjango model with the given model name. There’s a detailed example of using ogrinspect in the tutorial.

--blank BLANK

Use a comma separated list of OGR field names to add the blank=True keyword option to the field definition. Set with true to apply to all applicable fields.

--decimal DECIMAL

Use a comma separated list of OGR float fields to generate DecimalField instead of the default FloatField. Set to true to apply to all OGR float fields.

--geom-name GEOM_NAME

Specifies the model attribute name to use for the geometry field. Defaults to 'geom'.

--layer LAYER_KEY

The key for specifying which layer in the OGR DataSource source to use. Defaults to 0 (the first layer). May be an integer or a string identifier for the Layer. When inspecting databases, layer is generally the table name you want to inspect.

--mapping

Automatically generate a mapping dictionary for use with LayerMapping.

--multi-geom

When generating the geometry field, treat it as a geometry collection. For example, if this setting is enabled then a MultiPolygonField will be placed in the generated model rather than PolygonField.

--name-field NAME_FIELD

Generates a __str__ routine (__unicode__ on Python 2) on the model that will return the given field name.

--no-imports

Suppresses the from django.contrib.gis.db import models import statement.

--null NULL

Use a comma separated list of OGR field names to add the null=True keyword option to the field definition. Set with true to apply to all applicable fields.

--srid SRID

The SRID to use for the geometry field. If not set, ogrinspect attempts to automatically determine of the SRID of the data source.

GeoDjango’s admin site

GeoModelAdmin

class GeoModelAdmin

default_lon

The default center longitude.

default_lat

The default center latitude.

default_zoom

The default zoom level to use. Defaults to 4.

extra_js

Sequence of URLs to any extra JavaScript to include.

map_template

Override the template used to generate the JavaScript slippy map. Default is 'gis/admin/openlayers.html'.

map_width

Width of the map, in pixels. Defaults to 600.

map_height

Height of the map, in pixels. Defaults to 400.

openlayers_url

Link to the URL of the OpenLayers JavaScript. Defaults to 'http://openlayers.org/api/2.13/OpenLayers.js'.

modifiable

Defaults to True. When set to False, disables editing of existing geometry fields in the admin.

Note

This is different from adding the geometry field to readonly_fields, which will only display the WKT of the geometry. Setting modifiable=False, actually displays the geometry in a map, but disables the ability to edit its vertices.

OSMGeoAdmin

class OSMGeoAdmin

A subclass of GeoModelAdmin that uses a spherical mercator projection with OpenStreetMap street data tiles. See the OSMGeoAdmin introduction in the tutorial for a usage example.

Geographic Feeds

GeoDjango has its own Feed subclass that may embed location information in RSS/Atom feeds formatted according to either the Simple GeoRSS or W3C Geo standards. Because GeoDjango’s syndication API is a superset of Django’s, please consult Django’s syndication documentation for details on general usage.

Example

API Reference

Feed Subclass

class Feed[source]

In addition to methods provided by the django.contrib.syndication.views.Feed base class, GeoDjango’s Feed class provides the following overrides. Note that these overrides may be done in multiple ways:

from django.contrib.gis.feeds import Feed

class MyFeed(Feed):

# First, as a class attribute.
geometry = ...
item_geometry = ...

# Also a function with no arguments
def geometry(self):
...

def item_geometry(self):
...

# And as a function with a single argument
def geometry(self, obj):
...

def item_geometry(self, item):
...

geometry(obj)

Takes the object returned by get_object() and returns the feed’s geometry. Typically this is a GEOSGeometry instance, or can be a tuple to represent a point or a box. For example:

class ZipcodeFeed(Feed):

def geometry(self, obj):
# Can also return: `obj.poly`, and `obj.poly.centroid`.
return obj.poly.extent # tuple like: (X0, Y0, X1, Y1).

item_geometry(item)

Set this to return the geometry for each item in the feed. This can be a GEOSGeometry instance, or a tuple that represents a point coordinate or bounding box. For example:

class ZipcodeFeed(Feed):

def item_geometry(self, obj):
# Returns the polygon.
return obj.poly

SyndicationFeed Subclasses

The following django.utils.feedgenerator.SyndicationFeed subclasses are available:

class GeoRSSFeed[source]

class GeoAtom1Feed[source]

class W3CGeoFeed[source]

Note

W3C Geo formatted feeds only support PointField geometries.

Geographic Sitemaps

KML is an XML language focused on geographic visualization [1]. KMLSitemap and its compressed counterpart KMZSitemap allow you to present geolocated data in a machine-readable format.

Example

Reference

KMLSitemap

KMZSitemap

Footnotes

[1]

http://www.opengeospatial.org/standards/kml

Testing GeoDjango apps

Included in this documentation are some additional notes and settings for PostGIS users.

PostGIS

Settings

Note

The settings below have sensible defaults, and shouldn’t require manual setting.

POSTGIS_VERSION

When GeoDjango’s spatial backend initializes on PostGIS, it has to perform an SQL query to determine the version in order to figure out what features are available. Advanced users wishing to prevent this additional query may set the version manually using a 3-tuple of integers specifying the major, minor, and micro version numbers for PostGIS. For example, to configure for PostGIS X.Y.Z you would use:

POSTGIS_VERSION = (X, Y, Z)

Obtaining sufficient privileges

Depending on your configuration, this section describes several methods to configure a database user with sufficient privileges to run tests for GeoDjango applications on PostgreSQL. If your spatial database template was created like in the instructions, then your testing database user only needs to have the ability to create databases. In other configurations, you may be required to use a database superuser.

Create database user

To make a database user with the ability to create databases, use the following command:

$ createuser --createdb -R -S <user_name>

The -R -S flags indicate that we do not want the user to have the ability to create additional users (roles) or to be a superuser, respectively.

Alternatively, you may alter an existing user’s role from the SQL shell (assuming this is done from an existing superuser account):

postgres# ALTER ROLE <user_name> CREATEDB NOSUPERUSER NOCREATEROLE;

Create database superuser

This may be done at the time the user is created, for example:

$ createuser --superuser <user_name>

Or you may alter the user’s role from the SQL shell (assuming this is done from an existing superuser account):

postgres# ALTER ROLE <user_name> SUPERUSER;

Windows

On Windows platforms the pgAdmin III utility may also be used as a simple way to add superuser privileges to your database user.

By default, the PostGIS installer on Windows includes a template spatial database entitled template_postgis.

GeoDjango tests

To have the GeoDjango tests executed when running the Django test suite with runtests.py all of the databases in the settings file must be using one of the spatial database backends.

Example

The following is an example bare-bones settings file with spatial backends that can be used to run the entire Django test suite, including those in django.contrib.gis:

DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'geodjango',
'USER': 'geodjango',
},
'other': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'other',
'USER': 'geodjango',
},
}

SECRET_KEY = 'django_tests_secret_key'

Assuming the settings above were in a postgis.py file in the same directory as runtests.py, then all Django and GeoDjango tests would be performed when executing the command:

$ ./runtests.py --settings=postgis

To run only the GeoDjango test suite, specify gis_tests:

$ ./runtests.py --settings=postgis gis_tests

Deploying GeoDjango

Basically, the deployment of a GeoDjango application is not different from the deployment of a normal Django application. Please consult Django’s deployment documentation.

Warning

GeoDjango uses the GDAL geospatial library which is not thread safe at this time. Thus, it is highly recommended to not use threading when deploying – in other words, use an appropriate configuration of Apache.

For example, when configuring your application with mod_wsgi, set the WSGIDaemonProcess attribute threads to 1, unless Apache may crash when running your GeoDjango application. Increase the number of processes instead.

django.contrib.humanize

A set of Django template filters useful for adding a “human touch” to data.

To activate these filters, add 'django.contrib.humanize' to your INSTALLED_APPS setting. Once you’ve done that, use {% load humanize %} in a template, and you’ll have access to the following filters.

apnumber

For numbers 1-9, returns the number spelled out. Otherwise, returns the number. This follows Associated Press style.

Examples:

- 1 becomes one.

- 2 becomes two.

- 10 becomes 10.

You can pass in either an integer or a string representation of an integer.

intcomma

Converts an integer to a string containing commas every three digits.

Examples:

- 4500 becomes 4,500.

- 45000 becomes 45,000.

- 450000 becomes 450,000.

- 4500000 becomes 4,500,000.

Format localization will be respected if enabled, e.g. with the 'de' language:

- 45000 becomes '45.000'.

- 450000 becomes '450.000'.

You can pass in either an integer or a string representation of an integer.

intword

Converts a large integer to a friendly text representation. Works best for numbers over 1 million.

Examples:

- 1000000 becomes 1.0 million.

- 1200000 becomes 1.2 million.

- 1200000000 becomes 1.2 billion.

Values up to 10^100 (Googol) are supported.

Format localization will be respected if enabled, e.g. with the 'de' language:

- 1000000 becomes '1,0 Million'.

- 1200000 becomes '1,2 Million'.

- 1200000000 becomes '1,2 Milliarden'.

You can pass in either an integer or a string representation of an integer.

naturalday

For dates that are the current day or within one day, return “today”, “tomorrow” or “yesterday”, as appropriate. Otherwise, format the date using the passed in format string.

Argument: Date formatting string as described in the date tag.

Examples (when ‘today’ is 17 Feb 2007):

- 16 Feb 2007 becomes yesterday.

- 17 Feb 2007 becomes today.

- 18 Feb 2007 becomes tomorrow.

- Any other day is formatted according to given argument or the DATE_FORMAT setting if no argument is given.

naturaltime

For datetime values, returns a string representing how many seconds, minutes or hours ago it was – falling back to the timesince format if the value is more than a day old. In case the datetime value is in the future the return value will automatically use an appropriate phrase.

Examples (when ‘now’ is 17 Feb 2007 16:30:00):

- 17 Feb 2007 16:30:00 becomes now.

- 17 Feb 2007 16:29:31 becomes 29 seconds ago.

- 17 Feb 2007 16:29:00 becomes a minute ago.

- 17 Feb 2007 16:25:35 becomes 4 minutes ago.

- 17 Feb 2007 15:30:29 becomes 59 minutes ago.

- 17 Feb 2007 15:30:01 becomes 59 minutes ago.

- 17 Feb 2007 15:30:00 becomes an hour ago.

- 17 Feb 2007 13:31:29 becomes 2 hours ago.

- 16 Feb 2007 13:31:29 becomes 1 day, 2 hours ago.

- 16 Feb 2007 13:30:01 becomes 1 day, 2 hours ago.

- 16 Feb 2007 13:30:00 becomes 1 day, 3 hours ago.

- 17 Feb 2007 16:30:30 becomes 30 seconds from now.

- 17 Feb 2007 16:30:29 becomes 29 seconds from now.

- 17 Feb 2007 16:31:00 becomes a minute from now.

- 17 Feb 2007 16:34:35 becomes 4 minutes from now.

- 17 Feb 2007 17:30:29 becomes an hour from now.

- 17 Feb 2007 18:31:29 becomes 2 hours from now.

- 18 Feb 2007 16:31:29 becomes 1 day from now.

- 26 Feb 2007 18:31:29 becomes 1 week, 2 days from now.

ordinal

Converts an integer to its ordinal as a string.

Examples:

- 1 becomes 1st.

- 2 becomes 2nd.

- 3 becomes 3rd.

You can pass in either an integer or a string representation of an integer.

The messages framework

Quite commonly in web applications, you need to display a one-time notification message (also known as “flash message”) to the user after processing a form or some other types of user input.

For this, Django provides full support for cookie- and session-based messaging, for both anonymous and authenticated users. The messages framework allows you to temporarily store messages in one request and retrieve them for display in a subsequent request (usually the next one). Every message is tagged with a specific level that determines its priority (e.g., info, warning, or error).

Enabling messages

Messages are implemented through a middleware class and corresponding context processor.

The default settings.py created by django-admin startproject already contains all the settings required to enable message functionality:

- 'django.contrib.messages' is in INSTALLED_APPS.

- MIDDLEWARE_CLASSES contains 'django.contrib.sessions.middleware.SessionMiddleware' and 'django.contrib.messages.middleware.MessageMiddleware'.

The default storage backend relies on sessions. That’s why SessionMiddleware must be enabled and appear before MessageMiddleware in MIDDLEWARE_CLASSES.

- The 'context_processors' option of the DjangoTemplates backend defined in your TEMPLATES setting contains 'django.contrib.messages.context_processors.messages'.

If you don’t want to use messages, you can remove 'django.contrib.messages' from your INSTALLED_APPS, the MessageMiddleware line from MIDDLEWARE_CLASSES, and the messages context processor from TEMPLATES.

Configuring the message engine

Storage backends

The messages framework can use different backends to store temporary messages.

Django provides three built-in storage classes in django.contrib.messages:

class storage.session.SessionStorage

This class stores all messages inside of the request’s session. Therefore it requires Django’s contrib.sessions application.

class storage.cookie.CookieStorage

This class stores the message data in a cookie (signed with a secret hash to prevent manipulation) to persist notifications across requests. Old messages are dropped if the cookie data size would exceed 2048 bytes.

class storage.fallback.FallbackStorage

This class first uses CookieStorage, and falls back to using SessionStorage for the messages that could not fit in a single cookie. It also requires Django’s contrib.sessions application.

This behavior avoids writing to the session whenever possible. It should provide the best performance in the general case.

FallbackStorage is the default storage class. If it isn’t suitable to your needs, you can select another storage class by setting MESSAGE_STORAGE to its full import path, for example:

MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'

class storage.base.BaseStorage

To write your own storage class, subclass the BaseStorage class in django.contrib.messages.storage.base and implement the _get and _store methods.

Message levels

The messages framework is based on a configurable level architecture similar to that of the Python logging module. Message levels allow you to group messages by type so they can be filtered or displayed differently in views and templates.

The built-in levels, which can be imported from django.contrib.messages directly, are:

Constant

Purpose

DEBUG

Development-related messages that will be ignored (or removed) in a production deployment

INFO

Informational messages for the user

SUCCESS

An action was successful, e.g. “Your profile was updated successfully”

WARNING

A failure did not occur but may be imminent

ERROR

An action was not successful or some other failure occurred

The MESSAGE_LEVEL setting can be used to change the minimum recorded level (or it can be changed per request). Attempts to add messages of a level less than this will be ignored.

Message tags

Message tags are a string representation of the message level plus any extra tags that were added directly in the view (see Adding extra message tags below for more details). Tags are stored in a string and are separated by spaces. Typically, message tags are used as CSS classes to customize message style based on message type. By default, each level has a single tag that’s a lowercase version of its own constant:

Level Constant

Tag

DEBUG

debug

INFO

info

SUCCESS

success

WARNING

warning

ERROR

error

To change the default tags for a message level (either built-in or custom), set the MESSAGE_TAGS setting to a dictionary containing the levels you wish to change. As this extends the default tags, you only need to provide tags for the levels you wish to override:

from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.INFO: '',
50: 'critical',
}

Using messages in views and templates

add_message(request, level, message, extra_tags='', fail_silently=False)[source]

Adding a message

To add a message, call:

from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')

Some shortcut methods provide a standard way to add messages with commonly used tags (which are usually represented as HTML classes for the message):

messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')

Displaying messages

get_messages(request)[source]

In your template, use something like:

{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

If you’re using the context processor, your template should be rendered with a RequestContext. Otherwise, ensure messages is available to the template context.

Even if you know there is only just one message, you should still iterate over the messages sequence, because otherwise the message storage will not be cleared for the next request.

The context processor also provides a DEFAULT_MESSAGE_LEVELS variable which is a mapping of the message level names to their numeric value:

{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}

Outside of templates, you can use get_messages():

from django.contrib.messages import get_messages

storage = get_messages(request)
for message in storage:
do_something_with_the_message(message)

For instance, you can fetch all the messages to return them in a JSONResponseMixin instead of a TemplateResponseMixin.

get_messages() will return an instance of the configured storage backend.

The Message class

class storage.base.Message

When you loop over the list of messages in a template, what you get are instances of the Message class. It’s quite a simple object, with only a few attributes:

- message: The actual text of the message.

- level: An integer describing the type of the message (see the message levels section above).

- tags: A string combining all the message’s tags (extra_tags and level_tag) separated by spaces.

- extra_tags: A string containing custom tags for this message, separated by spaces. It’s empty by default.

- level_tag: The string representation of the level. By default, it’s the lowercase version of the name of the associated constant, but this can be changed if you need by using the MESSAGE_TAGS setting.

Creating custom message levels

Messages levels are nothing more than integers, so you can define your own level constants and use them to create more customized user feedback, e.g.:

CRITICAL = 50

def my_view(request):
messages.add_message(request, CRITICAL, 'A serious error occurred.')

When creating custom message levels you should be careful to avoid overloading existing levels. The values for the built-in levels are:

Level Constant

Value

DEBUG

10

INFO

20

SUCCESS

25

WARNING

30

ERROR

40

If you need to identify the custom levels in your HTML or CSS, you need to provide a mapping via the MESSAGE_TAGS setting.

Note

If you are creating a reusable application, it is recommended to use only the built-in message levels and not rely on any custom levels.

Changing the minimum recorded level per-request

The minimum recorded level can be set per request via the set_level method:

from django.contrib import messages

# Change the messages level to ensure the debug message is added.
messages.set_level(request, messages.DEBUG)
messages.debug(request, 'Test message...')

# In another request, record only messages with a level of WARNING and higher
messages.set_level(request, messages.WARNING)
messages.success(request, 'Your profile was updated.') # ignored
messages.warning(request, 'Your account is about to expire.') # recorded

# Set the messages level back to default.
messages.set_level(request, None)

Similarly, the current effective level can be retrieved with get_level:

from django.contrib import messages
current_level = messages.get_level(request)

For more information on how the minimum recorded level functions, see Message levels above.

Adding extra message tags

For more direct control over message tags, you can optionally provide a string containing extra tags to any of the add methods:

messages.add_message(request, messages.INFO, 'Over 9000!', extra_tags='dragonball')
messages.error(request, 'Email box full', extra_tags='email')

Extra tags are added before the default tag for that level and are space separated.

Failing silently when the message framework is disabled

If you’re writing a reusable app (or other piece of code) and want to include messaging functionality, but don’t want to require your users to enable it if they don’t want to, you may pass an additional keyword argument fail_silently=True to any of the add_message family of methods. For example:

messages.add_message(
request, messages.SUCCESS, 'Profile details updated.',
fail_silently=True,
)
messages.info(request, 'Hello world.', fail_silently=True)

Note

Setting fail_silently=True only hides the MessageFailure that would otherwise occur when the messages framework disabled and one attempts to use one of the add_message family of methods. It does not hide failures that may occur for other reasons.

Adding messages in class-based views

class views.SuccessMessageMixin

Adds a success message attribute to FormView based classes

get_success_message(cleaned_data)

cleaned_data is the cleaned data from the form which is used for string formatting

Example views.py:

from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(SuccessMessageMixin, CreateView):
model = Author
success_url = '/success/'
success_message = "%(name)s was created successfully"

The cleaned data from the form is available for string interpolation using the %(field_name)s syntax. For ModelForms, if you need access to fields from the saved object override the get_success_message() method.

Example views.py for ModelForms:

from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import ComplicatedModel

class ComplicatedCreate(SuccessMessageMixin, CreateView):
model = ComplicatedModel
success_url = '/success/'
success_message = "%(calculated_field)s was created successfully"

def get_success_message(self, cleaned_data):
return self.success_message % dict(
cleaned_data,
calculated_field=self.object.calculated_field,
)

Expiration of messages

The messages are marked to be cleared when the storage instance is iterated (and cleared when the response is processed).

To avoid the messages being cleared, you can set the messages storage to False after iterating:

storage = messages.get_messages(request)
for message in storage:
do_something_with(message)
storage.used = False

Behavior of parallel requests

Due to the way cookies (and hence sessions) work, the behavior of any backends that make use of cookies or sessions is undefined when the same client makes multiple requests that set or get messages in parallel. For example, if a client initiates a request that creates a message in one window (or tab) and then another that fetches any uniterated messages in another window, before the first window redirects, the message may appear in the second window instead of the first window where it may be expected.

In short, when multiple simultaneous requests from the same client are involved, messages are not guaranteed to be delivered to the same window that created them nor, in some cases, at all. Note that this is typically not a problem in most applications and will become a non-issue in HTML5, where each window/tab will have its own browsing context.

Settings

A few settings give you control over message behavior:

- MESSAGE_LEVEL

- MESSAGE_STORAGE

- MESSAGE_TAGS

For backends that use cookies, the settings for the cookie are taken from the session cookie settings:

- SESSION_COOKIE_DOMAIN

- SESSION_COOKIE_SECURE

- SESSION_COOKIE_HTTPONLY

django.contrib.postgres

New in Django 1.8.

PostgreSQL has a number of features which are not shared by the other databases Django supports. This optional module contains model fields and form fields for a number of PostgreSQL specific data types.

Psycopg2 2.5 or higher is required, though we highly recommend using the latest release. Some fields require higher versions.

Note

Django is, and will continue to be, a database-agnostic web framework. We would encourage those writing reusable applications for the Django community to write database-agnostic code where practical. However, we recognize that real world projects written using Django need not be database-agnostic. In fact, once a project reaches a given size changing the underlying data store is already a significant challenge and is likely to require changing the code base in some ways to handle differences between the data stores.

Django provides support for a number of data types which will only work with PostgreSQL. There is no fundamental reason why (for example) a contrib.mysql module does not exist, except that PostgreSQL has the richest feature set of the supported databases so its users have the most to gain.

- PostgreSQL specific aggregation functions

- General-purpose aggregation functions

- Aggregate functions for statistics

- Usage examples

- PostgreSQL specific model fields

- ArrayField

- HStoreField

- JSONField

- Range Fields

- PostgreSQL specific form fields and widgets

- Fields

- Widgets

- PostgreSQL specific database functions

- TransactionNow

- PostgreSQL specific lookups

- Unaccent

- Database migration operations

- CreateExtension

- HStoreExtension

- UnaccentExtension

- Validators

- KeysValidator

- Range validators

PostgreSQL specific aggregation functions

New in Django 1.9.

These functions are described in more detail in the PostgreSQL docs.

Note

All functions come without default aliases, so you must explicitly provide one. For example:

>>> SomeModel.objects.aggregate(arr=ArrayAgg('somefield'))
{'arr': [0, 1, 2]}

General-purpose aggregation functions

ArrayAgg

class ArrayAgg(expression, **extra)

Returns a list of values, including nulls, concatenated into an array.

BitAnd

class BitAnd(expression, **extra)

Returns an int of the bitwise AND of all non-null input values, or None if all values are null.

BitOr

class BitOr(expression, **extra)

Returns an int of the bitwise OR of all non-null input values, or None if all values are null.

BoolAnd

class BoolAnd(expression, **extra)

Returns True, if all input values are true, None if all values are null or if there are no values, otherwise False .

BoolOr

class BoolOr(expression, **extra)

Returns True if at least one input value is true, None if all values are null or if there are no values, otherwise False.

StringAgg

class StringAgg(expression, delimiter)

Returns the input values concatenated into a string, separated by the delimiter string.

delimiter

Required argument. Needs to be a string.

Aggregate functions for statistics

y and x

The arguments y and x for all these functions can be the name of a field or an expression returning a numeric data. Both are required.

Corr

class Corr(y, x)

Returns the correlation coefficient as a float, or None if there aren’t any matching rows.

CovarPop

class CovarPop(y, x, sample=False)

Returns the population covariance as a float, or None if there aren’t any matching rows.

Has one optional argument:

sample

By default CovarPop returns the general population covariance. However, if sample=True, the return value will be the sample population covariance.

RegrAvgX

class RegrAvgX(y, x)

Returns the average of the independent variable (sum(x)/N) as a float, or None if there aren’t any matching rows.

RegrAvgY

class RegrAvgY(y, x)

Returns the average of the dependent variable (sum(y)/N) as a float, or None if there aren’t any matching rows.

RegrCount

class RegrCount(y, x)

Returns an int of the number of input rows in which both expressions are not null.

RegrIntercept

class RegrIntercept(y, x)

Returns the y-intercept of the least-squares-fit linear equation determined by the (x, y) pairs as a float, or None if there aren’t any matching rows.

RegrR2

class RegrR2(y, x)

Returns the square of the correlation coefficient as a float, or None if there aren’t any matching rows.

RegrSlope

class RegrSlope(y, x)

Returns the slope of the least-squares-fit linear equation determined by the (x, y) pairs as a float, or None if there aren’t any matching rows.

RegrSXX

class RegrSXX(y, x)

Returns sum(x^2) - sum(x)^2/N (“sum of squares” of the independent variable) as a float, or None if there aren’t any matching rows.

RegrSXY

class RegrSXY(y, x)

Returns sum(x*y) - sum(x) * sum(y)/N (“sum of products” of independent times dependent variable) as a float, or None if there aren’t any matching rows.

RegrSYY

class RegrSYY(y, x)

Returns sum(y^2) - sum(y)^2/N (“sum of squares” of the dependent variable) as a float, or None if there aren’t any matching rows.

Usage examples

We will use this example table:

| FIELD1 | FIELD2 | FIELD3 |
|--------|--------|--------|
|    foo |      1 |     13 |
|    bar |      2 | (null) |
|   test |      3 |     13 |

Here’s some examples of some of the general-purpose aggregation functions:

>>> TestModel.objects.aggregate(result=StringAgg('field1', delimiter=';'))
{'result': 'foo;bar;test'}
>>> TestModel.objects.aggregate(result=ArrayAgg('field2'))
{'result': [1, 2, 3]}
>>> TestModel.objects.aggregate(result=ArrayAgg('field1'))
{'result': ['foo', 'bar', 'test']}

The next example shows the usage of statistical aggregate functions. The underlying math will be not described (you can read about this, for example, at wikipedia):

>>> TestModel.objects.aggregate(count=RegrCount(y='field3', x='field2'))
{'count': 2}
>>> TestModel.objects.aggregate(avgx=RegrAvgX(y='field3', x='field2'),
...                             avgy=RegrAvgY(y='field3', x='field2'))
{'avgx': 2, 'avgy': 13}

PostgreSQL specific model fields

All of these fields are available from the django.contrib.postgres.fields module.

ArrayField

class ArrayField(base_field, size=None, **options)

A field for storing lists of data. Most field types can be used, you simply pass another field instance as the base_field. You may also specify a size. ArrayField can be nested to store multi-dimensional arrays.

If you give the field a default, ensure it’s a callable such as list (for an empty default) or a callable that returns a list (such as a function). Incorrectly using default=[] creates a mutable default that is shared between all instances of ArrayField.

base_field

This is a required argument.

Specifies the underlying data type and behavior for the array. It should be an instance of a subclass of Field. For example, it could be an IntegerField or a CharField. Most field types are permitted, with the exception of those handling relational data (ForeignKey, OneToOneField and ManyToManyField).

It is possible to nest array fields - you can specify an instance of ArrayField as the base_field. For example:

from django.db import models
from django.contrib.postgres.fields import ArrayField

class ChessBoard(models.Model):
board = ArrayField(
ArrayField(
models.CharField(max_length=10, blank=True),
size=8,
),
size=8,
)

Transformation of values between the database and the model, validation of data and configuration, and serialization are all delegated to the underlying base field.

size

This is an optional argument.

If passed, the array will have a maximum size as specified. This will be passed to the database, although PostgreSQL at present does not enforce the restriction.

Note

When nesting ArrayField, whether you use the size parameter or not, PostgreSQL requires that the arrays are rectangular:

from django.contrib.postgres.fields import ArrayField
from django.db import models

class Board(models.Model):
pieces = ArrayField(ArrayField(models.IntegerField()))

# Valid
Board(pieces=[
[2, 3],
[2, 1],
])

# Not valid
Board(pieces=[
[2, 3],
[2],
])

If irregular shapes are required, then the underlying field should be made nullable and the values padded with None.

Querying ArrayField

There are a number of custom lookups and transforms for ArrayField. We will use the following example model:

from django.db import models
from django.contrib.postgres.fields import ArrayField

class Post(models.Model):
name = models.CharField(max_length=200)
tags = ArrayField(models.CharField(max_length=200), blank=True)

def __str__(self):  # __unicode__ on Python 2
return self.name

contains

The contains lookup is overridden on ArrayField. The returned objects will be those where the values passed are a subset of the data. It uses the SQL operator @>. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])

>>> Post.objects.filter(tags__contains=['thoughts'])
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__contains=['django'])
[<Post: First post>, <Post: Third post>]

>>> Post.objects.filter(tags__contains=['django', 'thoughts'])
[<Post: First post>]

contained_by

This is the inverse of the contains lookup - the objects returned will be those where the data is a subset of the values passed. It uses the SQL operator <@. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])

>>> Post.objects.filter(tags__contained_by=['thoughts', 'django'])
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__contained_by=['thoughts', 'django', 'tutorial'])
[<Post: First post>, <Post: Second post>, <Post: Third post>]

overlap

Returns objects where the data shares any results with the values passed. Uses the SQL operator &&. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])

>>> Post.objects.filter(tags__overlap=['thoughts'])
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
[<Post: First post>, <Post: Second post>, <Post: Third post>]

len

Returns the length of the array. The lookups available afterwards are those available for IntegerField. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])

>>> Post.objects.filter(tags__len=1)
[<Post: Second post>]

Index transforms

This class of transforms allows you to index into the array in queries. Any non-negative integer can be used. There are no errors if it exceeds the size of the array. The lookups available after the transform are those from the base_field. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])

>>> Post.objects.filter(tags__0='thoughts')
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__1__iexact='Django')
[<Post: First post>]

>>> Post.objects.filter(tags__276='javascript')
[]

Note

PostgreSQL uses 1-based indexing for array fields when writing raw SQL. However these indexes and those used in slices use 0-based indexing to be consistent with Python.

Slice transforms

This class of transforms allow you to take a slice of the array. Any two non-negative integers can be used, separated by a single underscore. The lookups available after the transform do not change. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['django', 'python', 'thoughts'])

>>> Post.objects.filter(tags__0_1=['thoughts'])
[<Post: First post>, <Post: Second post>]

>>> Post.objects.filter(tags__0_2__contains=['thoughts'])
[<Post: First post>, <Post: Second post>]

Note

PostgreSQL uses 1-based indexing for array fields when writing raw SQL. However these slices and those used in indexes use 0-based indexing to be consistent with Python.

Multidimensional arrays with indexes and slices

PostgreSQL has some rather esoteric behavior when using indexes and slices on multidimensional arrays. It will always work to use indexes to reach down to the final underlying data, but most other slices behave strangely at the database level and cannot be supported in a logical, consistent fashion by Django.

Indexing ArrayField

At present using db_index will create a btree index. This does not offer particularly significant help to querying. A more useful index is a GIN index, which you should create using a RunSQL operation.

HStoreField

class HStoreField(**options)

A field for storing mappings of strings to strings. The Python data type used is a dict.

To use this field, you’ll need to:

1. Add 'django.contrib.postgres' in your INSTALLED_APPS.

2. Setup the hstore extension in PostgreSQL before the first CreateModel or AddField operation by adding a migration with the HStoreExtension operation. For example:

from django.contrib.postgres.operations import HStoreExtension

class Migration(migrations.Migration):
...

operations = [
HStoreExtension(),
...
]

Creating the extension requires a database user with superuser privileges. If the Django database user doesn’t have superuser privileges, you’ll have to create the extension outside of Django migrations with a user that has the appropriate privileges. In that case, connect to your Django database and run the query CREATE EXTENSION IF NOT EXISTS hstore;

You’ll see an error like can't adapt type 'dict' if you skip the first step, or type "hstore" does not exist if you skip the second.

Note

On occasions it may be useful to require or restrict the keys which are valid for a given field. This can be done using the KeysValidator.

Querying HStoreField

In addition to the ability to query by key, there are a number of custom lookups available for HStoreField.

We will use the following example model:

from django.contrib.postgres.fields import HStoreField
from django.db import models

class Dog(models.Model):
name = models.CharField(max_length=200)
data = HStoreField()

def __str__(self):  # __unicode__ on Python 2
return self.name

Key lookups

To query based on a given key, you simply use that key as the lookup name:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})

>>> Dog.objects.filter(data__breed='collie')
[<Dog: Meg>]

You can chain other lookups after key lookups:

>>> Dog.objects.filter(data__breed__contains='l')
[<Dog: Rufus>, <Dog: Meg>]

If the key you wish to query by clashes with the name of another lookup, you need to use the hstorefield.contains lookup instead.

Warning

Since any string could be a key in a hstore value, any lookup other than those listed below will be interpreted as a key lookup. No errors are raised. Be extra careful for typing mistakes, and always check your queries work as you intend.

contains

The contains lookup is overridden on HStoreField. The returned objects are those where the given dict of key-value pairs are all contained in the field. It uses the SQL operator @>. For example:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
>>> Dog.objects.create(name='Fred', data={})

>>> Dog.objects.filter(data__contains={'owner': 'Bob'})
[<Dog: Rufus>, <Dog: Meg>]

>>> Dog.objects.filter(data__contains={'breed': 'collie'})
[<Dog: Meg>]

contained_by

This is the inverse of the contains lookup - the objects returned will be those where the key-value pairs on the object are a subset of those in the value passed. It uses the SQL operator <@. For example:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
>>> Dog.objects.create(name='Fred', data={})

>>> Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'})
[<Dog: Meg>, <Dog: Fred>]

>>> Dog.objects.filter(data__contained_by={'breed': 'collie'})
[<Dog: Fred>]

has_key

Returns objects where the given key is in the data. Uses the SQL operator ?. For example:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})

>>> Dog.objects.filter(data__has_key='owner')
[<Dog: Meg>]

has_any_keys

New in Django 1.9.

Returns objects where any of the given keys are in the data. Uses the SQL operator ?|. For example:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
>>> Dog.objects.create(name='Meg', data={'owner': 'Bob'})
>>> Dog.objects.create(name='Fred', data={})

>>> Dog.objects.filter(data__has_any_keys=['owner', 'breed'])
[<Dog: Rufus>, <Dog: Meg>]

has_keys

Returns objects where all of the given keys are in the data. Uses the SQL operator ?&. For example:

>>> Dog.objects.create(name='Rufus', data={})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})

>>> Dog.objects.filter(data__has_keys=['breed', 'owner'])
[<Dog: Meg>]

keys

Returns objects where the array of keys is the given value. Note that the order is not guaranteed to be reliable, so this transform is mainly useful for using in conjunction with lookups on ArrayField. Uses the SQL function akeys(). For example:

>>> Dog.objects.create(name='Rufus', data={'toy': 'bone'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})

>>> Dog.objects.filter(data__keys__overlap=['breed', 'toy'])
[<Dog: Rufus>, <Dog: Meg>]

values

Returns objects where the array of values is the given value. Note that the order is not guaranteed to be reliable, so this transform is mainly useful for using in conjunction with lookups on ArrayField. Uses the SQL function avalues(). For example:

>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})

>>> Dog.objects.filter(data__values__contains=['collie'])
[<Dog: Meg>]

JSONField

New in Django 1.9.

class JSONField(**options)

A field for storing JSON encoded data. In Python the data is represented in its Python native format: dictionaries, lists, strings, numbers, booleans and None.

If you want to store other data types, you’ll need to serialize them first. For example, you might cast a datetime to a string. You might also want to convert the string back to a datetime when you retrieve the data from the database. There are some third-party JSONField implementations which do this sort of thing automatically.

If you give the field a default, ensure it’s a callable such as dict (for an empty default) or a callable that returns a dict (such as a function). Incorrectly using default={} creates a mutable default that is shared between all instances of JSONField.

Note

PostgreSQL has two native JSON based data types: json and jsonb. The main difference between them is how they are stored and how they can be queried. PostgreSQL’s json field is stored as the original string representation of the JSON and must be decoded on the fly when queried based on keys. The jsonb field is stored based on the actual structure of the JSON which allows indexing. The trade-off is a small additional cost on writing to the jsonb field. JSONField uses jsonb.

As a result, this field requires PostgreSQL ≥ 9.4 and Psycopg2 ≥ 2.5.4.

Querying JSONField

We will use the following example model:

from django.contrib.postgres.fields import JSONField
from django.db import models

class Dog(models.Model):
name = models.CharField(max_length=200)
data = JSONField()

def __str__(self):  # __unicode__ on Python 2
return self.name

Key, index, and path lookups

To query based on a given dictionary key, simply use that key as the lookup name:

>>> Dog.objects.create(name='Rufus', data={
...     'breed': 'labrador',
...     'owner': {
...         'name': 'Bob',
...         'other_pets': [{
...             'name': 'Fishy',
...         }],
...     },
... })
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})

>>> Dog.objects.filter(data__breed='collie')
[<Dog: Meg>]

Multiple keys can be chained together to form a path lookup:

>>> Dog.objects.filter(data__owner__name='Bob')
[<Dog: Rufus>]

If the key is an integer, it will be interpreted as an index lookup in an array:

>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
[<Dog: Rufus>]

If the key you wish to query by clashes with the name of another lookup, use the jsonfield.contains lookup instead.

If only one key or index is used, the SQL operator -> is used. If multiple operators are used then the #> operator is used.

Warning

Since any string could be a key in a JSON object, any lookup other than those listed below will be interpreted as a key lookup. No errors are raised. Be extra careful for typing mistakes, and always check your queries work as you intend.

Containment and key operations

JSONField shares lookups relating to containment and keys with HStoreField.

- contains (accepts any JSON rather than just a dictionary of strings)

- contained_by (accepts any JSON rather than just a dictionary of strings)

- has_key

- has_any_keys

- has_keys

Range Fields

There are five range field types, corresponding to the built-in range types in PostgreSQL. These fields are used to store a range of values; for example the start and end timestamps of an event, or the range of ages an activity is suitable for.

All of the range fields translate to psycopg2 Range objects in python, but also accept tuples as input if no bounds information is necessary. The default is lower bound included, upper bound excluded; that is, [).

IntegerRangeField

class IntegerRangeField(**options)

Stores a range of integers. Based on an IntegerField. Represented by an int4range in the database and a NumericRange in Python.

Regardless of the bounds specified when saving the data, PostgreSQL always returns a range in a canonical form that includes the lower bound and excludes the upper bound; that is [).

BigIntegerRangeField

class BigIntegerRangeField(**options)

Stores a range of large integers. Based on a BigIntegerField. Represented by an int8range in the database and a NumericRange in Python.

Regardless of the bounds specified when saving the data, PostgreSQL always returns a range in a canonical form that includes the lower bound and excludes the upper bound; that is [).

FloatRangeField

class FloatRangeField(**options)

Stores a range of floating point values. Based on a FloatField. Represented by a numrange in the database and a NumericRange in Python.

DateTimeRangeField

class DateTimeRangeField(**options)

Stores a range of timestamps. Based on a DateTimeField. Represented by a tztsrange in the database and a DateTimeTZRange in Python.

DateRangeField

class DateRangeField(**options)

Stores a range of dates. Based on a DateField. Represented by a daterange in the database and a DateRange in Python.

Regardless of the bounds specified when saving the data, PostgreSQL always returns a range in a canonical form that includes the lower bound and excludes the upper bound; that is [).

Querying Range Fields

There are a number of custom lookups and transforms for range fields. They are available on all the above fields, but we will use the following example model:

from django.contrib.postgres.fields import IntegerRangeField
from django.db import models

class Event(models.Model):
name = models.CharField(max_length=200)
ages = IntegerRangeField()
start = models.DateTimeField()

def __str__(self):  # __unicode__ on Python 2
return self.name

We will also use the following example objects:

>>> import datetime
>>> from django.utils import timezone
>>> now = timezone.now()
>>> Event.objects.create(name='Soft play', ages=(0, 10), start=now)
>>> Event.objects.create(name='Pub trip', ages=(21, None), start=now - datetime.timedelta(days=1))

and NumericRange:

>>> from psycopg2.extras import NumericRange

Containment functions

As with other PostgreSQL fields, there are three standard containment operators: contains, contained_by and overlap, using the SQL operators @>, <@, and && respectively.

contains

>>> Event.objects.filter(ages__contains=NumericRange(4, 5))
[<Event: Soft play>]

contained_by

>>> Event.objects.filter(ages__contained_by=NumericRange(0, 15))
[<Event: Soft play>]

overlap

>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
[<Event: Soft play>]

Comparison functions

Range fields support the standard lookups: lt, gt, lte and gte. These are not particularly helpful - they compare the lower bounds first and then the upper bounds only if necessary. This is also the strategy used to order by a range field. It is better to use the specific range comparison operators.

fully_lt

The returned ranges are strictly less than the passed range. In other words, all the points in the returned range are less than all those in the passed range.

>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
[<Event: Soft play>]

fully_gt

The returned ranges are strictly greater than the passed range. In other words, the all the points in the returned range are greater than all those in the passed range.

>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
[<Event: Pub trip>]

not_lt

The returned ranges do not contain any points less than the passed range, that is the lower bound of the returned range is at least the lower bound of the passed range.

>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
[<Event: Soft play>, <Event: Pub trip>]

not_gt

The returned ranges do not contain any points greater than the passed range, that is the upper bound of the returned range is at most the upper bound of the passed range.

>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
[<Event: Soft play>]

adjacent_to

The returned ranges share a bound with the passed range.

>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
[<Event: Soft play>, <Event: Pub trip>]

Querying using the bounds

There are three transforms available for use in queries. You can extract the lower or upper bound, or query based on emptiness.

startswith

Returned objects have the given lower bound. Can be chained to valid lookups for the base field.

>>> Event.objects.filter(ages__startswith=21)
[<Event: Pub trip>]

endswith

Returned objects have the given upper bound. Can be chained to valid lookups for the base field.

>>> Event.objects.filter(ages__endswith=10)
[<Event: Soft play>]

isempty

Returned objects are empty ranges. Can be chained to valid lookups for a BooleanField.

>>> Event.objects.filter(ages__isempty=True)
[]

Defining your own range types

PostgreSQL allows the definition of custom range types. Django’s model and form field implementations use base classes below, and psycopg2 provides a register_range() to allow use of custom range types.

class RangeField(**options)

Base class for model range fields.

base_field

The model field to use.

range_type

The psycopg2 range type to use.

form_field

The form field class to use. Should be a subclass of django.contrib.postgres.forms.BaseRangeField.

class django.contrib.postgres.forms.BaseRangeField

Base class for form range fields.

base_field

The form field to use.

range_type

The psycopg2 range type to use.

PostgreSQL specific form fields and widgets

All of these fields and widgets are available from the django.contrib.postgres.forms module.

Fields

SimpleArrayField

class SimpleArrayField(base_field, delimiter=', ', max_length=None, min_length=None)

A simple field which maps to an array. It is represented by an HTML <input>.

base_field

This is a required argument.

It specifies the underlying form field for the array. This is not used to render any HTML, but it is used to process the submitted data and validate it. For example:

>>> from django.contrib.postgres.forms import SimpleArrayField
>>> from django import forms

>>> class NumberListForm(forms.Form):
...     numbers = SimpleArrayField(forms.IntegerField())

>>> form = NumberListForm({'numbers': '1,2,3'})
>>> form.is_valid()
True
>>> form.cleaned_data
{'numbers': [1, 2, 3]}

>>> form = NumberListForm({'numbers': '1,2,a'})
>>> form.is_valid()
False

delimiter

This is an optional argument which defaults to a comma: ,. This value is used to split the submitted data. It allows you to chain SimpleArrayField for multidimensional data:

>>> from django.contrib.postgres.forms import SimpleArrayField
>>> from django import forms

>>> class GridForm(forms.Form):
...     places = SimpleArrayField(SimpleArrayField(IntegerField()), delimiter='|')

>>> form = GridForm({'places': '1,2|2,1|4,3'})
>>> form.is_valid()
True
>>> form.cleaned_data
{'places': [[1, 2], [2, 1], [4, 3]]}

Note

The field does not support escaping of the delimiter, so be careful in cases where the delimiter is a valid character in the underlying field. The delimiter does not need to be only one character.

max_length

This is an optional argument which validates that the array does not exceed the stated length.

min_length

This is an optional argument which validates that the array reaches at least the stated length.

User friendly forms

SimpleArrayField is not particularly user friendly in most cases, however it is a useful way to format data from a client-side widget for submission to the server.

SplitArrayField

class SplitArrayField(base_field, size, remove_trailing_nulls=False)

This field handles arrays by reproducing the underlying field a fixed number of times.

base_field

This is a required argument. It specifies the form field to be repeated.

size

This is the fixed number of times the underlying field will be used.

remove_trailing_nulls

By default, this is set to False. When False, each value from the repeated fields is stored. When set to True, any trailing values which are blank will be stripped from the result. If the underlying field has required=True, but remove_trailing_nulls is True, then null values are only allowed at the end, and will be stripped.

Some examples:

SplitArrayField(IntegerField(required=True), size=3, remove_trailing_nulls=False)

['1', '2', '3']  # -> [1, 2, 3]
['1', '2', '']  # -> ValidationError - third entry required.
['1', '', '3']  # -> ValidationError - second entry required.
['', '2', '']  # -> ValidationError - first and third entries required.

SplitArrayField(IntegerField(required=False), size=3, remove_trailing_nulls=False)

['1', '2', '3']  # -> [1, 2, 3]
['1', '2', '']  # -> [1, 2, None]
['1', '', '3']  # -> [1, None, 3]
['', '2', '']  # -> [None, 2, None]

SplitArrayField(IntegerField(required=True), size=3, remove_trailing_nulls=True)

['1', '2', '3']  # -> [1, 2, 3]
['1', '2', '']  # -> [1, 2]
['1', '', '3']  # -> ValidationError - second entry required.
['', '2', '']  # -> ValidationError - first entry required.

SplitArrayField(IntegerField(required=False), size=3, remove_trailing_nulls=True)

['1', '2', '3']  # -> [1, 2, 3]
['1', '2', '']  # -> [1, 2]
['1', '', '3']  # -> [1, None, 3]
['', '2', '']  # -> [None, 2]

HStoreField

class HStoreField

A field which accepts JSON encoded data for an HStoreField. It will cast all the values to strings. It is represented by an HTML <textarea>.

User friendly forms

HStoreField is not particularly user friendly in most cases, however it is a useful way to format data from a client-side widget for submission to the server.

Note

On occasions it may be useful to require or restrict the keys which are valid for a given field. This can be done using the KeysValidator.

JSONField

class JSONField

A field which accepts JSON encoded data for a JSONField. It is represented by an HTML <textarea>.

User friendly forms

JSONField is not particularly user friendly in most cases, however it is a useful way to format data from a client-side widget for submission to the server.

Range Fields

This group of fields all share similar functionality for accepting range data. They are based on MultiValueField. They treat one omitted value as an unbounded range. They also validate that the lower bound is not greater than the upper bound. All of these fields use RangeWidget.

IntegerRangeField

class IntegerRangeField

Based on IntegerField and translates its input into NumericRange. Default for IntegerRangeField and BigIntegerRangeField.

FloatRangeField

class FloatRangeField

Based on FloatField and translates its input into NumericRange. Default for FloatRangeField.

DateTimeRangeField

class DateTimeRangeField

Based on DateTimeField and translates its input into DateTimeTZRange. Default for DateTimeRangeField.

DateRangeField

class DateRangeField

Based on DateField and translates its input into DateRange. Default for DateRangeField.

Widgets

RangeWidget

class RangeWidget(base_widget, attrs=None)

Widget used by all of the range fields. Based on MultiWidget.

RangeWidget has one required argument:

base_widget

A RangeWidget comprises a 2-tuple of base_widget.

decompress(value)

Takes a single “compressed” value of a field, for example a DateRangeField, and returns a tuple representing and lower and upper bound.

PostgreSQL specific database functions

All of these functions are available from the django.contrib.postgres.functions module.

TransactionNow

class TransactionNow[source]

New in Django 1.9.

Returns the date and time on the database server that the current transaction started. If you are not in a transaction it will return the date and time of the current statement. This is a complement to django.db.models.functions.Now, which returns the date and time of the current statement.

Note that only the outermost call to atomic() sets up a transaction and thus sets the time that TransactionNow() will return; nested calls create savepoints which do not affect the transaction time.

Usage example:

>>> from django.contrib.postgres.functions import TransactionNow
>>> Article.objects.filter(published__lte=TransactionNow())
[<Article: How to Django>]

PostgreSQL specific lookups

Unaccent

The unaccent lookup allows you to perform accent-insensitive lookups using a dedicated PostgreSQL extension.

This lookup is implemented using Transform, so it can be chained with other lookup functions. To use it, you need to add 'django.contrib.postgres' in your INSTALLED_APPS and activate the unaccent extension on PostgreSQL. The UnaccentExtension migration operation is available if you want to perform this activation using migrations).

The unaccent lookup can be used on CharField and TextField:

>>> City.objects.filter(name__unaccent="México")
['<City: Mexico>']

>>> User.objects.filter(first_name__unaccent__startswith="Jerem")
['<User: Jeremy>', '<User: Jérémy>', '<User: Jérémie>', '<User: Jeremie>']

Warning

unaccent lookups should perform fine in most use cases. However, queries using this filter will generally perform full table scans, which can be slow on large tables. In those cases, using dedicated full text indexing tools might be appropriate.

Database migration operations

All of these operations are available from the django.contrib.postgres.operations module.

CreateExtension

class CreateExtension(name)

An Operation subclass which installs PostgreSQL extensions.

name

This is a required argument. The name of the extension to be installed.

HStoreExtension

class HStoreExtension

A subclass of CreateExtension which will install the hstore extension and also immediately set up the connection to interpret hstore data.

UnaccentExtension

class UnaccentExtension

A subclass of CreateExtension which will install the unaccent extension.

Validators

KeysValidator

class KeysValidator(keys, strict=False, messages=None)[source]

Validates that the given keys are contained in the value. If strict is True, then it also checks that there are no other keys present.

The messages passed should be a dict containing the keys missing_keys and/or extra_keys.

Note

Note that this checks only for the existence of a given key, not that the value of a key is non-empty.

Range validators

RangeMaxValueValidator

class RangeMaxValueValidator(limit_value, message=None)[source]

Validates that the upper bound of the range is not greater than limit_value.

RangeMinValueValidator

class RangeMinValueValidator(limit_value, message=None)[source]

Validates that the lower bound of the range is not less than the limit_value.

The redirects app

Django comes with an optional redirects application. It lets you store simple redirects in a database and handles the redirecting for you. It uses the HTTP response status code 301 Moved Permanently by default.

Installation

To install the redirects app, follow these steps:

1. Ensure that the django.contrib.sites framework is installed.

2. Add 'django.contrib.redirects' to your INSTALLED_APPS setting.

3. Add 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' to your MIDDLEWARE_CLASSES setting.

4. Run the command manage.py migrate.

How it works

manage.py migrate creates a django_redirect table in your database. This is a simple lookup table with site_id, old_path and new_path fields.

The RedirectFallbackMiddleware does all of the work. Each time any Django application raises a 404 error, this middleware checks the redirects database for the requested URL as a last resort. Specifically, it checks for a redirect with the given old_path with a site ID that corresponds to the SITE_ID setting.

- If it finds a match, and new_path is not empty, it redirects to new_path using a 301 (“Moved Permanently”) redirect. You can subclass RedirectFallbackMiddleware and set response_redirect_class to django.http.HttpResponseRedirect to use a 302 Moved Temporarily redirect instead.

- If it finds a match, and new_path is empty, it sends a 410 (“Gone”) HTTP header and empty (content-less) response.

- If it doesn’t find a match, the request continues to be processed as usual.

The middleware only gets activated for 404s – not for 500s or responses of any other status code.

Note that the order of MIDDLEWARE_CLASSES matters. Generally, you can put RedirectFallbackMiddleware at the end of the list, because it’s a last resort.

For more on middleware, read the middleware docs.

How to add, change and delete redirects

Via the admin interface

If you’ve activated the automatic Django admin interface, you should see a “Redirects” section on the admin index page. Edit redirects as you edit any other object in the system.

Via the Python API

class models.Redirect

Redirects are represented by a standard Django model, which lives in django/contrib/redirects/models.py. You can access redirect objects via the Django database API.

Middleware

class middleware.RedirectFallbackMiddleware

You can change the HttpResponse classes used by the middleware by creating a subclass of RedirectFallbackMiddleware and overriding response_gone_class and/or response_redirect_class.

response_gone_class

The HttpResponse class used when a Redirect is not found for the requested path or has a blank new_path value.

Defaults to HttpResponseGone.

response_redirect_class

The HttpResponse class that handles the redirect.

Defaults to HttpResponsePermanentRedirect.

The sitemap framework

Django comes with a high-level sitemap-generating framework that makes creating sitemap XML files easy.

Overview

A sitemap is an XML file on your website that tells search-engine indexers how frequently your pages change and how “important” certain pages are in relation to other pages on your site. This information helps search engines index your site.

The Django sitemap framework automates the creation of this XML file by letting you express this information in Python code.

It works much like Django’s syndication framework. To create a sitemap, just write a Sitemap class and point to it in your URLconf.

Installation

To install the sitemap app, follow these steps:

1. Add 'django.contrib.sitemaps' to your INSTALLED_APPS setting.

2. Make sure your TEMPLATES setting contains a DjangoTemplates backend whose APP_DIRS options is set to True. It’s in there by default, so you’ll only need to change this if you’ve changed that setting.

3. Make sure you’ve installed the sites framework.

(Note: The sitemap application doesn’t install any database tables. The only reason it needs to go into INSTALLED_APPS is so that the Loader() template loader can find the default templates.)

Initialization

views.sitemap(request, sitemaps, section=None, template_name='sitemap.xml', content_type='application/xml')

To activate sitemap generation on your Django site, add this line to your URLconf:

from django.contrib.sitemaps.views import sitemap

url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap')

This tells Django to build a sitemap when a client accesses /sitemap.xml.

The name of the sitemap file is not important, but the location is. Search engines will only index links in your sitemap for the current URL level and below. For instance, if sitemap.xml lives in your root directory, it may reference any URL in your site. However, if your sitemap lives at /content/sitemap.xml, it may only reference URLs that begin with /content/.

The sitemap view takes an extra, required argument: {'sitemaps': sitemaps}. sitemaps should be a dictionary that maps a short section label (e.g., blog or news) to its Sitemap class (e.g., BlogSitemap or NewsSitemap). It may also map to an instance of a Sitemap class (e.g., BlogSitemap(some_var)).

Sitemap classes

A Sitemap class is a simple Python class that represents a “section” of entries in your sitemap. For example, one Sitemap class could represent all the entries of your Weblog, while another could represent all of the events in your events calendar.

In the simplest case, all these sections get lumped together into one sitemap.xml, but it’s also possible to use the framework to generate a sitemap index that references individual sitemap files, one per section. (See Creating a sitemap index below.)

Sitemap classes must subclass django.contrib.sitemaps.Sitemap. They can live anywhere in your codebase.

A simple example

Let’s assume you have a blog system, with an Entry model, and you want your sitemap to include all the links to your individual blog entries. Here’s how your sitemap class might look:

from django.contrib.sitemaps import Sitemap
from blog.models import Entry

class BlogSitemap(Sitemap):
changefreq = "never"
priority = 0.5

def items(self):
return Entry.objects.filter(is_draft=False)

def lastmod(self, obj):
return obj.pub_date

Note:

- changefreq and priority are class attributes corresponding to <changefreq> and <priority> elements, respectively. They can be made callable as functions, as lastmod was in the example.

- items() is simply a method that returns a list of objects. The objects returned will get passed to any callable methods corresponding to a sitemap property (location, lastmod, changefreq, and priority).

- lastmod should return a datetime.

- There is no location method in this example, but you can provide it in order to specify the URL for your object. By default, location() calls get_absolute_url() on each object and returns the result.

Sitemap class reference

class Sitemap[source]

A Sitemap class can define the following methods/attributes:

items[source]

Required. A method that returns a list of objects. The framework doesn’t care what type of objects they are; all that matters is that these objects get passed to the location(), lastmod(), changefreq() and priority() methods.

location[source]

Optional. Either a method or attribute.

If it’s a method, it should return the absolute path for a given object as returned by items().

If it’s an attribute, its value should be a string representing an absolute path to use for every object returned by items().

In both cases, “absolute path” means a URL that doesn’t include the protocol or domain. Examples:

- Good: '/foo/bar/'

- Bad: 'example.com/foo/bar/'

- Bad: 'https://example.com/foo/bar/'

If location isn’t provided, the framework will call the get_absolute_url() method on each object as returned by items().

To specify a protocol other than 'http', use protocol.

lastmod

Optional. Either a method or attribute.

If it’s a method, it should take one argument – an object as returned by items() – and return that object’s last-modified date/time as a datetime.

If it’s an attribute, its value should be a datetime representing the last-modified date/time for every object returned by items().

If all items in a sitemap have a lastmod, the sitemap generated by views.sitemap() will have a Last-Modified header equal to the latest lastmod. You can activate the ConditionalGetMiddleware to make Django respond appropriately to requests with an If-Modified-Since header which will prevent sending the sitemap if it hasn’t changed.

changefreq

Optional. Either a method or attribute.

If it’s a method, it should take one argument – an object as returned by items() – and return that object’s change frequency as a string.

If it’s an attribute, its value should be a string representing the change frequency of every object returned by items().

Possible values for changefreq, whether you use a method or attribute, are:

- 'always'

- 'hourly'

- 'daily'

- 'weekly'

- 'monthly'

- 'yearly'

- 'never'

priority

Optional. Either a method or attribute.

If it’s a method, it should take one argument – an object as returned by items() – and return that object’s priority as either a string or float.

If it’s an attribute, its value should be either a string or float representing the priority of every object returned by items().

Example values for priority: 0.4, 1.0. The default priority of a page is 0.5. See the sitemaps.org documentation for more.

protocol

Optional.

This attribute defines the protocol ('http' or 'https') of the URLs in the sitemap. If it isn’t set, the protocol with which the sitemap was requested is used. If the sitemap is built outside the context of a request, the default is 'http'.

limit

Optional.

This attribute defines the maximum number of URLs included on each page of the sitemap. Its value should not exceed the default value of 50000, which is the upper limit allowed in the Sitemaps protocol.

i18n

New in Django 1.8.

Optional.

A boolean attribute that defines if the URLs of this sitemap should be generated using all of your LANGUAGES. The default is False.

Shortcuts

The sitemap framework provides a convenience class for a common case:

class GenericSitemap[source]

The django.contrib.sitemaps.GenericSitemap class allows you to create a sitemap by passing it a dictionary which has to contain at least a queryset entry. This queryset will be used to generate the items of the sitemap. It may also have a date_field entry that specifies a date field for objects retrieved from the queryset. This will be used for the lastmod attribute in the generated sitemap. You may also pass priority and changefreq keyword arguments to the GenericSitemap constructor to specify these attributes for all URLs.

Example

Here’s an example of a URLconf using GenericSitemap:

from django.conf.urls import url
from django.contrib.sitemaps import GenericSitemap
from django.contrib.sitemaps.views import sitemap
from blog.models import Entry

info_dict = {
'queryset': Entry.objects.all(),
'date_field': 'pub_date',
}

urlpatterns = [
# some generic view using info_dict
# ...

# the sitemap
url(r'^sitemap\.xml$', sitemap,
{'sitemaps': {'blog': GenericSitemap(info_dict, priority=0.6)}},
name='django.contrib.sitemaps.views.sitemap'),
]

Sitemap for static views

Often you want the search engine crawlers to index views which are neither object detail pages nor flatpages. The solution is to explicitly list URL names for these views in items and call reverse() in the location method of the sitemap. For example:

# sitemaps.py
from django.contrib import sitemaps
from django.core.urlresolvers import reverse

class StaticViewSitemap(sitemaps.Sitemap):
priority = 0.5
changefreq = 'daily'

def items(self):
return ['main', 'about', 'license']

def location(self, item):
return reverse(item)

# urls.py
from django.conf.urls import url
from django.contrib.sitemaps.views import sitemap

from .sitemaps import StaticViewSitemap
from . import views

sitemaps = {
'static': StaticViewSitemap,
}

urlpatterns = [
url(r'^$', views.main, name='main'),
url(r'^about/$', views.about, name='about'),
url(r'^license/$', views.license, name='license'),
# ...
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap')
]

Creating a sitemap index

views.index(request, sitemaps, template_name='sitemap_index.xml', content_type='application/xml', sitemap_url_name='django.contrib.sitemaps.views.sitemap')

The sitemap framework also has the ability to create a sitemap index that references individual sitemap files, one per each section defined in your sitemaps dictionary. The only differences in usage are:

- You use two views in your URLconf: django.contrib.sitemaps.views.index() and django.contrib.sitemaps.views.sitemap().

- The django.contrib.sitemaps.views.sitemap() view should take a section keyword argument.

Here’s what the relevant URLconf lines would look like for the example above:

from django.contrib.sitemaps import views

urlpatterns = [
url(r'^sitemap\.xml$', views.index, {'sitemaps': sitemaps}),
url(r'^sitemap-(?P<section>.+)\.xml$', views.sitemap, {'sitemaps': sitemaps}),
]

This will automatically generate a sitemap.xml file that references both sitemap-flatpages.xml and sitemap-blog.xml. The Sitemap classes and the sitemaps dict don’t change at all.

You should create an index file if one of your sitemaps has more than 50,000 URLs. In this case, Django will automatically paginate the sitemap, and the index will reflect that.

If you’re not using the vanilla sitemap view – for example, if it’s wrapped with a caching decorator – you must name your sitemap view and pass sitemap_url_name to the index view:

from django.contrib.sitemaps import views as sitemaps_views
from django.views.decorators.cache import cache_page

urlpatterns = [
url(r'^sitemap\.xml$',
cache_page(86400)(sitemaps_views.index),
{'sitemaps': sitemaps, 'sitemap_url_name': 'sitemaps'}),
url(r'^sitemap-(?P<section>.+)\.xml$',
cache_page(86400)(sitemaps_views.sitemap),
{'sitemaps': sitemaps}, name='sitemaps'),
]

Template customization

If you wish to use a different template for each sitemap or sitemap index available on your site, you may specify it by passing a template_name parameter to the sitemap and index views via the URLconf:

from django.contrib.sitemaps import views

urlpatterns = [
url(r'^custom-sitemap\.xml$', views.index, {
'sitemaps': sitemaps,
'template_name': 'custom_sitemap.html'
}),
url(r'^custom-sitemap-(?P<section>.+)\.xml$', views.sitemap, {
'sitemaps': sitemaps,
'template_name': 'custom_sitemap.html'
}),
]

These views return TemplateResponse instances which allow you to easily customize the response data before rendering. For more details, see the TemplateResponse documentation.

Context variables

When customizing the templates for the index() and sitemap() views, you can rely on the following context variables.

Index

The variable sitemaps is a list of absolute URLs to each of the sitemaps.

Sitemap

The variable urlset is a list of URLs that should appear in the sitemap. Each URL exposes attributes as defined in the Sitemap class:

- changefreq

- item

- lastmod

- location

- priority

The item attribute has been added for each URL to allow more flexible customization of the templates, such as Google news sitemaps. Assuming Sitemap’s items() would return a list of items with publication_data and a tags field something like this would generate a Google News compatible sitemap:

<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="https://www.google.com/schemas/sitemap-news/0.9">
{% spaceless %}
{% for url in urlset %}
<url>
<loc>{{ url.location }}</loc>
{% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
{% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
{% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
<news:news>
{% if url.item.publication_date %}<news:publication_date>{{ url.item.publication_date|date:"Y-m-d" }}</news:publication_date>{% endif %}
{% if url.item.tags %}<news:keywords>{{ url.item.tags }}</news:keywords>{% endif %}
</news:news>
</url>
{% endfor %}
{% endspaceless %}
</urlset>

Pinging Google

You may want to “ping” Google when your sitemap changes, to let it know to reindex your site. The sitemaps framework provides a function to do just that: django.contrib.sitemaps.ping_google().

ping_google()[source]

ping_google() takes an optional argument, sitemap_url, which should be the absolute path to your site’s sitemap (e.g., '/sitemap.xml'). If this argument isn’t provided, ping_google() will attempt to figure out your sitemap by performing a reverse looking in your URLconf.

ping_google() raises the exception django.contrib.sitemaps.SitemapNotFound if it cannot determine your sitemap URL.

Register with Google first!

The ping_google() command only works if you have registered your site with Google Webmaster Tools.

One useful way to call ping_google() is from a model’s save() method:

from django.contrib.sitemaps import ping_google

class Entry(models.Model):
# ...
def save(self, force_insert=False, force_update=False):
super(Entry, self).save(force_insert, force_update)
try:
ping_google()
except Exception:
# Bare 'except' because we could get a variety
# of HTTP-related exceptions.
pass

A more efficient solution, however, would be to call ping_google() from a cron script, or some other scheduled task. The function makes an HTTP request to Google’s servers, so you may not want to introduce that network overhead each time you call save().

Pinging Google via manage.py

django-admin ping_google [sitemap_url]

Once the sitemaps application is added to your project, you may also ping Google using the ping_google management command:

python manage.py ping_google [/sitemap.xml]

The “sites” framework

Django comes with an optional “sites” framework. It’s a hook for associating objects and functionality to particular websites, and it’s a holding place for the domain names and “verbose” names of your Django-powered sites.

Use it if your single Django installation powers more than one site and you need to differentiate between those sites in some way.

The sites framework is mainly based on a simple model:

class models.Site

A model for storing the domain and name attributes of a website.

domain

The fully qualified domain name associated with the website. For example, www.example.com.

Changed in Django 1.9:
The domain field was set to be unique.

name

A human-readable “verbose” name for the website.

The SITE_ID setting specifies the database ID of the Site object associated with that particular settings file. If the setting is omitted, the get_current_site() function will try to get the current site by comparing the domain with the host name from the request.get_host() method.

How you use this is up to you, but Django uses it in a couple of ways automatically via simple conventions.

Example usage

Why would you use sites? It’s best explained through examples.

Associating content with multiple sites

The Django-powered sites LJWorld.com and Lawrence.com are operated by the same news organization – the Lawrence Journal-World newspaper in Lawrence, Kansas. LJWorld.com focuses on news, while Lawrence.com focuses on local entertainment. But sometimes editors want to publish an article on both sites.

The naive way of solving the problem would be to require site producers to publish the same story twice: once for LJWorld.com and again for Lawrence.com. But that’s inefficient for site producers, and it’s redundant to store multiple copies of the same story in the database.

The better solution is simple: Both sites use the same article database, and an article is associated with one or more sites. In Django model terminology, that’s represented by a ManyToManyField in the Article model:

from django.db import models
from django.contrib.sites.models import Site

class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
sites = models.ManyToManyField(Site)

This accomplishes several things quite nicely:

- It lets the site producers edit all content – on both sites – in a single interface (the Django admin).

- It means the same story doesn’t have to be published twice in the database; it only has a single record in the database.

- It lets the site developers use the same Django view code for both sites. The view code that displays a given story just checks to make sure the requested story is on the current site. It looks something like this:

from django.contrib.sites.shortcuts import get_current_site

def article_detail(request, article_id):
try:
a = Article.objects.get(id=article_id, sites__id=get_current_site(request).id)
except Article.DoesNotExist:
raise Http404("Article does not exist on this site")
# ...

Associating content with a single site

Similarly, you can associate a model to the Site model in a many-to-one relationship, using ForeignKey.

For example, if an article is only allowed on a single site, you’d use a model like this:

from django.db import models
from django.contrib.sites.models import Site

class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
site = models.ForeignKey(Site, on_delete=models.CASCADE)

This has the same benefits as described in the last section.

Hooking into the current site from views

You can use the sites framework in your Django views to do particular things based on the site in which the view is being called. For example:

from django.conf import settings

def my_view(request):
if settings.SITE_ID == 3:
# Do something.
pass
else:
# Do something else.
pass

Of course, it’s ugly to hard-code the site IDs like that. This sort of hard-coding is best for hackish fixes that you need done quickly. The cleaner way of accomplishing the same thing is to check the current site’s domain:

from django.contrib.sites.shortcuts import get_current_site

def my_view(request):
current_site = get_current_site(request)
if current_site.domain == 'foo.com':
# Do something
pass
else:
# Do something else.
pass

This has also the advantage of checking if the sites framework is installed, and return a RequestSite instance if it is not.

If you don’t have access to the request object, you can use the get_current() method of the Site model’s manager. You should then ensure that your settings file does contain the SITE_ID setting. This example is equivalent to the previous one:

from django.contrib.sites.models import Site

def my_function_without_request():
current_site = Site.objects.get_current()
if current_site.domain == 'foo.com':
# Do something
pass
else:
# Do something else.
pass

Getting the current domain for display

LJWorld.com and Lawrence.com both have email alert functionality, which lets readers sign up to get notifications when news happens. It’s pretty basic: A reader signs up on a Web form and immediately gets an email saying, “Thanks for your subscription.”

It’d be inefficient and redundant to implement this sign up processing code twice, so the sites use the same code behind the scenes. But the “thank you for signing up” notice needs to be different for each site. By using Site objects, we can abstract the “thank you” notice to use the values of the current site’s name and domain.

Here’s an example of what the form-handling view looks like:

from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import send_mail

def register_for_newsletter(request):
# Check form values, etc., and subscribe the user.
# ...

current_site = get_current_site(request)
send_mail(
'Thanks for subscribing to %s alerts' % current_site.name,
'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % (
current_site.name,
),
'editor@%s' % current_site.domain,
[user.email],
)

# ...

On Lawrence.com, this email has the subject line “Thanks for subscribing to lawrence.com alerts.” On LJWorld.com, the email has the subject “Thanks for subscribing to LJWorld.com alerts.” Same goes for the email’s message body.

Note that an even more flexible (but more heavyweight) way of doing this would be to use Django’s template system. Assuming Lawrence.com and LJWorld.com have different template directories (DIRS), you could simply farm out to the template system like so:

from django.core.mail import send_mail
from django.template import loader, Context

def register_for_newsletter(request):
# Check form values, etc., and subscribe the user.
# ...

subject = loader.get_template('alerts/subject.txt').render(Context({}))
message = loader.get_template('alerts/message.txt').render(Context({}))
send_mail(subject, message, 'editor@ljworld.com', [user.email])

# ...

In this case, you’d have to create subject.txt and message.txt template files for both the LJWorld.com and Lawrence.com template directories. That gives you more flexibility, but it’s also more complex.

It’s a good idea to exploit the Site objects as much as possible, to remove unneeded complexity and redundancy.

Getting the current domain for full URLs

Django’s get_absolute_url() convention is nice for getting your objects’ URL without the domain name, but in some cases you might want to display the full URL – with http:// and the domain and everything – for an object. To do this, you can use the sites framework. A simple example:

>>> from django.contrib.sites.models import Site
>>> obj = MyModel.objects.get(id=3)
>>> obj.get_absolute_url()
'/mymodel/objects/3/'
>>> Site.objects.get_current().domain
'example.com'
>>> 'https://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
'https://example.com/mymodel/objects/3/'

Enabling the sites framework

To enable the sites framework, follow these steps:

1. Add 'django.contrib.sites' to your INSTALLED_APPS setting.

2. Define a SITE_ID setting:

SITE_ID = 1

3. Run migrate.

django.contrib.sites registers a post_migrate signal handler which creates a default site named example.com with the domain example.com. This site will also be created after Django creates the test database. To set the correct name and domain for your project, you can use a data migration.

In order to serve different sites in production, you’d create a separate settings file with each SITE_ID (perhaps importing from a common settings file to avoid duplicating shared settings) and then specify the appropriate DJANGO_SETTINGS_MODULE for each site.

Caching the current Site object

As the current site is stored in the database, each call to Site.objects.get_current() could result in a database query. But Django is a little cleverer than that: on the first request, the current site is cached, and any subsequent call returns the cached data instead of hitting the database.

If for any reason you want to force a database query, you can tell Django to clear the cache using Site.objects.clear_cache():

# First call; current site fetched from database.
current_site = Site.objects.get_current()
# ...

# Second call; current site fetched from cache.
current_site = Site.objects.get_current()
# ...

# Force a database query for the third call.
Site.objects.clear_cache()
current_site = Site.objects.get_current()

The CurrentSiteManager

class managers.CurrentSiteManager

If Site plays a key role in your application, consider using the helpful CurrentSiteManager in your model(s). It’s a model manager that automatically filters its queries to include only objects associated with the current Site.

Mandatory SITE_ID

The CurrentSiteManager is only usable when the SITE_ID setting is defined in your settings.

Use CurrentSiteManager by adding it to your model explicitly. For example:

from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager

class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
pub_date = models.DateField()
site = models.ForeignKey(Site, on_delete=models.CASCADE)
objects = models.Manager()
on_site = CurrentSiteManager()

With this model, Photo.objects.all() will return all Photo objects in the database, but Photo.on_site.all() will return only the Photo objects associated with the current site, according to the SITE_ID setting.

Put another way, these two statements are equivalent:

Photo.objects.filter(site=settings.SITE_ID)
Photo.on_site.all()

How did CurrentSiteManager know which field of Photo was the Site? By default, CurrentSiteManager looks for a either a ForeignKey called site or a ManyToManyField called sites to filter on. If you use a field named something other than site or sites to identify which Site objects your object is related to, then you need to explicitly pass the custom field name as a parameter to CurrentSiteManager on your model. The following model, which has a field called publish_on, demonstrates this:

from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager

class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
pub_date = models.DateField()
publish_on = models.ForeignKey(Site, on_delete=models.CASCADE)
objects = models.Manager()
on_site = CurrentSiteManager('publish_on')

If you attempt to use CurrentSiteManager and pass a field name that doesn’t exist, Django will raise a ValueError.

Finally, note that you’ll probably want to keep a normal (non-site-specific) Manager on your model, even if you use CurrentSiteManager. As explained in the manager documentation, if you define a manager manually, then Django won’t create the automatic objects = models.Manager() manager for you. Also note that certain parts of Django – namely, the Django admin site and generic views – use whichever manager is defined first in the model, so if you want your admin site to have access to all objects (not just site-specific ones), put objects = models.Manager() in your model, before you define CurrentSiteManager.

Site middleware

If you often use this pattern:

from django.contrib.sites.models import Site

def my_view(request):
site = Site.objects.get_current()
...

there is simple way to avoid repetitions. Add django.contrib.sites.middleware.CurrentSiteMiddleware to MIDDLEWARE_CLASSES. The middleware sets the site attribute on every request object, so you can use request.site to get the current site.

How Django uses the sites framework

Although it’s not required that you use the sites framework, it’s strongly encouraged, because Django takes advantage of it in a few places. Even if your Django installation is powering only a single site, you should take the two seconds to create the site object with your domain and name, and point to its ID in your SITE_ID setting.

Here’s how Django uses the sites framework:

- In the redirects framework, each redirect object is associated with a particular site. When Django searches for a redirect, it takes into account the current site.

- In the flatpages framework, each flatpage is associated with a particular site. When a flatpage is created, you specify its Site, and the FlatpageFallbackMiddleware checks the current site in retrieving flatpages to display.

- In the syndication framework, the templates for title and description automatically have access to a variable {{ site }}, which is the Site object representing the current site. Also, the hook for providing item URLs will use the domain from the current Site object if you don’t specify a fully-qualified domain.

- In the authentication framework, the django.contrib.auth.views.login() view passes the current Site name to the template as {{ site_name }}.

- The shortcut view (django.contrib.contenttypes.views.shortcut) uses the domain of the current Site object when calculating an object’s URL.

- In the admin framework, the “view on site” link uses the current Site to work out the domain for the site that it will redirect to.

RequestSite objects

Some django.contrib applications take advantage of the sites framework but are architected in a way that doesn’t require the sites framework to be installed in your database. (Some people don’t want to, or just aren’t able to install the extra database table that the sites framework requires.) For those cases, the framework provides a django.contrib.sites.requests.RequestSite class, which can be used as a fallback when the database-backed sites framework is not available.

class requests.RequestSite

A class that shares the primary interface of Site (i.e., it has domain and name attributes) but gets its data from a Django HttpRequest object rather than from a database.

__init__(request)

Sets the name and domain attributes to the value of get_host().

A RequestSite object has a similar interface to a normal Site object, except its __init__() method takes an HttpRequest object. It’s able to deduce the domain and name by looking at the request’s domain. It has save() and delete() methods to match the interface of Site, but the methods raise NotImplementedError.

get_current_site shortcut

Finally, to avoid repetitive fallback code, the framework provides a django.contrib.sites.shortcuts.get_current_site() function.

shortcuts.get_current_site(request)

A function that checks if django.contrib.sites is installed and returns either the current Site object or a RequestSite object based on the request. It looks up the current site based on request.get_host() if the SITE_ID setting is not defined.

Both a domain and a port may be returned by request.get_host() when the Host header has a port explicitly specified, e.g. example.com:80. In such cases, if the lookup fails because the host does not match a record in the database, the port is stripped and the lookup is retried with the domain part only. This does not apply to RequestSite which will always use the unmodified host.

Changed in Django 1.8:
Looking up the current site based on request.get_host() was added.

Changed in Django 1.9:
Retrying the lookup with the port stripped was added.

The staticfiles app

django.contrib.staticfiles collects static files from each of your applications (and any other places you specify) into a single location that can easily be served in production.

See also

For an introduction to the static files app and some usage examples, see Managing static files (e.g. images, JavaScript, CSS). For guidelines on deploying static files, see Deploying static files.

Settings

See staticfiles settings for details on the following settings:

- STATIC_ROOT

- STATIC_URL

- STATICFILES_DIRS

- STATICFILES_STORAGE

- STATICFILES_FINDERS

Management Commands

django.contrib.staticfiles exposes three management commands.

collectstatic

django-admin collectstatic

Collects the static files into STATIC_ROOT.

Duplicate file names are by default resolved in a similar way to how template resolution works: the file that is first found in one of the specified locations will be used. If you’re confused, the findstatic command can help show you which files are found.

On subsequent collectstatic runs (if STATIC_ROOT isn’t empty), files are copied only if they have a modified timestamp greater than the timestamp of the file in STATIC_ROOT. Therefore if you remove an application from INSTALLED_APPS, it’s a good idea to use the collectstatic --clear option in order to remove stale static files.

Files are searched by using the enabled finders. The default is to look in all locations defined in STATICFILES_DIRS and in the 'static' directory of apps specified by the INSTALLED_APPS setting.

The collectstatic management command calls the post_process() method of the STATICFILES_STORAGE after each run and passes a list of paths that have been found by the management command. It also receives all command line options of collectstatic. This is used by the CachedStaticFilesStorage by default.

By default, collected files receive permissions from FILE_UPLOAD_PERMISSIONS and collected directories receive permissions from FILE_UPLOAD_DIRECTORY_PERMISSIONS. If you would like different permissions for these files and/or directories, you can subclass either of the static files storage classes and specify the file_permissions_mode and/or directory_permissions_mode parameters, respectively. For example:

from django.contrib.staticfiles import storage

class MyStaticFilesStorage(storage.StaticFilesStorage):
def __init__(self, *args, **kwargs):
kwargs['file_permissions_mode'] = 0o640
kwargs['directory_permissions_mode'] = 0o760
super(MyStaticFilesStorage, self).__init__(*args, **kwargs)

Then set the STATICFILES_STORAGE setting to 'path.to.MyStaticFilesStorage'.

Some commonly used options are:

--noinput, --no-input

Do NOT prompt the user for input of any kind.

Changed in Django 1.9:
The --no-input alias was added.

--ignore PATTERN, -i PATTERN

Ignore files or directories matching this glob-style pattern. Use multiple times to ignore more.

--dry-run, -n

Do everything except modify the filesystem.

--clear, -c

Clear the existing files before trying to copy or link the original file.

--link, -l

Create a symbolic link to each file instead of copying.

--no-post-process

Don’t call the post_process() method of the configured STATICFILES_STORAGE storage backend.

--no-default-ignore

Don’t ignore the common private glob-style patterns 'CVS', '.*' and '*~'.

For a full list of options, refer to the commands own help by running:

$ python manage.py collectstatic --help

findstatic

django-admin findstatic static file [static file ...]

Searches for one or more relative paths with the enabled finders.

For example:

$ python manage.py findstatic css/base.css admin/js/core.js
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
Found 'admin/js/core.js' here:
/home/polls.com/src/django/contrib/admin/media/js/core.js

findstatic --first

By default, all matching locations are found. To only return the first match for each relative path, use the --first option:

$ python manage.py findstatic css/base.css --first
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css

This is a debugging aid; it’ll show you exactly which static file will be collected for a given path.

By setting the --verbosity flag to 0, you can suppress the extra output and just get the path names:

$ python manage.py findstatic css/base.css --verbosity 0
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css

On the other hand, by setting the --verbosity flag to 2, you can get all the directories which were searched:

$ python manage.py findstatic css/base.css --verbosity 2
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
Looking in the following locations:
/home/special.polls.com/core/static
/home/polls.com/core/static
/some/other/path/static

runserver

django-admin runserver [addrport]

Overrides the core runserver command if the staticfiles app is installed and adds automatic serving of static files and the following new options.

--nostatic

Use the --nostatic option to disable serving of static files with the staticfiles app entirely. This option is only available if the staticfiles app is in your project’s INSTALLED_APPS setting.

Example usage:

django-admin runserver --nostatic

--insecure

Use the --insecure option to force serving of static files with the staticfiles app even if the DEBUG setting is False. By using this you acknowledge the fact that it’s grossly inefficient and probably insecure. This is only intended for local development, should never be used in production and is only available if the staticfiles app is in your project’s INSTALLED_APPS setting. runserver --insecure doesn’t work with CachedStaticFilesStorage.

Example usage:

django-admin runserver --insecure

Storages

StaticFilesStorage

class storage.StaticFilesStorage

A subclass of the FileSystemStorage storage backend that uses the STATIC_ROOT setting as the base file system location and the STATIC_URL setting respectively as the base URL.

storage.StaticFilesStorage.post_process(paths, **options)

This method is called by the collectstatic management command after each run and gets passed the local storages and paths of found files as a dictionary, as well as the command line options.

The CachedStaticFilesStorage uses this behind the scenes to replace the paths with their hashed counterparts and update the cache appropriately.

ManifestStaticFilesStorage

class storage.ManifestStaticFilesStorage

A subclass of the StaticFilesStorage storage backend which stores the file names it handles by appending the MD5 hash of the file’s content to the filename. For example, the file css/styles.css would also be saved as css/styles.55e7cbb9ba48.css.

The purpose of this storage is to keep serving the old files in case some pages still refer to those files, e.g. because they are cached by you or a 3rd party proxy server. Additionally, it’s very helpful if you want to apply far future Expires headers to the deployed files to speed up the load time for subsequent page visits.

The storage backend automatically replaces the paths found in the saved files matching other saved files with the path of the cached copy (using the post_process() method). The regular expressions used to find those paths (django.contrib.staticfiles.storage.HashedFilesMixin.patterns) by default covers the @import rule and url() statement of Cascading Style Sheets. For example, the 'css/styles.css' file with the content

@import url("../admin/css/base.css");

would be replaced by calling the url() method of the ManifestStaticFilesStorage storage backend, ultimately saving a 'css/styles.55e7cbb9ba48.css' file with the following content:

@import url("../admin/css/base.27e20196a850.css");

To enable the ManifestStaticFilesStorage you have to make sure the following requirements are met:

- the STATICFILES_STORAGE setting is set to 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

- the DEBUG setting is set to False

- you use the staticfiles static template tag to refer to your static files in your templates

- you’ve collected all your static files by using the collectstatic management command

Since creating the MD5 hash can be a performance burden to your website during runtime, staticfiles will automatically store the mapping with hashed names for all processed files in a file called staticfiles.json. This happens once when you run the collectstatic management command.

Due to the requirement of running collectstatic, this storage typically shouldn’t be used when running tests as collectstatic isn’t run as part of the normal test setup. During testing, ensure that the STATICFILES_STORAGE setting is set to something else like 'django.contrib.staticfiles.storage.StaticFilesStorage' (the default).

storage.ManifestStaticFilesStorage.file_hash(name, content=None)

The method that is used when creating the hashed name of a file. Needs to return a hash for the given file name and content. By default it calculates a MD5 hash from the content’s chunks as mentioned above. Feel free to override this method to use your own hashing algorithm.

CachedStaticFilesStorage

class storage.CachedStaticFilesStorage

CachedStaticFilesStorage is a similar class like the ManifestStaticFilesStorage class but uses Django’s caching framework for storing the hashed names of processed files instead of a static manifest file called staticfiles.json. This is mostly useful for situations in which you don’t have access to the file system.

If you want to override certain options of the cache backend the storage uses, simply specify a custom entry in the CACHES setting named 'staticfiles'. It falls back to using the 'default' cache backend.

Template tags

static

Uses the configured STATICFILES_STORAGE storage to create the full URL for the given relative path, e.g.:

{% load static from staticfiles %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

The previous example is equal to calling the url method of an instance of STATICFILES_STORAGE with "images/hi.jpg". This is especially useful when using a non-local storage backend to deploy files as documented in Serving static files from a cloud service or CDN.

If you’d like to retrieve a static URL without displaying it, you can use a slightly different call:

{% load static from staticfiles %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}" alt="Hi!" />

Using Jinja2 templates?

See django.template.backends.jinja2.Jinja2 for information on using the static tag with Jinja2.

Finders Module

staticfiles finders has a searched_locations attribute which is a list of directory paths in which the finders searched. Example usage:

from django.contrib.staticfiles import finders

result = finders.find('css/base.css')
searched_locations = finders.searched_locations

Other Helpers

There are a few other helpers outside of the staticfiles app to work with static files:

- The django.template.context_processors.static() context processor which adds STATIC_URL to every template context rendered with RequestContext contexts.

- The builtin template tag static which takes a path and urljoins it with the static prefix STATIC_URL.

- The builtin template tag get_static_prefix which populates a template variable with the static prefix STATIC_URL to be used as a variable or directly.

- The similar template tag get_media_prefix which works like get_static_prefix but uses MEDIA_URL.

Static file development view

The static files tools are mostly designed to help with getting static files successfully deployed into production. This usually means a separate, dedicated static file server, which is a lot of overhead to mess with when developing locally. Thus, the staticfiles app ships with a quick and dirty helper view that you can use to serve files locally in development.

views.serve(request, path)

This view function serves static files in development.

Warning

This view will only work if DEBUG is True.

That’s because this view is grossly inefficient and probably insecure. This is only intended for local development, and should never be used in production.

Note

To guess the served files’ content types, this view relies on the mimetypes module from the Python standard library, which itself relies on the underlying platform’s map files. If you find that this view doesn’t return proper content types for certain files, it is most likely that the platform’s map files need to be updated. This can be achieved, for example, by installing or updating the mailcap package on a Red Hat distribution, or mime-support on a Debian distribution.

This view is automatically enabled by runserver (with a DEBUG setting set to True). To use the view with a different local development server, add the following snippet to the end of your primary URL configuration:

from django.conf import settings
from django.contrib.staticfiles import views

if settings.DEBUG:
urlpatterns += [
url(r'^static/(?P<path>.*)$', views.serve),
]

Note, the beginning of the pattern (r'^static/') should be your STATIC_URL setting.

Since this is a bit finicky, there’s also a helper function that’ll do this for you:

urls.staticfiles_urlpatterns()

This will return the proper URL pattern for serving static files to your already defined pattern list. Use it like this:

from django.contrib.staticfiles.urls import staticfiles_urlpatterns

# ... the rest of your URLconf here ...

urlpatterns += staticfiles_urlpatterns()

This will inspect your STATIC_URL setting and wire up the view to serve static files accordingly. Don’t forget to set the STATICFILES_DIRS setting appropriately to let django.contrib.staticfiles know where to look for files in addition to files in app directories.

Warning

This helper function will only work if DEBUG is True and your STATIC_URL setting is neither empty nor a full URL such as http://static.example.com/.

That’s because this view is grossly inefficient and probably insecure. This is only intended for local development, and should never be used in production.

Specialized test case to support ‘live testing’

class testing.StaticLiveServerTestCase

This unittest TestCase subclass extends django.test.LiveServerTestCase.

Just like its parent, you can use it to write tests that involve running the code under test and consuming it with testing tools through HTTP (e.g. Selenium, PhantomJS, etc.), because of which it’s needed that the static assets are also published.

But given the fact that it makes use of the django.contrib.staticfiles.views.serve() view described above, it can transparently overlay at test execution-time the assets provided by the staticfiles finders. This means you don’t need to run collectstatic before or as a part of your tests setup.

The syndication feed framework

Django comes with a high-level syndication-feed-generating framework that makes creating RSS and Atom feeds easy.

To create any syndication feed, all you have to do is write a short Python class. You can create as many feeds as you want.

Django also comes with a lower-level feed-generating API. Use this if you want to generate feeds outside of a Web context, or in some other lower-level way.

The high-level framework

Overview

The high-level feed-generating framework is supplied by the Feed class. To create a feed, write a Feed class and point to an instance of it in your URLconf.

Feed classes

A Feed class is a Python class that represents a syndication feed. A feed can be simple (e.g., a “site news” feed, or a basic feed displaying the latest entries of a blog) or more complex (e.g., a feed displaying all the blog entries in a particular category, where the category is variable).

Feed classes subclass django.contrib.syndication.views.Feed. They can live anywhere in your codebase.

Instances of Feed classes are views which can be used in your URLconf.

A simple example

This simple example, taken from a hypothetical police beat news site describes a feed of the latest five news items:

from django.contrib.syndication.views import Feed
from django.core.urlresolvers import reverse
from policebeat.models import NewsItem

class LatestEntriesFeed(Feed):
title = "Police beat site news"
link = "/sitenews/"
description = "Updates on changes and additions to police beat central."

def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]

def item_title(self, item):
return item.title

def item_description(self, item):
return item.description

# item_link is only needed if NewsItem has no get_absolute_url method.
def item_link(self, item):
return reverse('news-item', args=[item.pk])

To connect a URL to this feed, put an instance of the Feed object in your URLconf. For example:

from django.conf.urls import url
from myproject.feeds import LatestEntriesFeed

urlpatterns = [
# ...
url(r'^latest/feed/$', LatestEntriesFeed()),
# ...
]

Note:

- The Feed class subclasses django.contrib.syndication.views.Feed.

- title, link and description correspond to the standard RSS <title>, <link> and <description> elements, respectively.

- items() is, simply, a method that returns a list of objects that should be included in the feed as <item> elements. Although this example returns NewsItem objects using Django’s object-relational mapper, items() doesn’t have to return model instances. Although you get a few bits of functionality “for free” by using Django models, items() can return any type of object you want.

- If you’re creating an Atom feed, rather than an RSS feed, set the subtitle attribute instead of the description attribute. See Publishing Atom and RSS feeds in tandem, later, for an example.

One thing is left to do. In an RSS feed, each <item> has a <title>, <link> and <description>. We need to tell the framework what data to put into those elements.

- For the contents of <title> and <description>, Django tries calling the methods item_title() and item_description() on the Feed class. They are passed a single parameter, item, which is the object itself. These are optional; by default, the unicode representation of the object is used for both.

If you want to do any special formatting for either the title or description, Django templates can be used instead. Their paths can be specified with the title_template and description_template attributes on the Feed class. The templates are rendered for each item and are passed two template context variables:

- {{ obj }} – The current object (one of whichever objects you returned in items()).

- {{ site }} – A django.contrib.sites.models.Site object representing the current site. This is useful for {{ site.domain }} or {{ site.name }}. If you do not have the Django sites framework installed, this will be set to a RequestSite object. See the RequestSite section of the sites framework documentation for more.

See a complex example below that uses a description template.

Feed.get_context_data(**kwargs)

There is also a way to pass additional information to title and description templates, if you need to supply more than the two variables mentioned before. You can provide your implementation of get_context_data method in your Feed subclass. For example:

from mysite.models import Article
from django.contrib.syndication.views import Feed

class ArticlesFeed(Feed):
title = "My articles"
description_template = "feeds/articles.html"

def items(self):
return Article.objects.order_by('-pub_date')[:5]

def get_context_data(self, **kwargs):
context = super(ArticlesFeed, self).get_context_data(**kwargs)
context['foo'] = 'bar'
return context

And the template:

Something about {{ foo }}: {{ obj.description }}

This method will be called once per each item in the list returned by items() with the following keyword arguments:

- item: the current item. For backward compatibility reasons, the name of this context variable is {{ obj }}.

- obj: the object returned by get_object(). By default this is not exposed to the templates to avoid confusion with {{ obj }} (see above), but you can use it in your implementation of get_context_data().

- site: current site as described above.

- request: current request.

The behavior of get_context_data() mimics that of generic views - you’re supposed to call super() to retrieve context data from parent class, add your data and return the modified dictionary.

- To specify the contents of <link>, you have two options. For each item in items(), Django first tries calling the item_link() method on the Feed class. In a similar way to the title and description, it is passed it a single parameter, item. If that method doesn’t exist, Django tries executing a get_absolute_url() method on that object. Both get_absolute_url() and item_link() should return the item’s URL as a normal Python string. As with get_absolute_url(), the result of item_link() will be included directly in the URL, so you are responsible for doing all necessary URL quoting and conversion to ASCII inside the method itself.

A complex example

The framework also supports more complex feeds, via arguments.

For example, a website could offer an RSS feed of recent crimes for every police beat in a city. It’d be silly to create a separate Feed class for each police beat; that would violate the DRY principle and would couple data to programming logic. Instead, the syndication framework lets you access the arguments passed from your URLconf so feeds can output items based on information in the feed’s URL.

The police beat feeds could be accessible via URLs like this:

- /beats/613/rss/ – Returns recent crimes for beat 613.

- /beats/1424/rss/ – Returns recent crimes for beat 1424.

These can be matched with a URLconf line such as:

url(r'^beats/(?P<beat_id>[0-9]+)/rss/$', BeatFeed()),

Like a view, the arguments in the URL are passed to the get_object() method along with the request object.

Here’s the code for these beat-specific feeds:

from django.contrib.syndication.views import Feed

class BeatFeed(Feed):
description_template = 'feeds/beat_description.html'

def get_object(self, request, beat_id):
return Beat.objects.get(pk=beat_id)

def title(self, obj):
return "Police beat central: Crimes for beat %s" % obj.beat

def link(self, obj):
return obj.get_absolute_url()

def description(self, obj):
return "Crimes recently reported in police beat %s" % obj.beat

def items(self, obj):
return Crime.objects.filter(beat=obj).order_by('-crime_date')[:30]

To generate the feed’s <title>, <link> and <description>, Django uses the title(), link() and description() methods. In the previous example, they were simple string class attributes, but this example illustrates that they can be either strings or methods. For each of title, link and description, Django follows this algorithm:

- First, it tries to call a method, passing the obj argument, where obj is the object returned by get_object().

- Failing that, it tries to call a method with no arguments.

- Failing that, it uses the class attribute.

Also note that items() also follows the same algorithm – first, it tries items(obj), then items(), then finally an items class attribute (which should be a list).

We are using a template for the item descriptions. It can be very simple:

{{ obj.description }}

However, you are free to add formatting as desired.

The ExampleFeed class below gives full documentation on methods and attributes of Feed classes.

Specifying the type of feed

By default, feeds produced in this framework use RSS 2.0.

To change that, add a feed_type attribute to your Feed class, like so:

from django.utils.feedgenerator import Atom1Feed

class MyFeed(Feed):
feed_type = Atom1Feed

Note that you set feed_type to a class object, not an instance.

Currently available feed types are:

- django.utils.feedgenerator.Rss201rev2Feed (RSS 2.01. Default.)

- django.utils.feedgenerator.RssUserland091Feed (RSS 0.91.)

- django.utils.feedgenerator.Atom1Feed (Atom 1.0.)

Enclosures

To specify enclosures, such as those used in creating podcast feeds, use the item_enclosures hook or, alternatively and if you only have a single enclosure per item, the item_enclosure_url, item_enclosure_length, and item_enclosure_mime_type hooks. See the ExampleFeed class below for usage examples.

Changed in Django 1.9:
Support for multiple enclosures per feed item was added through the item_enclosures hook.

Language

Feeds created by the syndication framework automatically include the appropriate <language> tag (RSS 2.0) or xml:lang attribute (Atom). This comes directly from your LANGUAGE_CODE setting.

URLs

The link method/attribute can return either an absolute path (e.g. "/blog/") or a URL with the fully-qualified domain and protocol (e.g. "https://www.example.com/blog/"). If link doesn’t return the domain, the syndication framework will insert the domain of the current site, according to your SITE_ID setting.

Atom feeds require a <link rel="self"> that defines the feed’s current location. The syndication framework populates this automatically, using the domain of the current site according to the SITE_ID setting.

Publishing Atom and RSS feeds in tandem

Some developers like to make available both Atom and RSS versions of their feeds. That’s easy to do with Django: Just create a subclass of your Feed class and set the feed_type to something different. Then update your URLconf to add the extra versions.

Here’s a full example:

from django.contrib.syndication.views import Feed
from policebeat.models import NewsItem
from django.utils.feedgenerator import Atom1Feed

class RssSiteNewsFeed(Feed):
title = "Police beat site news"
link = "/sitenews/"
description = "Updates on changes and additions to police beat central."

def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]

class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed
subtitle = RssSiteNewsFeed.description

Note

In this example, the RSS feed uses a description while the Atom feed uses a subtitle. That’s because Atom feeds don’t provide for a feed-level “description,” but they do provide for a “subtitle.”

If you provide a description in your Feed class, Django will not automatically put that into the subtitle element, because a subtitle and description are not necessarily the same thing. Instead, you should define a subtitle attribute.

In the above example, we simply set the Atom feed’s subtitle to the RSS feed’s description, because it’s quite short already.

And the accompanying URLconf:

from django.conf.urls import url
from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed

urlpatterns = [
# ...
url(r'^sitenews/rss/$', RssSiteNewsFeed()),
url(r'^sitenews/atom/$', AtomSiteNewsFeed()),
# ...
]

Feed class reference

class views.Feed

This example illustrates all possible attributes and methods for a Feed class:

from django.contrib.syndication.views import Feed
from django.utils import feedgenerator

class ExampleFeed(Feed):

# FEED TYPE -- Optional. This should be a class that subclasses
# django.utils.feedgenerator.SyndicationFeed. This designates
# which type of feed this should be: RSS 2.0, Atom 1.0, etc. If
# you don't specify feed_type, your feed will be RSS 2.0. This
# should be a class, not an instance of the class.

feed_type = feedgenerator.Rss201rev2Feed

# TEMPLATE NAMES -- Optional. These should be strings
# representing names of Django templates that the system should
# use in rendering the title and description of your feed items.
# Both are optional. If a template is not specified, the
# item_title() or item_description() methods are used instead.

title_template = None
description_template = None

# TITLE -- One of the following three is required. The framework
# looks for them in this order.

def title(self, obj):
"""
Takes the object returned by get_object() and returns the
feed's title as a normal Python string.
"""

def title(self):
"""
Returns the feed's title as a normal Python string.
"""

title = 'foo' # Hard-coded title.

# LINK -- One of the following three is required. The framework
# looks for them in this order.

def link(self, obj):
"""
# Takes the object returned by get_object() and returns the URL
# of the HTML version of the feed as a normal Python string.
"""

def link(self):
"""
Returns the URL of the HTML version of the feed as a normal Python
string.
"""

link = '/blog/' # Hard-coded URL.

# FEED_URL -- One of the following three is optional. The framework
# looks for them in this order.

def feed_url(self, obj):
"""
# Takes the object returned by get_object() and returns the feed's
# own URL as a normal Python string.
"""

def feed_url(self):
"""
Returns the feed's own URL as a normal Python string.
"""

feed_url = '/blog/rss/' # Hard-coded URL.

# GUID -- One of the following three is optional. The framework looks
# for them in this order. This property is only used for Atom feeds
# (where it is the feed-level ID element). If not provided, the feed
# link is used as the ID.

def feed_guid(self, obj):
"""
Takes the object returned by get_object() and returns the globally
unique ID for the feed as a normal Python string.
"""

def feed_guid(self):
"""
Returns the feed's globally unique ID as a normal Python string.
"""

feed_guid = '/foo/bar/1234' # Hard-coded guid.

# DESCRIPTION -- One of the following three is required. The framework
# looks for them in this order.

def description(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
description as a normal Python string.
"""

def description(self):
"""
Returns the feed's description as a normal Python string.
"""

description = 'Foo bar baz.' # Hard-coded description.

# AUTHOR NAME --One of the following three is optional. The framework
# looks for them in this order.

def author_name(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's name as a normal Python string.
"""

def author_name(self):
"""
Returns the feed's author's name as a normal Python string.
"""

author_name = 'Sally Smith' # Hard-coded author name.

# AUTHOR EMAIL --One of the following three is optional. The framework
# looks for them in this order.

def author_email(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's email as a normal Python string.
"""

def author_email(self):
"""
Returns the feed's author's email as a normal Python string.
"""

author_email = 'test@example.com' # Hard-coded author email.

# AUTHOR LINK --One of the following three is optional. The framework
# looks for them in this order. In each case, the URL should include
# the "http://" and domain name.

def author_link(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
author's URL as a normal Python string.
"""

def author_link(self):
"""
Returns the feed's author's URL as a normal Python string.
"""

author_link = 'https://www.example.com/' # Hard-coded author URL.

# CATEGORIES -- One of the following three is optional. The framework
# looks for them in this order. In each case, the method/attribute
# should return an iterable object that returns strings.

def categories(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
categories as iterable over strings.
"""

def categories(self):
"""
Returns the feed's categories as iterable over strings.
"""

categories = ("python", "django") # Hard-coded list of categories.

# COPYRIGHT NOTICE -- One of the following three is optional. The
# framework looks for them in this order.

def feed_copyright(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
copyright notice as a normal Python string.
"""

def feed_copyright(self):
"""
Returns the feed's copyright notice as a normal Python string.
"""

feed_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.

# TTL -- One of the following three is optional. The framework looks
# for them in this order. Ignored for Atom feeds.

def ttl(self, obj):
"""
Takes the object returned by get_object() and returns the feed's
TTL (Time To Live) as a normal Python string.
"""

def ttl(self):
"""
Returns the feed's TTL as a normal Python string.
"""

ttl = 600 # Hard-coded Time To Live.

# ITEMS -- One of the following three is required. The framework looks
# for them in this order.

def items(self, obj):
"""
Takes the object returned by get_object() and returns a list of
items to publish in this feed.
"""

def items(self):
"""
Returns a list of items to publish in this feed.
"""

items = ('Item 1', 'Item 2') # Hard-coded items.

# GET_OBJECT -- This is required for feeds that publish different data
# for different URL parameters. (See "A complex example" above.)

def get_object(self, request, *args, **kwargs):
"""
Takes the current request and the arguments from the URL, and
returns an object represented by this feed. Raises
django.core.exceptions.ObjectDoesNotExist on error.
"""

# ITEM TITLE AND DESCRIPTION -- If title_template or
# description_template are not defined, these are used instead. Both are
# optional, by default they will use the unicode representation of the
# item.

def item_title(self, item):
"""
Takes an item, as returned by items(), and returns the item's
title as a normal Python string.
"""

def item_title(self):
"""
Returns the title for every item in the feed.
"""

item_title = 'Breaking News: Nothing Happening' # Hard-coded title.

def item_description(self, item):
"""
Takes an item, as returned by items(), and returns the item's
description as a normal Python string.
"""

def item_description(self):
"""
Returns the description for every item in the feed.
"""

item_description = 'A description of the item.' # Hard-coded description.

def get_context_data(self, **kwargs):
"""
Returns a dictionary to use as extra context if either
description_template or item_template are used.

Default implementation preserves the old behavior
of using {'obj': item, 'site': current_site} as the context.
"""

# ITEM LINK -- One of these three is required. The framework looks for
# them in this order.

# First, the framework tries the two methods below, in
# order. Failing that, it falls back to the get_absolute_url()
# method on each item returned by items().

def item_link(self, item):
"""
Takes an item, as returned by items(), and returns the item's URL.
"""

def item_link(self):
"""
Returns the URL for every item in the feed.
"""

# ITEM_GUID -- The following method is optional. If not provided, the
# item's link is used by default.

def item_guid(self, obj):
"""
Takes an item, as return by items(), and returns the item's ID.
"""

# ITEM_GUID_IS_PERMALINK -- The following method is optional. If
# provided, it sets the 'isPermaLink' attribute of an item's
# GUID element. This method is used only when 'item_guid' is
# specified.

def item_guid_is_permalink(self, obj):
"""
Takes an item, as returned by items(), and returns a boolean.
"""

item_guid_is_permalink = False  # Hard coded value

# ITEM AUTHOR NAME -- One of the following three is optional. The
# framework looks for them in this order.

def item_author_name(self, item):
"""
Takes an item, as returned by items(), and returns the item's
author's name as a normal Python string.
"""

def item_author_name(self):
"""
Returns the author name for every item in the feed.
"""

item_author_name = 'Sally Smith' # Hard-coded author name.

# ITEM AUTHOR EMAIL --One of the following three is optional. The
# framework looks for them in this order.
#
# If you specify this, you must specify item_author_name.

def item_author_email(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
author's email as a normal Python string.
"""

def item_author_email(self):
"""
Returns the author email for every item in the feed.
"""

item_author_email = 'test@example.com' # Hard-coded author email.

# ITEM AUTHOR LINK -- One of the following three is optional. The
# framework looks for them in this order. In each case, the URL should
# include the "http://" and domain name.
#
# If you specify this, you must specify item_author_name.

def item_author_link(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
author's URL as a normal Python string.
"""

def item_author_link(self):
"""
Returns the author URL for every item in the feed.
"""

item_author_link = 'https://www.example.com/' # Hard-coded author URL.

# ITEM ENCLOSURES -- One of the following three is optional. The
# framework looks for them in this order. If one of them is defined,
# ``item_enclosure_url``, ``item_enclosure_length``, and
# ``item_enclosure_mime_type`` will have no effect.

def item_enclosures(self, item):
"""
Takes an item, as returned by items(), and returns a list of
``django.utils.feedgenerator.Enclosure`` objects.
"""

def item_enclosures(self):
"""
Returns the ``django.utils.feedgenerator.Enclosure`` list for every
item in the feed.
"""

item_enclosures = []  # Hard-coded enclosure list

# ITEM ENCLOSURE URL -- One of these three is required if you're
# publishing enclosures and you're not using ``item_enclosures``. The
# framework looks for them in this order.

def item_enclosure_url(self, item):
"""
Takes an item, as returned by items(), and returns the item's
enclosure URL.
"""

def item_enclosure_url(self):
"""
Returns the enclosure URL for every item in the feed.
"""

item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link.

# ITEM ENCLOSURE LENGTH -- One of these three is required if you're
# publishing enclosures and you're not using ``item_enclosures``. The
# framework looks for them in this order. In each case, the returned
# value should be either an integer, or a string representation of the
# integer, in bytes.

def item_enclosure_length(self, item):
"""
Takes an item, as returned by items(), and returns the item's
enclosure length.
"""

def item_enclosure_length(self):
"""
Returns the enclosure length for every item in the feed.
"""

item_enclosure_length = 32000 # Hard-coded enclosure length.

# ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're
# publishing enclosures and you're not using ``item_enclosures``. The
# framework looks for them in this order.

def item_enclosure_mime_type(self, item):
"""
Takes an item, as returned by items(), and returns the item's
enclosure MIME type.
"""

def item_enclosure_mime_type(self):
"""
Returns the enclosure MIME type for every item in the feed.
"""

item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure MIME type.

# ITEM PUBDATE -- It's optional to use one of these three. This is a
# hook that specifies how to get the pubdate for a given item.
# In each case, the method/attribute should return a Python
# datetime.datetime object.

def item_pubdate(self, item):
"""
Takes an item, as returned by items(), and returns the item's
pubdate.
"""

def item_pubdate(self):
"""
Returns the pubdate for every item in the feed.
"""

item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.

# ITEM UPDATED -- It's optional to use one of these three. This is a
# hook that specifies how to get the updateddate for a given item.
# In each case, the method/attribute should return a Python
# datetime.datetime object.

def item_updateddate(self, item):
"""
Takes an item, as returned by items(), and returns the item's
updateddate.
"""

def item_updateddate(self):
"""
Returns the updateddate for every item in the feed.
"""

item_updateddate = datetime.datetime(2005, 5, 3) # Hard-coded updateddate.

# ITEM CATEGORIES -- It's optional to use one of these three. This is
# a hook that specifies how to get the list of categories for a given
# item. In each case, the method/attribute should return an iterable
# object that returns strings.

def item_categories(self, item):
"""
Takes an item, as returned by items(), and returns the item's
categories.
"""

def item_categories(self):
"""
Returns the categories for every item in the feed.
"""

item_categories = ("python", "django") # Hard-coded categories.

# ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the
# following three is optional. The framework looks for them in this
# order.

def item_copyright(self, obj):
"""
Takes an item, as returned by items(), and returns the item's
copyright notice as a normal Python string.
"""

def item_copyright(self):
"""
Returns the copyright notice for every item in the feed.
"""

item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.

The low-level framework

Behind the scenes, the high-level RSS framework uses a lower-level framework for generating feeds’ XML. This framework lives in a single module: django/utils/feedgenerator.py.

You use this framework on your own, for lower-level feed generation. You can also create custom feed generator subclasses for use with the feed_type Feed option.

SyndicationFeed classes

The feedgenerator module contains a base class:

- django.utils.feedgenerator.SyndicationFeed

and several subclasses:

- django.utils.feedgenerator.RssUserland091Feed

- django.utils.feedgenerator.Rss201rev2Feed

- django.utils.feedgenerator.Atom1Feed

Each of these three classes knows how to render a certain type of feed as XML. They share this interface:

SyndicationFeed.__init__()

Initialize the feed with the given dictionary of metadata, which applies to the entire feed. Required keyword arguments are:

- title

- link

- description

There’s also a bunch of other optional keywords:

- language

- author_email

- author_name

- author_link

- subtitle

- categories

- feed_url

- feed_copyright

- feed_guid

- ttl

Any extra keyword arguments you pass to __init__ will be stored in self.feed for use with custom feed generators.

All parameters should be Unicode objects, except categories, which should be a sequence of Unicode objects. Beware that some control characters are not allowed in XML documents. If your content has some of them, you might encounter a ValueError when producing the feed.

SyndicationFeed.add_item()

Add an item to the feed with the given parameters.

Required keyword arguments are:

- title

- link

- description

Optional keyword arguments are:

- author_email

- author_name

- author_link

- pubdate

- comments

- unique_id

- enclosure

- enclosures

- categories

- item_copyright

- ttl

- updateddate

Extra keyword arguments will be stored for custom feed generators.

All parameters, if given, should be Unicode objects, except:

- pubdate should be a Python datetime object.

- updateddate should be a Python datetime object.

- enclosure should be an instance of django.utils.feedgenerator.Enclosure.

- enclosures should be a list of django.utils.feedgenerator.Enclosure instances.

- categories should be a sequence of Unicode objects.

Deprecated since version 1.9: The enclosure keyword argument is deprecated in favor of the enclosures keyword argument.

SyndicationFeed.write()

Outputs the feed in the given encoding to outfile, which is a file-like object.

SyndicationFeed.writeString()

Returns the feed as a string in the given encoding.

For example, to create an Atom 1.0 feed and print it to standard output:

>>> from django.utils import feedgenerator
>>> from datetime import datetime
>>> f = feedgenerator.Atom1Feed(
...     title="My Weblog",
...     link="https://www.example.com/",
...     description="In which I write about what I ate today.",
...     language="en",
...     author_name="Myself",
...     feed_url="https://example.com/atom.xml")
>>> f.add_item(title="Hot dog today",
...     link="https://www.example.com/entries/1/",
...     pubdate=datetime.now(),
...     description="<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>")
>>> print(f.writeString('UTF-8'))
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
...
</feed>

Custom feed generators

If you need to produce a custom feed format, you’ve got a couple of options.

If the feed format is totally custom, you’ll want to subclass SyndicationFeed and completely replace the write() and writeString() methods.

However, if the feed format is a spin-off of RSS or Atom (i.e. GeoRSS, Apple’s iTunes podcast format, etc.), you’ve got a better choice. These types of feeds typically add extra elements and/or attributes to the underlying format, and there are a set of methods that SyndicationFeed calls to get these extra attributes. Thus, you can subclass the appropriate feed generator class (Atom1Feed or Rss201rev2Feed) and extend these callbacks. They are:

SyndicationFeed.root_attributes(self, )

Return a dict of attributes to add to the root feed element (feed/channel).

SyndicationFeed.add_root_elements(self, handler)

Callback to add elements inside the root feed element (feed/channel). handler is an XMLGenerator from Python’s built-in SAX library; you’ll call methods on it to add to the XML document in process.

SyndicationFeed.item_attributes(self, item)

Return a dict of attributes to add to each item (item/entry) element. The argument, item, is a dictionary of all the data passed to SyndicationFeed.add_item().

SyndicationFeed.add_item_elements(self, handler, item)

Callback to add elements to each item (item/entry) element. handler and item are as above.

Warning

If you override any of these methods, be sure to call the superclass methods since they add the required elements for each feed format.

For example, you might start implementing an iTunes RSS feed generator like so:

class iTunesFeed(Rss201rev2Feed):
def root_attributes(self):
attrs = super(iTunesFeed, self).root_attributes()
attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
return attrs

def add_root_elements(self, handler):
super(iTunesFeed, self).add_root_elements(handler)
handler.addQuickElement('itunes:explicit', 'clean')

Obviously there’s a lot more work to be done for a complete custom feed class, but the above example should demonstrate the basic idea.

django.contrib.webdesign

Deprecated since version 1.8: The package contained only a single template tag and it has been moved to the built-in tags (lorem).

Cross Site Request Forgery protection

The CSRF middleware and template tag provides easy-to-use protection against Cross Site Request Forgeries. This type of attack occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials of a logged-in user who visits the malicious site in their browser. A related type of attack, ‘login CSRF’, where an attacking site tricks a user’s browser into logging into a site with someone else’s credentials, is also covered.

The first defense against CSRF attacks is to ensure that GET requests (and other ‘safe’ methods, as defined by RFC 7231#section-4.2.1) are side effect free. Requests via ‘unsafe’ methods, such as POST, PUT, and DELETE, can then be protected by following the steps below.

How to use it

To take advantage of CSRF protection in your views, follow these steps:

1. The CSRF middleware is activated by default in the MIDDLEWARE_CLASSES setting. If you override that setting, remember that 'django.middleware.csrf.CsrfViewMiddleware' should come before any view middleware that assume that CSRF attacks have been dealt with.

If you disabled it, which is not recommended, you can use csrf_protect() on particular views you want to protect (see below).

2. In any template that uses a POST form, use the csrf_token tag inside the <form> element if the form is for an internal URL, e.g.:

<form action="" method="post">{% csrf_token %}

This should not be done for POST forms that target external URLs, since that would cause the CSRF token to be leaked, leading to a vulnerability.

3. In the corresponding view functions, ensure that RequestContext is used to render the response so that {% csrf_token %} will work properly. If you’re using the render() function, generic views, or contrib apps, you are covered already since these all use RequestContext.

AJAX

While the above method can be used for AJAX POST requests, it has some inconveniences: you have to remember to pass the CSRF token in as POST data with every POST request. For this reason, there is an alternative method: on each XMLHttpRequest, set a custom X-CSRFToken header to the value of the CSRF token. This is often easier, because many JavaScript frameworks provide hooks that allow headers to be set on every request.

As a first step, you must get the CSRF token itself. The recommended source for the token is the csrftoken cookie, which will be set if you’ve enabled CSRF protection for your views as outlined above.

Note

The CSRF token cookie is named csrftoken by default, but you can control the cookie name via the CSRF_COOKIE_NAME setting.

The CSRF header name is HTTP_X_CSRFTOKEN by default, but you can customize it using the CSRF_HEADER_NAME setting.

Acquiring the token is straightforward:

// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');

The above code could be simplified by using the JavaScript Cookie library to replace getCookie:

var csrftoken = Cookies.get('csrftoken');

Note

The CSRF token is also present in the DOM, but only if explicitly included using csrf_token in a template. The cookie contains the canonical token; the CsrfViewMiddleware will prefer the cookie to the token in the DOM. Regardless, you’re guaranteed to have the cookie if the token is present in the DOM, so you should use the cookie!

Warning

If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie().

Finally, you’ll have to actually set the header on your AJAX request, while protecting the CSRF token from being sent to other domains using settings.crossDomain in jQuery 1.5.1 and newer:

function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});

If you’re using AngularJS 1.1.3 and newer, it’s sufficient to configure the $http provider with the cookie and header names:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

Using CSRF in Jinja2 templates

Django’s Jinja2 template backend adds {{ csrf_input }} to the context of all templates which is equivalent to {% csrf_token %} in the Django template language. For example:

<form action="" method="post">{{ csrf_input }}

The decorator method

Rather than adding CsrfViewMiddleware as a blanket protection, you can use the csrf_protect decorator, which has exactly the same functionality, on particular views that need the protection. It must be used both on views that insert the CSRF token in the output, and on those that accept the POST form data. (These are often the same view function, but not always).

Use of the decorator by itself is not recommended, since if you forget to use it, you will have a security hole. The ‘belt and braces’ strategy of using both is fine, and will incur minimal overhead.

csrf_protect(view)

Decorator that provides the protection of CsrfViewMiddleware to a view.

Usage:

from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render

@csrf_protect
def my_view(request):
c = {}
# ...
return render(request, "a_template.html", c)

If you are using class-based views, you can refer to Decorating class-based views.

Rejected requests

By default, a ‘403 Forbidden’ response is sent to the user if an incoming request fails the checks performed by CsrfViewMiddleware. This should usually only be seen when there is a genuine Cross Site Request Forgery, or when, due to a programming error, the CSRF token has not been included with a POST form.

The error page, however, is not very friendly, so you may want to provide your own view for handling this condition. To do this, simply set the CSRF_FAILURE_VIEW setting.

CSRF failures are logged as warnings to the django.request logger.

How it works

The CSRF protection is based on the following things:

1. A CSRF cookie that is set to a random value (a session independent nonce, as it is called), which other sites will not have access to.

This cookie is set by CsrfViewMiddleware. It is meant to be permanent, but since there is no way to set a cookie that never expires, it is sent with every response that has called django.middleware.csrf.get_token() (the function used internally to retrieve the CSRF token).

For security reasons, the value of the CSRF cookie is changed each time a user logs in.

2. A hidden form field with the name ‘csrfmiddlewaretoken’ present in all outgoing POST forms. The value of this field is the value of the CSRF cookie.

This part is done by the template tag.

3. For all incoming requests that are not using HTTP GET, HEAD, OPTIONS or TRACE, a CSRF cookie must be present, and the ‘csrfmiddlewaretoken’ field must be present and correct. If it isn’t, the user will get a 403 error.

This check is done by CsrfViewMiddleware.

4. In addition, for HTTPS requests, strict referer checking is done by CsrfViewMiddleware. This means that even if a subdomain can set or modify cookies on your domain, it can’t force a user to post to your application since that request won’t come from your own exact domain.

This also addresses a man-in-the-middle attack that’s possible under HTTPS when using a session independent nonce, due to the fact that HTTP Set-Cookie headers are (unfortunately) accepted by clients even when they are talking to a site under HTTPS. (Referer checking is not done for HTTP requests because the presence of the Referer header isn’t reliable enough under HTTP.)

If the CSRF_COOKIE_DOMAIN setting is set, the referer is compared against it. This setting supports subdomains. For example, CSRF_COOKIE_DOMAIN = '.example.com' will allow POST requests from www.example.com and api.example.com. If the setting is not set, then the referer must match the HTTP Host header.

Expanding the accepted referers beyond the current host or cookie domain can be done with the CSRF_TRUSTED_ORIGINS setting.

This ensures that only forms that have originated from trusted domains can be used to POST data back.

It deliberately ignores GET requests (and other requests that are defined as ‘safe’ by RFC 7231). These requests ought never to have any potentially dangerous side effects , and so a CSRF attack with a GET request ought to be harmless. RFC 7231 defines POST, PUT, and DELETE as ‘unsafe’, and all other methods are also assumed to be unsafe, for maximum protection.

The CSRF protection cannot protect against man-in-the-middle attacks, so use HTTPS with HTTP Strict Transport Security. It also assumes validation of the HOST header and that there aren’t any cross-site scripting vulnerabilities on your site (because XSS vulnerabilities already let an attacker do anything a CSRF vulnerability allows and much worse).

Changed in Django 1.9:
Checking against the CSRF_COOKIE_DOMAIN setting was added.

Caching

If the csrf_token template tag is used by a template (or the get_token function is called some other way), CsrfViewMiddleware will add a cookie and a Vary: Cookie header to the response. This means that the middleware will play well with the cache middleware if it is used as instructed (UpdateCacheMiddleware goes before all other middleware).

However, if you use cache decorators on individual views, the CSRF middleware will not yet have been able to set the Vary header or the CSRF cookie, and the response will be cached without either one. In this case, on any views that will require a CSRF token to be inserted you should use the django.views.decorators.csrf.csrf_protect() decorator first:

from django.views.decorators.cache import cache_page
from django.views.decorators.csrf import csrf_protect

@cache_page(60 * 15)
@csrf_protect
def my_view(request):
...

If you are using class-based views, you can refer to Decorating class-based views.

Testing

The CsrfViewMiddleware will usually be a big hindrance to testing view functions, due to the need for the CSRF token which must be sent with every POST request. For this reason, Django’s HTTP client for tests has been modified to set a flag on requests which relaxes the middleware and the csrf_protect decorator so that they no longer rejects requests. In every other respect (e.g. sending cookies etc.), they behave the same.

If, for some reason, you want the test client to perform CSRF checks, you can create an instance of the test client that enforces CSRF checks:

>>> from django.test import Client
>>> csrf_client = Client(enforce_csrf_checks=True)

Limitations

Subdomains within a site will be able to set cookies on the client for the whole domain. By setting the cookie and using a corresponding token, subdomains will be able to circumvent the CSRF protection. The only way to avoid this is to ensure that subdomains are controlled by trusted users (or, are at least unable to set cookies). Note that even without CSRF, there are other vulnerabilities, such as session fixation, that make giving subdomains to untrusted parties a bad idea, and these vulnerabilities cannot easily be fixed with current browsers.

Edge cases

Certain views can have unusual requirements that mean they don’t fit the normal pattern envisaged here. A number of utilities can be useful in these situations. The scenarios they might be needed in are described in the following section.

Utilities

The examples below assume you are using function-based views. If you are working with class-based views, you can refer to Decorating class-based views.

csrf_exempt(view)[source]

This decorator marks a view as being exempt from the protection ensured by the middleware. Example:

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')

requires_csrf_token(view)

Normally the csrf_token template tag will not work if CsrfViewMiddleware.process_view or an equivalent like csrf_protect has not run. The view decorator requires_csrf_token can be used to ensure the template tag does work. This decorator works similarly to csrf_protect, but never rejects an incoming request.

Example:

from django.views.decorators.csrf import requires_csrf_token
from django.shortcuts import render

@requires_csrf_token
def my_view(request):
c = {}
# ...
return render(request, "a_template.html", c)

ensure_csrf_cookie(view)

This decorator forces a view to send the CSRF cookie.

Scenarios

CSRF protection should be disabled for just a few views

Most views requires CSRF protection, but a few do not.

Solution: rather than disabling the middleware and applying csrf_protect to all the views that need it, enable the middleware and use csrf_exempt().

CsrfViewMiddleware.process_view not used

There are cases when CsrfViewMiddleware.process_view may not have run before your view is run - 404 and 500 handlers, for example - but you still need the CSRF token in a form.

Solution: use requires_csrf_token()

Unprotected view needs the CSRF token

There may be some views that are unprotected and have been exempted by csrf_exempt, but still need to include the CSRF token.

Solution: use csrf_exempt() followed by requires_csrf_token(). (i.e. requires_csrf_token should be the innermost decorator).

View needs protection for one path

A view needs CSRF protection under one set of conditions only, and mustn’t have it for the rest of the time.

Solution: use csrf_exempt() for the whole view function, and csrf_protect() for the path within it that needs protection. Example:

from django.views.decorators.csrf import csrf_exempt, csrf_protect

@csrf_exempt
def my_view(request):

@csrf_protect
def protected_path(request):
do_something()

if some_condition():
return protected_path(request)
else:
do_something_else()

Page uses AJAX without any HTML form

A page makes a POST request via AJAX, and the page does not have an HTML form with a csrf_token that would cause the required CSRF cookie to be sent.

Solution: use ensure_csrf_cookie() on the view that sends the page.

Contrib and reusable apps

Because it is possible for the developer to turn off the CsrfViewMiddleware, all relevant views in contrib apps use the csrf_protect decorator to ensure the security of these applications against CSRF. It is recommended that the developers of other reusable apps that want the same guarantees also use the csrf_protect decorator on their views.

Settings

A number of settings can be used to control Django’s CSRF behavior:

- CSRF_COOKIE_AGE

- CSRF_COOKIE_DOMAIN

- CSRF_COOKIE_HTTPONLY

- CSRF_COOKIE_NAME

- CSRF_COOKIE_PATH

- CSRF_COOKIE_SECURE

- CSRF_FAILURE_VIEW

- CSRF_HEADER_NAME

- CSRF_TRUSTED_ORIGINS

Frequently Asked Questions

Is posting an arbitrary CSRF token pair (cookie and POST data) a vulnerability?

No, this is by design. Without a man-in-the-middle attack, there is no way for an attacker to send a CSRF token cookie to a victim’s browser, so a successful attack would need to obtain the victim’s browser’s cookie via XSS or similar, in which case an attacker usually doesn’t need CSRF attacks.

Some security audit tools flag this as a problem but as mentioned before, an attacker cannot steal a user’s browser’s CSRF cookie. “Stealing” or modifying your own token using Firebug, Chrome dev tools, etc. isn’t a vulnerability.

Is the fact that Django’s CSRF protection isn’t linked to a session a problem?

No, this is by design. Not linking CSRF protection to a session allows using the protection on sites such as a pastebin that allow submissions from anonymous users which don’t have a session.

Why not use a new token for each request?

Generating a new token for each request is problematic from a UI perspective because it invalidates all previous forms. Most users would be very unhappy to find that opening a new tab on your site has invalidated the form they had just spent time filling out in another tab or that a form they accessed via the back button could not be filled out.

Why might a user encounter a CSRF validation failure after logging in?

For security reasons, CSRF tokens are rotated each time a user logs in. Any page with a form generated before a login will have an old, invalid CSRF token and need to be reloaded. This might happen if a user uses the back button after a login or if they log in in a different browser tab.

Databases

Django attempts to support as many features as possible on all database backends. However, not all database backends are alike, and we’ve had to make design decisions on which features to support and which assumptions we can make safely.

This file describes some of the features that might be relevant to Django usage. Of course, it is not intended as a replacement for server-specific documentation or reference manuals.

General notes

Persistent connections

Persistent connections avoid the overhead of re-establishing a connection to the database in each request. They’re controlled by the CONN_MAX_AGE parameter which defines the maximum lifetime of a connection. It can be set independently for each database.

The default value is 0, preserving the historical behavior of closing the database connection at the end of each request. To enable persistent connections, set CONN_MAX_AGE to a positive number of seconds. For unlimited persistent connections, set it to None.

Connection management

Django opens a connection to the database when it first makes a database query. It keeps this connection open and reuses it in subsequent requests. Django closes the connection once it exceeds the maximum age defined by CONN_MAX_AGE or when it isn’t usable any longer.

In detail, Django automatically opens a connection to the database whenever it needs one and doesn’t have one already — either because this is the first connection, or because the previous connection was closed.

At the beginning of each request, Django closes the connection if it has reached its maximum age. If your database terminates idle connections after some time, you should set CONN_MAX_AGE to a lower value, so that Django doesn’t attempt to use a connection that has been terminated by the database server. (This problem may only affect very low traffic sites.)

At the end of each request, Django closes the connection if it has reached its maximum age or if it is in an unrecoverable error state. If any database errors have occurred while processing the requests, Django checks whether the connection still works, and closes it if it doesn’t. Thus, database errors affect at most one request; if the connection becomes unusable, the next request gets a fresh connection.

Caveats

Since each thread maintains its own connection, your database must support at least as many simultaneous connections as you have worker threads.

Sometimes a database won’t be accessed by the majority of your views, for example because it’s the database of an external system, or thanks to caching. In such cases, you should set CONN_MAX_AGE to a low value or even 0, because it doesn’t make sense to maintain a connection that’s unlikely to be reused. This will help keep the number of simultaneous connections to this database small.

The development server creates a new thread for each request it handles, negating the effect of persistent connections. Don’t enable them during development.

When Django establishes a connection to the database, it sets up appropriate parameters, depending on the backend being used. If you enable persistent connections, this setup is no longer repeated every request. If you modify parameters such as the connection’s isolation level or time zone, you should either restore Django’s defaults at the end of each request, force an appropriate value at the beginning of each request, or disable persistent connections.

Encoding

Django assumes that all databases use UTF-8 encoding. Using other encodings may result in unexpected behavior such as “value too long” errors from your database for data that is valid in Django. See the database specific notes below for information on how to set up your database correctly.

PostgreSQL notes

Django supports PostgreSQL 9.1 and higher. It requires the use of psycopg2 2.4.5 or higher (or 2.5+ if you want to use django.contrib.postgres).

PostgreSQL connection settings

See HOST for details.

Optimizing PostgreSQL’s configuration

Django needs the following parameters for its database connections:

- client_encoding: 'UTF8',

- default_transaction_isolation: 'read committed' by default, or the value set in the connection options (see below),

- timezone: 'UTC' when USE_TZ is True, value of TIME_ZONE otherwise.

If these parameters already have the correct values, Django won’t set them for every new connection, which improves performance slightly. You can configure them directly in postgresql.conf or more conveniently per database user with ALTER ROLE.

Django will work just fine without this optimization, but each new connection will do some additional queries to set these parameters.

Isolation level

Like PostgreSQL itself, Django defaults to the READ COMMITTED isolation level. If you need a higher isolation level such as REPEATABLE READ or SERIALIZABLE, set it in the OPTIONS part of your database configuration in DATABASES:

import psycopg2.extensions

DATABASES = {
# ...
'OPTIONS': {
'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
},
}

Note

Under higher isolation levels, your application should be prepared to handle exceptions raised on serialization failures. This option is designed for advanced uses.

Indexes for varchar and text columns

When specifying db_index=True on your model fields, Django typically outputs a single CREATE INDEX statement. However, if the database type for the field is either varchar or text (e.g., used by CharField, FileField, and TextField), then Django will create an additional index that uses an appropriate PostgreSQL operator class for the column. The extra index is necessary to correctly perform lookups that use the LIKE operator in their SQL, as is done with the contains and startswith lookup types.

Speeding up test execution with non-durable settings

You can speed up test execution times by configuring PostgreSQL to be non-durable.

Warning

This is dangerous: it will make your database more susceptible to data loss or corruption in the case of a server crash or power loss. Only use this on a development machine where you can easily restore the entire contents of all databases in the cluster.

MySQL notes

Version support

Django supports MySQL 5.5 and higher.

Django’s inspectdb feature uses the information_schema database, which contains detailed data on all database schemas.

Django expects the database to support Unicode (UTF-8 encoding) and delegates to it the task of enforcing transactions and referential integrity. It is important to be aware of the fact that the two latter ones aren’t actually enforced by MySQL when using the MyISAM storage engine, see the next section.

Storage engines

MySQL has several storage engines. You can change the default storage engine in the server configuration.

Until MySQL 5.5.4, the default engine was MyISAM [1]. The main drawbacks of MyISAM are that it doesn’t support transactions or enforce foreign-key constraints. On the plus side, it was the only engine that supported full-text indexing and searching until MySQL 5.6.4.

Since MySQL 5.5.5, the default storage engine is InnoDB. This engine is fully transactional and supports foreign key references. It’s probably the best choice at this point. However, note that the InnoDB autoincrement counter is lost on a MySQL restart because it does not remember the AUTO_INCREMENT value, instead recreating it as “max(id)+1”. This may result in an inadvertent reuse of AutoField values.

If you upgrade an existing project to MySQL 5.5.5 and subsequently add some tables, ensure that your tables are using the same storage engine (i.e. MyISAM vs. InnoDB). Specifically, if tables that have a ForeignKey between them use different storage engines, you may see an error like the following when running migrate:

_mysql_exceptions.OperationalError: (
1005, "Can't create table '\\db_name\\.#sql-4a8_ab' (errno: 150)"
)

[1]

Unless this was changed by the packager of your MySQL package. We’ve had reports that the Windows Community Server installer sets up InnoDB as the default storage engine, for example.

MySQL DB API Drivers

The Python Database API is described in PEP 249. MySQL has three prominent drivers that implement this API:

- MySQLdb is a native driver that has been developed and supported for over a decade by Andy Dustman.

- mysqlclient is a fork of MySQLdb which notably supports Python 3 and can be used as a drop-in replacement for MySQLdb. At the time of this writing, this is the recommended choice for using MySQL with Django.

- MySQL Connector/Python is a pure Python driver from Oracle that does not require the MySQL client library or any Python modules outside the standard library.

All these drivers are thread-safe and provide connection pooling. MySQLdb is the only one not supporting Python 3 currently.

In addition to a DB API driver, Django needs an adapter to access the database drivers from its ORM. Django provides an adapter for MySQLdb/mysqlclient while MySQL Connector/Python includes its own.

MySQLdb

Django requires MySQLdb version 1.2.1p2 or later.

At the time of writing, the latest release of MySQLdb (1.2.5) doesn’t support Python 3. In order to use MySQLdb under Python 3, you’ll have to install mysqlclient instead.

Note

There are known issues with the way MySQLdb converts date strings into datetime objects. Specifically, date strings with value 0000-00-00 are valid for MySQL but will be converted into None by MySQLdb.

This means you should be careful while using loaddata and dumpdata with rows that may have 0000-00-00 values, as they will be converted to None.

mysqlclient

Django requires mysqlclient 1.3.3 or later. Note that Python 3.2 is not supported. Except for the Python 3.3+ support, mysqlclient should mostly behave the same as MySQLDB.

MySQL Connector/Python

MySQL Connector/Python is available from the download page. The Django adapter is available in versions 1.1.X and later. It may not support the most recent releases of Django.

Time zone definitions

If you plan on using Django’s timezone support, use mysql_tzinfo_to_sql to load time zone tables into the MySQL database. This needs to be done just once for your MySQL server, not per database.

Creating your database

You can create your database using the command-line tools and this SQL:

CREATE DATABASE <dbname> CHARACTER SET utf8;

This ensures all tables and columns will use UTF-8 by default.

Collation settings

The collation setting for a column controls the order in which data is sorted as well as what strings compare as equal. It can be set on a database-wide level and also per-table and per-column. This is documented thoroughly in the MySQL documentation. In all cases, you set the collation by directly manipulating the database tables; Django doesn’t provide a way to set this on the model definition.

By default, with a UTF-8 database, MySQL will use the utf8_general_ci collation. This results in all string equality comparisons being done in a case-insensitive manner. That is, "Fred" and "freD" are considered equal at the database level. If you have a unique constraint on a field, it would be illegal to try to insert both "aa" and "AA" into the same column, since they compare as equal (and, hence, non-unique) with the default collation.

In many cases, this default will not be a problem. However, if you really want case-sensitive comparisons on a particular column or table, you would change the column or table to use the utf8_bin collation. The main thing to be aware of in this case is that if you are using MySQLdb 1.2.2, the database backend in Django will then return bytestrings (instead of unicode strings) for any character fields it receive from the database. This is a strong variation from Django’s normal practice of always returning unicode strings. It is up to you, the developer, to handle the fact that you will receive bytestrings if you configure your table(s) to use utf8_bin collation. Django itself should mostly work smoothly with such columns (except for the contrib.sessions Session and contrib.admin LogEntry tables described below), but your code must be prepared to call django.utils.encoding.smart_text() at times if it really wants to work with consistent data – Django will not do this for you (the database backend layer and the model population layer are separated internally so the database layer doesn’t know it needs to make this conversion in this one particular case).

If you’re using MySQLdb 1.2.1p2, Django’s standard CharField class will return unicode strings even with utf8_bin collation. However, TextField fields will be returned as an array.array instance (from Python’s standard array module). There isn’t a lot Django can do about that, since, again, the information needed to make the necessary conversions isn’t available when the data is read in from the database. This problem was fixed in MySQLdb 1.2.2, so if you want to use TextField with utf8_bin collation, upgrading to version 1.2.2 and then dealing with the bytestrings (which shouldn’t be too difficult) as described above is the recommended solution.

Should you decide to use utf8_bin collation for some of your tables with MySQLdb 1.2.1p2 or 1.2.2, you should still use utf8_general_ci (the default) collation for the django.contrib.sessions.models.Session table (usually called django_session) and the django.contrib.admin.models.LogEntry table (usually called django_admin_log). Those are the two standard tables that use TextField internally.

Please note that according to MySQL Unicode Character Sets, comparisons for the utf8_general_ci collation are faster, but slightly less correct, than comparisons for utf8_unicode_ci. If this is acceptable for your application, you should use utf8_general_ci because it is faster. If this is not acceptable (for example, if you require German dictionary order), use utf8_unicode_ci because it is more accurate.

Warning

Model formsets validate unique fields in a case-sensitive manner. Thus when using a case-insensitive collation, a formset with unique field values that differ only by case will pass validation, but upon calling save(), an IntegrityError will be raised.

Connecting to the database

Refer to the settings documentation.

Connection settings are used in this order:

1. OPTIONS.

2. NAME, USER, PASSWORD, HOST, PORT

3. MySQL option files.

In other words, if you set the name of the database in OPTIONS, this will take precedence over NAME, which would override anything in a MySQL option file.

Here’s a sample configuration which uses a MySQL option file:

# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/path/to/my.cnf',
},
}
}

# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8

Several other MySQLdb connection options may be useful, such as ssl, init_command, and sql_mode. Consult the MySQLdb documentation for more details.

Setting sql_mode

From MySQL 5.7 onwards and on fresh installs of MySQL 5.6, the default value of the sql_mode option contains STRICT_TRANS_TABLES. That option escalates warnings into errors when data are truncated upon insertion, so Django highly recommends activating a strict mode for MySQL to prevent data loss (either STRICT_TRANS_TABLES or STRICT_ALL_TABLES).

If you need to customize the SQL mode, you can set the sql_mode variable like other MySQL options: either in a config file or with the entry 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" in the OPTIONS part of your database configuration in DATABASES.

Creating your tables

When Django generates the schema, it doesn’t specify a storage engine, so tables will be created with whatever default storage engine your database server is configured for. The easiest solution is to set your database server’s default storage engine to the desired engine.

If you’re using a hosting service and can’t change your server’s default storage engine, you have a couple of options.

- After the tables are created, execute an ALTER TABLE statement to convert a table to a new storage engine (such as InnoDB):

ALTER TABLE <tablename> ENGINE=INNODB;

This can be tedious if you have a lot of tables.

- Another option is to use the init_command option for MySQLdb prior to creating your tables:

'OPTIONS': {
'init_command': 'SET default_storage_engine=INNODB',
}

This sets the default storage engine upon connecting to the database. After your tables have been created, you should remove this option as it adds a query that is only needed during table creation to each database connection.

Table names

There are known issues in even the latest versions of MySQL that can cause the case of a table name to be altered when certain SQL statements are executed under certain conditions. It is recommended that you use lowercase table names, if possible, to avoid any problems that might arise from this behavior. Django uses lowercase table names when it auto-generates table names from models, so this is mainly a consideration if you are overriding the table name via the db_table parameter.

Savepoints

Both the Django ORM and MySQL (when using the InnoDB storage engine) support database savepoints.

If you use the MyISAM storage engine please be aware of the fact that you will receive database-generated errors if you try to use the savepoint-related methods of the transactions API. The reason for this is that detecting the storage engine of a MySQL database/table is an expensive operation so it was decided it isn’t worth to dynamically convert these methods in no-op’s based in the results of such detection.

Notes on specific fields

Character fields

Any fields that are stored with VARCHAR column types have their max_length restricted to 255 characters if you are using unique=True for the field. This affects CharField, SlugField and CommaSeparatedIntegerField.

TextField limitations

MySQL can index only the first N chars of a BLOB or TEXT column. Since TextField doesn’t have a defined length, you can’t mark it as unique=True. MySQL will report: “BLOB/TEXT column ‘<db_column>’ used in key specification without a key length”.

Fractional seconds support for Time and DateTime fields

MySQL 5.6.4 and later can store fractional seconds, provided that the column definition includes a fractional indication (e.g. DATETIME(6)). Earlier versions do not support them at all. In addition, versions of MySQLdb older than 1.2.5 have a bug that also prevents the use of fractional seconds with MySQL.

Django will not upgrade existing columns to include fractional seconds if the database server supports it. If you want to enable them on an existing database, it’s up to you to either manually update the column on the target database, by executing a command like:

ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)

or using a RunSQL operation in a data migration.

Changed in Django 1.8:
Previously, Django truncated fractional seconds from datetime and time values when using the MySQL backend. Now it lets the database decide whether it should drop that part of the value or not. By default, new DateTimeField or TimeField columns are now created with fractional seconds support on MySQL 5.6.4 or later with either mysqlclient or MySQLdb 1.2.5 or later.

TIMESTAMP columns

If you are using a legacy database that contains TIMESTAMP columns, you must set USE_TZ = False to avoid data corruption. inspectdb maps these columns to DateTimeField and if you enable timezone support, both MySQL and Django will attempt to convert the values from UTC to local time.

Row locking with QuerySet.select_for_update()

MySQL does not support the NOWAIT option to the SELECT ... FOR UPDATE statement. If select_for_update() is used with nowait=True then a DatabaseError will be raised.

Automatic typecasting can cause unexpected results

When performing a query on a string type, but with an integer value, MySQL will coerce the types of all values in the table to an integer before performing the comparison. If your table contains the values 'abc', 'def' and you query for WHERE mycolumn=0, both rows will match. Similarly, WHERE mycolumn=1 will match the value 'abc1'. Therefore, string type fields included in Django will always cast the value to a string before using it in a query.

If you implement custom model fields that inherit from Field directly, are overriding get_prep_value(), or use RawSQL, extra(), or raw(), you should ensure that you perform appropriate typecasting.

SQLite notes

SQLite provides an excellent development alternative for applications that are predominantly read-only or require a smaller installation footprint. As with all database servers, though, there are some differences that are specific to SQLite that you should be aware of.

Substring matching and case sensitivity

For all SQLite versions, there is some slightly counter-intuitive behavior when attempting to match some types of strings. These are triggered when using the iexact or contains filters in Querysets. The behavior splits into two cases:

1. For substring matching, all matches are done case-insensitively. That is a filter such as filter(name__contains="aa") will match a name of "Aabb".

2. For strings containing characters outside the ASCII range, all exact string matches are performed case-sensitively, even when the case-insensitive options are passed into the query. So the iexact filter will behave exactly the same as the exact filter in these cases.

Some possible workarounds for this are documented at sqlite.org, but they aren’t utilized by the default SQLite backend in Django, as incorporating them would be fairly difficult to do robustly. Thus, Django exposes the default SQLite behavior and you should be aware of this when doing case-insensitive or substring filtering.

Old SQLite and CASE expressions

SQLite 3.6.23.1 and older contains a bug when handling query parameters in a CASE expression that contains an ELSE and arithmetic.

SQLite 3.6.23.1 was released in March 2010, and most current binary distributions for different platforms include a newer version of SQLite, with the notable exception of the Python 2.7 installers for Windows.

As of this writing, the latest release for Windows - Python 2.7.10 - includes SQLite 3.6.21. You can install pysqlite2 or replace sqlite3.dll (by default installed in C:\Python27\DLLs) with a newer version from https://www.sqlite.org/ to remedy this issue.

Using newer versions of the SQLite DB-API 2.0 driver

Django will use a pysqlite2 module in preference to sqlite3 as shipped with the Python standard library if it finds one is available.

This provides the ability to upgrade both the DB-API 2.0 interface or SQLite 3 itself to versions newer than the ones included with your particular Python binary distribution, if needed.

“Database is locked” errors

SQLite is meant to be a lightweight database, and thus can’t support a high level of concurrency. OperationalError: database is locked errors indicate that your application is experiencing more concurrency than sqlite can handle in default configuration. This error means that one thread or process has an exclusive lock on the database connection and another thread timed out waiting for the lock the be released.

Python’s SQLite wrapper has a default timeout value that determines how long the second thread is allowed to wait on the lock before it times out and raises the OperationalError: database is locked error.

If you’re getting this error, you can solve it by:

- Switching to another database backend. At a certain point SQLite becomes too “lite” for real-world applications, and these sorts of concurrency errors indicate you’ve reached that point.

- Rewriting your code to reduce concurrency and ensure that database transactions are short-lived.

- Increase the default timeout value by setting the timeout database option:

'OPTIONS': {
# ...
'timeout': 20,
# ...
}

This will simply make SQLite wait a bit longer before throwing “database is locked” errors; it won’t really do anything to solve them.

QuerySet.select_for_update() not supported

SQLite does not support the SELECT ... FOR UPDATE syntax. Calling it will have no effect.

“pyformat” parameter style in raw queries not supported

For most backends, raw queries (Manager.raw() or cursor.execute()) can use the “pyformat” parameter style, where placeholders in the query are given as '%(name)s' and the parameters are passed as a dictionary rather than a list. SQLite does not support this.

Oracle notes

Django supports Oracle Database Server versions 11.2 and higher. Version 4.3.1 or higher of the cx_Oracle Python driver is required, although we recommend version 5.1.3 or later as these versions support Python 3.

Note that due to a Unicode-corruption bug in cx_Oracle 5.0, that version of the driver should not be used with Django; cx_Oracle 5.0.1 resolved this issue, so if you’d like to use a more recent cx_Oracle, use version 5.0.1.

cx_Oracle 5.0.1 or greater can optionally be compiled with the WITH_UNICODE environment variable. This is recommended but not required.

In order for the python manage.py migrate command to work, your Oracle database user must have privileges to run the following commands:

- CREATE TABLE

- CREATE SEQUENCE

- CREATE PROCEDURE

- CREATE TRIGGER

To run a project’s test suite, the user usually needs these additional privileges:

- CREATE USER

- DROP USER

- CREATE TABLESPACE

- DROP TABLESPACE

- CREATE SESSION WITH ADMIN OPTION

- CREATE TABLE WITH ADMIN OPTION

- CREATE SEQUENCE WITH ADMIN OPTION

- CREATE PROCEDURE WITH ADMIN OPTION

- CREATE TRIGGER WITH ADMIN OPTION

Note that, while the RESOURCE role has the required CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE and CREATE TRIGGER privileges, and a user granted RESOURCE WITH ADMIN OPTION can grant RESOURCE, such a user cannot grant the individual privileges (e.g. CREATE TABLE), and thus RESOURCE WITH ADMIN OPTION is not usually sufficient for running tests.

Some test suites also create views; to run these, the user also needs the CREATE VIEW WITH ADMIN OPTION privilege. In particular, this is needed for Django’s own test suite.

Changed in Django 1.8:
Prior to Django 1.8, the test user was granted the CONNECT and RESOURCE roles, so the extra privileges required for running the test suite were different.

All of these privileges are included in the DBA role, which is appropriate for use on a private developer’s database.

The Oracle database backend uses the SYS.DBMS_LOB and SYS.DBMS_RANDOM packages, so your user will require execute permissions on it. It’s normally accessible to all users by default, but in case it is not, you’ll need to grant permissions like so:

GRANT EXECUTE ON SYS.DBMS_LOB TO user;
GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;

Connecting to the database

To connect using the service name of your Oracle database, your settings.py file should look something like this:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'xe',
'USER': 'a_user',
'PASSWORD': 'a_password',
'HOST': '',
'PORT': '',
}
}

In this case, you should leave both HOST and PORT empty. However, if you don’t use a tnsnames.ora file or a similar naming method and want to connect using the SID (“xe” in this example), then fill in both HOST and PORT like so:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'xe',
'USER': 'a_user',
'PASSWORD': 'a_password',
'HOST': 'dbprod01ned.mycompany.com',
'PORT': '1540',
}
}

You should either supply both HOST and PORT, or leave both as empty strings. Django will use a different connect descriptor depending on that choice.

Threaded option

If you plan to run Django in a multithreaded environment (e.g. Apache using the default MPM module on any modern operating system), then you must set the threaded option of your Oracle database configuration to True:

'OPTIONS': {
'threaded': True,
},

Failure to do this may result in crashes and other odd behavior.

INSERT ... RETURNING INTO

By default, the Oracle backend uses a RETURNING INTO clause to efficiently retrieve the value of an AutoField when inserting new rows. This behavior may result in a DatabaseError in certain unusual setups, such as when inserting into a remote table, or into a view with an INSTEAD OF trigger. The RETURNING INTO clause can be disabled by setting the use_returning_into option of the database configuration to False:

'OPTIONS': {
'use_returning_into': False,
},

In this case, the Oracle backend will use a separate SELECT query to retrieve AutoField values.

Naming issues

Oracle imposes a name length limit of 30 characters. To accommodate this, the backend truncates database identifiers to fit, replacing the final four characters of the truncated name with a repeatable MD5 hash value. Additionally, the backend turns database identifiers to all-uppercase.

To prevent these transformations (this is usually required only when dealing with legacy databases or accessing tables which belong to other users), use a quoted name as the value for db_table:

class LegacyModel(models.Model):
class Meta:
db_table = '"name_left_in_lowercase"'

class ForeignModel(models.Model):
class Meta:
db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'

Quoted names can also be used with Django’s other supported database backends; except for Oracle, however, the quotes have no effect.

When running migrate, an ORA-06552 error may be encountered if certain Oracle keywords are used as the name of a model field or the value of a db_column option. Django quotes all identifiers used in queries to prevent most such problems, but this error can still occur when an Oracle datatype is used as a column name. In particular, take care to avoid using the names date, timestamp, number or float as a field name.

NULL and empty strings

Django generally prefers to use the empty string (‘’) rather than NULL, but Oracle treats both identically. To get around this, the Oracle backend ignores an explicit null option on fields that have the empty string as a possible value and generates DDL as if null=True. When fetching from the database, it is assumed that a NULL value in one of these fields really means the empty string, and the data is silently converted to reflect this assumption.

TextField limitations

The Oracle backend stores TextFields as NCLOB columns. Oracle imposes some limitations on the usage of such LOB columns in general:

- LOB columns may not be used as primary keys.

- LOB columns may not be used in indexes.

- LOB columns may not be used in a SELECT DISTINCT list. This means that attempting to use the QuerySet.distinct method on a model that includes TextField columns will result in an ORA-00932 error when run against Oracle. As a workaround, use the QuerySet.defer method in conjunction with distinct() to prevent TextField columns from being included in the SELECT DISTINCT list.

Using a 3rd-party database backend

In addition to the officially supported databases, there are backends provided by 3rd parties that allow you to use other databases with Django:

- SAP SQL Anywhere

- IBM DB2

- Microsoft SQL Server

- Firebird

- ODBC

The Django versions and ORM features supported by these unofficial backends vary considerably. Queries regarding the specific capabilities of these unofficial backends, along with any support queries, should be directed to the support channels provided by each 3rd party project.

django-admin and manage.py

django-admin is Django’s command-line utility for administrative tasks. This document outlines all it can do.

In addition, manage.py is automatically created in each Django project. manage.py does the same thing as django-admin but takes care of a few things for you:

- It puts your project’s package on sys.path.

- It sets the DJANGO_SETTINGS_MODULE environment variable so that it points to your project’s settings.py file.

The django-admin script should be on your system path if you installed Django via its setup.py utility. If it’s not on your path, you can find it in site-packages/django/bin within your Python installation. Consider symlinking it from some place on your path, such as /usr/local/bin.

For Windows users, who do not have symlinking functionality available, you can copy django-admin.exe to a location on your existing path or edit the PATH settings (under Settings - Control Panel - System - Advanced - Environment...) to point to its installed location.

Generally, when working on a single Django project, it’s easier to use manage.py than django-admin. If you need to switch between multiple Django settings files, use django-admin with DJANGO_SETTINGS_MODULE or the --settings command line option.

The command-line examples throughout this document use django-admin to be consistent, but any example can use manage.py or python -m django just as well.

New in Django 1.9:
python -m django was added.

Usage

$ django-admin <command> [options]
$ manage.py <command> [options]
$ python -m django <command> [options]

command should be one of the commands listed in this document. options, which is optional, should be zero or more of the options available for the given command.

Getting runtime help

django-admin help

Run django-admin help to display usage information and a list of the commands provided by each application.

Run django-admin help --commands to display a list of all available commands.

Run django-admin help <command> to display a description of the given command and a list of its available options.

App names

Many commands take a list of “app names.” An “app name” is the basename of the package containing your models. For example, if your INSTALLED_APPS contains the string 'mysite.blog', the app name is blog.

Determining the version

django-admin version

Run django-admin version to display the current Django version.

The output follows the schema described in PEP 386:

1.4.dev17026
1.4a1
1.4

Displaying debug output

Use --verbosity to specify the amount of notification and debug information that django-admin prints to the console.

Available commands

check

django-admin check [app_label [app_label ...]]

Uses the system check framework to inspect the entire Django project for common problems.

By default, all apps will be checked. You can check a subset of apps by providing a list of app labels as arguments:

django-admin check auth admin myapp

If you do not specify any app, all apps will be checked.

--tag TAGS, -t TAGS

The system check framework performs many different types of checks that are categorized with tags. You can use these tags to restrict the checks performed to just those in a particular category. For example, to perform only models and compatibility checks, run:

django-admin check --tag models --tag compatibility

--list-tags

Lists all available tags.

--deploy

New in Django 1.8.

Activates some additional checks that are only relevant in a deployment setting.

You can use this option in your local development environment, but since your local development settings module may not have many of your production settings, you will probably want to point the check command at a different settings module, either by setting the DJANGO_SETTINGS_MODULE environment variable, or by passing the --settings option:

django-admin check --deploy --settings=production_settings

Or you could run it directly on a production or staging deployment to verify that the correct settings are in use (omitting --settings). You could even make it part of your integration test suite.

compilemessages

django-admin compilemessages

Compiles .po files created by makemessages to .mo files for use with the built-in gettext support. See Internationalization and localization.

--locale LOCALE, -l LOCALE

Specifies the locale(s) to process. If not provided, all locales are processed.

--exclude EXCLUDE, -x EXCLUDE

Specifies the locale(s) to exclude from processing. If not provided, no locales are excluded.

--use-fuzzy, -f

Includes fuzzy translations into compiled files.

Changed in Django 1.9:
compilemessages now matches the operation of makemessages, scanning the project tree for .po files to compile.

Changed in Django 1.8:
Added --exclude and --use-fuzzy options.

Example usage:

django-admin compilemessages --locale=pt_BR
django-admin compilemessages --locale=pt_BR --locale=fr -f
django-admin compilemessages -l pt_BR
django-admin compilemessages -l pt_BR -l fr --use-fuzzy
django-admin compilemessages --exclude=pt_BR
django-admin compilemessages --exclude=pt_BR --exclude=fr
django-admin compilemessages -x pt_BR
django-admin compilemessages -x pt_BR -x fr

createcachetable

django-admin createcachetable

Creates the cache tables for use with the database cache backend using the information from your settings file. See Django’s cache framework for more information.

--database DATABASE

Specifies the database in which the cache table(s) will be created. Defaults to default.

--dry-run

Prints the SQL that would be run without actually running it, so you can customize it or use the migrations framework.

Changed in Django 1.9:
The --dry-run option was added.

dbshell

django-admin dbshell

Runs the command-line client for the database engine specified in your ENGINE setting, with the connection parameters specified in your USER, PASSWORD, etc., settings.

- For PostgreSQL, this runs the psql command-line client.

- For MySQL, this runs the mysql command-line client.

- For SQLite, this runs the sqlite3 command-line client.

- For Oracle, this runs the sqlplus command-line client.

This command assumes the programs are on your PATH so that a simple call to the program name (psql, mysql, sqlite3, sqlplus) will find the program in the right place. There’s no way to specify the location of the program manually.

--database DATABASE

Specifies the database onto which to open a shell. Defaults to default.

diffsettings

django-admin diffsettings

Displays differences between the current settings file and Django’s default settings.

Settings that don’t appear in the defaults are followed by "###". For example, the default settings don’t define ROOT_URLCONF, so ROOT_URLCONF is followed by "###" in the output of diffsettings.

--all

Displays all settings, even if they have Django’s default value. Such settings are prefixed by "###".

dumpdata

django-admin dumpdata [app_label[.ModelName] [app_label[.ModelName] ...]]

Outputs to standard output all data in the database associated with the named application(s).

If no application name is provided, all installed applications will be dumped.

The output of dumpdata can be used as input for loaddata.

Note that dumpdata uses the default manager on the model for selecting the records to dump. If you’re using a custom manager as the default manager and it filters some of the available records, not all of the objects will be dumped.

--all, -a

Uses Django’s base manager, dumping records which might otherwise be filtered or modified by a custom manager.

--format FORMAT

Specifies the serialization format of the output. Defaults to JSON. Supported formats are listed in Serialization formats.

--indent INDENT

Specifies the number of indentation spaces to use in the output. Defaults to None which displays all data on single line.

--exclude EXCLUDE, -e EXCLUDE

Prevents specific applications or models (specified in the form of app_label.ModelName) from being dumped. If you specify a model name, the output will be restricted to that model, rather than the entire application. You can also mix application names and model names.

If you want to exclude multiple applications, pass --exclude more than once:

django-admin dumpdata --exclude=auth --exclude=contenttypes

--database DATABASE

Specifies the database from which data will be dumped. Defaults to default.

--natural-foreign

Uses the natural_key() model method to serialize any foreign key and many-to-many relationship to objects of the type that defines the method. If you’re dumping contrib.auth Permission objects or contrib.contenttypes ContentType objects, you should probably use this flag. See the natural keys documentation for more details on this and the next option.

--natural-primary

Omits the primary key in the serialized data of this object since it can be calculated during deserialization.

--pks PRIMARY_KEYS

Outputs only the objects specified by a comma separated list of primary keys. This is only available when dumping one model. By default, all the records of the model are output.

--output OUTPUT, -o OUTPUT

New in Django 1.8.

Specifies a file to write the serialized data to. By default, the data goes to standard output.

When this option is set and --verbosity is greater than 0 (the default), a progress bar is shown in the terminal.

Changed in Django 1.9:
The progress bar in the terminal was added.

flush

django-admin flush

Removes all data from the database and re-executes any post-synchronization handlers. The table of which migrations have been applied is not cleared.

If you would rather start from an empty database and re-run all migrations, you should drop and recreate the database and then run migrate instead.

--noinput, --no-input

Suppresses all user prompts.

Changed in Django 1.9:
The --no-input alias was added.

--database DATABASE

Specifies the database to flush. Defaults to default.

inspectdb

django-admin inspectdb

Introspects the database tables in the database pointed-to by the NAME setting and outputs a Django model module (a models.py file) to standard output.

Use this if you have a legacy database with which you’d like to use Django. The script will inspect the database and create a model for each table within it.

As you might expect, the created models will have an attribute for every field in the table. Note that inspectdb has a few special cases in its field-name output:

- If inspectdb cannot map a column’s type to a model field type, it’ll use TextField and will insert the Python comment 'This field type is a guess.' next to the field in the generated model.

- If the database column name is a Python reserved word (such as 'pass', 'class' or 'for'), inspectdb will append '_field' to the attribute name. For example, if a table has a column 'for', the generated model will have a field 'for_field', with the db_column attribute set to 'for'. inspectdb will insert the Python comment 'Field renamed because it was a Python reserved word.' next to the field.

This feature is meant as a shortcut, not as definitive model generation. After you run it, you’ll want to look over the generated models yourself to make customizations. In particular, you’ll need to rearrange models’ order, so that models that refer to other models are ordered properly.

Primary keys are automatically introspected for PostgreSQL, MySQL and SQLite, in which case Django puts in the primary_key=True where needed.

inspectdb works with PostgreSQL, MySQL and SQLite. Foreign-key detection only works in PostgreSQL and with certain types of MySQL tables.

Django doesn’t create database defaults when a default is specified on a model field. Similarly, database defaults aren’t translated to model field defaults or detected in any fashion by inspectdb.

By default, inspectdb creates unmanaged models. That is, managed = False in the model’s Meta class tells Django not to manage each table’s creation, modification, and deletion. If you do want to allow Django to manage the table’s lifecycle, you’ll need to change the managed option to True (or simply remove it because True is its default value).

--database DATABASE

Specifies the database to introspect. Defaults to default.

loaddata

django-admin loaddata fixture [fixture ...]

Searches for and loads the contents of the named fixture into the database.

--database DATABASE

Specifies the database into which the data will be loaded. Defaults to default.

--ignorenonexistent, -i

Ignores fields and models that may have been removed since the fixture was originally generated.

--app APP_LABEL

Specifies a single app to look for fixtures in rather than looking in all apps.

Changed in Django 1.8:
--ignorenonexistent also ignores non-existent models.

What’s a “fixture”?

A fixture is a collection of files that contain the serialized contents of the database. Each fixture has a unique name, and the files that comprise the fixture can be distributed over multiple directories, in multiple applications.

Django will search in three locations for fixtures:

1. In the fixtures directory of every installed application

2. In any directory named in the FIXTURE_DIRS setting

3. In the literal path named by the fixture

Django will load any and all fixtures it finds in these locations that match the provided fixture names.

If the named fixture has a file extension, only fixtures of that type will be loaded. For example:

django-admin loaddata mydata.json

would only load JSON fixtures called mydata. The fixture extension must correspond to the registered name of a serializer (e.g., json or xml).

If you omit the extensions, Django will search all available fixture types for a matching fixture. For example:

django-admin loaddata mydata

would look for any fixture of any fixture type called mydata. If a fixture directory contained mydata.json, that fixture would be loaded as a JSON fixture.

The fixtures that are named can include directory components. These directories will be included in the search path. For example:

django-admin loaddata foo/bar/mydata.json

would search <app_label>/fixtures/foo/bar/mydata.json for each installed application, <dirname>/foo/bar/mydata.json for each directory in FIXTURE_DIRS, and the literal path foo/bar/mydata.json.

When fixture files are processed, the data is saved to the database as is. Model defined save() methods are not called, and any pre_save or post_save signals will be called with raw=True since the instance only contains attributes that are local to the model. You may, for example, want to disable handlers that access related fields that aren’t present during fixture loading and would otherwise raise an exception:

from django.db.models.signals import post_save
from .models import MyModel

def my_handler(**kwargs):
# disable the handler during fixture loading
if kwargs['raw']:
return
...

post_save.connect(my_handler, sender=MyModel)

You could also write a simple decorator to encapsulate this logic:

from functools import wraps

def disable_for_loaddata(signal_handler):
"""
Decorator that turns off signal handlers when loading fixture data.
"""
@wraps(signal_handler)
def wrapper(*args, **kwargs):
if kwargs['raw']:
return
signal_handler(*args, **kwargs)
return wrapper

@disable_for_loaddata
def my_handler(**kwargs):
...

Just be aware that this logic will disable the signals whenever fixtures are deserialized, not just during loaddata.

Note that the order in which fixture files are processed is undefined. However, all fixture data is installed as a single transaction, so data in one fixture can reference data in another fixture. If the database backend supports row-level constraints, these constraints will be checked at the end of the transaction.

The dumpdata command can be used to generate input for loaddata.

Compressed fixtures

Fixtures may be compressed in zip, gz, or bz2 format. For example:

django-admin loaddata mydata.json

would look for any of mydata.json, mydata.json.zip, mydata.json.gz, or mydata.json.bz2. The first file contained within a zip-compressed archive is used.

Note that if two fixtures with the same name but different fixture type are discovered (for example, if mydata.json and mydata.xml.gz were found in the same fixture directory), fixture installation will be aborted, and any data installed in the call to loaddata will be removed from the database.

MySQL with MyISAM and fixtures

The MyISAM storage engine of MySQL doesn’t support transactions or constraints, so if you use MyISAM, you won’t get validation of fixture data, or a rollback if multiple transaction files are found.

Database-specific fixtures

If you’re in a multi-database setup, you might have fixture data that you want to load onto one database, but not onto another. In this situation, you can add a database identifier into the names of your fixtures.

For example, if your DATABASES setting has a ‘master’ database defined, name the fixture mydata.master.json or mydata.master.json.gz and the fixture will only be loaded when you specify you want to load data into the master database.

makemessages

django-admin makemessages

Runs over the entire source tree of the current directory and pulls out all strings marked for translation. It creates (or updates) a message file in the conf/locale (in the Django tree) or locale (for project and application) directory. After making changes to the messages files you need to compile them with compilemessages for use with the builtin gettext support. See the i18n documentation for details.

--all, -a

Updates the message files for all available languages.

--extension EXTENSIONS, -e EXTENSIONS

Specifies a list of file extensions to examine (default: html, txt, py or js if --domain is js).

Example usage:

django-admin makemessages --locale=de --extension xhtml

Separate multiple extensions with commas or use -e or --extension multiple times:

django-admin makemessages --locale=de --extension=html,txt --extension xml

--locale LOCALE, -l LOCALE

Specifies the locale(s) to process.

--exclude EXCLUDE, -x EXCLUDE

New in Django 1.8.

Specifies the locale(s) to exclude from processing. If not provided, no locales are excluded.

Example usage:

django-admin makemessages --locale=pt_BR
django-admin makemessages --locale=pt_BR --locale=fr
django-admin makemessages -l pt_BR
django-admin makemessages -l pt_BR -l fr
django-admin makemessages --exclude=pt_BR
django-admin makemessages --exclude=pt_BR --exclude=fr
django-admin makemessages -x pt_BR
django-admin makemessages -x pt_BR -x fr

--domain DOMAIN, -d DOMAIN

Specifies the domain of the messages files. Supported options are:

- django for all *.py, *.html and *.txt files (default)

- djangojs for *.js files

--symlinks, -s

Follows symlinks to directories when looking for new translation strings.

Example usage:

django-admin makemessages --locale=de --symlinks

--ignore PATTERN, -i PATTERN

Ignores files or directories matching the given glob-style pattern. Use multiple times to ignore more.

These patterns are used by default: 'CVS', '.*', '*~', '*.pyc'.

Example usage:

django-admin makemessages --locale=en_US --ignore=apps/* --ignore=secret/*.html

--no-default-ignore

Disables the default values of --ignore.

--no-wrap

Disables breaking long message lines into several lines in language files.

--no-location

Suppresses writing ‘#: filename:line’ comment lines in language files. Using this option makes it harder for technically skilled translators to understand each message’s context.

--keep-pot

Prevents deleting the temporary .pot files generated before creating the .po file. This is useful for debugging errors which may prevent the final language files from being created.

See also

See Customizing the makemessages command for instructions on how to customize the keywords that makemessages passes to xgettext.

makemigrations

django-admin makemigrations [app_label [app_label ...]]

Creates new migrations based on the changes detected to your models. Migrations, their relationship with apps and more are covered in depth in the migrations documentation.

Providing one or more app names as arguments will limit the migrations created to the app(s) specified and any dependencies needed (the table at the other end of a ForeignKey, for example).

--noinput, --no-input

Suppresses all user prompts. If a suppressed prompt cannot be resolved automatically, the command will exit with error code 3.

Changed in Django 1.9:
The --no-input alias was added.

--empty

Outputs an empty migration for the specified apps, for manual editing. This is for advanced users and should not be used unless you are familiar with the migration format, migration operations, and the dependencies between your migrations.

--dry-run

Shows what migrations would be made without actually writing any migrations files to disk. Using this option along with --verbosity 3 will also show the complete migrations files that would be written.

--merge

Enables fixing of migration conflicts.

--name NAME, -n NAME

New in Django 1.8.

Allows naming the generated migration(s) instead of using a generated name.

--exit, -e

New in Django 1.8.

Makes makemigrations exit with error code 1 when no migrations are created (or would have been created, if combined with --dry-run).

migrate

django-admin migrate [app_label] [migration_name]

Synchronizes the database state with the current set of models and migrations. Migrations, their relationship with apps and more are covered in depth in the migrations documentation.

The behavior of this command changes depending on the arguments provided:

- No arguments: All apps have all of their migrations run.

- <app_label>: The specified app has its migrations run, up to the most recent migration. This may involve running other apps’ migrations too, due to dependencies.

- <app_label> <migrationname>: Brings the database schema to a state where the named migration is applied, but no later migrations in the same app are applied. This may involve unapplying migrations if you have previously migrated past the named migration. Use the name zero to unapply all migrations for an app.

--database DATABASE

Specifies the database to migrate. Defaults to default.

--fake

Tells Django to mark the migrations as having been applied or unapplied, but without actually running the SQL to change your database schema.

This is intended for advanced users to manipulate the current migration state directly if they’re manually applying changes; be warned that using --fake runs the risk of putting the migration state table into a state where manual recovery will be needed to make migrations run correctly.

--fake-initial

New in Django 1.8.

Allows Django to skip an app’s initial migration if all database tables with the names of all models created by all CreateModel operations in that migration already exist. This option is intended for use when first running migrations against a database that preexisted the use of migrations. This option does not, however, check for matching database schema beyond matching table names and so is only safe to use if you are confident that your existing schema matches what is recorded in your initial migration.

--run-syncdb

New in Django 1.9.

Allows creating tables for apps without migrations. While this isn’t recommended, the migrations framework is sometimes too slow on large projects with hundreds of models.

--list, -l

Deprecated since version 1.8: The --list option has been moved to the showmigrations command.

--noinput, --no-input

Suppresses all user prompts. An example prompt is asking about removing stale content types.

Changed in Django 1.9:
The --no-input alias was added.

runserver

django-admin runserver [addrport]

Starts a lightweight development Web server on the local machine. By default, the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an IP address and port number explicitly.

If you run this script as a user with normal privileges (recommended), you might not have access to start a port on a low port number. Low port numbers are reserved for the superuser (root).

This server uses the WSGI application object specified by the WSGI_APPLICATION setting.

DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through security audits or performance tests. (And that’s how it’s gonna stay. We’re in the business of making Web frameworks, not Web servers, so improving this server to be able to handle a production environment is outside the scope of Django.)

The development server automatically reloads Python code for each request, as needed. You don’t need to restart the server for code changes to take effect. However, some actions like adding files don’t trigger a restart, so you’ll have to restart the server in these cases.

If you are using Linux and install pyinotify, kernel signals will be used to autoreload the server (rather than polling file modification timestamps each second). This offers better scaling to large projects, reduction in response time to code modification, more robust change detection, and battery usage reduction.

When you start the server, and each time you change Python code while the server is running, the system check framework will check your entire Django project for some common errors (see the check command). If any errors are found, they will be printed to standard output.

You can run as many concurrent servers as you want, as long as they’re on separate ports. Just execute django-admin runserver more than once.

Note that the default IP address, 127.0.0.1, is not accessible from other machines on your network. To make your development server viewable to other machines on the network, use its own IP address (e.g. 192.168.2.1) or 0.0.0.0 or :: (with IPv6 enabled).

You can provide an IPv6 address surrounded by brackets (e.g. [200a::1]:8000). This will automatically enable IPv6 support.

A hostname containing ASCII-only characters can also be used.

If the staticfiles contrib app is enabled (default in new projects) the runserver command will be overridden with its own runserver command.

If migrate was not previously executed, the table that stores the history of migrations is created at first run of runserver.

--noreload

Disables the auto-reloader. This means any Python code changes you make while the server is running will not take effect if the particular Python modules have already been loaded into memory.

--nothreading

Disables use of threading in the development server. The server is multithreaded by default.

--ipv6, -6

Uses IPv6 for the development server. This changes the default IP address from 127.0.0.1 to ::1.

Examples of using different ports and addresses

Port 8000 on IP address 127.0.0.1:

django-admin runserver

Port 8000 on IP address 1.2.3.4:

django-admin runserver 1.2.3.4:8000

Port 7000 on IP address 127.0.0.1:

django-admin runserver 7000

Port 7000 on IP address 1.2.3.4:

django-admin runserver 1.2.3.4:7000

Port 8000 on IPv6 address ::1:

django-admin runserver -6

Port 7000 on IPv6 address ::1:

django-admin runserver -6 7000

Port 7000 on IPv6 address 2001:0db8:1234:5678::9:

django-admin runserver [2001:0db8:1234:5678::9]:7000

Port 8000 on IPv4 address of host localhost:

django-admin runserver localhost:8000

Port 8000 on IPv6 address of host localhost:

django-admin runserver -6 localhost:8000

Serving static files with the development server

By default, the development server doesn’t serve any static files for your site (such as CSS files, images, things under MEDIA_URL and so forth). If you want to configure Django to serve static media, read Managing static files (e.g. images, JavaScript, CSS).

sendtestemail

django-admin sendtestemail [email [email ...]]

New in Django 1.9.

Sends a test email (to confirm email sending through Django is working) to the recipient(s) specified. For example:

django-admin sendtestemail foo@example.com bar@example.com

There are a couple of options, and you may use any combination of them together:

--managers

Mails the email addresses specified in MANAGERS using mail_managers().

--admins

Mails the email addresses specified in ADMINS using mail_admins().

shell

django-admin shell

Starts the Python interactive interpreter.

--interface {ipython,bpython}, -i {ipython,bpython}

Specifies the shell to use. By default, Django will use IPython or bpython if either is installed. If both are installed, specify which one you want like so:

IPython:

django-admin shell -i ipython

bpython:

django-admin shell -i bpython

--plain

If you have a rich shell installed but want to force use of the “plain” Python interpreter, use the --plain option, like so:

django-admin shell --plain

--nostartup

Disables reading the startup script for the “plain” Python interpreter. By default, the script pointed to by the PYTHONSTARTUP environment variable or the ~/.pythonrc.py script is read.

showmigrations

django-admin showmigrations [app_label [app_label ...]]

New in Django 1.8.

Shows all migrations in a project. You can choose from one of two formats:

--list, -l

Lists all of the apps Django knows about, the migrations available for each app, and whether or not each migration is applied (marked by an [X] next to the migration name).

Apps without migrations are also listed, but have (no migrations) printed under them.

This is the default output format.

--plan, -p

Shows the migration plan Django will follow to apply migrations. Any supplied app labels are ignored because the plan might go beyond those apps. Like --list, applied migrations are marked by an [X]. For a --verbosity of 2 and above, all dependencies of a migration will also be shown.

--database DATABASE

Specifies the database to examine. Defaults to default.

sqlflush

django-admin sqlflush

Prints the SQL statements that would be executed for the flush command.

--database DATABASE

Specifies the database for which to print the SQL. Defaults to default.

sqlmigrate

django-admin sqlmigrate app_label migration_name

Prints the SQL for the named migration. This requires an active database connection, which it will use to resolve constraint names; this means you must generate the SQL against a copy of the database you wish to later apply it on.

Note that sqlmigrate doesn’t colorize its output.

--backwards

Generates the SQL for unapplying the migration. By default, the SQL created is for running the migration in the forwards direction.

--database DATABASE

Specifies the database for which to generate the SQL. Defaults to default.

Changed in Django 1.9:
To increase the readability of the overall SQL output the SQL code generated for each migration operation is preceded by the operation’s description.

sqlsequencereset

django-admin sqlsequencereset app_label [app_label ...]

Prints the SQL statements for resetting sequences for the given app name(s).

Sequences are indexes used by some database engines to track the next available number for automatically incremented fields.

Use this command to generate SQL which will fix cases where a sequence is out of sync with its automatically incremented field data.

--database DATABASE

Specifies the database for which to print the SQL. Defaults to default.

squashmigrations

django-admin squashmigrations app_label [start_migration_name] migration_name

Squashes the migrations for app_label up to and including migration_name down into fewer migrations, if possible. The resulting squashed migrations can live alongside the unsquashed ones safely. For more information, please read Squashing migrations.

New in Django 1.9.

When start_migration_name is given, Django will only include migrations starting from and including this migration. This helps to mitigate the squashing limitation of RunPython and django.db.migrations.operations.RunSQL migration operations.

--no-optimize

Disables the optimizer when generating a squashed migration. By default, Django will try to optimize the operations in your migrations to reduce the size of the resulting file. Use this option if this process is failing or creating incorrect migrations, though please also file a Django bug report about the behavior, as optimization is meant to be safe.

--noinput, --no-input

Suppresses all user prompts.

Changed in Django 1.9:
The --no-input alias was added.

startapp

django-admin startapp name [directory]

Creates a Django app directory structure for the given app name in the current directory or the given destination.

By default the directory created contains a models.py file and other app template files. (See the source for more details.) If only the app name is given, the app directory will be created in the current working directory.

If the optional destination is provided, Django will use that existing directory rather than creating a new one. You can use ‘.’ to denote the current working directory.

For example:

django-admin startapp myapp /Users/jezdez/Code/myapp

--template TEMPLATE

Provides the path to a directory with a custom app template file or a path to a compressed file (.tar.gz, .tar.bz2, .tgz, .tbz, .zip) containing the app template files.

For example, this would look for an app template in the given directory when creating the myapp app:

django-admin startapp --template=/Users/jezdez/Code/my_app_template myapp

Django will also accept URLs (http, https, ftp) to compressed archives with the app template files, downloading and extracting them on the fly.

For example, taking advantage of GitHub’s feature to expose repositories as zip files, you can use a URL like:

django-admin startapp --template=https://github.com/githubuser/django-app-template/archive/master.zip myapp

--extension EXTENSIONS, -e EXTENSIONS

Specifies which file extensions in the app template should be rendered with the template engine. Defaults to py.

--name FILES, -n FILES

Specifies which files in the app template (in addition to those matching --extension) should be rendered with the template engine. Defaults to an empty list.

The template context used for all matching files is:

- Any option passed to the startapp command (among the command’s supported options)

- app_name – the app name as passed to the command

- app_directory – the full path of the newly created app

- camel_case_app_name – the app name in camel case format

- docs_version – the version of the documentation: 'dev' or '1.x'

New in Django 1.9:
camel_case_app_name was added.

Warning

When the app template files are rendered with the Django template engine (by default all *.py files), Django will also replace all stray template variables contained. For example, if one of the Python files contains a docstring explaining a particular feature related to template rendering, it might result in an incorrect example.

To work around this problem, you can use the templatetag templatetag to “escape” the various parts of the template syntax.

In addition, to allow Python template files that contain Django template language syntax while also preventing packaging systems from trying to byte-compile invalid *.py files, template files ending with .py-tpl will be renamed to .py.

Changed in Django 1.9.2:
Renaming of .py-tpl to .py was added.

startproject

django-admin startproject name [directory]

Creates a Django project directory structure for the given project name in the current directory or the given destination.

By default, the new directory contains manage.py and a project package (containing a settings.py and other files). See the template source for details.

If only the project name is given, both the project directory and project package will be named <projectname> and the project directory will be created in the current working directory.

If the optional destination is provided, Django will use that existing directory as the project directory, and create manage.py and the project package within it. Use ‘.’ to denote the current working directory.

For example:

django-admin startproject myproject /Users/jezdez/Code/myproject_repo

--template TEMPLATE

Specifies a directory, file path, or URL of a custom project template. See the startapp --template documentation for examples and usage.

--extension EXTENSIONS, -e EXTENSIONS

Specifies which file extensions in the project template should be rendered with the template engine. Defaults to py.

--name FILES, -n FILES

Specifies which files in the project template (in addition to those matching --extension) should be rendered with the template engine. Defaults to an empty list.

The template context used is:

- Any option passed to the startproject command (among the command’s supported options)

- project_name – the project name as passed to the command

- project_directory – the full path of the newly created project

- secret_key – a random key for the SECRET_KEY setting

- docs_version – the version of the documentation: 'dev' or '1.x'

Please also see the rendering warning as mentioned for startapp.

test

django-admin test [test_label [test_label ...]]

Runs tests for all installed apps. See Testing in Django for more information.

--failfast

Stops running tests and reports the failure immediately after a test fails.

--testrunner TESTRUNNER

Controls the test runner class that is used to execute tests. This value overrides the value provided by the TEST_RUNNER setting.

--liveserver LIVESERVER

Overrides the default address where the live server (used with LiveServerTestCase) is expected to run from. The default value is localhost:8081-8179.

Changed in Django 1.9:
In earlier versions, the default value was localhost:8081.

--noinput, --no-input

Suppresses all user prompts. A typical prompt is a warning about deleting an existing test database.

Changed in Django 1.9:
The --no-input alias was added.

Test runner options

The test command receives options on behalf of the specified --testrunner. These are the options of the default test runner: DiscoverRunner.

--keepdb, -k

New in Django 1.8.

Preserves the test database between test runs. This has the advantage of skipping both the create and destroy actions which can greatly decrease the time to run tests, especially those in a large test suite. If the test database does not exist, it will be created on the first run and then preserved for each subsequent run. Any unapplied migrations will also be applied to the test database before running the test suite.

--reverse, -r

New in Django 1.8.

Sorts test cases in the opposite execution order. This may help in debugging the side effects of tests that aren’t properly isolated. Grouping by test class is preserved when using this option.

--debug-sql, -d

New in Django 1.8.

Enables SQL logging for failing tests. If --verbosity is 2, then queries in passing tests are also output.

--parallel [N]

New in Django 1.9.

Runs tests in separate parallel processes. Since modern processors have multiple cores, this allows running tests significantly faster.

By default --parallel runs one process per core according to multiprocessing.cpu_count(). You can adjust the number of processes either by providing it as the option’s value, e.g. --parallel=4, or by setting the DJANGO_TEST_PROCESSES environment variable.

Django distributes test cases — unittest.TestCase subclasses — to subprocesses. If there are fewer test cases than configured processes, Django will reduce the number of processes accordingly.

Each process gets its own database. You must ensure that different test cases don’t access the same resources. For instance, test cases that touch the filesystem should create a temporary directory for their own use.

This option requires the third-party tblib package to display tracebacks correctly:

$ pip install tblib

This feature isn’t available on Windows. It doesn’t work with the Oracle database backend either.

If you want to use pdb while debugging tests, you must disable parallel execution (--parallel=1). You’ll see something like bdb.BdbQuit if you don’t.

Warning

When test parallelization is enabled and a test fails, Django may be unable to display the exception traceback. This can make debugging difficult. If you encounter this problem, run the affected test without parallelization to see the traceback of the failure.

This is a known limitation. It arises from the need to serialize objects in order to exchange them between processes. See What can be pickled and unpickled? for details.

testserver

django-admin testserver [fixture [fixture ...]]

Runs a Django development server (as in runserver) using data from the given fixture(s).

For example, this command:

django-admin testserver mydata.json

...would perform the following steps:

1. Create a test database, as described in The test database.

2. Populate the test database with fixture data from the given fixtures. (For more on fixtures, see the documentation for loaddata above.)

3. Runs the Django development server (as in runserver), pointed at this newly created test database instead of your production database.

This is useful in a number of ways:

- When you’re writing unit tests of how your views act with certain fixture data, you can use testserver to interact with the views in a Web browser, manually.

- Let’s say you’re developing your Django application and have a “pristine” copy of a database that you’d like to interact with. You can dump your database to a fixture (using the dumpdata command, explained above), then use testserver to run your Web application with that data. With this arrangement, you have the flexibility of messing up your data in any way, knowing that whatever data changes you’re making are only being made to a test database.

Note that this server does not automatically detect changes to your Python source code (as runserver does). It does, however, detect changes to templates.

--addrport ADDRPORT

Specifies a different port, or IP address and port, from the default of 127.0.0.1:8000. This value follows exactly the same format and serves exactly the same function as the argument to the runserver command.

Examples:

To run the test server on port 7000 with fixture1 and fixture2:

django-admin testserver --addrport 7000 fixture1 fixture2
django-admin testserver fixture1 fixture2 --addrport 7000

(The above statements are equivalent. We include both of them to demonstrate that it doesn’t matter whether the options come before or after the fixture arguments.)

To run on 1.2.3.4:7000 with a test fixture:

django-admin testserver --addrport 1.2.3.4:7000 test

--noinput, --no-input

Suppresses all user prompts. A typical prompt is a warning about deleting an existing test database.

Changed in Django 1.9:
The --no-input alias was added.

Commands provided by applications

Some commands are only available when the django.contrib application that implements them has been enabled. This section describes them grouped by their application.

django.contrib.auth

changepassword

django-admin changepassword [<username>]

This command is only available if Django’s authentication system (django.contrib.auth) is installed.

Allows changing a user’s password. It prompts you to enter a new password twice for the given user. If the entries are identical, this immediately becomes the new password. If you do not supply a user, the command will attempt to change the password whose username matches the current user.

--database DATABASE

Specifies the database to query for the user. Defaults to default.

Example usage:

django-admin changepassword ringo

createsuperuser

django-admin createsuperuser

This command is only available if Django’s authentication system (django.contrib.auth) is installed.

Creates a superuser account (a user who has all permissions). This is useful if you need to create an initial superuser account or if you need to programmatically generate superuser accounts for your site(s).

When run interactively, this command will prompt for a password for the new superuser account. When run non-interactively, no password will be set, and the superuser account will not be able to log in until a password has been manually set for it.

--username USERNAME

--email EMAIL

The username and email address for the new account can be supplied by using the --username and --email arguments on the command line. If either of those is not supplied, createsuperuser will prompt for it when running interactively.

--database DATABASE

Specifies the database into which the superuser object will be saved.

New in Django 1.8.

You can subclass the management command and override get_input_data() if you want to customize data input and validation. Consult the source code for details on the existing implementation and the method’s parameters. For example, it could be useful if you have a ForeignKey in REQUIRED_FIELDS and want to allow creating an instance instead of entering the primary key of an existing instance.

django.contrib.gis

ogrinspect

This command is only available if GeoDjango (django.contrib.gis) is installed.

Please refer to its description in the GeoDjango documentation.

django.contrib.sessions

clearsessions

django-admin clearsessions

Can be run as a cron job or directly to clean out expired sessions.

django.contrib.sitemaps

ping_google

This command is only available if the Sitemaps framework (django.contrib.sitemaps) is installed.

Please refer to its description in the Sitemaps documentation.

django.contrib.staticfiles

collectstatic

This command is only available if the static files application (django.contrib.staticfiles) is installed.

Please refer to its description in the staticfiles documentation.

findstatic

This command is only available if the static files application (django.contrib.staticfiles) is installed.

Please refer to its description in the staticfiles documentation.

Default options

Although some commands may allow their own custom options, every command allows for the following options:

--pythonpath PYTHONPATH

Adds the given filesystem path to the Python import search path. If this isn’t provided, django-admin will use the PYTHONPATH environment variable.

This option is unnecessary in manage.py, because it takes care of setting the Python path for you.

Example usage:

django-admin migrate --pythonpath='/home/djangoprojects/myproject'

--settings SETTINGS

Specifies the settings module to use. The settings module should be in Python package syntax, e.g. mysite.settings. If this isn’t provided, django-admin will use the DJANGO_SETTINGS_MODULE environment variable.

This option is unnecessary in manage.py, because it uses settings.py from the current project by default.

Example usage:

django-admin migrate --settings=mysite.settings

--traceback

Displays a full stack trace when a CommandError is raised. By default, django-admin will show a simple error message when a CommandError occurs and a full stack trace for any other exception.

Example usage:

django-admin migrate --traceback

--verbosity {0,1,2,3}, --v {0,1,2,3}

Specifies the amount of notification and debug information that a command should print to the console.

- 0 means no output.

- 1 means normal output (default).

- 2 means verbose output.

- 3 means very verbose output.

Example usage:

django-admin migrate --verbosity 2

--no-color

Disables colorized command output. Some commands format their output to be colorized. For example, errors will be printed to the console in red and SQL statements will be syntax highlighted.

Example usage:

django-admin runserver --no-color

Extra niceties

Syntax coloring

The django-admin / manage.py commands will use pretty color-coded output if your terminal supports ANSI-colored output. It won’t use the color codes if you’re piping the command’s output to another program.

Under Windows, the native console doesn’t support ANSI escape sequences so by default there is no color output. But you can install the ANSICON third-party tool, the Django commands will detect its presence and will make use of its services to color output just like on Unix-based platforms.

The colors used for syntax highlighting can be customized. Django ships with three color palettes:

- dark, suited to terminals that show white text on a black background. This is the default palette.

- light, suited to terminals that show black text on a white background.

- nocolor, which disables syntax highlighting.

You select a palette by setting a DJANGO_COLORS environment variable to specify the palette you want to use. For example, to specify the light palette under a Unix or OS/X BASH shell, you would run the following at a command prompt:

export DJANGO_COLORS="light"

You can also customize the colors that are used. Django specifies a number of roles in which color is used:

- error - A major error.

- notice - A minor error.

- success - A success.

- warning - A warning.

- sql_field - The name of a model field in SQL.

- sql_coltype - The type of a model field in SQL.

- sql_keyword - An SQL keyword.

- sql_table - The name of a model in SQL.

- http_info - A 1XX HTTP Informational server response.

- http_success - A 2XX HTTP Success server response.

- http_not_modified - A 304 HTTP Not Modified server response.

- http_redirect - A 3XX HTTP Redirect server response other than 304.

- http_not_found - A 404 HTTP Not Found server response.

- http_bad_request - A 4XX HTTP Bad Request server response other than 404.

- http_server_error - A 5XX HTTP Server Error response.

- migrate_heading - A heading in a migrations management command.

- migrate_label - A migration name.

Changed in Django 1.9:
success was added.

Each of these roles can be assigned a specific foreground and background color, from the following list:

- black

- red

- green

- yellow

- blue

- magenta

- cyan

- white

Each of these colors can then be modified by using the following display options:

- bold

- underscore

- blink

- reverse

- conceal

A color specification follows one of the following patterns:

- role=fg

- role=fg/bg

- role=fg,option,option

- role=fg/bg,option,option

where role is the name of a valid color role, fg is the foreground color, bg is the background color and each option is one of the color modifying options. Multiple color specifications are then separated by a semicolon. For example:

export DJANGO_COLORS="error=yellow/blue,blink;notice=magenta"

would specify that errors be displayed using blinking yellow on blue, and notices displayed using magenta. All other color roles would be left uncolored.

Colors can also be specified by extending a base palette. If you put a palette name in a color specification, all the colors implied by that palette will be loaded. So:

export DJANGO_COLORS="light;error=yellow/blue,blink;notice=magenta"

would specify the use of all the colors in the light color palette, except for the colors for errors and notices which would be overridden as specified.

Bash completion

If you use the Bash shell, consider installing the Django bash completion script, which lives in extras/django_bash_completion in the Django distribution. It enables tab-completion of django-admin and manage.py commands, so you can, for instance...

- Type django-admin.

- Press [TAB] to see all available options.

- Type sql, then [TAB], to see all available options whose names start with sql.

See Writing custom django-admin commands for how to add customized actions.

Running management commands from your code

django.core.management.call_command(name, *args, **options)

To call a management command from code use call_command.

name

the name of the command to call.

*args

a list of arguments accepted by the command. Arguments are passed to the argument parser, so you can use the same style as you would on the command line. For example, call_command('flush', 'verbosity=0').

**options

named options accepted on the command-line. Options are passed to the command without triggering the argument parser, which means you’ll need to pass the correct type. For example, call_command('flush', verbosity=0) (zero must be an integer rather than a string).

Examples:

from django.core import management
management.call_command('flush', verbosity=0, interactive=False)
management.call_command('loaddata', 'test_data', verbosity=0)

Note that command options that take no arguments are passed as keywords with True or False, as you can see with the interactive option above.

Named arguments can be passed by using either one of the following syntaxes:

# Similar to the command line
management.call_command('dumpdata', '--natural-foreign')

# Named argument similar to the command line minus the initial dashes and
# with internal dashes replaced by underscores
management.call_command('dumpdata', natural_foreign=True)

# `use_natural_foreign_keys` is the option destination variable
management.call_command('dumpdata', use_natural_foreign_keys=True)

Changed in Django 1.8:
The first syntax is now supported thanks to management commands using the argparse module. For the second syntax, Django previously passed the option name as-is to the command, now it is always using the dest variable name (which may or may not be the same as the option name).

Command options which take multiple options are passed a list:

management.call_command('dumpdata', exclude=['contenttypes', 'auth'])

Output redirection

Note that you can redirect standard output and error streams as all commands support the stdout and stderr options. For example, you could write:

with open('/path/to/command_output') as f:
management.call_command('dumpdata', stdout=f)

Django Exceptions

Django raises some of its own exceptions as well as standard Python exceptions.

Django Core Exceptions

Django core exception classes are defined in django.core.exceptions.

ObjectDoesNotExist

exception ObjectDoesNotExist[source]

The base class for DoesNotExist exceptions; a try/except for ObjectDoesNotExist will catch DoesNotExist exceptions for all models.

See get() for further information on ObjectDoesNotExist and DoesNotExist.

FieldDoesNotExist

exception FieldDoesNotExist[source]

The FieldDoesNotExist exception is raised by a model’s _meta.get_field() method when the requested field does not exist on the model or on the model’s parents.

Changed in Django 1.8:
This exception was previously defined only in django.db.models.fields and wasn’t part of the public API.

MultipleObjectsReturned

exception MultipleObjectsReturned[source]

The MultipleObjectsReturned exception is raised by a query if only one object is expected, but multiple objects are returned. A base version of this exception is provided in django.core.exceptions; each model class contains a subclassed version that can be used to identify the specific object type that has returned multiple objects.

See get() for further information.

SuspiciousOperation

exception SuspiciousOperation[source]

The SuspiciousOperation exception is raised when a user has performed an operation that should be considered suspicious from a security perspective, such as tampering with a session cookie. Subclasses of SuspiciousOperation include:

- DisallowedHost

- DisallowedModelAdminLookup

- DisallowedModelAdminToField

- DisallowedRedirect

- InvalidSessionKey

- SuspiciousFileOperation

- SuspiciousMultipartForm

- SuspiciousSession

If a SuspiciousOperation exception reaches the WSGI handler level it is logged at the Error level and results in a HttpResponseBadRequest. See the logging documentation for more information.

PermissionDenied

exception PermissionDenied[source]

The PermissionDenied exception is raised when a user does not have permission to perform the action requested.

ViewDoesNotExist

exception ViewDoesNotExist[source]

The ViewDoesNotExist exception is raised by django.core.urlresolvers when a requested view does not exist.

MiddlewareNotUsed

exception MiddlewareNotUsed[source]

The MiddlewareNotUsed exception is raised when a middleware is not used in the server configuration.

ImproperlyConfigured

exception ImproperlyConfigured[source]

The ImproperlyConfigured exception is raised when Django is somehow improperly configured – for example, if a value in settings.py is incorrect or unparseable.

FieldError

exception FieldError[source]

The FieldError exception is raised when there is a problem with a model field. This can happen for several reasons:

- A field in a model clashes with a field of the same name from an abstract base class

- An infinite loop is caused by ordering

- A keyword cannot be parsed from the filter parameters

- A field cannot be determined from a keyword in the query parameters

- A join is not permitted on the specified field

- A field name is invalid

- A query contains invalid order_by arguments

ValidationError

exception ValidationError[source]

The ValidationError exception is raised when data fails form or model field validation. For more information about validation, see Form and Field Validation, Model Field Validation and the Validator Reference.

NON_FIELD_ERRORS

NON_FIELD_ERRORS

ValidationErrors that don’t belong to a particular field in a form or model are classified as NON_FIELD_ERRORS. This constant is used as a key in dictionaries that otherwise map fields to their respective list of errors.

URL Resolver exceptions

URL Resolver exceptions are defined in django.core.urlresolvers.

Resolver404

exception Resolver404[source]

The Resolver404 exception is raised by django.core.urlresolvers.resolve() if the path passed to resolve() doesn’t map to a view. It’s a subclass of django.http.Http404.

NoReverseMatch

exception NoReverseMatch[source]

The NoReverseMatch exception is raised by django.core.urlresolvers when a matching URL in your URLconf cannot be identified based on the parameters supplied.

Database Exceptions

Database exceptions may be imported from django.db.

Django wraps the standard database exceptions so that your Django code has a guaranteed common implementation of these classes.

exception Error[source]

exception InterfaceError[source]

exception DatabaseError[source]

exception DataError[source]

exception OperationalError[source]

exception IntegrityError[source]

exception InternalError[source]

exception ProgrammingError[source]

exception NotSupportedError[source]

The Django wrappers for database exceptions behave exactly the same as the underlying database exceptions. See PEP 249, the Python Database API Specification v2.0, for further information.

As per PEP 3134, a __cause__ attribute is set with the original (underlying) database exception, allowing access to any additional information provided. (Note that this attribute is available under both Python 2 and Python 3, although PEP 3134 normally only applies to Python 3.)

exception models.ProtectedError

Raised to prevent deletion of referenced objects when using django.db.models.PROTECT. models.ProtectedError is a subclass of IntegrityError.

Http Exceptions

Http exceptions may be imported from django.http.

UnreadablePostError

exception UnreadablePostError[source]

UnreadablePostError is raised when a user cancels an upload.

Transaction Exceptions

Transaction exceptions are defined in django.db.transaction.

TransactionManagementError

exception TransactionManagementError[source]

TransactionManagementError is raised for any and all problems related to database transactions.

Testing Framework Exceptions

Exceptions provided by the django.test package.

RedirectCycleError

exception client.RedirectCycleError

New in Django 1.8.

RedirectCycleError is raised when the test client detects a loop or an overly long chain of redirects.

Python Exceptions

Django raises built-in Python exceptions when appropriate as well. See the Python documentation for further information on the Built-in Exceptions.

File handling

- The File object

- The File class

- The ContentFile class

- The ImageFile class

- Additional methods on files attached to objects

- File storage API

- Getting the current storage class

- The FileSystemStorage class

- The Storage class

- Uploaded Files and Upload Handlers

- Uploaded files

- Built-in upload handlers

- Writing custom upload handlers

The File object

The django.core.files module and its submodules contain built-in classes for basic file handling in Django.

The File class

class File(file_object)[source]

The File class is a thin wrapper around a Python file object with some Django-specific additions. Internally, Django uses this class when it needs to represent a file.

File objects have the following attributes and methods:

name

The name of the file including the relative path from MEDIA_ROOT.

size

The size of the file in bytes.

file

The underlying file object that this class wraps.

Be careful with this attribute in subclasses.

Some subclasses of File, including ContentFile and FieldFile, may replace this attribute with an object other than a Python file object. In these cases, this attribute may itself be a File subclass (and not necessarily the same subclass). Whenever possible, use the attributes and methods of the subclass itself rather than the those of the subclass’s file attribute.

mode

The read/write mode for the file.

open(mode=None)[source]

Open or reopen the file (which also does File.seek(0)). The mode argument allows the same values as Python’s built-in open().

When reopening a file, mode will override whatever mode the file was originally opened with; None means to reopen with the original mode.

read(num_bytes=None)

Read content from the file. The optional size is the number of bytes to read; if not specified, the file will be read to the end.

__iter__()[source]

Iterate over the file yielding one line at a time.

Changed in Django 1.8:
File now uses universal newlines. The following are recognized as ending a line: the Unix end-of-line convention '\n', the Windows convention '\r\n', and the old Macintosh convention '\r'.

chunks(chunk_size=None)[source]

Iterate over the file yielding “chunks” of a given size. chunk_size defaults to 64 KB.

This is especially useful with very large files since it allows them to be streamed off disk and avoids storing the whole file in memory.

multiple_chunks(chunk_size=None)[source]

Returns True if the file is large enough to require multiple chunks to access all of its content give some chunk_size.

write(content)

Writes the specified content string to the file. Depending on the storage system behind the scenes, this content might not be fully committed until close() is called on the file.

close()[source]

Close the file.

In addition to the listed methods, File exposes the following attributes and methods of its file object: encoding, fileno, flush, isatty, newlines, read, readinto, readlines, seek, softspace, tell, truncate, writelines, xreadlines. If you are using Python 3, the seekable method is also available.

Changed in Django 1.9:
The seekable method was added.

The ContentFile class

class ContentFile(File)[source]

The ContentFile class inherits from File, but unlike File it operates on string content (bytes also supported), rather than an actual file. For example:

from __future__ import unicode_literals
from django.core.files.base import ContentFile

f1 = ContentFile("esta sentencia está en español")
f2 = ContentFile(b"these are bytes")

The ImageFile class

class ImageFile(file_object)[source]

Django provides a built-in class specifically for images. django.core.files.images.ImageFile inherits all the attributes and methods of File, and additionally provides the following:

width

Width of the image in pixels.

height

Height of the image in pixels.

Additional methods on files attached to objects

Any File that is associated with an object (as with Car.photo, below) will also have a couple of extra methods:

File.save(name, content, save=True)

Saves a new file with the file name and contents provided. This will not replace the existing file, but will create a new file and update the object to point to it. If save is True, the model’s save() method will be called once the file is saved. That is, these two lines:

>>> car.photo.save('myphoto.jpg', content, save=False)
>>> car.save()

are equivalent to:

>>> car.photo.save('myphoto.jpg', content, save=True)

Note that the content argument must be an instance of either File or of a subclass of File, such as ContentFile.

File.delete(save=True)

Removes the file from the model instance and deletes the underlying file. If save is True, the model’s save() method will be called once the file is deleted.

File storage API

Getting the current storage class

Django provides two convenient ways to access the current storage class:

class DefaultStorage[source]

DefaultStorage provides lazy access to the current default storage system as defined by DEFAULT_FILE_STORAGE. DefaultStorage uses get_storage_class() internally.

get_storage_class(import_path=None)[source]

Returns a class or module which implements the storage API.

When called without the import_path parameter get_storage_class will return the current default storage system as defined by DEFAULT_FILE_STORAGE. If import_path is provided, get_storage_class will attempt to import the class or module from the given path and will return it if successful. An exception will be raised if the import is unsuccessful.

The FileSystemStorage class

class FileSystemStorage(location=None, base_url=None, file_permissions_mode=None, directory_permissions_mode=None)[source]

The FileSystemStorage class implements basic file storage on a local filesystem. It inherits from Storage and provides implementations for all the public methods thereof.

location

Absolute path to the directory that will hold the files. Defaults to the value of your MEDIA_ROOT setting.

base_url

URL that serves the files stored at this location. Defaults to the value of your MEDIA_URL setting.

file_permissions_mode

The file system permissions that the file will receive when it is saved. Defaults to FILE_UPLOAD_PERMISSIONS.

directory_permissions_mode

The file system permissions that the directory will receive when it is saved. Defaults to FILE_UPLOAD_DIRECTORY_PERMISSIONS.

Note

The FileSystemStorage.delete() method will not raise an exception if the given file name does not exist.

The Storage class

class Storage[source]

The Storage class provides a standardized API for storing files, along with a set of default behaviors that all other storage systems can inherit or override as necessary.

Note

For methods returning naive datetime objects, the effective timezone used will be the current value of os.environ['TZ']; note that this is usually set from Django’s TIME_ZONE.

accessed_time(name)[source]

Returns a naive datetime object containing the last accessed time of the file. For storage systems that aren’t able to return the last accessed time this will raise NotImplementedError instead.

created_time(name)[source]

Returns a naive datetime object containing the creation time of the file. For storage systems that aren’t able to return the creation time this will raise NotImplementedError instead.

delete(name)[source]

Deletes the file referenced by name. If deletion is not supported on the target storage system this will raise NotImplementedError instead

exists(name)[source]

Returns True if a file referenced by the given name already exists in the storage system, or False if the name is available for a new file.

get_available_name(name, max_length=None)[source]

Returns a filename based on the name parameter that’s free and available for new content to be written to on the target storage system.

The length of the filename will not exceed max_length, if provided. If a free unique filename cannot be found, a SuspiciousFileOperation exception will be raised.

If a file with name already exists, an underscore plus a random 7 character alphanumeric string is appended to the filename before the extension.

Changed in Django 1.8:
The max_length argument was added.

get_valid_name(name)[source]

Returns a filename based on the name parameter that’s suitable for use on the target storage system.

listdir(path)[source]

Lists the contents of the specified path, returning a 2-tuple of lists; the first item being directories, the second item being files. For storage systems that aren’t able to provide such a listing, this will raise a NotImplementedError instead.

modified_time(name)[source]

Returns a naive datetime object containing the last modified time. For storage systems that aren’t able to return the last modified time, this will raise NotImplementedError instead.

open(name, mode='rb')[source]

Opens the file given by name. Note that although the returned file is guaranteed to be a File object, it might actually be some subclass. In the case of remote file storage this means that reading/writing could be quite slow, so be warned.

path(name)[source]

The local filesystem path where the file can be opened using Python’s standard open(). For storage systems that aren’t accessible from the local filesystem, this will raise NotImplementedError instead.

save(name, content, max_length=None)[source]

Saves a new file using the storage system, preferably with the name specified. If there already exists a file with this name name, the storage system may modify the filename as necessary to get a unique name. The actual name of the stored file will be returned.

The max_length argument is passed along to get_available_name().

The content argument must be an instance of django.core.files.File or of a subclass of File.

Changed in Django 1.8:
The max_length argument was added.

size(name)[source]

Returns the total size, in bytes, of the file referenced by name. For storage systems that aren’t able to return the file size this will raise NotImplementedError instead.

url(name)[source]

Returns the URL where the contents of the file referenced by name can be accessed. For storage systems that don’t support access by URL this will raise NotImplementedError instead.

Uploaded Files and Upload Handlers

Uploaded files

class UploadedFile[source]

During file uploads, the actual file data is stored in request.FILES. Each entry in this dictionary is an UploadedFile object (or a subclass) – a simple wrapper around an uploaded file. You’ll usually use one of these methods to access the uploaded content:

UploadedFile.read()

Read the entire uploaded data from the file. Be careful with this method: if the uploaded file is huge it can overwhelm your system if you try to read it into memory. You’ll probably want to use chunks() instead; see below.

UploadedFile.multiple_chunks(chunk_size=None)

Returns True if the uploaded file is big enough to require reading in multiple chunks. By default this will be any file larger than 2.5 megabytes, but that’s configurable; see below.

UploadedFile.chunks(chunk_size=None)

A generator returning chunks of the file. If multiple_chunks() is True, you should use this method in a loop instead of read().

In practice, it’s often easiest simply to use chunks() all the time. Looping over chunks() instead of using read() ensures that large files don’t overwhelm your system’s memory.

Here are some useful attributes of UploadedFile:

UploadedFile.name

The name of the uploaded file (e.g. my_file.txt).

UploadedFile.size

The size, in bytes, of the uploaded file.

UploadedFile.content_type

The content-type header uploaded with the file (e.g. text/plain or application/pdf). Like any data supplied by the user, you shouldn’t trust that the uploaded file is actually this type. You’ll still need to validate that the file contains the content that the content-type header claims – “trust but verify.”

UploadedFile.content_type_extra

A dictionary containing extra parameters passed to the content-type header. This is typically provided by services, such as Google App Engine, that intercept and handle file uploads on your behalf. As a result your handler may not receive the uploaded file content, but instead a URL or other pointer to the file. (see RFC 2388 section 5.3).

UploadedFile.charset

For text/* content-types, the character set (i.e. utf8) supplied by the browser. Again, “trust but verify” is the best policy here.

Note

Like regular Python files, you can read the file line-by-line simply by iterating over the uploaded file:

for line in uploadedfile:
do_something_with(line)

Lines are split using universal newlines. The following are recognized as ending a line: the Unix end-of-line convention '\n', the Windows convention '\r\n', and the old Macintosh convention '\r'.

Changed in Django 1.8:
Previously lines were only split on the Unix end-of-line '\n'.

Subclasses of UploadedFile include:

class TemporaryUploadedFile[source]

A file uploaded to a temporary location (i.e. stream-to-disk). This class is used by the TemporaryFileUploadHandler. In addition to the methods from UploadedFile, it has one additional method:

TemporaryUploadedFile.temporary_file_path()[source]

Returns the full path to the temporary uploaded file.

class InMemoryUploadedFile[source]

A file uploaded into memory (i.e. stream-to-memory). This class is used by the MemoryFileUploadHandler.

Built-in upload handlers

Together the MemoryFileUploadHandler and TemporaryFileUploadHandler provide Django’s default file upload behavior of reading small files into memory and large ones onto disk. They are located in django.core.files.uploadhandler.

class MemoryFileUploadHandler[source]

File upload handler to stream uploads into memory (used for small files).

class TemporaryFileUploadHandler[source]

Upload handler that streams data into a temporary file using TemporaryUploadedFile.

Writing custom upload handlers

class FileUploadHandler[source]

All file upload handlers should be subclasses of django.core.files.uploadhandler.FileUploadHandler. You can define upload handlers wherever you wish.

Required methods

Custom file upload handlers must define the following methods:

FileUploadHandler.receive_data_chunk(raw_data, start)[source]

Receives a “chunk” of data from the file upload.

raw_data is a byte string containing the uploaded data.

start is the position in the file where this raw_data chunk begins.

The data you return will get fed into the subsequent upload handlers’ receive_data_chunk methods. In this way, one handler can be a “filter” for other handlers.

Return None from receive_data_chunk to short-circuit remaining upload handlers from getting this chunk. This is useful if you’re storing the uploaded data yourself and don’t want future handlers to store a copy of the data.

If you raise a StopUpload or a SkipFile exception, the upload will abort or the file will be completely skipped.

FileUploadHandler.file_complete(file_size)[source]

Called when a file has finished uploading.

The handler should return an UploadedFile object that will be stored in request.FILES. Handlers may also return None to indicate that the UploadedFile object should come from subsequent upload handlers.

Optional methods

Custom upload handlers may also define any of the following optional methods or attributes:

FileUploadHandler.chunk_size

Size, in bytes, of the “chunks” Django should store into memory and feed into the handler. That is, this attribute controls the size of chunks fed into FileUploadHandler.receive_data_chunk.

For maximum performance the chunk sizes should be divisible by 4 and should not exceed 2 GB (2^31 bytes) in size. When there are multiple chunk sizes provided by multiple handlers, Django will use the smallest chunk size defined by any handler.

The default is 64*2^10 bytes, or 64 KB.

FileUploadHandler.new_file(field_name, file_name, content_type, content_length, charset, content_type_extra)[source]

Callback signaling that a new file upload is starting. This is called before any data has been fed to any upload handlers.

field_name is a string name of the file <input> field.

file_name is the unicode filename that was provided by the browser.

content_type is the MIME type provided by the browser – E.g. 'image/jpeg'.

content_length is the length of the image given by the browser. Sometimes this won’t be provided and will be None.

charset is the character set (i.e. utf8) given by the browser. Like content_length, this sometimes won’t be provided.

content_type_extra is extra information about the file from the content-type header. See UploadedFile.content_type_extra.

This method may raise a StopFutureHandlers exception to prevent future handlers from handling this file.

FileUploadHandler.upload_complete()[source]

Callback signaling that the entire upload (all files) has completed.

FileUploadHandler.handle_raw_input(input_data, META, content_length, boundary, encoding)[source]

Allows the handler to completely override the parsing of the raw HTTP input.

input_data is a file-like object that supports read()-ing.

META is the same object as request.META.

content_length is the length of the data in input_data. Don’t read more than content_length bytes from input_data.

boundary is the MIME boundary for this request.

encoding is the encoding of the request.

Return None if you want upload handling to continue, or a tuple of (POST, FILES) if you want to return the new data structures suitable for the request directly.

Forms

Detailed form API reference. For introductory material, see the Working with forms topic guide.

- The Forms API

- Bound and unbound forms

- Using forms to validate data

- Dynamic initial values

- Checking which form data has changed

- Accessing the fields from the form

- Accessing “clean” data

- Outputting forms as HTML

- More granular output

- Customizing BoundField

- Binding uploaded files to a form

- Subclassing forms

- Prefixes for forms

- Form fields

- Core field arguments

- Checking if the field data has changed

- Built-in Field classes

- Slightly complex built-in Field classes

- Fields which handle relationships

- Creating custom fields

- Model Form Functions

- modelform_factory

- modelformset_factory

- inlineformset_factory

- Formset Functions

- formset_factory

- Widgets

- Specifying widgets

- Setting arguments for widgets

- Widgets inheriting from the Select widget

- Customizing widget instances

- Base widget classes

- Built-in widgets

- Form and field validation

- Raising ValidationError

- Using validation in practice

The Forms API

About this document

This document covers the gritty details of Django’s forms API. You should read the introduction to working with forms first.

Bound and unbound forms

A Form instance is either bound to a set of data, or unbound.

- If it’s bound to a set of data, it’s capable of validating that data and rendering the form as HTML with the data displayed in the HTML.

- If it’s unbound, it cannot do validation (because there’s no data to validate!), but it can still render the blank form as HTML.

class Form[source]

To create an unbound Form instance, simply instantiate the class:

>>> f = ContactForm()

To bind data to a form, pass the data as a dictionary as the first parameter to your Form class constructor:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)

In this dictionary, the keys are the field names, which correspond to the attributes in your Form class. The values are the data you’re trying to validate. These will usually be strings, but there’s no requirement that they be strings; the type of data you pass depends on the Field, as we’ll see in a moment.

Form.is_bound

If you need to distinguish between bound and unbound form instances at runtime, check the value of the form’s is_bound attribute:

>>> f = ContactForm()
>>> f.is_bound
False
>>> f = ContactForm({'subject': 'hello'})
>>> f.is_bound
True

Note that passing an empty dictionary creates a bound form with empty data:

>>> f = ContactForm({})
>>> f.is_bound
True

If you have a bound Form instance and want to change the data somehow, or if you want to bind an unbound Form instance to some data, create another Form instance. There is no way to change data in a Form instance. Once a Form instance has been created, you should consider its data immutable, whether it has data or not.

Using forms to validate data

Form.clean()

Implement a clean() method on your Form when you must add custom validation for fields that are interdependent. See Cleaning and validating fields that depend on each other for example usage.

Form.is_valid()

The primary task of a Form object is to validate data. With a bound Form instance, call the is_valid() method to run validation and return a boolean designating whether the data was valid:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True

Let’s try with some invalid data. In this case, subject is blank (an error, because all fields are required by default) and sender is not a valid email address:

>>> data = {'subject': '',
...         'message': 'Hi there',
...         'sender': 'invalid email address',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False

Form.errors

Access the errors attribute to get a dictionary of error messages:

>>> f.errors
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}

In this dictionary, the keys are the field names, and the values are lists of Unicode strings representing the error messages. The error messages are stored in lists because a field can have multiple error messages.

You can access errors without having to call is_valid() first. The form’s data will be validated the first time either you call is_valid() or access errors.

The validation routines will only get called once, regardless of how many times you access errors or call is_valid(). This means that if validation has side effects, those side effects will only be triggered once.

Form.errors.as_data()

Returns a dict that maps fields to their original ValidationError instances.

>>> f.errors.as_data()
{'sender': [ValidationError(['Enter a valid email address.'])],
'subject': [ValidationError(['This field is required.'])]}

Use this method anytime you need to identify an error by its code. This enables things like rewriting the error’s message or writing custom logic in a view when a given error is present. It can also be used to serialize the errors in a custom format (e.g. XML); for instance, as_json() relies on as_data().

The need for the as_data() method is due to backwards compatibility. Previously ValidationError instances were lost as soon as their rendered error messages were added to the Form.errors dictionary. Ideally Form.errors would have stored ValidationError instances and methods with an as_ prefix could render them, but it had to be done the other way around in order not to break code that expects rendered error messages in Form.errors.

Form.errors.as_json(escape_html=False)

Returns the errors serialized as JSON.

>>> f.errors.as_json()
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}]}

By default, as_json() does not escape its output. If you are using it for something like AJAX requests to a form view where the client interprets the response and inserts errors into the page, you’ll want to be sure to escape the results on the client-side to avoid the possibility of a cross-site scripting attack. It’s trivial to do so using a JavaScript library like jQuery - simply use $(el).text(errorText) rather than .html().

If for some reason you don’t want to use client-side escaping, you can also set escape_html=True and error messages will be escaped so you can use them directly in HTML.

Form.add_error(field, error)

This method allows adding errors to specific fields from within the Form.clean() method, or from outside the form altogether; for instance from a view.

The field argument is the name of the field to which the errors should be added. If its value is None the error will be treated as a non-field error as returned by Form.non_field_errors().

The error argument can be a simple string, or preferably an instance of ValidationError. See Raising ValidationError for best practices when defining form errors.

Note that Form.add_error() automatically removes the relevant field from cleaned_data.

Form.has_error(field, code=None)

New in Django 1.8.

This method returns a boolean designating whether a field has an error with a specific error code. If code is None, it will return True if the field contains any errors at all.

To check for non-field errors use NON_FIELD_ERRORS as the field parameter.

Form.non_field_errors()

This method returns the list of errors from Form.errors that aren’t associated with a particular field. This includes ValidationErrors that are raised in Form.clean() and errors added using Form.add_error(None, "...").

Behavior of unbound forms

It’s meaningless to validate a form with no data, but, for the record, here’s what happens with unbound forms:

>>> f = ContactForm()
>>> f.is_valid()
False
>>> f.errors
{}

Dynamic initial values

Form.initial

Use initial to declare the initial value of form fields at runtime. For example, you might want to fill in a username field with the username of the current session.

To accomplish this, use the initial argument to a Form. This argument, if given, should be a dictionary mapping field names to initial values. Only include the fields for which you’re specifying an initial value; it’s not necessary to include every field in your form. For example:

>>> f = ContactForm(initial={'subject': 'Hi there!'})

These values are only displayed for unbound forms, and they’re not used as fallback values if a particular value isn’t provided.

Note that if a Field defines initial and you include initial when instantiating the Form, then the latter initial will have precedence. In this example, initial is provided both at the field level and at the form instance level, and the latter gets precedence:

>>> from django import forms
>>> class CommentForm(forms.Form):
...     name = forms.CharField(initial='class')
...     url = forms.URLField()
...     comment = forms.CharField()
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
>>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>

Checking which form data has changed

Form.has_changed()

Use the has_changed() method on your Form when you need to check if the form data has been changed from the initial data.

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data, initial=data)
>>> f.has_changed()
False

When the form is submitted, we reconstruct it and provide the original data so that the comparison can be done:

>>> f = ContactForm(request.POST, initial=data)
>>> f.has_changed()

has_changed() will be True if the data from request.POST differs from what was provided in initial or False otherwise. The result is computed by calling Field.has_changed() for each field in the form.

Form.changed_data

The changed_data attribute returns a list of the names of the fields whose values in the form’s bound data (usually request.POST) differ from what was provided in initial. It returns an empty list if no data differs.

>>> f = ContactForm(request.POST, initial=data)
>>> if f.has_changed():
...     print("The following fields changed: %s" % ", ".join(f.changed_data))

Accessing the fields from the form

Form.fields

You can access the fields of Form instance from its fields attribute:

>>> for row in f.fields.values(): print(row)
...
<django.forms.fields.CharField object at 0x7ffaac632510>
<django.forms.fields.URLField object at 0x7ffaac632f90>
<django.forms.fields.CharField object at 0x7ffaac3aa050>
>>> f.fields['name']
<django.forms.fields.CharField object at 0x7ffaac6324d0>

You can alter the field of Form instance to change the way it is presented in the form:

>>> f.as_table().split('\n')[0]
'<tr><th>Name:</th><td><input name="name" type="text" value="instance" /></td></tr>'
>>> f.fields['name'].label = "Username"
>>> f.as_table().split('\n')[0]
'<tr><th>Username:</th><td><input name="name" type="text" value="instance" /></td></tr>'

Beware not to alter the base_fields attribute because this modification will influence all subsequent ContactForm instances within the same Python process:

>>> f.base_fields['name'].label = "Username"
>>> another_f = CommentForm(auto_id=False)
>>> another_f.as_table().split('\n')[0]
'<tr><th>Username:</th><td><input name="name" type="text" value="class" /></td></tr>'

Accessing “clean” data

Form.cleaned_data

Each field in a Form class is responsible not only for validating data, but also for “cleaning” it – normalizing it to a consistent format. This is a nice feature, because it allows data for a particular field to be input in a variety of ways, always resulting in consistent output.

For example, DateField normalizes input into a Python datetime.date object. Regardless of whether you pass it a string in the format '1994-07-15', a datetime.date object, or a number of other formats, DateField will always normalize it to a datetime.date object as long as it’s valid.

Once you’ve created a Form instance with a set of data and validated it, you can access the clean data via its cleaned_data attribute:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}

Note that any text-based field – such as CharField or EmailField – always cleans the input into a Unicode string. We’ll cover the encoding implications later in this document.

If your data does not validate, the cleaned_data dictionary contains only the valid fields:

>>> data = {'subject': '',
...         'message': 'Hi there',
...         'sender': 'invalid email address',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there'}

cleaned_data will always only contain a key for fields defined in the Form, even if you pass extra data when you define the Form. In this example, we pass a bunch of extra fields to the ContactForm constructor, but cleaned_data contains only the form’s fields:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True,
...         'extra_field_1': 'foo',
...         'extra_field_2': 'bar',
...         'extra_field_3': 'baz'}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data # Doesn't contain extra_field_1, etc.
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}

When the Form is valid, cleaned_data will include a key and value for all its fields, even if the data didn’t include a value for some optional fields. In this example, the data dictionary doesn’t include a value for the nick_name field, but cleaned_data includes it, with an empty value:

>>> from django.forms import Form
>>> class OptionalPersonForm(Form):
...     first_name = CharField()
...     last_name = CharField()
...     nick_name = CharField(required=False)
>>> data = {'first_name': 'John', 'last_name': 'Lennon'}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}

In this above example, the cleaned_data value for nick_name is set to an empty string, because nick_name is CharField, and CharFields treat empty values as an empty string. Each field type knows what its “blank” value is – e.g., for DateField, it’s None instead of the empty string. For full details on each field’s behavior in this case, see the “Empty value” note for each field in the “Built-in Field classes” section below.

You can write code to perform validation for particular form fields (based on their name) or for the form as a whole (considering combinations of various fields). More information about this is in Form and field validation.

Outputting forms as HTML

The second task of a Form object is to render itself as HTML. To do so, simply print it:

>>> f = ContactForm()
>>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>

If the form is bound to data, the HTML output will include that data appropriately. For example, if a field is represented by an <input type="text">, the data will be in the value attribute. If a field is represented by an <input type="checkbox">, then that HTML will include checked="checked" if appropriate:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> print(f)
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>

This default output is a two-column HTML table, with a <tr> for each field. Notice the following:

- For flexibility, the output does not include the <table> and </table> tags, nor does it include the <form> and </form> tags or an <input type="submit"> tag. It’s your job to do that.

- Each field type has a default HTML representation. CharField is represented by an <input type="text"> and EmailField by an <input type="email">. BooleanField is represented by an <input type="checkbox">. Note these are merely sensible defaults; you can specify which HTML to use for a given field by using widgets, which we’ll explain shortly.

- The HTML name for each tag is taken directly from its attribute name in the ContactForm class.

- The text label for each field – e.g. 'Subject:', 'Message:' and 'Cc myself:' is generated from the field name by converting all underscores to spaces and upper-casing the first letter. Again, note these are merely sensible defaults; you can also specify labels manually.

- Each text label is surrounded in an HTML <label> tag, which points to the appropriate form field via its id. Its id, in turn, is generated by prepending 'id_' to the field name. The id attributes and <label> tags are included in the output by default, to follow best practices, but you can change that behavior.

Although <table> output is the default output style when you print a form, other output styles are available. Each style is available as a method on a form object, and each rendering method returns a Unicode object.

as_p()

Form.as_p()

as_p() renders the form as a series of <p> tags, with each <p> containing one field:

>>> f = ContactForm()
>>> f.as_p()
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>'
>>> print(f.as_p())
<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
<p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></p>
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>

as_ul()

Form.as_ul()

as_ul() renders the form as a series of <li> tags, with each <li> containing one field. It does not include the <ul> or </ul>, so that you can specify any HTML attributes on the <ul> for flexibility:

>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>

as_table()

Form.as_table()

Finally, as_table() outputs the form as an HTML <table>. This is exactly the same as print. In fact, when you print a form object, it calls its as_table() method behind the scenes:

>>> f = ContactForm()
>>> f.as_table()
'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
>>> print(f.as_table())
<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>

Styling required or erroneous form rows

Form.error_css_class

Form.required_css_class

It’s pretty common to style form rows and fields that are required or have errors. For example, you might want to present required form rows in bold and highlight errors in red.

The Form class has a couple of hooks you can use to add class attributes to required rows or to rows with errors: simply set the Form.error_css_class and/or Form.required_css_class attributes:

from django.forms import Form

class ContactForm(Form):
error_css_class = 'error'
required_css_class = 'required'

# ... and the rest of your fields here

Once you’ve done that, rows will be given "error" and/or "required" classes, as needed. The HTML will look something like:

>>> f = ContactForm(data)
>>> print(f.as_table())
<tr class="required"><th><label class="required" for="id_subject">Subject:</label>    ...
<tr class="required"><th><label class="required" for="id_message">Message:</label>    ...
<tr class="required error"><th><label class="required" for="id_sender">Sender:</label>      ...
<tr><th><label for="id_cc_myself">Cc myself:<label> ...
>>> f['subject'].label_tag()
<label class="required" for="id_subject">Subject:</label>
>>> f['subject'].label_tag(attrs={'class': 'foo'})
<label for="id_subject" class="foo required">Subject:</label>

Changed in Django 1.8:
The required_css_class will also be added to the <label> tag as seen above.

Configuring form elements’ HTML id attributes and <label> tags

Form.auto_id

By default, the form rendering methods include:

- HTML id attributes on the form elements.

- The corresponding <label> tags around the labels. An HTML <label> tag designates which label text is associated with which form element. This small enhancement makes forms more usable and more accessible to assistive devices. It’s always a good idea to use <label> tags.

The id attribute values are generated by prepending id_ to the form field names. This behavior is configurable, though, if you want to change the id convention or remove HTML id attributes and <label> tags entirely.

Use the auto_id argument to the Form constructor to control the id and label behavior. This argument must be True, False or a string.

If auto_id is False, then the form output will not include <label> tags nor id attributes:

>>> f = ContactForm(auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
<tr><th>Sender:</th><td><input type="email" name="sender" /></td></tr>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
>>> print(f.as_ul())
<li>Subject: <input type="text" name="subject" maxlength="100" /></li>
<li>Message: <input type="text" name="message" /></li>
<li>Sender: <input type="email" name="sender" /></li>
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
>>> print(f.as_p())
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
<p>Message: <input type="text" name="message" /></p>
<p>Sender: <input type="email" name="sender" /></p>
<p>Cc myself: <input type="checkbox" name="cc_myself" /></p>

If auto_id is set to True, then the form output will include <label> tags and will simply use the field name as its id for each form field:

>>> f = ContactForm(auto_id=True)
>>> print(f.as_table())
<tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr>
<tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr>
<tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" /></td></tr>
<tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr>
>>> print(f.as_ul())
<li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li>
<li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li>
<li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" /></li>
<li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li>
>>> print(f.as_p())
<p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p>
<p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" /></p>
<p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p>

If auto_id is set to a string containing the format character '%s', then the form output will include <label> tags, and will generate id attributes based on the format string. For example, for a format string 'field_%s', a field named subject will get the id value 'field_subject'. Continuing our example:

>>> f = ContactForm(auto_id='id_for_%s')
>>> print(f.as_table())
<tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr>
<tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr>
<tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" /></td></tr>
<tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr>
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
<li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li>
<li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" /></li>
<li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
>>> print(f.as_p())
<p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p>
<p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p>
<p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" /></p>
<p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p>

If auto_id is set to any other true value – such as a string that doesn’t include %s – then the library will act as if auto_id is True.

By default, auto_id is set to the string 'id_%s'.

Form.label_suffix

A translatable string (defaults to a colon (:) in English) that will be appended after any label name when a form is rendered.

It’s possible to customize that character, or omit it entirely, using the label_suffix parameter:

>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
<li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li>
<li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" /></li>
<li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
>>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
>>> print(f.as_ul())
<li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
<li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li>
<li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" /></li>
<li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>

Note that the label suffix is added only if the last character of the label isn’t a punctuation character (in English, those are ., !, ? or :).

New in Django 1.8.

Fields can also define their own label_suffix. This will take precedence over Form.label_suffix. The suffix can also be overridden at runtime using the label_suffix parameter to label_tag().

Notes on field ordering

In the as_p(), as_ul() and as_table() shortcuts, the fields are displayed in the order in which you define them in your form class. For example, in the ContactForm example, the fields are defined in the order subject, message, sender, cc_myself. To reorder the HTML output, just change the order in which those fields are listed in the class.

There are several other ways to customize the order:

Form.field_order

New in Django 1.9.

By default Form.field_order=None, which retains the order in which you define the fields in your form class. If field_order is a list of field names, the fields are ordered as specified by the list and remaining fields are appended according to the default order. Unknown field names in the list are ignored. This makes it possible to disable a field in a subclass by setting it to None without having to redefine ordering.

You can also use the Form.field_order argument to a Form to override the field order. If a Form defines field_order and you include field_order when instantiating the Form, then the latter field_order will have precedence.

Form.order_fields(field_order)

New in Django 1.9.

You may rearrange the fields any time using order_fields() with a list of field names as in field_order.

How errors are displayed

If you render a bound Form object, the act of rendering will automatically run the form’s validation if it hasn’t already happened, and the HTML output will include the validation errors as a <ul class="errorlist"> near the field. The particular positioning of the error messages depends on the output method you’re using:

>>> data = {'subject': '',
...         'message': 'Hi there',
...         'sender': 'invalid email address',
...         'cc_myself': True}
>>> f = ContactForm(data, auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
<tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" /></td></tr>
<tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
>>> print(f.as_ul())
<li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
<li>Message: <input type="text" name="message" value="Hi there" /></li>
<li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" /></li>
<li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
>>> print(f.as_p())
<p><ul class="errorlist"><li>This field is required.</li></ul></p>
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
<p>Message: <input type="text" name="message" value="Hi there" /></p>
<p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
<p>Sender: <input type="email" name="sender" value="invalid email address" /></p>
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>

Customizing the error list format

By default, forms use django.forms.utils.ErrorList to format validation errors. If you’d like to use an alternate class for displaying errors, you can pass that in at construction time (replace __str__ by __unicode__ on Python 2):

>>> from django.forms.utils import ErrorList
>>> class DivErrorList(ErrorList):
...     def __str__(self):              # __unicode__ on Python 2
...         return self.as_divs()
...     def as_divs(self):
...         if not self: return ''
...         return '<div class="errorlist">%s</div>' % ''.join(['<div class="error">%s</div>' % e for e in self])
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
>>> f.as_p()
<div class="errorlist"><div class="error">This field is required.</div></div>
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
<p>Message: <input type="text" name="message" value="Hi there" /></p>
<div class="errorlist"><div class="error">Enter a valid email address.</div></div>
<p>Sender: <input type="email" name="sender" value="invalid email address" /></p>
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>

More granular output

The as_p(), as_ul(), and as_table() methods are simply shortcuts – they’re not the only way a form object can be displayed.

class BoundField[source]

Used to display HTML or access attributes for a single field of a Form instance.

The __str__() (__unicode__ on Python 2) method of this object displays the HTML for this field.

To retrieve a single BoundField, use dictionary lookup syntax on your form using the field’s name as the key:

>>> form = ContactForm()
>>> print(form['subject'])
<input id="id_subject" type="text" name="subject" maxlength="100" />

To retrieve all BoundField objects, iterate the form:

>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
<input id="id_subject" type="text" name="subject" maxlength="100" />
<input type="text" name="message" id="id_message" />
<input type="email" name="sender" id="id_sender" />
<input type="checkbox" name="cc_myself" id="id_cc_myself" />

The field-specific output honors the form object’s auto_id setting:

>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
<input type="text" name="message" />
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
<input type="text" name="message" id="id_message" />

Attributes of BoundField

BoundField.auto_id

The HTML ID attribute for this BoundField. Returns an empty string if Form.auto_id is False.

BoundField.data

This property returns the data for this BoundField extracted by the widget’s value_from_datadict() method, or None if it wasn’t given:

>>> unbound_form = ContactForm()
>>> print(unbound_form['subject'].data)
None
>>> bound_form = ContactForm(data={'subject': 'My Subject'})
>>> print(bound_form['subject'].data)
My Subject

BoundField.errors

A list-like object that is displayed as an HTML <ul class="errorlist"> when printed:

>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
>>> f = ContactForm(data, auto_id=False)
>>> print(f['message'])
<input type="text" name="message" />
>>> f['message'].errors
['This field is required.']
>>> print(f['message'].errors)
<ul class="errorlist"><li>This field is required.</li></ul>
>>> f['subject'].errors
[]
>>> print(f['subject'].errors)

>>> str(f['subject'].errors)
''

BoundField.field

The form Field instance from the form class that this BoundField wraps.

BoundField.form

The Form instance this BoundField is bound to.

BoundField.help_text

The help_text of the field.

BoundField.html_name

The name that will be used in the widget’s HTML name attribute. It takes the form prefix into account.

BoundField.id_for_label

Use this property to render the ID of this field. For example, if you are manually constructing a <label> in your template (despite the fact that label_tag() will do this for you):

<label for="{{ form.my_field.id_for_label }}">...</label>{{ my_field }}

By default, this will be the field’s name prefixed by id_ (“id_my_field” for the example above). You may modify the ID by setting attrs on the field’s widget. For example, declaring a field like this:

my_field = forms.CharField(widget=forms.TextInput(attrs={'id': 'myFIELD'}))

and using the template above, would render something like:

<label for="myFIELD">...</label><input id="myFIELD" type="text" name="my_field" />

BoundField.is_hidden

Returns True if this BoundField‘s widget is hidden.

BoundField.label

The label of the field. This is used in label_tag().

BoundField.name

The name of this field in the form:

>>> f = ContactForm()
>>> print(f['subject'].name)
subject
>>> print(f['message'].name)
message

Methods of BoundField

BoundField.as_hidden(attrs=None, **kwargs)[source]

Returns a string of HTML for representing this as an <input type="hidden">.

**kwargs are passed to as_widget().

This method is primarily used internally. You should use a widget instead.

BoundField.as_widget(widget=None, attrs=None, only_initial=False)[source]

Renders the field by rendering the passed widget, adding any HTML attributes passed as attrs. If no widget is specified, then the field’s default widget will be used.

only_initial is used by Django internals and should not be set explicitly.

BoundField.css_classes()[source]

When you use Django’s rendering shortcuts, CSS classes are used to indicate required form fields or fields that contain errors. If you’re manually rendering a form, you can access these CSS classes using the css_classes method:

>>> f = ContactForm(data={'message': ''})
>>> f['message'].css_classes()
'required'

If you want to provide some additional classes in addition to the error and required classes that may be required, you can provide those classes as an argument:

>>> f = ContactForm(data={'message': ''})
>>> f['message'].css_classes('foo bar')
'foo bar required'

BoundField.label_tag(contents=None, attrs=None, label_suffix=None)[source]

To separately render the label tag of a form field, you can call its label_tag() method:

>>> f = ContactForm(data={'message': ''})
>>> print(f['message'].label_tag())
<label for="id_message">Message:</label>

You can provide the contents parameter which will replace the auto-generated label tag. An attrs dictionary may contain additional attributes for the <label> tag.

The HTML that’s generated includes the form’s label_suffix (a colon, by default) or, if set, the current field’s label_suffix. The optional label_suffix parameter allows you to override any previously set suffix. For example, you can use an empty string to hide the label on selected fields. If you need to do this in a template, you could write a custom filter to allow passing parameters to label_tag.

Changed in Django 1.8:
The label includes required_css_class if applicable.

BoundField.value()[source]

Use this method to render the raw value of this field as it would be rendered by a Widget:

>>> initial = {'subject': 'welcome'}
>>> unbound_form = ContactForm(initial=initial)
>>> bound_form = ContactForm(data={'subject': 'hi'}, initial=initial)
>>> print(unbound_form['subject'].value())
welcome
>>> print(bound_form['subject'].value())
hi

Customizing BoundField

New in Django 1.9.

If you need to access some additional information about a form field in a template and using a subclass of Field isn’t sufficient, consider also customizing BoundField.

A custom form field can override get_bound_field():

Field.get_bound_field(form, field_name)[source]

Takes an instance of Form and the name of the field. The return value will be used when accessing the field in a template. Most likely it will be an instance of a subclass of BoundField.

If you have a GPSCoordinatesField, for example, and want to be able to access additional information about the coordinates in a template, this could be implemented as follows:

class GPSCoordinatesBoundField(BoundField):
@property
def country(self):
"""
Return the country the coordinates lie in or None if it can't be
determined.
"""
value = self.value()
if value:
return get_country_from_coordinates(value)
else:
return None

class GPSCoordinatesField(Field):
def get_bound_field(self, form, field_name):
return GPSCoordinatesBoundField(form, self, field_name)

Now you can access the country in a template with {{ form.coordinates.country }}.

Binding uploaded files to a form

Dealing with forms that have FileField and ImageField fields is a little more complicated than a normal form.

Firstly, in order to upload files, you’ll need to make sure that your <form> element correctly defines the enctype as "multipart/form-data":

<form enctype="multipart/form-data" method="post" action="/foo/">

Secondly, when you use the form, you need to bind the file data. File data is handled separately to normal form data, so when your form contains a FileField and ImageField, you will need to specify a second argument when you bind your form. So if we extend our ContactForm to include an ImageField called mugshot, we need to bind the file data containing the mugshot image:

# Bound form with an image field
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)}
>>> f = ContactFormWithMugshot(data, file_data)

In practice, you will usually specify request.FILES as the source of file data (just like you use request.POST as the source of form data):

# Bound form with an image field, data from the request
>>> f = ContactFormWithMugshot(request.POST, request.FILES)

Constructing an unbound form is the same as always – just omit both form data and file data:

# Unbound form with an image field
>>> f = ContactFormWithMugshot()

Testing for multipart forms

Form.is_multipart()

If you’re writing reusable views or templates, you may not know ahead of time whether your form is a multipart form or not. The is_multipart() method tells you whether the form requires multipart encoding for submission:

>>> f = ContactFormWithMugshot()
>>> f.is_multipart()
True

Here’s an example of how you might use this in a template:

{% if form.is_multipart %}
<form enctype="multipart/form-data" method="post" action="/foo/">
{% else %}
<form method="post" action="/foo/">
{% endif %}
{{ form }}
</form>

Subclassing forms

If you have multiple Form classes that share fields, you can use subclassing to remove redundancy.

When you subclass a custom Form class, the resulting subclass will include all fields of the parent class(es), followed by the fields you define in the subclass.

In this example, ContactFormWithPriority contains all the fields from ContactForm, plus an additional field, priority. The ContactForm fields are ordered first:

>>> class ContactFormWithPriority(ContactForm):
...     priority = forms.CharField()
>>> f = ContactFormWithPriority(auto_id=False)
>>> print(f.as_ul())
<li>Subject: <input type="text" name="subject" maxlength="100" /></li>
<li>Message: <input type="text" name="message" /></li>
<li>Sender: <input type="email" name="sender" /></li>
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
<li>Priority: <input type="text" name="priority" /></li>

It’s possible to subclass multiple forms, treating forms as mixins. In this example, BeatleForm subclasses both PersonForm and InstrumentForm (in that order), and its field list includes the fields from the parent classes:

>>> from django.forms import Form
>>> class PersonForm(Form):
...     first_name = CharField()
...     last_name = CharField()
>>> class InstrumentForm(Form):
...     instrument = CharField()
>>> class BeatleForm(PersonForm, InstrumentForm):
...     haircut_type = CharField()
>>> b = BeatleForm(auto_id=False)
>>> print(b.as_ul())
<li>First name: <input type="text" name="first_name" /></li>
<li>Last name: <input type="text" name="last_name" /></li>
<li>Instrument: <input type="text" name="instrument" /></li>
<li>Haircut type: <input type="text" name="haircut_type" /></li>

It’s possible to declaratively remove a Field inherited from a parent class by setting the name of the field to None on the subclass. For example:

>>> from django import forms

>>> class ParentForm(forms.Form):
...     name = forms.CharField()
...     age = forms.IntegerField()

>>> class ChildForm(ParentForm):
...     name = None

>>> ChildForm().fields.keys()
... ['age']

Prefixes for forms

Form.prefix

You can put several Django forms inside one <form> tag. To give each Form its own namespace, use the prefix keyword argument:

>>> mother = PersonForm(prefix="mother")
>>> father = PersonForm(prefix="father")
>>> print(mother.as_ul())
<li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" /></li>
<li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" /></li>
>>> print(father.as_ul())
<li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li>
<li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li>

The prefix can also be specified on the form class:

>>> class PersonForm(forms.Form):
...     ...
...     prefix = 'person'

New in Django 1.9:
The ability to specify prefix on the form class was added.

Form fields

class Field(**kwargs)[source]

When you create a Form class, the most important part is defining the fields of the form. Each field has custom validation logic, along with a few other hooks.

Field.clean(value)[source]

Although the primary way you’ll use Field classes is in Form classes, you can also instantiate them and use them directly to get a better idea of how they work. Each Field instance has a clean() method, which takes a single argument and either raises a django.forms.ValidationError exception or returns the clean value:

>>> from django import forms
>>> f = forms.EmailField()
>>> f.clean('foo@example.com')
'foo@example.com'
>>> f.clean('invalid email address')
Traceback (most recent call last):
...
ValidationError: ['Enter a valid email address.']

Core field arguments

Each Field class constructor takes at least these arguments. Some Field classes take additional, field-specific arguments, but the following should always be accepted:

required

Field.required

By default, each Field class assumes the value is required, so if you pass an empty value – either None or the empty string ("") – then clean() will raise a ValidationError exception:

>>> from django import forms
>>> f = forms.CharField()
>>> f.clean('foo')
'foo'
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: ['This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: ['This field is required.']
>>> f.clean(' ')
' '
>>> f.clean(0)
'0'
>>> f.clean(True)
'True'
>>> f.clean(False)
'False'

To specify that a field is not required, pass required=False to the Field constructor:

>>> f = forms.CharField(required=False)
>>> f.clean('foo')
'foo'
>>> f.clean('')
''
>>> f.clean(None)
''
>>> f.clean(0)
'0'
>>> f.clean(True)
'True'
>>> f.clean(False)
'False'

If a Field has required=False and you pass clean() an empty value, then clean() will return a normalized empty value rather than raising ValidationError. For CharField, this will be a Unicode empty string. For other Field classes, it might be None. (This varies from field to field.)

label

Field.label

The label argument lets you specify the “human-friendly” label for this field. This is used when the Field is displayed in a Form.

As explained in “Outputting forms as HTML” above, the default label for a Field is generated from the field name by converting all underscores to spaces and upper-casing the first letter. Specify label if that default behavior doesn’t result in an adequate label.

Here’s a full example Form that implements label for two of its fields. We’ve specified auto_id=False to simplify the output:

>>> from django import forms
>>> class CommentForm(forms.Form):
...     name = forms.CharField(label='Your name')
...     url = forms.URLField(label='Your website', required=False)
...     comment = forms.CharField()
>>> f = CommentForm(auto_id=False)
>>> print(f)
<tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
<tr><th>Your website:</th><td><input type="url" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>

label_suffix

Field.label_suffix

New in Django 1.8.

The label_suffix argument lets you override the form’s label_suffix on a per-field basis:

>>> class ContactForm(forms.Form):
...     age = forms.IntegerField()
...     nationality = forms.CharField()
...     captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
>>> f = ContactForm(label_suffix='?')
>>> print(f.as_p())
<p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" /></p>
<p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" /></p>
<p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" /></p>

initial

Field.initial

The initial argument lets you specify the initial value to use when rendering this Field in an unbound Form.

To specify dynamic initial data, see the Form.initial parameter.

The use-case for this is when you want to display an “empty” form in which a field is initialized to a particular value. For example:

>>> from django import forms
>>> class CommentForm(forms.Form):
...     name = forms.CharField(initial='Your name')
...     url = forms.URLField(initial='http://')
...     comment = forms.CharField()
>>> f = CommentForm(auto_id=False)
>>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" value="http://" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>

You may be thinking, why not just pass a dictionary of the initial values as data when displaying the form? Well, if you do that, you’ll trigger validation, and the HTML output will include any validation errors:

>>> class CommentForm(forms.Form):
...     name = forms.CharField()
...     url = forms.URLField()
...     comment = forms.CharField()
>>> default_data = {'name': 'Your name', 'url': 'http://'}
>>> f = CommentForm(default_data, auto_id=False)
>>> print(f)
<tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
<tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="url" name="url" value="http://" /></td></tr>
<tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>

This is why initial values are only displayed for unbound forms. For bound forms, the HTML output will use the bound data.

Also note that initial values are not used as “fallback” data in validation if a particular field’s value is not given. initial values are only intended for initial form display:

>>> class CommentForm(forms.Form):
...     name = forms.CharField(initial='Your name')
...     url = forms.URLField(initial='http://')
...     comment = forms.CharField()
>>> data = {'name': '', 'url': '', 'comment': 'Foo'}
>>> f = CommentForm(data)
>>> f.is_valid()
False
# The form does *not* fall back to using the initial values.
>>> f.errors
{'url': ['This field is required.'], 'name': ['This field is required.']}

Instead of a constant, you can also pass any callable:

>>> import datetime
>>> class DateForm(forms.Form):
...     day = forms.DateField(initial=datetime.date.today)
>>> print(DateForm())
<tr><th>Day:</th><td><input type="text" name="day" value="12/23/2008" /><td></tr>

The callable will be evaluated only when the unbound form is displayed, not when it is defined.

widget

Field.widget

The widget argument lets you specify a Widget class to use when rendering this Field. See Widgets for more information.

help_text

Field.help_text

The help_text argument lets you specify descriptive text for this Field. If you provide help_text, it will be displayed next to the Field when the Field is rendered by one of the convenience Form methods (e.g., as_ul()).

Like the model field’s help_text, this value isn’t HTML-escaped in automatically-generated forms.

Here’s a full example Form that implements help_text for two of its fields. We’ve specified auto_id=False to simplify the output:

>>> from django import forms
>>> class HelpTextContactForm(forms.Form):
...     subject = forms.CharField(max_length=100, help_text='100 characters max.')
...     message = forms.CharField()
...     sender = forms.EmailField(help_text='A valid email address, please.')
...     cc_myself = forms.BooleanField(required=False)
>>> f = HelpTextContactForm(auto_id=False)
>>> print(f.as_table())
<tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br /><span class="helptext">100 characters max.</span></td></tr>
<tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
<tr><th>Sender:</th><td><input type="email" name="sender" /><br />A valid email address, please.</td></tr>
<tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
>>> print(f.as_ul()))
<li>Subject: <input type="text" name="subject" maxlength="100" /> <span class="helptext">100 characters max.</span></li>
<li>Message: <input type="text" name="message" /></li>
<li>Sender: <input type="email" name="sender" /> A valid email address, please.</li>
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
>>> print(f.as_p())
<p>Subject: <input type="text" name="subject" maxlength="100" /> <span class="helptext">100 characters max.</span></p>
<p>Message: <input type="text" name="message" /></p>
<p>Sender: <input type="email" name="sender" /> A valid email address, please.</p>
<p>Cc myself: <input type="checkbox" name="cc_myself" /></p>

error_messages

Field.error_messages

The error_messages argument lets you override the default messages that the field will raise. Pass in a dictionary with keys matching the error messages you want to override. For example, here is the default error message:

>>> from django import forms
>>> generic = forms.CharField()
>>> generic.clean('')
Traceback (most recent call last):
...
ValidationError: ['This field is required.']

And here is a custom error message:

>>> name = forms.CharField(error_messages={'required': 'Please enter your name'})
>>> name.clean('')
Traceback (most recent call last):
...
ValidationError: ['Please enter your name']

In the built-in Field classes section below, each Field defines the error message keys it uses.

validators

Field.validators

The validators argument lets you provide a list of validation functions for this field.

See the validators documentation for more information.

localize

Field.localize

The localize argument enables the localization of form data input, as well as the rendered output.

See the format localization documentation for more information.

disabled

Field.disabled

New in Django 1.9.

The disabled boolean argument, when set to True, disables a form field using the disabled HTML attribute so that it won’t be editable by users. Even if a user tampers with the field’s value submitted to the server, it will be ignored in favor of the value from the form’s initial data.

Checking if the field data has changed

has_changed()

Field.has_changed()[source]

Changed in Django 1.8:
This method was renamed from _has_changed().

The has_changed() method is used to determine if the field value has changed from the initial value. Returns True or False.

See the Form.has_changed() documentation for more information.

Built-in Field classes

Naturally, the forms library comes with a set of Field classes that represent common validation needs. This section documents each built-in field.

For each field, we describe the default widget used if you don’t specify widget. We also specify the value returned when you provide an empty value (see the section on required above to understand what that means).

BooleanField

class BooleanField(**kwargs)[source]

- Default widget: CheckboxInput

- Empty value: False

- Normalizes to: A Python True or False value.

- Validates that the value is True (e.g. the check box is checked) if the field has required=True.

- Error message keys: required

Note

Since all Field subclasses have required=True by default, the validation condition here is important. If you want to include a boolean in your form that can be either True or False (e.g. a checked or unchecked checkbox), you must remember to pass in required=False when creating the BooleanField.

CharField

class CharField(**kwargs)[source]

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates max_length or min_length, if they are provided. Otherwise, all inputs are valid.

- Error message keys: required, max_length, min_length

Has three optional arguments for validation:

max_length

min_length

If provided, these arguments ensure that the string is at most or at least the given length.

strip

New in Django 1.9.

If True (default), the value will be stripped of leading and trailing whitespace.

ChoiceField

class ChoiceField(**kwargs)[source]

- Default widget: Select

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates that the given value exists in the list of choices.

- Error message keys: required, invalid_choice

The invalid_choice error message may contain %(value)s, which will be replaced with the selected choice.

Takes one extra required argument:

choices

Either an iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field, or a callable that returns such an iterable. This argument accepts the same formats as the choices argument to a model field. See the model field reference documentation on choices for more details. If the argument is a callable, it is evaluated each time the field’s form is initialized.

Changed in Django 1.8:
The ability to pass a callable to choices was added.

TypedChoiceField

class TypedChoiceField(**kwargs)[source]

Just like a ChoiceField, except TypedChoiceField takes two extra arguments, coerce and empty_value.

- Default widget: Select

- Empty value: Whatever you’ve given as empty_value.

- Normalizes to: A value of the type provided by the coerce argument.

- Validates that the given value exists in the list of choices and can be coerced.

- Error message keys: required, invalid_choice

Takes extra arguments:

coerce

A function that takes one argument and returns a coerced value. Examples include the built-in int, float, bool and other types. Defaults to an identity function. Note that coercion happens after input validation, so it is possible to coerce to a value not present in choices.

empty_value

The value to use to represent “empty.” Defaults to the empty string; None is another common choice here. Note that this value will not be coerced by the function given in the coerce argument, so choose it accordingly.

DateField

class DateField(**kwargs)[source]

- Default widget: DateInput

- Empty value: None

- Normalizes to: A Python datetime.date object.

- Validates that the given value is either a datetime.date, datetime.datetime or string formatted in a particular date format.

- Error message keys: required, invalid

Takes one optional argument:

input_formats

A list of formats used to attempt to convert a string to a valid datetime.date object.

If no input_formats argument is provided, the default input formats are:

['%Y-%m-%d',      # '2006-10-25'
'%m/%d/%Y',      # '10/25/2006'
'%m/%d/%y']      # '10/25/06'

Additionally, if you specify USE_L10N=False in your settings, the following will also be included in the default input formats:

['%b %d %Y',      # 'Oct 25 2006'
'%b %d, %Y',     # 'Oct 25, 2006'
'%d %b %Y',      # '25 Oct 2006'
'%d %b, %Y',     # '25 Oct, 2006'
'%B %d %Y',      # 'October 25 2006'
'%B %d, %Y',     # 'October 25, 2006'
'%d %B %Y',      # '25 October 2006'
'%d %B, %Y']     # '25 October, 2006'

See also format localization.

DateTimeField

class DateTimeField(**kwargs)[source]

- Default widget: DateTimeInput

- Empty value: None

- Normalizes to: A Python datetime.datetime object.

- Validates that the given value is either a datetime.datetime, datetime.date or string formatted in a particular datetime format.

- Error message keys: required, invalid

Takes one optional argument:

input_formats

A list of formats used to attempt to convert a string to a valid datetime.datetime object.

If no input_formats argument is provided, the default input formats are:

['%Y-%m-%d %H:%M:%S',    # '2006-10-25 14:30:59'
'%Y-%m-%d %H:%M',       # '2006-10-25 14:30'
'%Y-%m-%d',             # '2006-10-25'
'%m/%d/%Y %H:%M:%S',    # '10/25/2006 14:30:59'
'%m/%d/%Y %H:%M',       # '10/25/2006 14:30'
'%m/%d/%Y',             # '10/25/2006'
'%m/%d/%y %H:%M:%S',    # '10/25/06 14:30:59'
'%m/%d/%y %H:%M',       # '10/25/06 14:30'
'%m/%d/%y']             # '10/25/06'

See also format localization.

DecimalField

class DecimalField(**kwargs)[source]

- Default widget: NumberInput when Field.localize is False, else TextInput.

- Empty value: None

- Normalizes to: A Python decimal.

- Validates that the given value is a decimal. Leading and trailing whitespace is ignored.

- Error message keys: required, invalid, max_value, min_value, max_digits, max_decimal_places, max_whole_digits

The max_value and min_value error messages may contain %(limit_value)s, which will be substituted by the appropriate limit. Similarly, the max_digits, max_decimal_places and max_whole_digits error messages may contain %(max)s.

Takes four optional arguments:

max_value

min_value

These control the range of values permitted in the field, and should be given as decimal.Decimal values.

max_digits

The maximum number of digits (those before the decimal point plus those after the decimal point, with leading zeros stripped) permitted in the value.

decimal_places

The maximum number of decimal places permitted.

DurationField

New in Django 1.8.

class DurationField(**kwargs)[source]

- Default widget: TextInput

- Empty value: None

- Normalizes to: A Python timedelta.

- Validates that the given value is a string which can be converted into a timedelta.

- Error message keys: required, invalid.

Accepts any format understood by parse_duration().

EmailField

class EmailField(**kwargs)[source]

- Default widget: EmailInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates that the given value is a valid email address, using a moderately complex regular expression.

- Error message keys: required, invalid

Has two optional arguments for validation, max_length and min_length. If provided, these arguments ensure that the string is at most or at least the given length.

FileField

class FileField(**kwargs)[source]

- Default widget: ClearableFileInput

- Empty value: None

- Normalizes to: An UploadedFile object that wraps the file content and file name into a single object.

- Can validate that non-empty file data has been bound to the form.

- Error message keys: required, invalid, missing, empty, max_length

Has two optional arguments for validation, max_length and allow_empty_file. If provided, these ensure that the file name is at most the given length, and that validation will succeed even if the file content is empty.

To learn more about the UploadedFile object, see the file uploads documentation.

When you use a FileField in a form, you must also remember to bind the file data to the form.

The max_length error refers to the length of the filename. In the error message for that key, %(max)d will be replaced with the maximum filename length and %(length)d will be replaced with the current filename length.

FilePathField

class FilePathField(**kwargs)[source]

- Default widget: Select

- Empty value: None

- Normalizes to: A unicode object

- Validates that the selected choice exists in the list of choices.

- Error message keys: required, invalid_choice

The field allows choosing from files inside a certain directory. It takes five extra arguments; only path is required:

path

The absolute path to the directory whose contents you want listed. This directory must exist.

recursive

If False (the default) only the direct contents of path will be offered as choices. If True, the directory will be descended into recursively and all descendants will be listed as choices.

match

A regular expression pattern; only files with names matching this expression will be allowed as choices.

allow_files

Optional. Either True or False. Default is True. Specifies whether files in the specified location should be included. Either this or allow_folders must be True.

allow_folders

Optional. Either True or False. Default is False. Specifies whether folders in the specified location should be included. Either this or allow_files must be True.

FloatField

class FloatField(**kwargs)[source]

- Default widget: NumberInput when Field.localize is False, else TextInput.

- Empty value: None

- Normalizes to: A Python float.

- Validates that the given value is a float. Leading and trailing whitespace is allowed, as in Python’s float() function.

- Error message keys: required, invalid, max_value, min_value

Takes two optional arguments for validation, max_value and min_value. These control the range of values permitted in the field.

ImageField

class ImageField(**kwargs)[source]

- Default widget: ClearableFileInput

- Empty value: None

- Normalizes to: An UploadedFile object that wraps the file content and file name into a single object.

- Validates that file data has been bound to the form, and that the file is of an image format understood by Pillow.

- Error message keys: required, invalid, missing, empty, invalid_image

Using an ImageField requires that Pillow is installed with support for the image formats you use. If you encounter a corrupt image error when you upload an image, it usually means that Pillow doesn’t understand its format. To fix this, install the appropriate library and reinstall Pillow.

When you use an ImageField on a form, you must also remember to bind the file data to the form.

After the field has been cleaned and validated, the UploadedFile object will have an additional image attribute containing the Pillow Image instance used to check if the file was a valid image. Also, UploadedFile.content_type will be updated with the image’s content type if Pillow can determine it, otherwise it will be set to None.

Changed in Django 1.8:
The image and content_type attributes described in the last paragraph were added.

IntegerField

class IntegerField(**kwargs)[source]

- Default widget: NumberInput when Field.localize is False, else TextInput.

- Empty value: None

- Normalizes to: A Python integer or long integer.

- Validates that the given value is an integer. Leading and trailing whitespace is allowed, as in Python’s int() function.

- Error message keys: required, invalid, max_value, min_value

The max_value and min_value error messages may contain %(limit_value)s, which will be substituted by the appropriate limit.

Takes two optional arguments for validation:

max_value

min_value

These control the range of values permitted in the field.

GenericIPAddressField

class GenericIPAddressField(**kwargs)[source]

A field containing either an IPv4 or an IPv6 address.

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object. IPv6 addresses are normalized as described below.

- Validates that the given value is a valid IP address.

- Error message keys: required, invalid

The IPv6 address normalization follows RFC 4291#section-2.2 section 2.2, including using the IPv4 format suggested in paragraph 3 of that section, like ::ffff:192.0.2.0. For example, 2001:0::0:01 would be normalized to 2001::1, and ::ffff:0a0a:0a0a to ::ffff:10.10.10.10. All characters are converted to lowercase.

Takes two optional arguments:

protocol

Limits valid inputs to the specified protocol. Accepted values are both (default), IPv4 or IPv6. Matching is case insensitive.

unpack_ipv4

Unpacks IPv4 mapped addresses like ::ffff:192.0.2.1. If this option is enabled that address would be unpacked to 192.0.2.1. Default is disabled. Can only be used when protocol is set to 'both'.

MultipleChoiceField

class MultipleChoiceField(**kwargs)[source]

- Default widget: SelectMultiple

- Empty value: [] (an empty list)

- Normalizes to: A list of Unicode objects.

- Validates that every value in the given list of values exists in the list of choices.

- Error message keys: required, invalid_choice, invalid_list

The invalid_choice error message may contain %(value)s, which will be replaced with the selected choice.

Takes one extra required argument, choices, as for ChoiceField.

TypedMultipleChoiceField

class TypedMultipleChoiceField(**kwargs)[source]

Just like a MultipleChoiceField, except TypedMultipleChoiceField takes two extra arguments, coerce and empty_value.

- Default widget: SelectMultiple

- Empty value: Whatever you’ve given as empty_value

- Normalizes to: A list of values of the type provided by the coerce argument.

- Validates that the given values exists in the list of choices and can be coerced.

- Error message keys: required, invalid_choice

The invalid_choice error message may contain %(value)s, which will be replaced with the selected choice.

Takes two extra arguments, coerce and empty_value, as for TypedChoiceField.

NullBooleanField

class NullBooleanField(**kwargs)[source]

- Default widget: NullBooleanSelect

- Empty value: None

- Normalizes to: A Python True, False or None value.

- Validates nothing (i.e., it never raises a ValidationError).

RegexField

class RegexField(**kwargs)[source]

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates that the given value matches against a certain regular expression.

- Error message keys: required, invalid

Takes one required argument:

regex

A regular expression specified either as a string or a compiled regular expression object.

Also takes max_length, min_length, and strip, which work just as they do for CharField.

strip

New in Django 1.9.

Defaults to False. If enabled, stripping will be applied before the regex validation.

Deprecated since version 1.8: The optional argument error_message is also accepted for backwards compatibility but will be removed in Django 1.10. The preferred way to provide an error message is to use the error_messages argument, passing a dictionary with 'invalid' as a key and the error message as the value.

SlugField

class SlugField(**kwargs)[source]

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates that the given value contains only letters, numbers, underscores, and hyphens.

- Error messages: required, invalid

This field is intended for use in representing a model SlugField in forms.

Takes an optional parameter:

allow_unicode

New in Django 1.9.

A boolean instructing the field to accept Unicode letters in addition to ASCII letters. Defaults to False.

TimeField

class TimeField(**kwargs)[source]

- Default widget: TextInput

- Empty value: None

- Normalizes to: A Python datetime.time object.

- Validates that the given value is either a datetime.time or string formatted in a particular time format.

- Error message keys: required, invalid

Takes one optional argument:

input_formats

A list of formats used to attempt to convert a string to a valid datetime.time object.

If no input_formats argument is provided, the default input formats are:

'%H:%M:%S',     # '14:30:59'
'%H:%M',        # '14:30'

URLField

class URLField(**kwargs)[source]

- Default widget: URLInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates that the given value is a valid URL.

- Error message keys: required, invalid

Takes the following optional arguments:

max_length

min_length

These are the same as CharField.max_length and CharField.min_length.

UUIDField

New in Django 1.8.

class UUIDField(**kwargs)[source]

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: A UUID object.

- Error message keys: required, invalid

This field will accept any string format accepted as the hex argument to the UUID constructor.

Slightly complex built-in Field classes

ComboField

class ComboField(**kwargs)[source]

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: A Unicode object.

- Validates the given value against each of the fields specified as an argument to the ComboField.

- Error message keys: required, invalid

Takes one extra required argument:

fields

The list of fields that should be used to validate the field’s value (in the order in which they are provided).

>>> from django.forms import ComboField
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
>>> f.clean('test@example.com')
'test@example.com'
>>> f.clean('longemailaddress@example.com')
Traceback (most recent call last):
...
ValidationError: ['Ensure this value has at most 20 characters (it has 28).']

MultiValueField

class MultiValueField(fields=(), **kwargs)[source]

- Default widget: TextInput

- Empty value: '' (an empty string)

- Normalizes to: the type returned by the compress method of the subclass.

- Validates the given value against each of the fields specified as an argument to the MultiValueField.

- Error message keys: required, invalid, incomplete

Aggregates the logic of multiple fields that together produce a single value.

This field is abstract and must be subclassed. In contrast with the single-value fields, subclasses of MultiValueField must not implement clean() but instead - implement compress().

Takes one extra required argument:

fields

A tuple of fields whose values are cleaned and subsequently combined into a single value. Each value of the field is cleaned by the corresponding field in fields – the first value is cleaned by the first field, the second value is cleaned by the second field, etc. Once all fields are cleaned, the list of clean values is combined into a single value by compress().

Also takes one extra optional argument:

require_all_fields

Defaults to True, in which case a required validation error will be raised if no value is supplied for any field.

When set to False, the Field.required attribute can be set to False for individual fields to make them optional. If no value is supplied for a required field, an incomplete validation error will be raised.

A default incomplete error message can be defined on the MultiValueField subclass, or different messages can be defined on each individual field. For example:

from django.core.validators import RegexValidator

class PhoneField(MultiValueField):
def __init__(self, *args, **kwargs):
# Define one message for all fields.
error_messages = {
'incomplete': 'Enter a country calling code and a phone number.',
}
# Or define a different message for each field.
fields = (
CharField(
error_messages={'incomplete': 'Enter a country calling code.'},
validators=[
RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),
],
),
CharField(
error_messages={'incomplete': 'Enter a phone number.'},
validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],
),
CharField(
validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],
required=False,
),
)
super(PhoneField, self).__init__(
error_messages=error_messages, fields=fields,
require_all_fields=False, *args, **kwargs
)

widget

Must be a subclass of django.forms.MultiWidget. Default value is TextInput, which probably is not very useful in this case.

compress(data_list)[source]

Takes a list of valid values and returns a “compressed” version of those values – in a single value. For example, SplitDateTimeField is a subclass which combines a time field and a date field into a datetime object.

This method must be implemented in the subclasses.

SplitDateTimeField

class SplitDateTimeField(**kwargs)[source]

- Default widget: SplitDateTimeWidget

- Empty value: None

- Normalizes to: A Python datetime.datetime object.

- Validates that the given value is a datetime.datetime or string formatted in a particular datetime format.

- Error message keys: required, invalid, invalid_date, invalid_time

Takes two optional arguments:

input_date_formats

A list of formats used to attempt to convert a string to a valid datetime.date object.

If no input_date_formats argument is provided, the default input formats for DateField are used.

input_time_formats

A list of formats used to attempt to convert a string to a valid datetime.time object.

If no input_time_formats argument is provided, the default input formats for TimeField are used.

Fields which handle relationships

Two fields are available for representing relationships between models: ModelChoiceField and ModelMultipleChoiceField. Both of these fields require a single queryset parameter that is used to create the choices for the field. Upon form validation, these fields will place either one model object (in the case of ModelChoiceField) or multiple model objects (in the case of ModelMultipleChoiceField) into the cleaned_data dictionary of the form.

For more complex uses, you can specify queryset=None when declaring the form field and then populate the queryset in the form’s __init__() method:

class FooMultipleChoiceForm(forms.Form):
foo_select = forms.ModelMultipleChoiceField(queryset=None)

def __init__(self, *args, **kwargs):
super(FooMultipleChoiceForm, self).__init__(*args, **kwargs)
self.fields['foo_select'].queryset = ...

ModelChoiceField

class ModelChoiceField(**kwargs)[source]

- Default widget: Select

- Empty value: None

- Normalizes to: A model instance.

- Validates that the given id exists in the queryset.

- Error message keys: required, invalid_choice

Allows the selection of a single model object, suitable for representing a foreign key. Note that the default widget for ModelChoiceField becomes impractical when the number of entries increases. You should avoid using it for more than 100 items.

A single argument is required:

queryset

A QuerySet of model objects from which the choices for the field will be derived, and which will be used to validate the user’s selection.

ModelChoiceField also takes two optional arguments:

empty_label

By default the <select> widget used by ModelChoiceField will have an empty choice at the top of the list. You can change the text of this label (which is "---------" by default) with the empty_label attribute, or you can disable the empty label entirely by setting empty_label to None:

# A custom empty label
field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")

# No empty label
field2 = forms.ModelChoiceField(queryset=..., empty_label=None)

Note that if a ModelChoiceField is required and has a default initial value, no empty choice is created (regardless of the value of empty_label).

to_field_name

This optional argument is used to specify the field to use as the value of the choices in the field’s widget. Be sure it’s a unique field for the model, otherwise the selected value could match more than one object. By default it is set to None, in which case the primary key of each object will be used. For example:

# No custom to_field_name
field1 = forms.ModelChoiceField(queryset=...)

would yield:

<select id="id_field1" name="field1">
<option value="obj1.pk">Object1</option>
<option value="obj2.pk">Object2</option>
...
</select>

and:

# to_field_name provided
field2 = forms.ModelChoiceField(queryset=..., to_field_name="name")

would yield:

<select id="id_field2" name="field2">
<option value="obj1.name">Object1</option>
<option value="obj2.name">Object2</option>
...
</select>

The __str__ (__unicode__ on Python 2) method of the model will be called to generate string representations of the objects for use in the field’s choices; to provide customized representations, subclass ModelChoiceField and override label_from_instance. This method will receive a model object, and should return a string suitable for representing it. For example:

from django.forms import ModelChoiceField

class MyModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return "My Object #%i" % obj.id

ModelMultipleChoiceField

class ModelMultipleChoiceField(**kwargs)[source]

- Default widget: SelectMultiple

- Empty value: An empty QuerySet (self.queryset.none())

- Normalizes to: A QuerySet of model instances.

- Validates that every id in the given list of values exists in the queryset.

- Error message keys: required, list, invalid_choice, invalid_pk_value

The invalid_choice message may contain %(value)s and the invalid_pk_value message may contain %(pk)s, which will be substituted by the appropriate values.

Allows the selection of one or more model objects, suitable for representing a many-to-many relation. As with ModelChoiceField, you can use label_from_instance to customize the object representations.

A single argument is required:

queryset

Same as ModelChoiceField.queryset.

Takes one optional argument:

to_field_name

Same as ModelChoiceField.to_field_name.

Creating custom fields

If the built-in Field classes don’t meet your needs, you can easily create custom Field classes. To do this, just create a subclass of django.forms.Field. Its only requirements are that it implement a clean() method and that its __init__() method accept the core arguments mentioned above (required, label, initial, widget, help_text).

You can also customize how a field will be accessed by overriding get_bound_field().

Model Form Functions

Model Form API reference. For introductory material about model forms, see the Creating forms from models topic guide.

modelform_factory

modelform_factory(model, form=ModelForm, fields=None, exclude=None, formfield_callback=None, widgets=None, localized_fields=None, labels=None, help_texts=None, error_messages=None, field_classes=None)[source]

Returns a ModelForm class for the given model. You can optionally pass a form argument to use as a starting point for constructing the ModelForm.

fields is an optional list of field names. If provided, only the named fields will be included in the returned fields.

exclude is an optional list of field names. If provided, the named fields will be excluded from the returned fields, even if they are listed in the fields argument.

formfield_callback is a callable that takes a model field and returns a form field.

widgets is a dictionary of model field names mapped to a widget.

localized_fields is a list of names of fields which should be localized.

labels is a dictionary of model field names mapped to a label.

help_texts is a dictionary of model field names mapped to a help text.

error_messages is a dictionary of model field names mapped to a dictionary of error messages.

field_classes is a dictionary of model field names mapped to a form field class.

See ModelForm factory function for example usage.

You must provide the list of fields explicitly, either via keyword arguments fields or exclude, or the corresponding attributes on the form’s inner Meta class. See Selecting the fields to use for more information. Omitting any definition of the fields to use will result in an ImproperlyConfigured exception.

Changed in Django 1.8:
Previously, omitting the list of fields was allowed and resulted in a form with all fields of the model.

New in Django 1.9:
The field_classes keyword argument was added.

modelformset_factory

modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None)[source]

Returns a FormSet class for the given model class.

Arguments model, form, fields, exclude, formfield_callback, widgets, localized_fields, labels, help_texts, error_messages, and field_classes are all passed through to modelform_factory().

Arguments formset, extra, max_num, can_order, can_delete and validate_max are passed through to formset_factory(). See formsets for details.

See Model formsets for example usage.

New in Django 1.9:
The field_classes keyword argument was added.

inlineformset_factory

inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None)[source]

Returns an InlineFormSet using modelformset_factory() with defaults of formset=BaseInlineFormSet, can_delete=True, and extra=3.

If your model has more than one ForeignKey to the parent_model, you must specify a fk_name.

See Inline formsets for example usage.

New in Django 1.9:
The field_classes keyword argument was added.

Formset Functions

Formset API reference. For introductory material about formsets, see the Formsets topic guide.

formset_factory

formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False, min_num=None, validate_min=False)[source]

Returns a FormSet class for the given form class.

See formsets for example usage.

Widgets

A widget is Django’s representation of an HTML input element. The widget handles the rendering of the HTML, and the extraction of data from a GET/POST dictionary that corresponds to the widget.

Tip

Widgets should not be confused with the form fields. Form fields deal with the logic of input validation and are used directly in templates. Widgets deal with rendering of HTML form input elements on the web page and extraction of raw submitted data. However, widgets do need to be assigned to form fields.

Specifying widgets

Whenever you specify a field on a form, Django will use a default widget that is appropriate to the type of data that is to be displayed. To find which widget is used on which field, see the documentation about Built-in Field classes.

However, if you want to use a different widget for a field, you can just use the widget argument on the field definition. For example:

from django import forms

class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)

This would specify a form with a comment that uses a larger Textarea widget, rather than the default TextInput widget.

Setting arguments for widgets

Many widgets have optional extra arguments; they can be set when defining the widget on the field. In the following example, the years attribute is set for a SelectDateWidget:

from django import forms

BIRTH_YEAR_CHOICES = ('1980', '1981', '1982')
FAVORITE_COLORS_CHOICES = (
('blue', 'Blue'),
('green', 'Green'),
('black', 'Black'),
)

class SimpleForm(forms.Form):
birth_year = forms.DateField(widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES))
favorite_colors = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
choices=FAVORITE_COLORS_CHOICES,
)

See the Built-in widgets for more information about which widgets are available and which arguments they accept.

Widgets inheriting from the Select widget

Widgets inheriting from the Select widget deal with choices. They present the user with a list of options to choose from. The different widgets present this choice differently; the Select widget itself uses a <select> HTML list representation, while RadioSelect uses radio buttons.

Select widgets are used by default on ChoiceField fields. The choices displayed on the widget are inherited from the ChoiceField and changing ChoiceField.choices will update Select.choices. For example:

>>> from django import forms
>>> CHOICES = (('1', 'First',), ('2', 'Second',))
>>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
>>> choice_field.choices
[('1', 'First'), ('2', 'Second')]
>>> choice_field.widget.choices
[('1', 'First'), ('2', 'Second')]
>>> choice_field.widget.choices = ()
>>> choice_field.choices = (('1', 'First and only',),)
>>> choice_field.widget.choices
[('1', 'First and only')]

Widgets which offer a choices attribute can however be used with fields which are not based on choice – such as a CharField – but it is recommended to use a ChoiceField-based field when the choices are inherent to the model and not just the representational widget.

Customizing widget instances

When Django renders a widget as HTML, it only renders very minimal markup - Django doesn’t add class names, or any other widget-specific attributes. This means, for example, that all TextInput widgets will appear the same on your Web pages.

There are two ways to customize widgets: per widget instance and per widget class.

Styling widget instances

If you want to make one widget instance look different from another, you will need to specify additional attributes at the time when the widget object is instantiated and assigned to a form field (and perhaps add some rules to your CSS files).

For example, take the following simple form:

from django import forms

class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField()

This form will include three default TextInput widgets, with default rendering – no CSS class, no extra attributes. This means that the input boxes provided for each widget will be rendered exactly the same:

>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
<tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>

On a real Web page, you probably don’t want every widget to look the same. You might want a larger input element for the comment, and you might want the ‘name’ widget to have some special CSS class. It is also possible to specify the ‘type’ attribute to take advantage of the new HTML5 input types. To do this, you use the Widget.attrs argument when creating the widget:

class CommentForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
url = forms.URLField()
comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))

Django will then include the extra attributes in the rendered output:

>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr>
<tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr>

You can also set the HTML id using attrs. See BoundField.id_for_label for an example.

Styling widget classes

With widgets, it is possible to add assets (css and javascript) and more deeply customize their appearance and behavior.

In a nutshell, you will need to subclass the widget and either define a “Media” inner class or create a “media” property.

These methods involve somewhat advanced Python programming and are described in detail in the Form Assets topic guide.

Base widget classes

Base widget classes Widget and MultiWidget are subclassed by all the built-in widgets and may serve as a foundation for custom widgets.

Widget

class Widget(attrs=None)[source]

This abstract class cannot be rendered, but provides the basic attribute attrs. You may also implement or override the render() method on custom widgets.

attrs

A dictionary containing HTML attributes to be set on the rendered widget.

>>> from django import forms
>>> name = forms.TextInput(attrs={'size': 10, 'title': 'Your name',})
>>> name.render('name', 'A name')
'<input title="Your name" type="text" name="name" value="A name" size="10" />'

Changed in Django 1.8:
If you assign a value of True or False to an attribute, it will be rendered as an HTML5 boolean attribute:

>>> name = forms.TextInput(attrs={'required': True})
>>> name.render('name', 'A name')
'<input name="name" type="text" value="A name" required />'
>>>
>>> name = forms.TextInput(attrs={'required': False})
>>> name.render('name', 'A name')
'<input name="name" type="text" value="A name" />'

supports_microseconds

An attribute that defaults to True. If set to False, the microseconds part of datetime and time values will be set to 0.

New in Django 1.9:
In older versions, this attribute was only defined on the date and time widgets (as False).

id_for_label(self, id_)[source]

Returns the HTML ID attribute of this widget for use by a <label>, given the ID of the field. Returns None if an ID isn’t available.

This hook is necessary because some widgets have multiple HTML elements and, thus, multiple IDs. In that case, this method should return an ID value that corresponds to the first ID in the widget’s tags.

render(name, value, attrs=None)[source]

Returns HTML for the widget, as a Unicode string. This method must be implemented by the subclass, otherwise NotImplementedError will be raised.

The ‘value’ given is not guaranteed to be valid input, therefore subclass implementations should program defensively.

value_from_datadict(data, files, name)[source]

Given a dictionary of data and this widget’s name, returns the value of this widget. files may contain data coming from request.FILES. Returns None if a value wasn’t provided. Note also that value_from_datadict may be called more than once during handling of form data, so if you customize it and add expensive processing, you should implement some caching mechanism yourself.

MultiWidget

class MultiWidget(widgets, attrs=None)[source]

A widget that is composed of multiple widgets. MultiWidget works hand in hand with the MultiValueField.

MultiWidget has one required argument:

widgets

An iterable containing the widgets needed.

And one required method:

decompress(value)[source]

This method takes a single “compressed” value from the field and returns a list of “decompressed” values. The input value can be assumed valid, but not necessarily non-empty.

This method must be implemented by the subclass, and since the value may be empty, the implementation must be defensive.

The rationale behind “decompression” is that it is necessary to “split” the combined value of the form field into the values for each widget.

An example of this is how SplitDateTimeWidget turns a datetime value into a list with date and time split into two separate values:

from django.forms import MultiWidget

class SplitDateTimeWidget(MultiWidget):

# ...

def decompress(self, value):
if value:
return [value.date(), value.time().replace(microsecond=0)]
return [None, None]

Tip

Note that MultiValueField has a complementary method compress() with the opposite responsibility - to combine cleaned values of all member fields into one.

Other methods that may be useful to override include:

render(name, value, attrs=None)[source]

Argument value is handled differently in this method from the subclasses of Widget because it has to figure out how to split a single value for display in multiple widgets.

The value argument used when rendering can be one of two things:

- A list.

- A single value (e.g., a string) that is the “compressed” representation of a list of values.

If value is a list, the output of render() will be a concatenation of rendered child widgets. If value is not a list, it will first be processed by the method decompress() to create the list and then rendered.

When render() executes its HTML rendering, each value in the list is rendered with the corresponding widget – the first value is rendered in the first widget, the second value is rendered in the second widget, etc.

Unlike in the single value widgets, method render() need not be implemented in the subclasses.

format_output(rendered_widgets)[source]

Given a list of rendered widgets (as strings), returns a Unicode string representing the HTML for the whole lot.

This hook allows you to format the HTML design of the widgets any way you’d like.

Here’s an example widget which subclasses MultiWidget to display a date with the day, month, and year in different select boxes. This widget is intended to be used with a DateField rather than a MultiValueField, thus we have implemented value_from_datadict():

from datetime import date
from django.forms import widgets

class DateSelectorWidget(widgets.MultiWidget):
def __init__(self, attrs=None):
# create choices for days, months, years
# example below, the rest snipped for brevity.
years = [(year, year) for year in (2011, 2012, 2013)]
_widgets = (
widgets.Select(attrs=attrs, choices=days),
widgets.Select(attrs=attrs, choices=months),
widgets.Select(attrs=attrs, choices=years),
)
super(DateSelectorWidget, self).__init__(_widgets, attrs)

def decompress(self, value):
if value:
return [value.day, value.month, value.year]
return [None, None, None]

def format_output(self, rendered_widgets):
return ''.join(rendered_widgets)

def value_from_datadict(self, data, files, name):
datelist = [
widget.value_from_datadict(data, files, name + '_%s' % i)
for i, widget in enumerate(self.widgets)]
try:
D = date(
day=int(datelist[0]),
month=int(datelist[1]),
year=int(datelist[2]),
)
except ValueError:
return ''
else:
return str(D)

The constructor creates several Select widgets in a tuple. The super class uses this tuple to setup the widget.

The format_output() method is fairly vanilla here (in fact, it’s the same as what’s been implemented as the default for MultiWidget), but the idea is that you could add custom HTML between the widgets should you wish.

The required method decompress() breaks up a datetime.date value into the day, month, and year values corresponding to each widget. Note how the method handles the case where value is None.

The default implementation of value_from_datadict() returns a list of values corresponding to each Widget. This is appropriate when using a MultiWidget with a MultiValueField, but since we want to use this widget with a DateField which takes a single value, we have overridden this method to combine the data of all the subwidgets into a datetime.date. The method extracts data from the POST dictionary and constructs and validates the date. If it is valid, we return the string, otherwise, we return an empty string which will cause form.is_valid to return False.

Built-in widgets

Django provides a representation of all the basic HTML widgets, plus some commonly used groups of widgets in the django.forms.widgets module, including the input of text, various checkboxes and selectors, uploading files, and handling of multi-valued input.

Widgets handling input of text

These widgets make use of the HTML elements input and textarea.

TextInput

class TextInput[source]

Text input: <input type="text" ...>

NumberInput

class NumberInput[source]

Text input: <input type="number" ...>

Beware that not all browsers support entering localized numbers in number input types. Django itself avoids using them for fields having their localize property set to True.

EmailInput

class EmailInput[source]

Text input: <input type="email" ...>

URLInput

class URLInput[source]

Text input: <input type="url" ...>

PasswordInput

class PasswordInput[source]

Password input: <input type='password' ...>

Takes one optional argument:

render_value

Determines whether the widget will have a value filled in when the form is re-displayed after a validation error (default is False).

HiddenInput

class HiddenInput[source]

Hidden input: <input type='hidden' ...>

Note that there also is a MultipleHiddenInput widget that encapsulates a set of hidden input elements.

DateInput

class DateInput[source]

Date input as a simple text box: <input type='text' ...>

Takes same arguments as TextInput, with one more optional argument:

format

The format in which this field’s initial value will be displayed.

If no format argument is provided, the default format is the first format found in DATE_INPUT_FORMATS and respects Format localization.

DateTimeInput

class DateTimeInput[source]

Date/time input as a simple text box: <input type='text' ...>

Takes same arguments as TextInput, with one more optional argument:

format

The format in which this field’s initial value will be displayed.

If no format argument is provided, the default format is the first format found in DATETIME_INPUT_FORMATS and respects Format localization.

By default, the microseconds part of the time value is always set to 0. If microseconds are required, use a subclass with the supports_microseconds attribute set to True.

TimeInput

class TimeInput[source]

Time input as a simple text box: <input type='text' ...>

Takes same arguments as TextInput, with one more optional argument:

format

The format in which this field’s initial value will be displayed.

If no format argument is provided, the default format is the first format found in TIME_INPUT_FORMATS and respects Format localization.

For the treatment of microseconds, see DateTimeInput.

Textarea

class Textarea[source]

Text area: <textarea>...</textarea>

Selector and checkbox widgets

CheckboxInput

class CheckboxInput[source]

Checkbox: <input type='checkbox' ...>

Takes one optional argument:

check_test

A callable that takes the value of the CheckboxInput and returns True if the checkbox should be checked for that value.

Select

class Select[source]

Select widget: <select><option ...>...</select>

choices

This attribute is optional when the form field does not have a choices attribute. If it does, it will override anything you set here when the attribute is updated on the Field.

NullBooleanSelect

class NullBooleanSelect[source]

Select widget with options ‘Unknown’, ‘Yes’ and ‘No’

SelectMultiple

class SelectMultiple[source]

Similar to Select, but allows multiple selection: <select multiple='multiple'>...</select>

RadioSelect

class RadioSelect[source]

Similar to Select, but rendered as a list of radio buttons within <li> tags:

<ul>
<li><input type='radio' name='...'></li>
...
</ul>

For more granular control over the generated markup, you can loop over the radio buttons in the template. Assuming a form myform with a field beatles that uses a RadioSelect as its widget:

{% for radio in myform.beatles %}
<div class="myradio">
{{ radio }}
</div>
{% endfor %}

This would generate the following HTML:

<div class="myradio">
<label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" /> John</label>
</div>
<div class="myradio">
<label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /> Paul</label>
</div>
<div class="myradio">
<label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" /> George</label>
</div>
<div class="myradio">
<label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /> Ringo</label>
</div>

That included the <label> tags. To get more granular, you can use each radio button’s tag, choice_label and id_for_label attributes. For example, this template...

{% for radio in myform.beatles %}
<label for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
<span class="radio">{{ radio.tag }}</span>
</label>
{% endfor %}

...will result in the following HTML:

<label for="id_beatles_0">
John
<span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" /></span>
</label>

<label for="id_beatles_1">
Paul
<span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /></span>
</label>

<label for="id_beatles_2">
George
<span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" /></span>
</label>

<label for="id_beatles_3">
Ringo
<span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /></span>
</label>

If you decide not to loop over the radio buttons – e.g., if your template simply includes {{ myform.beatles }} – they’ll be output in a <ul> with <li> tags, as above.

The outer <ul> container receives the id attribute of the widget, if defined, or BoundField.auto_id otherwise.

When looping over the radio buttons, the label and input tags include for and id attributes, respectively. Each radio button has an id_for_label attribute to output the element’s ID.

CheckboxSelectMultiple

class CheckboxSelectMultiple[source]

Similar to SelectMultiple, but rendered as a list of check buttons:

<ul>
<li><input type='checkbox' name='...' ></li>
...
</ul>

The outer <ul> container receives the id attribute of the widget, if defined, or BoundField.auto_id otherwise.

Like RadioSelect, you can now loop over the individual checkboxes making up the lists. See the documentation of RadioSelect for more details.

When looping over the checkboxes, the label and input tags include for and id attributes, respectively. Each checkbox has an id_for_label attribute to output the element’s ID.

File upload widgets

FileInput

class FileInput[source]

File upload input: <input type='file' ...>

ClearableFileInput

class ClearableFileInput[source]

File upload input: <input type='file' ...>, with an additional checkbox input to clear the field’s value, if the field is not required and has initial data.

Composite widgets

MultipleHiddenInput

class MultipleHiddenInput[source]

Multiple <input type='hidden' ...> widgets.

A widget that handles multiple hidden widgets for fields that have a list of values.

choices

This attribute is optional when the form field does not have a choices attribute. If it does, it will override anything you set here when the attribute is updated on the Field.

SplitDateTimeWidget

class SplitDateTimeWidget[source]

Wrapper (using MultiWidget) around two widgets: DateInput for the date, and TimeInput for the time. Must be used with SplitDateTimeField rather than DateTimeField.

SplitDateTimeWidget has two optional attributes:

date_format

Similar to DateInput.format

time_format

Similar to TimeInput.format

SplitHiddenDateTimeWidget

class SplitHiddenDateTimeWidget[source]

Similar to SplitDateTimeWidget, but uses HiddenInput for both date and time.

SelectDateWidget

class SelectDateWidget[source]

Wrapper around three Select widgets: one each for month, day, and year.

Takes several optional arguments:

years

An optional list/tuple of years to use in the “year” select box. The default is a list containing the current year and the next 9 years.

months

An optional dict of months to use in the “months” select box.

The keys of the dict correspond to the month number (1-indexed) and the values are the displayed months:

MONTHS = {
1:_('jan'), 2:_('feb'), 3:_('mar'), 4:_('apr'),
5:_('may'), 6:_('jun'), 7:_('jul'), 8:_('aug'),
9:_('sep'), 10:_('oct'), 11:_('nov'), 12:_('dec')
}

empty_label

New in Django 1.8.

If the DateField is not required, SelectDateWidget will have an empty choice at the top of the list (which is --- by default). You can change the text of this label with the empty_label attribute. empty_label can be a string, list, or tuple. When a string is used, all select boxes will each have an empty choice with this label. If empty_label is a list or tuple of 3 string elements, the select boxes will have their own custom label. The labels should be in this order ('year_label', 'month_label', 'day_label').

# A custom empty label with string
field1 = forms.DateField(widget=SelectDateWidget(empty_label="Nothing"))

# A custom empty label with tuple
field1 = forms.DateField(
widget=SelectDateWidget(
empty_label=("Choose Year", "Choose Month", "Choose Day"),
),
)

Changed in Django 1.9:
This widget used to be located in the django.forms.extras.widgets package. It is now defined in django.forms.widgets and like the other widgets it can be imported directly from django.forms.

Form and field validation

Form validation happens when the data is cleaned. If you want to customize this process, there are various places to make changes, each one serving a different purpose. Three types of cleaning methods are run during form processing. These are normally executed when you call the is_valid() method on a form. There are other things that can also trigger cleaning and validation (accessing the errors attribute or calling full_clean() directly), but normally they won’t be needed.

In general, any cleaning method can raise ValidationError if there is a problem with the data it is processing, passing the relevant information to the ValidationError constructor. See below for the best practice in raising ValidationError. If no ValidationError is raised, the method should return the cleaned (normalized) data as a Python object.

Most validation can be done using validators - simple helpers that can be reused easily. Validators are simple functions (or callables) that take a single argument and raise ValidationError on invalid input. Validators are run after the field’s to_python and validate methods have been called.

Validation of a form is split into several steps, which can be customized or overridden:

- The to_python() method on a Field is the first step in every validation. It coerces the value to a correct datatype and raises ValidationError if that is not possible. This method accepts the raw value from the widget and returns the converted value. For example, a FloatField will turn the data into a Python float or raise a ValidationError.

- The validate() method on a Field handles field-specific validation that is not suitable for a validator. It takes a value that has been coerced to a correct datatype and raises ValidationError on any error. This method does not return anything and shouldn’t alter the value. You should override it to handle validation logic that you can’t or don’t want to put in a validator.

- The run_validators() method on a Field runs all of the field’s validators and aggregates all the errors into a single ValidationError. You shouldn’t need to override this method.

- The clean() method on a Field subclass is responsible for running to_python(), validate(), and run_validators() in the correct order and propagating their errors. If, at any time, any of the methods raise ValidationError, the validation stops and that error is raised. This method returns the clean data, which is then inserted into the cleaned_data dictionary of the form.

- The clean_<fieldname>() method is called on a form subclass – where <fieldname> is replaced with the name of the form field attribute. This method does any cleaning that is specific to that particular attribute, unrelated to the type of field that it is. This method is not passed any parameters. You will need to look up the value of the field in self.cleaned_data and remember that it will be a Python object at this point, not the original string submitted in the form (it will be in cleaned_data because the general field clean() method, above, has already cleaned the data once).

For example, if you wanted to validate that the contents of a CharField called serialnumber was unique, clean_serialnumber() would be the right place to do this. You don’t need a specific field (it’s just a CharField), but you want a formfield-specific piece of validation and, possibly, cleaning/normalizing the data.

This method should return the cleaned value obtained from cleaned_data, regardless of whether it changed anything or not.

- The form subclass’s clean() method can perform validation that requires access to multiple form fields. This is where you might put in checks such as “if field A is supplied, field B must contain a valid email address”. This method can return a completely different dictionary if it wishes, which will be used as the cleaned_data.

Since the field validation methods have been run by the time clean() is called, you also have access to the form’s errors attribute which contains all the errors raised by cleaning of individual fields.

Note that any errors raised by your Form.clean() override will not be associated with any field in particular. They go into a special “field” (called __all__), which you can access via the non_field_errors() method if you need to. If you want to attach errors to a specific field in the form, you need to call add_error().

Also note that there are special considerations when overriding the clean() method of a ModelForm subclass. (see the ModelForm documentation for more information)

These methods are run in the order given above, one field at a time. That is, for each field in the form (in the order they are declared in the form definition), the Field.clean() method (or its override) is run, then clean_<fieldname>(). Finally, once those two methods are run for every field, the Form.clean() method, or its override, is executed whether or not the previous methods have raised errors.

Examples of each of these methods are provided below.

As mentioned, any of these methods can raise a ValidationError. For any field, if the Field.clean() method raises a ValidationError, any field-specific cleaning method is not called. However, the cleaning methods for all remaining fields are still executed.

Raising ValidationError

In order to make error messages flexible and easy to override, consider the following guidelines:

- Provide a descriptive error code to the constructor:

# Good
ValidationError(_('Invalid value'), code='invalid')

# Bad
ValidationError(_('Invalid value'))

- Don’t coerce variables into the message; use placeholders and the params argument of the constructor:

# Good
ValidationError(
_('Invalid value: %(value)s'),
params={'value': '42'},
)

# Bad
ValidationError(_('Invalid value: %s') % value)

- Use mapping keys instead of positional formatting. This enables putting the variables in any order or omitting them altogether when rewriting the message:

# Good
ValidationError(
_('Invalid value: %(value)s'),
params={'value': '42'},
)

# Bad
ValidationError(
_('Invalid value: %s'),
params=('42',),
)

- Wrap the message with gettext to enable translation:

# Good
ValidationError(_('Invalid value'))

# Bad
ValidationError('Invalid value')

Putting it all together:

raise ValidationError(
_('Invalid value: %(value)s'),
code='invalid',
params={'value': '42'},
)

Following these guidelines is particularly necessary if you write reusable forms, form fields, and model fields.

While not recommended, if you are at the end of the validation chain (i.e. your form clean() method) and you know you will never need to override your error message you can still opt for the less verbose:

ValidationError(_('Invalid value: %s') % value)

The Form.errors.as_data() and Form.errors.as_json() methods greatly benefit from fully featured ValidationErrors (with a code name and a params dictionary).

Raising multiple errors

If you detect multiple errors during a cleaning method and wish to signal all of them to the form submitter, it is possible to pass a list of errors to the ValidationError constructor.

As above, it is recommended to pass a list of ValidationError instances with codes and params but a list of strings will also work:

# Good
raise ValidationError([
ValidationError(_('Error 1'), code='error1'),
ValidationError(_('Error 2'), code='error2'),
])

# Bad
raise ValidationError([
_('Error 1'),
_('Error 2'),
])

Using validation in practice

The previous sections explained how validation works in general for forms. Since it can sometimes be easier to put things into place by seeing each feature in use, here are a series of small examples that use each of the previous features.

Using validators

Django’s form (and model) fields support use of simple utility functions and classes known as validators. A validator is merely a callable object or function that takes a value and simply returns nothing if the value is valid or raises a ValidationError if not. These can be passed to a field’s constructor, via the field’s validators argument, or defined on the Field class itself with the default_validators attribute.

Simple validators can be used to validate values inside the field, let’s have a look at Django’s SlugField:

from django.forms import CharField
from django.core import validators

class SlugField(CharField):
default_validators = [validators.validate_slug]

As you can see, SlugField is just a CharField with a customized validator that validates that submitted text obeys to some character rules. This can also be done on field definition so:

slug = forms.SlugField()

is equivalent to:

slug = forms.CharField(validators=[validators.validate_slug])

Common cases such as validating against an email or a regular expression can be handled using existing validator classes available in Django. For example, validators.validate_slug is an instance of a RegexValidator constructed with the first argument being the pattern: ^[-a-zA-Z0-9_]+$. See the section on writing validators to see a list of what is already available and for an example of how to write a validator.

Form field default cleaning

Let’s first create a custom form field that validates its input is a string containing comma-separated email addresses. The full class looks like this:

from django import forms
from django.core.validators import validate_email

class MultiEmailField(forms.Field):
def to_python(self, value):
"""Normalize data to a list of strings."""
# Return an empty list if no input was given.
if not value:
return []
return value.split(',')

def validate(self, value):
"""Check if value consists only of valid emails."""
# Use the parent's handling of required fields, etc.
super(MultiEmailField, self).validate(value)
for email in value:
validate_email(email)

Every form that uses this field will have these methods run before anything else can be done with the field’s data. This is cleaning that is specific to this type of field, regardless of how it is subsequently used.

Let’s create a simple ContactForm to demonstrate how you’d use this field:

class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
recipients = MultiEmailField()
cc_myself = forms.BooleanField(required=False)

Simply use MultiEmailField like any other form field. When the is_valid() method is called on the form, the MultiEmailField.clean() method will be run as part of the cleaning process and it will, in turn, call the custom to_python() and validate() methods.

Cleaning a specific field attribute

Continuing on from the previous example, suppose that in our ContactForm, we want to make sure that the recipients field always contains the address "fred@example.com". This is validation that is specific to our form, so we don’t want to put it into the general MultiEmailField class. Instead, we write a cleaning method that operates on the recipients field, like so:

from django import forms

class ContactForm(forms.Form):
# Everything as before.
...

def clean_recipients(self):
data = self.cleaned_data['recipients']
if "fred@example.com" not in data:
raise forms.ValidationError("You have forgotten about Fred!")

# Always return the cleaned data, whether you have changed it or
# not.
return data

Cleaning and validating fields that depend on each other

Suppose we add another requirement to our contact form: if the cc_myself field is True, the subject must contain the word "help". We are performing validation on more than one field at a time, so the form’s clean() method is a good spot to do this. Notice that we are talking about the clean() method on the form here, whereas earlier we were writing a clean() method on a field. It’s important to keep the field and form difference clear when working out where to validate things. Fields are single data points, forms are a collection of fields.

By the time the form’s clean() method is called, all the individual field clean methods will have been run (the previous two sections), so self.cleaned_data will be populated with any data that has survived so far. So you also need to remember to allow for the fact that the fields you are wanting to validate might not have survived the initial individual field checks.

There are two ways to report any errors from this step. Probably the most common method is to display the error at the top of the form. To create such an error, you can raise a ValidationError from the clean() method. For example:

from django import forms

class ContactForm(forms.Form):
# Everything as before.
...

def clean(self):
cleaned_data = super(ContactForm, self).clean()
cc_myself = cleaned_data.get("cc_myself")
subject = cleaned_data.get("subject")

if cc_myself and subject:
# Only do something if both fields are valid so far.
if "help" not in subject:
raise forms.ValidationError(
"Did not send for 'help' in the subject despite "
"CC'ing yourself."
)

In this code, if the validation error is raised, the form will display an error message at the top of the form (normally) describing the problem.

The call to super(ContactForm, self).clean() in the example code ensures that any validation logic in parent classes is maintained. If your form inherits another that doesn’t return a cleaned_data dictionary in its clean() method (doing so is optional), then don’t assign cleaned_data to the result of the super() call and use self.cleaned_data instead:

def clean(self):
super(ContactForm, self).clean()
cc_myself = self.cleaned_data.get("cc_myself")
...

The second approach for reporting validation errors might involve assigning the error message to one of the fields. In this case, let’s assign an error message to both the “subject” and “cc_myself” rows in the form display. Be careful when doing this in practice, since it can lead to confusing form output. We’re showing what is possible here and leaving it up to you and your designers to work out what works effectively in your particular situation. Our new code (replacing the previous sample) looks like this:

from django import forms

class ContactForm(forms.Form):
# Everything as before.
...

def clean(self):
cleaned_data = super(ContactForm, self).clean()
cc_myself = cleaned_data.get("cc_myself")
subject = cleaned_data.get("subject")

if cc_myself and subject and "help" not in subject:
msg = "Must put 'help' in subject when cc'ing yourself."
self.add_error('cc_myself', msg)
self.add_error('subject', msg)

The second argument of add_error() can be a simple string, or preferably an instance of ValidationError. See Raising ValidationError for more details. Note that add_error() automatically removes the field from cleaned_data.

Middleware

This document explains all middleware components that come with Django. For information on how to use them and how to write your own middleware, see the middleware usage guide.

Available middleware

Cache middleware

class UpdateCacheMiddleware[source]

class FetchFromCacheMiddleware[source]

Enable the site-wide cache. If these are enabled, each Django-powered page will be cached for as long as the CACHE_MIDDLEWARE_SECONDS setting defines. See the cache documentation.

“Common” middleware

class CommonMiddleware[source]

Adds a few conveniences for perfectionists:

- Forbids access to user agents in the DISALLOWED_USER_AGENTS setting, which should be a list of compiled regular expression objects.

- Performs URL rewriting based on the APPEND_SLASH and PREPEND_WWW settings.

If APPEND_SLASH is True and the initial URL doesn’t end with a slash, and it is not found in the URLconf, then a new URL is formed by appending a slash at the end. If this new URL is found in the URLconf, then Django redirects the request to this new URL. Otherwise, the initial URL is processed as usual.

For example, foo.com/bar will be redirected to foo.com/bar/ if you don’t have a valid URL pattern for foo.com/bar but do have a valid pattern for foo.com/bar/.

If PREPEND_WWW is True, URLs that lack a leading “www.” will be redirected to the same URL with a leading “www.”

Both of these options are meant to normalize URLs. The philosophy is that each URL should exist in one, and only one, place. Technically a URL foo.com/bar is distinct from foo.com/bar/ – a search-engine indexer would treat them as separate URLs – so it’s best practice to normalize URLs.

- Handles ETags based on the USE_ETAGS setting. If USE_ETAGS is set to True, Django will calculate an ETag for each request by MD5-hashing the page content, and it’ll take care of sending Not Modified responses, if appropriate.

CommonMiddleware.response_redirect_class

New in Django 1.8.

Defaults to HttpResponsePermanentRedirect. Subclass CommonMiddleware and override the attribute to customize the redirects issued by the middleware.

class BrokenLinkEmailsMiddleware[source]

- Sends broken link notification emails to MANAGERS (see Error reporting).

GZip middleware

class GZipMiddleware[source]

Warning

Security researchers recently revealed that when compression techniques (including GZipMiddleware) are used on a website, the site becomes exposed to a number of possible attacks. These approaches can be used to compromise, among other things, Django’s CSRF protection. Before using GZipMiddleware on your site, you should consider very carefully whether you are subject to these attacks. If you’re in any doubt about whether you’re affected, you should avoid using GZipMiddleware. For more details, see the the BREACH paper (PDF) and breachattack.com.

Compresses content for browsers that understand GZip compression (all modern browsers).

This middleware should be placed before any other middleware that need to read or write the response body so that compression happens afterward.

It will NOT compress content if any of the following are true:

- The content body is less than 200 bytes long.

- The response has already set the Content-Encoding header.

- The request (the browser) hasn’t sent an Accept-Encoding header containing gzip.

You can apply GZip compression to individual views using the gzip_page() decorator.

Conditional GET middleware

class ConditionalGetMiddleware[source]

Handles conditional GET operations. If the response has a ETag or Last-Modified header, and the request has If-None-Match or If-Modified-Since, the response is replaced by an HttpResponseNotModified.

Also sets the Date and Content-Length response-headers.

Locale middleware

class LocaleMiddleware[source]

Enables language selection based on data from the request. It customizes content for each user. See the internationalization documentation.

LocaleMiddleware.response_redirect_class

Defaults to HttpResponseRedirect. Subclass LocaleMiddleware and override the attribute to customize the redirects issued by the middleware.

Message middleware

class MessageMiddleware[source]

Enables cookie- and session-based message support. See the messages documentation.

Security middleware

Warning

If your deployment situation allows, it’s usually a good idea to have your front-end Web server perform the functionality provided by the SecurityMiddleware. That way, if there are requests that aren’t served by Django (such as static media or user-uploaded files), they will have the same protections as requests to your Django application.

class SecurityMiddleware[source]

New in Django 1.8.

The django.middleware.security.SecurityMiddleware provides several security enhancements to the request/response cycle. Each one can be independently enabled or disabled with a setting.

- SECURE_BROWSER_XSS_FILTER

- SECURE_CONTENT_TYPE_NOSNIFF

- SECURE_HSTS_INCLUDE_SUBDOMAINS

- SECURE_HSTS_SECONDS

- SECURE_REDIRECT_EXEMPT

- SECURE_SSL_HOST

- SECURE_SSL_REDIRECT

HTTP Strict Transport Security

For sites that should only be accessed over HTTPS, you can instruct modern browsers to refuse to connect to your domain name via an insecure connection (for a given period of time) by setting the “Strict-Transport-Security” header. This reduces your exposure to some SSL-stripping man-in-the-middle (MITM) attacks.

SecurityMiddleware will set this header for you on all HTTPS responses if you set the SECURE_HSTS_SECONDS setting to a non-zero integer value.

When enabling HSTS, it’s a good idea to first use a small value for testing, for example, SECURE_HSTS_SECONDS = 3600 for one hour. Each time a Web browser sees the HSTS header from your site, it will refuse to communicate non-securely (using HTTP) with your domain for the given period of time. Once you confirm that all assets are served securely on your site (i.e. HSTS didn’t break anything), it’s a good idea to increase this value so that infrequent visitors will be protected (31536000 seconds, i.e. 1 year, is common).

Additionally, if you set the SECURE_HSTS_INCLUDE_SUBDOMAINS setting to True, SecurityMiddleware will add the includeSubDomains tag to the Strict-Transport-Security header. This is recommended (assuming all subdomains are served exclusively using HTTPS), otherwise your site may still be vulnerable via an insecure connection to a subdomain.

Warning

The HSTS policy applies to your entire domain, not just the URL of the response that you set the header on. Therefore, you should only use it if your entire domain is served via HTTPS only.

Browsers properly respecting the HSTS header will refuse to allow users to bypass warnings and connect to a site with an expired, self-signed, or otherwise invalid SSL certificate. If you use HSTS, make sure your certificates are in good shape and stay that way!

Note

If you are deployed behind a load-balancer or reverse-proxy server, and the Strict-Transport-Security header is not being added to your responses, it may be because Django doesn’t realize that it’s on a secure connection; you may need to set the SECURE_PROXY_SSL_HEADER setting.

X-Content-Type-Options: nosniff

Some browsers will try to guess the content types of the assets that they fetch, overriding the Content-Type header. While this can help display sites with improperly configured servers, it can also pose a security risk.

If your site serves user-uploaded files, a malicious user could upload a specially-crafted file that would be interpreted as HTML or JavaScript by the browser when you expected it to be something harmless.

To learn more about this header and how the browser treats it, you can read about it on the IE Security Blog.

To prevent the browser from guessing the content type and force it to always use the type provided in the Content-Type header, you can pass the X-Content-Type-Options: nosniff header. SecurityMiddleware will do this for all responses if the SECURE_CONTENT_TYPE_NOSNIFF setting is True.

Note that in most deployment situations where Django isn’t involved in serving user-uploaded files, this setting won’t help you. For example, if your MEDIA_URL is served directly by your front-end Web server (nginx, Apache, etc.) then you’d want to set this header there. On the other hand, if you are using Django to do something like require authorization in order to download files and you cannot set the header using your Web server, this setting will be useful.

X-XSS-Protection: 1; mode=block

Some browsers have the ability to block content that appears to be an XSS attack. They work by looking for JavaScript content in the GET or POST parameters of a page. If the JavaScript is replayed in the server’s response, the page is blocked from rendering and an error page is shown instead.

The X-XSS-Protection header is used to control the operation of the XSS filter.

To enable the XSS filter in the browser, and force it to always block suspected XSS attacks, you can pass the X-XSS-Protection: 1; mode=block header. SecurityMiddleware will do this for all responses if the SECURE_BROWSER_XSS_FILTER setting is True.

Warning

The browser XSS filter is a useful defense measure, but must not be relied upon exclusively. It cannot detect all XSS attacks and not all browsers support the header. Ensure you are still validating and sanitizing all input to prevent XSS attacks.

SSL Redirect

If your site offers both HTTP and HTTPS connections, most users will end up with an unsecured connection by default. For best security, you should redirect all HTTP connections to HTTPS.

If you set the SECURE_SSL_REDIRECT setting to True, SecurityMiddleware will permanently (HTTP 301) redirect all HTTP connections to HTTPS.

Note

For performance reasons, it’s preferable to do these redirects outside of Django, in a front-end load balancer or reverse-proxy server such as nginx. SECURE_SSL_REDIRECT is intended for the deployment situations where this isn’t an option.

If the SECURE_SSL_HOST setting has a value, all redirects will be sent to that host instead of the originally-requested host.

If there are a few pages on your site that should be available over HTTP, and not redirected to HTTPS, you can list regular expressions to match those URLs in the SECURE_REDIRECT_EXEMPT setting.

Note

If you are deployed behind a load-balancer or reverse-proxy server and Django can’t seem to tell when a request actually is already secure, you may need to set the SECURE_PROXY_SSL_HEADER setting.

Session middleware

class SessionMiddleware[source]

Enables session support. See the session documentation.

Site middleware

class CurrentSiteMiddleware[source]

Adds the site attribute representing the current site to every incoming HttpRequest object. See the sites documentation.

Authentication middleware

class AuthenticationMiddleware

Adds the user attribute, representing the currently-logged-in user, to every incoming HttpRequest object. See Authentication in Web requests.

class RemoteUserMiddleware

Middleware for utilizing Web server provided authentication. See Authentication using REMOTE_USER for usage details.

class PersistentRemoteUserMiddleware

New in Django 1.9.

Middleware for utilizing Web server provided authentication when enabled only on the login page. See Using REMOTE_USER on login pages only for usage details.

class SessionAuthenticationMiddleware

Allows a user’s sessions to be invalidated when their password changes. See Session invalidation on password change for details. This middleware must appear after django.contrib.auth.middleware.AuthenticationMiddleware in MIDDLEWARE_CLASSES.

CSRF protection middleware

class CsrfViewMiddleware[source]

Adds protection against Cross Site Request Forgeries by adding hidden form fields to POST forms and checking requests for the correct value. See the Cross Site Request Forgery protection documentation.

X-Frame-Options middleware

class XFrameOptionsMiddleware[source]

Simple clickjacking protection via the X-Frame-Options header.

Middleware ordering

Here are some hints about the ordering of various Django middleware classes:

1. SecurityMiddleware

It should go near the top of the list if you’re going to turn on the SSL redirect as that avoids running through a bunch of other unnecessary middleware.

2. UpdateCacheMiddleware

Before those that modify the Vary header (SessionMiddleware, GZipMiddleware, LocaleMiddleware).

3. GZipMiddleware

Before any middleware that may change or use the response body.

After UpdateCacheMiddleware: Modifies Vary header.

4. ConditionalGetMiddleware

Before CommonMiddleware: uses its Etag header when USE_ETAGS = True.

5. SessionMiddleware

After UpdateCacheMiddleware: Modifies Vary header.

6. LocaleMiddleware

One of the topmost, after SessionMiddleware (uses session data) and UpdateCacheMiddleware (modifies Vary header).

7. CommonMiddleware

Before any middleware that may change the response (it calculates ETags).

After GZipMiddleware so it won’t calculate an ETag header on gzipped contents.

Close to the top: it redirects when APPEND_SLASH or PREPEND_WWW are set to True.

8. CsrfViewMiddleware

Before any view middleware that assumes that CSRF attacks have been dealt with.

9. AuthenticationMiddleware

After SessionMiddleware: uses session storage.

10. MessageMiddleware

After SessionMiddleware: can use session-based storage.

11. FetchFromCacheMiddleware

After any middleware that modifies the Vary header: that header is used to pick a value for the cache hash-key.

12. FlatpageFallbackMiddleware

Should be near the bottom as it’s a last-resort type of middleware.

13. RedirectFallbackMiddleware

Should be near the bottom as it’s a last-resort type of middleware.

Migration Operations

Migration files are composed of one or more Operations, objects that declaratively record what the migration should do to your database.

Django also uses these Operation objects to work out what your models looked like historically, and to calculate what changes you’ve made to your models since the last migration so it can automatically write your migrations; that’s why they’re declarative, as it means Django can easily load them all into memory and run through them without touching the database to work out what your project should look like.

There are also more specialized Operation objects which are for things like data migrations and for advanced manual database manipulation. You can also write your own Operation classes if you want to encapsulate a custom change you commonly make.

If you need an empty migration file to write your own Operation objects into, just use python manage.py makemigrations --empty yourappname, but be aware that manually adding schema-altering operations can confuse the migration autodetector and make resulting runs of makemigrations output incorrect code.

All of the core Django operations are available from the django.db.migrations.operations module.

For introductory material, see the migrations topic guide.

Schema Operations

CreateModel

class CreateModel(name, fields, options=None, bases=None, managers=None)[source]

Creates a new model in the project history and a corresponding table in the database to match it.

name is the model name, as would be written in the models.py file.

fields is a list of 2-tuples of (field_name, field_instance). The field instance should be an unbound field (so just models.CharField(...), rather than a field taken from another model).

options is an optional dictionary of values from the model’s Meta class.

bases is an optional list of other classes to have this model inherit from; it can contain both class objects as well as strings in the format "appname.ModelName" if you want to depend on another model (so you inherit from the historical version). If it’s not supplied, it defaults to just inheriting from the standard models.Model.

managers takes a list of 2-tuples of (manager_name, manager_instance). The first manager in the list will be the default manager for this model during migrations.

Changed in Django 1.8:
The managers argument was added.

DeleteModel

class DeleteModel(name)[source]

Deletes the model from the project history and its table from the database.

RenameModel

class RenameModel(old_name, new_name)[source]

Renames the model from an old name to a new one.

You may have to manually add this if you change the model’s name and quite a few of its fields at once; to the autodetector, this will look like you deleted a model with the old name and added a new one with a different name, and the migration it creates will lose any data in the old table.

AlterModelTable

class AlterModelTable(name, table)[source]

Changes the model’s table name (the db_table option on the Meta subclass).

AlterUniqueTogether

class AlterUniqueTogether(name, unique_together)[source]

Changes the model’s set of unique constraints (the unique_together option on the Meta subclass).

AlterIndexTogether

class AlterIndexTogether(name, index_together)[source]

Changes the model’s set of custom indexes (the index_together option on the Meta subclass).

AlterOrderWithRespectTo

class AlterOrderWithRespectTo(name, order_with_respect_to)[source]

Makes or deletes the _order column needed for the order_with_respect_to option on the Meta subclass.

AlterModelOptions

class AlterModelOptions(name, options)[source]

Stores changes to miscellaneous model options (settings on a model’s Meta) like permissions and verbose_name. Does not affect the database, but persists these changes for RunPython instances to use. options should be a dictionary mapping option names to values.

AlterModelManagers

New in Django 1.8.

class AlterModelManagers(name, managers)[source]

Alters the managers that are available during migrations.

AddField

class AddField(model_name, name, field, preserve_default=True)[source]

Adds a field to a model. model_name is the model’s name, name is the field’s name, and field is an unbound Field instance (the thing you would put in the field declaration in models.py - for example, models.IntegerField(null=True).

The preserve_default argument indicates whether the field’s default value is permanent and should be baked into the project state (True), or if it is temporary and just for this migration (False) - usually because the migration is adding a non-nullable field to a table and needs a default value to put into existing rows. It does not affect the behavior of setting defaults in the database directly - Django never sets database defaults and always applies them in the Django ORM code.

RemoveField

class RemoveField(model_name, name)[source]

Removes a field from a model.

Bear in mind that when reversed, this is actually adding a field to a model. The operation is reversible (apart from any data loss, which of course is irreversible) if the field is nullable or if it has a default value that can be used to populate the recreated column. If the field is not nullable and does not have a default value, the operation is irreversible.

AlterField

class AlterField(model_name, name, field, preserve_default=True)[source]

Alters a field’s definition, including changes to its type, null, unique, db_column and other field attributes.

The preserve_default argument indicates whether the field’s default value is permanent and should be baked into the project state (True), or if it is temporary and just for this migration (False) - usually because the migration is altering a nullable field to a non-nullable one and needs a default value to put into existing rows. It does not affect the behavior of setting defaults in the database directly - Django never sets database defaults and always applies them in the Django ORM code.

Note that not all changes are possible on all databases - for example, you cannot change a text-type field like models.TextField() into a number-type field like models.IntegerField() on most databases.

RenameField

class RenameField(model_name, old_name, new_name)[source]

Changes a field’s name (and, unless db_column is set, its column name).

Special Operations

RunSQL

class RunSQL(sql, reverse_sql=None, state_operations=None, hints=None)[source]

Allows running of arbitrary SQL on the database - useful for more advanced features of database backends that Django doesn’t support directly, like partial indexes.

sql, and reverse_sql if provided, should be strings of SQL to run on the database. On most database backends (all but PostgreSQL), Django will split the SQL into individual statements prior to executing them. This requires installing the sqlparse Python library.

You can also pass a list of strings or 2-tuples. The latter is used for passing queries and parameters in the same way as cursor.execute(). These three operations are equivalent:

migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
migrations.RunSQL([("INSERT INTO musician (name) VALUES ('Reinhardt');", None)])
migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])])

If you want to include literal percent signs in the query, you have to double them if you are passing parameters.

The reverse_sql queries are executed when the migration is unapplied, so you can reverse the changes done in the forwards queries:

migrations.RunSQL(
[("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])],
[("DELETE FROM musician where name=%s;", ['Reinhardt'])],
)

The state_operations argument is so you can supply operations that are equivalent to the SQL in terms of project state; for example, if you are manually creating a column, you should pass in a list containing an AddField operation here so that the autodetector still has an up-to-date state of the model (otherwise, when you next run makemigrations, it won’t see any operation that adds that field and so will try to run it again). For example:

migrations.RunSQL(
"ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
state_operations=[
migrations.AddField(
'musician',
'name',
models.CharField(max_length=255),
),
],
)

The optional hints argument will be passed as **hints to the allow_migrate() method of database routers to assist them in making routing decisions. See Hints for more details on database hints.

Changed in Django 1.8:
The ability to pass parameters to the sql and reverse_sql queries was added.

The hints argument was added.

RunSQL.noop

New in Django 1.8.

Pass the RunSQL.noop attribute to sql or reverse_sql when you want the operation not to do anything in the given direction. This is especially useful in making the operation reversible.

RunPython

class RunPython(code, reverse_code=None, atomic=True, hints=None)[source]

Runs custom Python code in a historical context. code (and reverse_code if supplied) should be callable objects that accept two arguments; the first is an instance of django.apps.registry.Apps containing historical models that match the operation’s place in the project history, and the second is an instance of SchemaEditor.

The reverse_code argument is called when unapplying migrations. This callable should undo what is done in the code callable so that the migration is reversible.

The optional hints argument will be passed as **hints to the allow_migrate() method of database routers to assist them in making a routing decision. See Hints for more details on database hints.

New in Django 1.8:
The hints argument was added.

You are advised to write the code as a separate function above the Migration class in the migration file, and just pass it to RunPython. Here’s an example of using RunPython to create some initial objects on a Country model:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])

def reverse_func(apps, schema_editor):
# forwards_func() creates two Country instances,
# so reverse_func() should delete them.
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).filter(name="USA", code="us").delete()
Country.objects.using(db_alias).filter(name="France", code="fr").delete()

class Migration(migrations.Migration):

dependencies = []

operations = [
migrations.RunPython(forwards_func, reverse_func),
]

This is generally the operation you would use to create data migrations, run custom data updates and alterations, and anything else you need access to an ORM and/or Python code for.

If you’re upgrading from South, this is basically the South pattern as an operation - one or two methods for forwards and backwards, with an ORM and schema operations available. Most of the time, you should be able to translate the orm.Model or orm["appname", "Model"] references from South directly into apps.get_model("appname", "Model") references here and leave most of the rest of the code unchanged for data migrations. However, apps will only have references to models in the current app unless migrations in other apps are added to the migration’s dependencies.

Much like RunSQL, ensure that if you change schema inside here you’re either doing it outside the scope of the Django model system (e.g. triggers) or that you use SeparateDatabaseAndState to add in operations that will reflect your changes to the model state - otherwise, the versioned ORM and the autodetector will stop working correctly.

By default, RunPython will run its contents inside a transaction on databases that do not support DDL transactions (for example, MySQL and Oracle). This should be safe, but may cause a crash if you attempt to use the schema_editor provided on these backends; in this case, pass atomic=False to the RunPython operation.

On databases that do support DDL transactions (SQLite and PostgreSQL), RunPython operations do not have any transactions automatically added besides the transactions created for each migration (the atomic parameter has no effect on these databases). Thus, on PostgreSQL, for example, you should avoid combining schema changes and RunPython operations in the same migration or you may hit errors like OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events.

If you have a different database and aren’t sure if it supports DDL transactions, check the django.db.connection.features.can_rollback_ddl attribute.

Warning

RunPython does not magically alter the connection of the models for you; any model methods you call will go to the default database unless you give them the current database alias (available from schema_editor.connection.alias, where schema_editor is the second argument to your function).

static RunPython.noop()[source]

New in Django 1.8.

Pass the RunPython.noop method to code or reverse_code when you want the operation not to do anything in the given direction. This is especially useful in making the operation reversible.

SeparateDatabaseAndState

class SeparateDatabaseAndState(database_operations=None, state_operations=None)[source]

A highly specialized operation that let you mix and match the database (schema-changing) and state (autodetector-powering) aspects of operations.

It accepts two list of operations, and when asked to apply state will use the state list, and when asked to apply changes to the database will use the database list. Do not use this operation unless you’re very sure you know what you’re doing.

Writing your own

Operations have a relatively simple API, and they’re designed so that you can easily write your own to supplement the built-in Django ones. The basic structure of an Operation looks like this:

from django.db.migrations.operations.base import Operation

class MyCustomOperation(Operation):

# If this is False, it means that this operation will be ignored by
# sqlmigrate; if true, it will be run and the SQL collected for its output.
reduces_to_sql = False

# If this is False, Django will refuse to reverse past this operation.
reversible = False

def __init__(self, arg1, arg2):
# Operations are usually instantiated with arguments in migration
# files. Store the values of them on self for later use.
pass

def state_forwards(self, app_label, state):
# The Operation should take the 'state' parameter (an instance of
# django.db.migrations.state.ProjectState) and mutate it to match
# any schema changes that have occurred.
pass

def database_forwards(self, app_label, schema_editor, from_state, to_state):
# The Operation should use schema_editor to apply any changes it
# wants to make to the database.
pass

def database_backwards(self, app_label, schema_editor, from_state, to_state):
# If reversible is True, this is called when the operation is reversed.
pass

def describe(self):
# This is used to describe what the operation does in console output.
return "Custom Operation"

You can take this template and work from it, though we suggest looking at the built-in Django operations in django.db.migrations.operations - they’re easy to read and cover a lot of the example usage of semi-internal aspects of the migration framework like ProjectState and the patterns used to get historical models, as well as ModelState and the patterns used to mutate historical models in state_forwards().

Some things to note:

- You don’t need to learn too much about ProjectState to just write simple migrations; just know that it has an apps property that gives access to an app registry (which you can then call get_model on).

- database_forwards and database_backwards both get two states passed to them; these just represent the difference the state_forwards method would have applied, but are given to you for convenience and speed reasons.

- to_state in the database_backwards method is the older state; that is, the one that will be the current state once the migration has finished reversing.

- You might see implementations of references_model on the built-in operations; this is part of the autodetection code and does not matter for custom operations.

Warning

For performance reasons, the Field instances in ModelState.fields are reused across migrations. You must never change the attributes on these instances. If you need to mutate a field in state_forwards(), you must remove the old instance from ModelState.fields and add a new instance in its place. The same is true for the Manager instances in ModelState.managers.

As a simple example, let’s make an operation that loads PostgreSQL extensions (which contain some of PostgreSQL’s more exciting features). It’s simple enough; there’s no model state changes, and all it does is run one command:

from django.db.migrations.operations.base import Operation

class LoadExtension(Operation):

reversible = True

def __init__(self, name):
self.name = name

def state_forwards(self, app_label, state):
pass

def database_forwards(self, app_label, schema_editor, from_state, to_state):
schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" % self.name)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
schema_editor.execute("DROP EXTENSION %s" % self.name)

def describe(self):
return "Creates extension %s" % self.name

Models

Model API reference. For introductory material, see Models.

- Model field reference

- Field attribute reference

- Model _meta API

- Related objects reference

- Model class reference

- Model Meta options

- Model instance reference

- QuerySet API reference

- Lookup API reference

- Query Expressions

- Conditional Expressions

- Database Functions

Model field reference

This document contains all the API references of Field including the field options and field types Django offers.

See also

If the built-in fields don’t do the trick, you can try django-localflavor (documentation), which contains assorted pieces of code that are useful for particular countries and cultures.

Also, you can easily write your own custom model fields.

Note

Technically, these models are defined in django.db.models.fields, but for convenience they’re imported into django.db.models; the standard convention is to use from django.db import models and refer to fields as models.<Foo>Field.

Field options

The following arguments are available to all field types. All are optional.

null

Field.null

If True, Django will store empty values as NULL in the database. Default is False.

Avoid using null on string-based fields such as CharField and TextField because empty string values will always be stored as empty strings, not as NULL. If a string-based field has null=True, that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it’s redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL.

For both string-based and non-string-based fields, you will also need to set blank=True if you wish to permit empty values in forms, as the null parameter only affects database storage (see blank).

Note

When using the Oracle database backend, the value NULL will be stored to denote the empty string regardless of this attribute.

If you want to accept null values with BooleanField, use NullBooleanField instead.

blank

Field.blank

If True, the field is allowed to be blank. Default is False.

Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.

choices

Field.choices

An iterable (e.g., a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A, B), (A, B) ...]) to use as choices for this field. If this is given, the default form widget will be a select box with these choices instead of the standard text field.

The first element in each tuple is the actual value to be set on the model, and the second element is the human-readable name. For example:

YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
)

Generally, it’s best to define choices inside a model class, and to define a suitably-named constant for each value:

from django.db import models

class Student(models.Model):
FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
YEAR_IN_SCHOOL_CHOICES = (
(FRESHMAN, 'Freshman'),
(SOPHOMORE, 'Sophomore'),
(JUNIOR, 'Junior'),
(SENIOR, 'Senior'),
)
year_in_school = models.CharField(
max_length=2,
choices=YEAR_IN_SCHOOL_CHOICES,
default=FRESHMAN,
)

def is_upperclass(self):
return self.year_in_school in (self.JUNIOR, self.SENIOR)

Though you can define a choices list outside of a model class and then refer to it, defining the choices and names for each choice inside the model class keeps all of that information with the class that uses it, and makes the choices easy to reference (e.g, Student.SOPHOMORE will work anywhere that the Student model has been imported).

You can also collect your available choices into named groups that can be used for organizational purposes:

MEDIA_CHOICES = (
('Audio', (
('vinyl', 'Vinyl'),
('cd', 'CD'),
)
),
('Video', (
('vhs', 'VHS Tape'),
('dvd', 'DVD'),
)
),
('unknown', 'Unknown'),
)

The first element in each tuple is the name to apply to the group. The second element is an iterable of 2-tuples, with each 2-tuple containing a value and a human-readable name for an option. Grouped options may be combined with ungrouped options within a single list (such as the unknown option in this example).

For each model field that has choices set, Django will add a method to retrieve the human-readable name for the field’s current value. See get_FOO_display() in the database API documentation.

Note that choices can be any iterable object – not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking choices to be dynamic, you’re probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn’t change much, if ever.

Unless blank=False is set on the field along with a default then a label containing "---------" will be rendered with the select box. To override this behavior, add a tuple to choices containing None; e.g. (None, 'Your String For Display'). Alternatively, you can use an empty string instead of None where this makes sense - such as on a CharField.

db_column

Field.db_column

The name of the database column to use for this field. If this isn’t given, Django will use the field’s name.

If your database column name is an SQL reserved word, or contains characters that aren’t allowed in Python variable names – notably, the hyphen – that’s OK. Django quotes column and table names behind the scenes.

db_index

Field.db_index

If True, a database index will be created for this field.

db_tablespace

Field.db_tablespace

The name of the database tablespace to use for this field’s index, if this field is indexed. The default is the project’s DEFAULT_INDEX_TABLESPACE setting, if set, or the db_tablespace of the model, if any. If the backend doesn’t support tablespaces for indexes, this option is ignored.

default

Field.default

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

The default cannot be a mutable object (model instance, list, set, etc.), as a reference to the same instance of that object would be used as the default value in all new model instances. Instead, wrap the desired default in a callable. For example, if you had a custom JSONField and wanted to specify a dictionary as the default, use a function as follows:

def contact_default():
return {"email": "to1@example.com"}

contact_info = JSONField("ContactInfo", default=contact_default)

Note that lambdas cannot be used for field options like default because they cannot be serialized by migrations. See that documentation for other caveats.

For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.

The default value is used when new model instances are created and a value isn’t provided for the field. When the field is a primary key, the default is also used when the field is set to None.

Changed in Django 1.8:
The default wasn’t used for None primary key values in previous versions.

editable

Field.editable

If False, the field will not be displayed in the admin or any other ModelForm. They are also skipped during model validation. Default is True.

error_messages

Field.error_messages

The error_messages argument lets you override the default messages that the field will raise. Pass in a dictionary with keys matching the error messages you want to override.

Error message keys include null, blank, invalid, invalid_choice, unique, and unique_for_date. Additional error message keys are specified for each field in the Field types section below.

help_text

Field.help_text

Extra “help” text to be displayed with the form widget. It’s useful for documentation even if your field isn’t used on a form.

Note that this value is not HTML-escaped in automatically-generated forms. This lets you include HTML in help_text if you so desire. For example:

help_text="Please use the following format: <em>YYYY-MM-DD</em>."

Alternatively you can use plain text and django.utils.html.escape() to escape any HTML special characters. Ensure that you escape any help text that may come from untrusted users to avoid a cross-site scripting attack.

primary_key

Field.primary_key

If True, this field is the primary key for the model.

If you don’t specify primary_key=True for any field in your model, Django will automatically add an AutoField to hold the primary key, so you don’t need to set primary_key=True on any of your fields unless you want to override the default primary-key behavior. For more, see Automatic primary key fields.

primary_key=True implies null=False and unique=True. Only one primary key is allowed on an object.

The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one.

unique

Field.unique

If True, this field must be unique throughout the table.

This is enforced at the database level and by model validation. If you try to save a model with a duplicate value in a unique field, a django.db.IntegrityError will be raised by the model’s save() method.

This option is valid on all field types except ManyToManyField, OneToOneField, and FileField.

Note that when unique is True, you don’t need to specify db_index, because unique implies the creation of an index.

unique_for_date

Field.unique_for_date

Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field.

For example, if you have a field title that has unique_for_date="pub_date", then Django wouldn’t allow the entry of two records with the same title and pub_date.

Note that if you set this to point to a DateTimeField, only the date portion of the field will be considered. Besides, when USE_TZ is True, the check will be performed in the current time zone at the time the object gets saved.

This is enforced by Model.validate_unique() during model validation but not at the database level. If any unique_for_date constraint involves fields that are not part of a ModelForm (for example, if one of the fields is listed in exclude or has editable=False), Model.validate_unique() will skip validation for that particular constraint.

unique_for_month

Field.unique_for_month

Like unique_for_date, but requires the field to be unique with respect to the month.

unique_for_year

Field.unique_for_year

Like unique_for_date and unique_for_month.

verbose_name

Field.verbose_name

A human-readable name for the field. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name, converting underscores to spaces. See Verbose field names.

validators

Field.validators

A list of validators to run for this field. See the validators documentation for more information.

Registering and fetching lookups

Field implements the lookup registration API. The API can be used to customize which lookups are available for a field class, and how lookups are fetched from a field.

Field types

AutoField

class AutoField(**options)[source]

An IntegerField that automatically increments according to available IDs. You usually won’t need to use this directly; a primary key field will automatically be added to your model if you don’t specify otherwise. See Automatic primary key fields.

BigIntegerField

class BigIntegerField(**options)[source]

A 64 bit integer, much like an IntegerField except that it is guaranteed to fit numbers from -9223372036854775808 to 9223372036854775807. The default form widget for this field is a TextInput.

BinaryField

class BinaryField(**options)[source]

A field to store raw binary data. It only supports bytes assignment. Be aware that this field has limited functionality. For example, it is not possible to filter a queryset on a BinaryField value.

Abusing BinaryField

Although you might think about storing files in the database, consider that it is bad design in 99% of the cases. This field is not a replacement for proper static files handling.

BooleanField

class BooleanField(**options)[source]

A true/false field.

The default form widget for this field is a CheckboxInput.

If you need to accept null values then use NullBooleanField instead.

The default value of BooleanField is None when Field.default isn’t defined.

CharField

class CharField(max_length=None, **options)[source]

A string field, for small- to large-sized strings.

For large amounts of text, use TextField.

The default form widget for this field is a TextInput.

CharField has one extra required argument:

CharField.max_length

The maximum length (in characters) of the field. The max_length is enforced at the database level and in Django’s validation.

Note

If you are writing an application that must be portable to multiple database backends, you should be aware that there are restrictions on max_length for some backends. Refer to the database backend notes for details.

MySQL users

If you are using this field with MySQLdb 1.2.2 and the utf8_bin collation (which is not the default), there are some issues to be aware of. Refer to the MySQL database notes for details.

CommaSeparatedIntegerField

class CommaSeparatedIntegerField(max_length=None, **options)[source]

A field of integers separated by commas. As in CharField, the max_length argument is required and the note about database portability mentioned there should be heeded.

DateField

class DateField(auto_now=False, auto_now_add=False, **options)[source]

A date, represented in Python by a datetime.date instance. Has a few extra, optional arguments:

DateField.auto_now

Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. Note that the current date is always used; it’s not just a default value that you can override.

The field is only automatically updated when calling Model.save(). The field isn’t updated when making updates to other fields in other ways such as QuerySet.update(), though you can specify a custom value for the field in an update like that.

DateField.auto_now_add

Automatically set the field to now when the object is first created. Useful for creation of timestamps. Note that the current date is always used; it’s not just a default value that you can override. So even if you set a value for this field when creating the object, it will be ignored. If you want to be able to modify this field, set the following instead of auto_now_add=True:

- For DateField: default=date.today - from datetime.date.today()

- For DateTimeField: default=timezone.now - from django.utils.timezone.now()

The default form widget for this field is a TextInput. The admin adds a JavaScript calendar, and a shortcut for “Today”. Includes an additional invalid_date error message key.

The options auto_now_add, auto_now, and default are mutually exclusive. Any combination of these options will result in an error.

Note

As currently implemented, setting auto_now or auto_now_add to True will cause the field to have editable=False and blank=True set.

Note

The auto_now and auto_now_add options will always use the date in the default timezone at the moment of creation or update. If you need something different, you may want to consider simply using your own callable default or overriding save() instead of using auto_now or auto_now_add; or using a DateTimeField instead of a DateField and deciding how to handle the conversion from datetime to date at display time.

DateTimeField

class DateTimeField(auto_now=False, auto_now_add=False, **options)[source]

A date and time, represented in Python by a datetime.datetime instance. Takes the same extra arguments as DateField.

The default form widget for this field is a single TextInput. The admin uses two separate TextInput widgets with JavaScript shortcuts.

DecimalField

class DecimalField(max_digits=None, decimal_places=None, **options)[source]

A fixed-precision decimal number, represented in Python by a Decimal instance. Has two required arguments:

DecimalField.max_digits

The maximum number of digits allowed in the number. Note that this number must be greater than or equal to decimal_places.

DecimalField.decimal_places

The number of decimal places to store with the number.

For example, to store numbers up to 999 with a resolution of 2 decimal places, you’d use:

models.DecimalField(..., max_digits=5, decimal_places=2)

And to store numbers up to approximately one billion with a resolution of 10 decimal places:

models.DecimalField(..., max_digits=19, decimal_places=10)

The default form widget for this field is a NumberInput when localize is False or TextInput otherwise.

Note

For more information about the differences between the FloatField and DecimalField classes, please see FloatField vs. DecimalField.

DurationField

New in Django 1.8.

class DurationField(**options)[source]

A field for storing periods of time - modeled in Python by timedelta. When used on PostgreSQL, the data type used is an interval and on Oracle the data type is INTERVAL DAY(9) TO SECOND(6). Otherwise a bigint of microseconds is used.

Note

Arithmetic with DurationField works in most cases. However on all databases other than PostgreSQL, comparing the value of a DurationField to arithmetic on DateTimeField instances will not work as expected.

EmailField

class EmailField(max_length=254, **options)[source]

A CharField that checks that the value is a valid email address. It uses EmailValidator to validate the input.

Changed in Django 1.8:
The default max_length was increased from 75 to 254 in order to be compliant with RFC3696/5321.

FileField

class FileField(upload_to=None, max_length=100, **options)[source]

A file-upload field.

Note

The primary_key and unique arguments are not supported, and will raise a TypeError if used.

Has two optional arguments:

FileField.upload_to

This attribute provides a way of setting the upload directory and file name, and can be set in two ways. In both cases, the value is passed to the Storage.save() method.

If you specify a string value, it may contain strftime() formatting, which will be replaced by the date/time of the file upload (so that uploaded files don’t fill up the given directory). For example:

class MyModel(models.Model):
# file will be uploaded to MEDIA_ROOT/uploads
upload = models.FileField(upload_to='uploads/')
# or...
# file will be saved to MEDIA_ROOT/uploads/2015/01/30
upload = models.FileField(upload_to='uploads/%Y/%m/%d/')

If you are using the default FileSystemStorage, the string value will be appended to your MEDIA_ROOT path to form the location on the local filesystem where uploaded files will be stored. If you are using a different storage, check that storage’s documentation to see how it handles upload_to.

upload_to may also be a callable, such as a function. This will be called to obtain the upload path, including the filename. This callable must accept two arguments and return a Unix-style path (with forward slashes) to be passed along to the storage system. The two arguments are:

Argument

Description

instance

An instance of the model where the FileField is defined. More specifically, this is the particular instance where the current file is being attached.

In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.

filename

The filename that was originally given to the file. This may or may not be taken into account when determining the final destination path.

For example:

def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)

class MyModel(models.Model):
upload = models.FileField(upload_to=user_directory_path)

FileField.storage

A storage object, which handles the storage and retrieval of your files. See Managing files for details on how to provide this object.

The default form widget for this field is a ClearableFileInput.

Using a FileField or an ImageField (see below) in a model takes a few steps:

1. In your settings file, you’ll need to define MEDIA_ROOT as the full path to a directory where you’d like Django to store uploaded files. (For performance, these files are not stored in the database.) Define MEDIA_URL as the base public URL of that directory. Make sure that this directory is writable by the Web server’s user account.

2. Add the FileField or ImageField to your model, defining the upload_to option to specify a subdirectory of MEDIA_ROOT to use for uploaded files.

3. All that will be stored in your database is a path to the file (relative to MEDIA_ROOT). You’ll most likely want to use the convenience url attribute provided by Django. For example, if your ImageField is called mug_shot, you can get the absolute path to your image in a template with {{ object.mug_shot.url }}.

For example, say your MEDIA_ROOT is set to '/home/media', and upload_to is set to 'photos/%Y/%m/%d'. The '%Y/%m/%d' part of upload_to is strftime() formatting; '%Y' is the four-digit year, '%m' is the two-digit month and '%d' is the two-digit day. If you upload a file on Jan. 15, 2007, it will be saved in the directory /home/media/photos/2007/01/15.

If you wanted to retrieve the uploaded file’s on-disk filename, or the file’s size, you could use the name and size attributes respectively; for more information on the available attributes and methods, see the File class reference and the Managing files topic guide.

Note

The file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.

The uploaded file’s relative URL can be obtained using the url attribute. Internally, this calls the url() method of the underlying Storage class.

Note that whenever you deal with uploaded files, you should pay close attention to where you’re uploading them and what type of files they are, to avoid security holes. Validate all uploaded files so that you’re sure the files are what you think they are. For example, if you blindly let somebody upload files, without validation, to a directory that’s within your Web server’s document root, then somebody could upload a CGI or PHP script and execute that script by visiting its URL on your site. Don’t allow that.

Also note that even an uploaded HTML file, since it can be executed by the browser (though not by the server), can pose security threats that are equivalent to XSS or CSRF attacks.

FileField instances are created in your database as varchar columns with a default max length of 100 characters. As with other fields, you can change the maximum length using the max_length argument.

FileField and FieldFile

class FieldFile[source]

When you access a FileField on a model, you are given an instance of FieldFile as a proxy for accessing the underlying file.

The API of FieldFile mirrors that of File, with one key difference: The object wrapped by the class is not necessarily a wrapper around Python’s built-in file object. Instead, it is a wrapper around the result of the Storage.open() method, which may be a File object, or it may be a custom storage’s implementation of the File API.

In addition to the API inherited from File such as read() and write(), FieldFile includes several methods that can be used to interact with the underlying file:

Warning

Two methods of this class, save() and delete(), default to saving the model object of the associated FieldFile in the database.

FieldFile.name

The name of the file including the relative path from the root of the Storage of the associated FileField.

FieldFile.size

The result of the underlying Storage.size() method.

FieldFile.url

A read-only property to access the file’s relative URL by calling the url() method of the underlying Storage class.

FieldFile.open(mode='rb')[source]

Opens or reopens the file associated with this instance in the specified mode. Unlike the standard Python open() method, it doesn’t return a file descriptor.

Since the underlying file is opened implicitly when accessing it, it may be unnecessary to call this method except to reset the pointer to the underlying file or to change the mode.

FieldFile.close()[source]

Behaves like the standard Python file.close() method and closes the file associated with this instance.

FieldFile.save(name, content, save=True)[source]

This method takes a filename and file contents and passes them to the storage class for the field, then associates the stored file with the model field. If you want to manually associate file data with FileField instances on your model, the save() method is used to persist that file data.

Takes two required arguments: name which is the name of the file, and content which is an object containing the file’s contents. The optional save argument controls whether or not the model instance is saved after the file associated with this field has been altered. Defaults to True.

Note that the content argument should be an instance of django.core.files.File, not Python’s built-in file object. You can construct a File from an existing Python file object like this:

from django.core.files import File
# Open an existing file using Python's built-in open()
f = open('/path/to/hello.world')
myfile = File(f)

Or you can construct one from a Python string like this:

from django.core.files.base import ContentFile
myfile = ContentFile("hello world")

For more information, see Managing files.

FieldFile.delete(save=True)[source]

Deletes the file associated with this instance and clears all attributes on the field. Note: This method will close the file if it happens to be open when delete() is called.

The optional save argument controls whether or not the model instance is saved after the file associated with this field has been deleted. Defaults to True.

Note that when a model is deleted, related files are not deleted. If you need to cleanup orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).

FilePathField

class FilePathField(path=None, match=None, recursive=False, max_length=100, **options)[source]

A CharField whose choices are limited to the filenames in a certain directory on the filesystem. Has three special arguments, of which the first is required:

FilePathField.path

Required. The absolute filesystem path to a directory from which this FilePathField should get its choices. Example: "/home/images".

FilePathField.match

Optional. A regular expression, as a string, that FilePathField will use to filter filenames. Note that the regex will be applied to the base filename, not the full path. Example: "foo.*\.txt$", which will match a file called foo23.txt but not bar.txt or foo23.png.

FilePathField.recursive

Optional. Either True or False. Default is False. Specifies whether all subdirectories of path should be included

FilePathField.allow_files

Optional. Either True or False. Default is True. Specifies whether files in the specified location should be included. Either this or allow_folders must be True.

FilePathField.allow_folders

Optional. Either True or False. Default is False. Specifies whether folders in the specified location should be included. Either this or allow_files must be True.

Of course, these arguments can be used together.

The one potential gotcha is that match applies to the base filename, not the full path. So, this example:

FilePathField(path="/home/images", match="foo.*", recursive=True)

...will match /home/images/foo.png but not /home/images/foo/bar.png because the match applies to the base filename (foo.png and bar.png).

FilePathField instances are created in your database as varchar columns with a default max length of 100 characters. As with other fields, you can change the maximum length using the max_length argument.

FloatField

class FloatField(**options)[source]

A floating-point number represented in Python by a float instance.

The default form widget for this field is a NumberInput when localize is False or TextInput otherwise.

FloatField vs. DecimalField

The FloatField class is sometimes mixed up with the DecimalField class. Although they both represent real numbers, they represent those numbers differently. FloatField uses Python’s float type internally, while DecimalField uses Python’s Decimal type. For information on the difference between the two, see Python’s documentation for the decimal module.

ImageField

class ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, **options)[source]

Inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.

In addition to the special attributes that are available for FileField, an ImageField also has height and width attributes.

To facilitate querying on those attributes, ImageField has two extra optional arguments:

ImageField.height_field

Name of a model field which will be auto-populated with the height of the image each time the model instance is saved.

ImageField.width_field

Name of a model field which will be auto-populated with the width of the image each time the model instance is saved.

Requires the Pillow library.

ImageField instances are created in your database as varchar columns with a default max length of 100 characters. As with other fields, you can change the maximum length using the max_length argument.

The default form widget for this field is a ClearableFileInput.

IntegerField

class IntegerField(**options)[source]

An integer. Values from -2147483648 to 2147483647 are safe in all databases supported by Django. The default form widget for this field is a NumberInput when localize is False or TextInput otherwise.

GenericIPAddressField

class GenericIPAddressField(protocol='both', unpack_ipv4=False, **options)[source]

An IPv4 or IPv6 address, in string format (e.g. 192.0.2.30 or 2a02:42fe::4). The default form widget for this field is a TextInput.

The IPv6 address normalization follows RFC 4291#section-2.2 section 2.2, including using the IPv4 format suggested in paragraph 3 of that section, like ::ffff:192.0.2.0. For example, 2001:0::0:01 would be normalized to 2001::1, and ::ffff:0a0a:0a0a to ::ffff:10.10.10.10. All characters are converted to lowercase.

GenericIPAddressField.protocol

Limits valid inputs to the specified protocol. Accepted values are 'both' (default), 'IPv4' or 'IPv6'. Matching is case insensitive.

GenericIPAddressField.unpack_ipv4

Unpacks IPv4 mapped addresses like ::ffff:192.0.2.1. If this option is enabled that address would be unpacked to 192.0.2.1. Default is disabled. Can only be used when protocol is set to 'both'.

If you allow for blank values, you have to allow for null values since blank values are stored as null.

NullBooleanField

class NullBooleanField(**options)[source]

Like a BooleanField, but allows NULL as one of the options. Use this instead of a BooleanField with null=True. The default form widget for this field is a NullBooleanSelect.

PositiveIntegerField

class PositiveIntegerField(**options)[source]

Like an IntegerField, but must be either positive or zero (0). Values from 0 to 2147483647 are safe in all databases supported by Django. The value 0 is accepted for backward compatibility reasons.

PositiveSmallIntegerField

class PositiveSmallIntegerField(**options)[source]

Like a PositiveIntegerField, but only allows values under a certain (database-dependent) point. Values from 0 to 32767 are safe in all databases supported by Django.

SlugField

class SlugField(max_length=50, **options)[source]

Slug is a newspaper term. A slug is a short label for something, containing only letters, numbers, underscores or hyphens. They’re generally used in URLs.

Like a CharField, you can specify max_length (read the note about database portability and max_length in that section, too). If max_length is not specified, Django will use a default length of 50.

Implies setting Field.db_index to True.

It is often useful to automatically prepopulate a SlugField based on the value of some other value. You can do this automatically in the admin using prepopulated_fields.

SlugField.allow_unicode

New in Django 1.9.

If True, the field accepts Unicode letters in addition to ASCII letters. Defaults to False.

SmallIntegerField

class SmallIntegerField(**options)[source]

Like an IntegerField, but only allows values under a certain (database-dependent) point. Values from -32768 to 32767 are safe in all databases supported by Django.

TextField

class TextField(**options)[source]

A large text field. The default form widget for this field is a Textarea.

If you specify a max_length attribute, it will be reflected in the Textarea widget of the auto-generated form field. However it is not enforced at the model or database level. Use a CharField for that.

MySQL users

If you are using this field with MySQLdb 1.2.1p2 and the utf8_bin collation (which is not the default), there are some issues to be aware of. Refer to the MySQL database notes for details.

TimeField

class TimeField(auto_now=False, auto_now_add=False, **options)[source]

A time, represented in Python by a datetime.time instance. Accepts the same auto-population options as DateField.

The default form widget for this field is a TextInput. The admin adds some JavaScript shortcuts.

URLField

class URLField(max_length=200, **options)[source]

A CharField for a URL.

The default form widget for this field is a TextInput.

Like all CharField subclasses, URLField takes the optional max_length argument. If you don’t specify max_length, a default of 200 is used.

UUIDField

New in Django 1.8.

class UUIDField(**options)[source]

A field for storing universally unique identifiers. Uses Python’s UUID class. When used on PostgreSQL, this stores in a uuid datatype, otherwise in a char(32).

Universally unique identifiers are a good alternative to AutoField for primary_key. The database will not generate the UUID for you, so it is recommended to use default:

import uuid
from django.db import models

class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# other fields

Note that a callable (with the parentheses omitted) is passed to default, not an instance of UUID.

Relationship fields

Django also defines a set of fields that represent relations.

ForeignKey

class ForeignKey(othermodel, on_delete, **options)[source]

A many-to-one relationship. Requires a positional argument: the class to which the model is related.

Changed in Django 1.9:
on_delete can now be used as the second positional argument (previously it was typically only passed as a keyword argument). It will be a required argument in Django 2.0.

To create a recursive relationship – an object that has a many-to-one relationship with itself – use models.ForeignKey('self', on_delete=models.CASCADE).

If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself:

from django.db import models

class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...

class Manufacturer(models.Model):
# ...
pass

Relationships defined this way on abstract models are resolved when the model is subclassed as a concrete model and are not relative to the abstract model’s app_label:

products/models.py

from django.db import models

class AbstractCar(models.Model):
manufacturer = models.ForeignKey('Manufacturer', on_delete=models.CASCADE)

class Meta:
abstract = True

production/models.py

from django.db import models
from products.models import AbstractCar

class Manufacturer(models.Model):
pass

class Car(AbstractCar):
pass

# Car.manufacturer will point to `production.Manufacturer` here.

To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you’d need to use:

class Car(models.Model):
manufacturer = models.ForeignKey(
'production.Manufacturer',
on_delete=models.CASCADE,
)

This sort of reference can be useful when resolving circular import dependencies between two applications.

A database index is automatically created on the ForeignKey. You can disable this by setting db_index to False. You may want to avoid the overhead of an index if you are creating a foreign key for consistency rather than joins, or if you will be creating an alternative index like a partial or multiple column index.

Database Representation

Behind the scenes, Django appends "_id" to the field name to create its database column name. In the above example, the database table for the Car model will have a manufacturer_id column. (You can change this explicitly by specifying db_column) However, your code should never have to deal with the database column name, unless you write custom SQL. You’ll always deal with the field names of your model object.

Arguments

ForeignKey accepts other arguments that define the details of how the relation works.

ForeignKey.on_delete

When an object referenced by a ForeignKey is deleted, Django will emulate the behavior of the SQL constraint specified by the on_delete argument. For example, if you have a nullable ForeignKey and you want it to be set null when the referenced object is deleted:

user = models.ForeignKey(
User,
models.SET_NULL,
blank=True,
null=True,
)

Deprecated since version 1.9: on_delete will become a required argument in Django 2.0. In older versions it defaults to CASCADE.

The possible values for on_delete are found in django.db.models:

- CASCADE[source]

Cascade deletes. Django emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey.

- PROTECT[source]

Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db.IntegrityError.

- SET_NULL[source]

Set the ForeignKey null; this is only possible if null is True.

- SET_DEFAULT[source]

Set the ForeignKey to its default value; a default for the ForeignKey must be set.

- SET()[source]

Set the ForeignKey to the value passed to SET(), or if a callable is passed in, the result of calling it. In most cases, passing a callable will be necessary to avoid executing queries at the time your models.py is imported:

from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models

def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]

class MyModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user),
)

- DO_NOTHING[source]

Take no action. If your database backend enforces referential integrity, this will cause an IntegrityError unless you manually add an SQL ON DELETE constraint to the database field.

ForeignKey.limit_choices_to

Sets a limit to the available choices for this field when this field is rendered using a ModelForm or the admin (by default, all objects in the queryset are available to choose). Either a dictionary, a Q object, or a callable returning a dictionary or Q object can be used.

For example:

staff_member = models.ForeignKey(
User,
on_delete=models.CASCADE,
limit_choices_to={'is_staff': True},
)

causes the corresponding field on the ModelForm to list only Users that have is_staff=True. This may be helpful in the Django admin.

The callable form can be helpful, for instance, when used in conjunction with the Python datetime module to limit selections by date range. For example:

def limit_pub_date_choices():
return {'pub_date__lte': datetime.date.utcnow()}

limit_choices_to = limit_pub_date_choices

If limit_choices_to is or returns a Q object, which is useful for complex queries, then it will only have an effect on the choices available in the admin when the field is not listed in raw_id_fields in the ModelAdmin for the model.

Note

If a callable is used for limit_choices_to, it will be invoked every time a new form is instantiated. It may also be invoked when a model is validated, for example by management commands or the admin. The admin constructs querysets to validate its form inputs in various edge cases multiple times, so there is a possibility your callable may be invoked several times.

ForeignKey.related_name

The name to use for the relation from the related object back to this one. It’s also the default value for related_query_name (the name to use for the reverse filter name from the target model). See the related objects documentation for a full explanation and example. Note that you must set this value when defining relations on abstract models; and when you do so some special syntax is available.

If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'. For example, this will ensure that the User model won’t have a backwards relation to this model:

user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='+',
)

ForeignKey.related_query_name

The name to use for the reverse filter name from the target model. Defaults to the value of related_name if it is set, otherwise it defaults to the name of the model:

# Declare the ForeignKey with related_query_name
class Tag(models.Model):
article = models.ForeignKey(
Article,
on_delete=models.CASCADE,
related_name="tags",
related_query_name="tag",
)
name = models.CharField(max_length=255)

# That's now the name of the reverse filter
Article.objects.filter(tag__name="important")

ForeignKey.to_field

The field on the related object that the relation is to. By default, Django uses the primary key of the related object.

ForeignKey.db_constraint

Controls whether or not a constraint should be created in the database for this foreign key. The default is True, and that’s almost certainly what you want; setting this to False can be very bad for data integrity. That said, here are some scenarios where you might want to do this:

- You have legacy data that is not valid.

- You’re sharding your database.

If this is set to False, accessing a related object that doesn’t exist will raise its DoesNotExist exception.

ForeignKey.swappable

Controls the migration framework’s reaction if this ForeignKey is pointing at a swappable model. If it is True - the default - then if the ForeignKey is pointing at a model which matches the current value of settings.AUTH_USER_MODEL (or another swappable model setting) the relationship will be stored in the migration using a reference to the setting, not to the model directly.

You only want to override this to be False if you are sure your model should always point towards the swapped-in model - for example, if it is a profile model designed specifically for your custom user model.

Setting it to False does not mean you can reference a swappable model even if it is swapped out - False just means that the migrations made with this ForeignKey will always reference the exact model you specify (so it will fail hard if the user tries to run with a User model you don’t support, for example).

If in doubt, leave it to its default of True.

ManyToManyField

class ManyToManyField(othermodel, **options)[source]

A many-to-many relationship. Requires a positional argument: the class to which the model is related, which works exactly the same as it does for ForeignKey, including recursive and lazy relationships.

Related objects can be added, removed, or created with the field’s RelatedManager.

Database Representation

Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship. By default, this table name is generated using the name of the many-to-many field and the name of the table for the model that contains it. Since some databases don’t support table names above a certain length, these table names will be automatically truncated to 64 characters and a uniqueness hash will be used. This means you might see table names like author_books_9cdf4; this is perfectly normal. You can manually provide the name of the join table using the db_table option.

Arguments

ManyToManyField accepts an extra set of arguments – all optional – that control how the relationship functions.

ManyToManyField.related_name

Same as ForeignKey.related_name.

ManyToManyField.related_query_name

Same as ForeignKey.related_query_name.

ManyToManyField.limit_choices_to

Same as ForeignKey.limit_choices_to.

limit_choices_to has no effect when used on a ManyToManyField with a custom intermediate table specified using the through parameter.

ManyToManyField.symmetrical

Only used in the definition of ManyToManyFields on self. Consider the following model:

from django.db import models

class Person(models.Model):
friends = models.ManyToManyField("self")

When Django processes this model, it identifies that it has a ManyToManyField on itself, and as a result, it doesn’t add a person_set attribute to the Person class. Instead, the ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend.

If you do not want symmetry in many-to-many relationships with self, set symmetrical to False. This will force Django to add the descriptor for the reverse relationship, allowing ManyToManyField relationships to be non-symmetrical.

ManyToManyField.through

Django will automatically generate a table to manage many-to-many relationships. However, if you want to manually specify the intermediary table, you can use the through option to specify the Django model that represents the intermediate table that you want to use.

The most common use for this option is when you want to associate extra data with a many-to-many relationship.

If you don’t specify an explicit through model, there is still an implicit through model class you can use to directly access the table created to hold the association. It has three fields to link the models.

If the source and target models differ, the following fields are generated:

- id: the primary key of the relation.

- <containing_model>_id: the id of the model that declares the ManyToManyField.

- <other_model>_id: the id of the model that the ManyToManyField points to.

If the ManyToManyField points from and to the same model, the following fields are generated:

- id: the primary key of the relation.

- from_<model>_id: the id of the instance which points at the model (i.e. the source instance).

- to_<model>_id: the id of the instance to which the relationship points (i.e. the target model instance).

This class can be used to query associated records for a given model instance like a normal model.

ManyToManyField.through_fields

Only used when a custom intermediary model is specified. Django will normally determine which fields of the intermediary model to use in order to establish a many-to-many relationship automatically. However, consider the following models:

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=50)

class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
)

class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)

Membership has two foreign keys to Person (person and inviter), which makes the relationship ambiguous and Django can’t know which one to use. In this case, you must explicitly specify which foreign keys Django should use using through_fields, as in the example above.

through_fields accepts a 2-tuple ('field1', 'field2'), where field1 is the name of the foreign key to the model the ManyToManyField is defined on (group in this case), and field2 the name of the foreign key to the target model (person in this case).

When you have more than one foreign key on an intermediary model to any (or even both) of the models participating in a many-to-many relationship, you must specify through_fields. This also applies to recursive relationships when an intermediary model is used and there are more than two foreign keys to the model, or you want to explicitly specify which two Django should use.

Recursive relationships using an intermediary model are always defined as non-symmetrical – that is, with symmetrical=False – therefore, there is the concept of a “source” and a “target”. In that case 'field1' will be treated as the “source” of the relationship and 'field2' as the “target”.

ManyToManyField.db_table

The name of the table to create for storing the many-to-many data. If this is not provided, Django will assume a default name based upon the names of: the table for the model defining the relationship and the name of the field itself.

ManyToManyField.db_constraint

Controls whether or not constraints should be created in the database for the foreign keys in the intermediary table. The default is True, and that’s almost certainly what you want; setting this to False can be very bad for data integrity. That said, here are some scenarios where you might want to do this:

- You have legacy data that is not valid.

- You’re sharding your database.

It is an error to pass both db_constraint and through.

ManyToManyField.swappable

Controls the migration framework’s reaction if this ManyToManyField is pointing at a swappable model. If it is True - the default - then if the ManyToManyField is pointing at a model which matches the current value of settings.AUTH_USER_MODEL (or another swappable model setting) the relationship will be stored in the migration using a reference to the setting, not to the model directly.

You only want to override this to be False if you are sure your model should always point towards the swapped-in model - for example, if it is a profile model designed specifically for your custom user model.

If in doubt, leave it to its default of True.

ManyToManyField does not support validators.

null has no effect since there is no way to require a relationship at the database level.

OneToOneField

class OneToOneField(othermodel, on_delete, parent_link=False, **options)[source]

A one-to-one relationship. Conceptually, this is similar to a ForeignKey with unique=True, but the “reverse” side of the relation will directly return a single object.

Changed in Django 1.9:
on_delete can now be used as the second positional argument (previously it was typically only passed as a keyword argument). It will be a required argument in Django 2.0.

This is most useful as the primary key of a model which “extends” another model in some way; Multi-table inheritance is implemented by adding an implicit one-to-one relation from the child model to the parent model, for example.

One positional argument is required: the class to which the model will be related. This works exactly the same as it does for ForeignKey, including all the options regarding recursive and lazy relationships.

If you do not specify the related_name argument for the OneToOneField, Django will use the lower-case name of the current model as default value.

With the following example:

from django.conf import settings
from django.db import models

class MySpecialUser(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
supervisor = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='supervisor_of',
)

your resulting User model will have the following attributes:

>>> user = User.objects.get(pk=1)
>>> hasattr(user, 'myspecialuser')
True
>>> hasattr(user, 'supervisor_of')
True

A DoesNotExist exception is raised when accessing the reverse relationship if an entry in the related table doesn’t exist. For example, if a user doesn’t have a supervisor designated by MySpecialUser:

>>> user.supervisor_of
Traceback (most recent call last):
...
DoesNotExist: User matching query does not exist.

Additionally, OneToOneField accepts all of the extra arguments accepted by ForeignKey, plus one extra argument:

OneToOneField.parent_link

When True and used in a model which inherits from another concrete model, indicates that this field should be used as the link back to the parent class, rather than the extra OneToOneField which would normally be implicitly created by subclassing.

See One-to-one relationships for usage examples of OneToOneField.

Field API reference

class Field[source]

Field is an abstract class that represents a database table column. Django uses fields to create the database table (db_type()), to map Python types to database (get_prep_value()) and vice-versa (from_db_value()), and to apply Lookup API reference (get_prep_lookup()).

A field is thus a fundamental piece in different Django APIs, notably, models and querysets.

In models, a field is instantiated as a class attribute and represents a particular table column, see Models. It has attributes such as null and unique, and methods that Django uses to map the field value to database-specific values.

A Field is a subclass of RegisterLookupMixin and thus both Transform and Lookup can be registered on it to be used in QuerySets (e.g. field_name__exact="foo"). All built-in lookups are registered by default.

All of Django’s built-in fields, such as CharField, are particular implementations of Field. If you need a custom field, you can either subclass any of the built-in fields or write a Field from scratch. In either case, see Writing custom model fields.

description

A verbose description of the field, e.g. for the django.contrib.admindocs application.

The description can be of the form:

description = _("String (up to %(max_length)s)")

where the arguments are interpolated from the field’s __dict__.

To map a Field to a database-specific type, Django exposes two methods:

get_internal_type()[source]

Returns a string naming this field for backend specific purposes. By default, it returns the class name.

See Emulating built-in field types for usage in custom fields.

db_type(connection)[source]

Returns the database column data type for the Field, taking into account the connection.

See Custom database types for usage in custom fields.

There are three main situations where Django needs to interact with the database backend and fields:

- when it queries the database (Python value -> database backend value)

- when it loads data from the database (database backend value -> Python value)

- when it saves to the database (Python value -> database backend value)

When querying, get_db_prep_value() and get_prep_value() are used:

get_prep_value(value)[source]

value is the current value of the model’s attribute, and the method should return data in a format that has been prepared for use as a parameter in a query.

See Converting Python objects to query values for usage.

get_db_prep_value(value, connection, prepared=False)[source]

Converts value to a backend-specific value. By default it returns value if prepared=True and get_prep_value() if is False.

See Converting query values to database values for usage.

When loading data, from_db_value() is used:

from_db_value(value, expression, connection, context)

New in Django 1.8.

Converts a value as returned by the database to a Python object. It is the reverse of get_prep_value().

This method is not used for most built-in fields as the database backend already returns the correct Python type, or the backend itself does the conversion.

See Converting values to Python objects for usage.

Note

For performance reasons, from_db_value is not implemented as a no-op on fields which do not require it (all Django fields). Consequently you may not call super in your definition.

When saving, pre_save() and get_db_prep_save() are used:

get_db_prep_save(value, connection)[source]

Same as the get_db_prep_value(), but called when the field value must be saved to the database. By default returns get_db_prep_value().

pre_save(model_instance, add)[source]

Method called prior to get_db_prep_save() to prepare the value before being saved (e.g. for DateField.auto_now).

model_instance is the instance this field belongs to and add is whether the instance is being saved to the database for the first time.

It should return the value of the appropriate attribute from model_instance for this field. The attribute name is in self.attname (this is set up by Field).

See Preprocessing values before saving for usage.

When a lookup is used on a field, the value may need to be “prepared”. Django exposes two methods for this:

get_prep_lookup(lookup_type, value)[source]

Prepares value to the database prior to be used in a lookup. The lookup_type will be one of the valid Django filter lookups: "exact", "iexact", "contains", "icontains", "gt", "gte", "lt", "lte", "in", "startswith", "istartswith", "endswith", "iendswith", "range", "year", "month", "day", "isnull", "search", "regex", and "iregex".

If you are using Custom lookups the lookup_type can be any lookup_name registered in the field.

See Preparing values for use in database lookups for usage.

get_db_prep_lookup(lookup_type, value, connection, prepared=False)[source]

Similar to get_db_prep_value(), but for performing a lookup.

As with get_db_prep_value(), the specific connection that will be used for the query is passed as connection. In addition, prepared describes whether the value has already been prepared with get_prep_lookup().

Fields often receive their values as a different type, either from serialization or from forms.

to_python(value)[source]

Converts the value into the correct Python object. It acts as the reverse of value_to_string(), and is also called in clean().

See Converting values to Python objects for usage.

Besides saving to the database, the field also needs to know how to serialize its value:

value_to_string(obj)[source]

Converts obj to a string. Used to serialize the value of the field.

See Converting field data for serialization for usage.

When using model forms, the Field needs to know which form field it should be represented by:

formfield(form_class=None, choices_form_class=None, **kwargs)[source]

Returns the default django.forms.Field of this field for ModelForm.

By default, if both form_class and choices_form_class are None, it uses CharField; if choices_form_class is given, it returns TypedChoiceField.

See Specifying the form field for a model field for usage.

deconstruct()[source]

Returns a 4-tuple with enough information to recreate the field:

1. The name of the field on the model.

2. The import path of the field (e.g. "django.db.models.IntegerField"). This should be the most portable version, so less specific may be better.

3. A list of positional arguments.

4. A dict of keyword arguments.

This method must be added to fields prior to 1.7 to migrate its data using Migrations.

Field attribute reference

New in Django 1.8.

Every Field instance contains several attributes that allow introspecting its behavior. Use these attributes instead of isinstance checks when you need to write code that depends on a field’s functionality. These attributes can be used together with the Model._meta API to narrow down a search for specific field types. Custom model fields should implement these flags.

Attributes for fields

Field.auto_created

Boolean flag that indicates if the field was automatically created, such as the OneToOneField used by model inheritance.

Field.concrete

Boolean flag that indicates if the field has a database column associated with it.

Field.hidden

Boolean flag that indicates if a field is used to back another non-hidden field’s functionality (e.g. the content_type and object_id fields that make up a GenericForeignKey). The hidden flag is used to distinguish what constitutes the public subset of fields on the model from all the fields on the model.

Note

Options.get_fields() excludes hidden fields by default. Pass in include_hidden=True to return hidden fields in the results.

Field.is_relation

Boolean flag that indicates if a field contains references to one or more other models for its functionality (e.g. ForeignKey, ManyToManyField, OneToOneField, etc.).

Field.model

Returns the model on which the field is defined. If a field is defined on a superclass of a model, model will refer to the superclass, not the class of the instance.

Attributes for fields with relations

These attributes are used to query for the cardinality and other details of a relation. These attribute are present on all fields; however, they will only have boolean values (rather than None) if the field is a relation type (Field.is_relation=True).

Field.many_to_many

Boolean flag that is True if the field has a many-to-many relation; False otherwise. The only field included with Django where this is True is ManyToManyField.

Field.many_to_one

Boolean flag that is True if the field has a many-to-one relation, such as a ForeignKey; False otherwise.

Field.one_to_many

Boolean flag that is True if the field has a one-to-many relation, such as a GenericRelation or the reverse of a ForeignKey; False otherwise.

Field.one_to_one

Boolean flag that is True if the field has a one-to-one relation, such as a OneToOneField; False otherwise.

Field.related_model

Points to the model the field relates to. For example, Author in ForeignKey(Author, on_delete=models.CASCADE). If a field has a generic relation (such as a GenericForeignKey or a GenericRelation) then related_model will be None.

Model _meta API

class Options[source]

The model _meta API is at the core of the Django ORM. It enables other parts of the system such as lookups, queries, forms, and the admin to understand the capabilities of each model. The API is accessible through the _meta attribute of each model class, which is an instance of an django.db.models.options.Options object.

Methods that it provides can be used to:

- Retrieve all field instances of a model

- Retrieve a single field instance of a model by name

Changed in Django 1.8:
The Model _meta API has always existed as a Django internal, but wasn’t formally documented and supported. As part of the effort to make this API public, some of the already existing API entry points have changed slightly. A migration guide has been provided to assist in converting your code to use the new, official API.

Field access API

Retrieving a single field instance of a model by name

Options.get_field(field_name)[source]

Returns the field instance given a name of a field.

field_name can be the name of a field on the model, a field on an abstract or inherited model, or a field defined on another model that points to the model. In the latter case, the field_name will be the related_name defined by the user or the name automatically generated by Django itself.

Hidden fields cannot be retrieved by name.

If a field with the given name is not found a FieldDoesNotExist exception will be raised.

>>> from django.contrib.auth.models import User

# A field on the model
>>> User._meta.get_field('username')
<django.db.models.fields.CharField: username>

# A field from another model that has a relation with the current model
>>> User._meta.get_field('logentry')
<ManyToOneRel: admin.logentry>

# A non existent field
>>> User._meta.get_field('does_not_exist')
Traceback (most recent call last):
...
FieldDoesNotExist: User has no field named 'does_not_exist'

Deprecated since version 1.8: Options.get_field() previously accepted a many_to_many parameter which could be set to False to avoid searching ManyToManyFields. The old behavior has been preserved for backwards compatibility; however, the parameter and this behavior has been deprecated.

If you wish to filter out ManyToManyFields, you can inspect the Field.many_to_many attribute after calling get_field().

Retrieving all field instances of a model

Options.get_fields(include_parents=True, include_hidden=False)[source]

New in Django 1.8.

Returns a tuple of fields associated with a model. get_fields() accepts two parameters that can be used to control which fields are returned:

include_parents

True by default. Recursively includes fields defined on parent classes. If set to False, get_fields() will only search for fields declared directly on the current model. Fields from models that directly inherit from abstract models or proxy classes are considered to be local, not on the parent.

include_hidden

False by default. If set to True, get_fields() will include fields that are used to back other field’s functionality. This will also include any fields that have a related_name (such as ManyToManyField, or ForeignKey) that start with a “+”.

>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(<ManyToOneRel: admin.logentry>,
<django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: password>,
<django.db.models.fields.DateTimeField: last_login>,
<django.db.models.fields.BooleanField: is_superuser>,
<django.db.models.fields.CharField: username>,
<django.db.models.fields.CharField: first_name>,
<django.db.models.fields.CharField: last_name>,
<django.db.models.fields.EmailField: email>,
<django.db.models.fields.BooleanField: is_staff>,
<django.db.models.fields.BooleanField: is_active>,
<django.db.models.fields.DateTimeField: date_joined>,
<django.db.models.fields.related.ManyToManyField: groups>,
<django.db.models.fields.related.ManyToManyField: user_permissions>)

# Also include hidden fields.
>>> User._meta.get_fields(include_hidden=True)
(<ManyToOneRel: auth.user_groups>,
<ManyToOneRel: auth.user_user_permissions>,
<ManyToOneRel: admin.logentry>,
<django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: password>,
<django.db.models.fields.DateTimeField: last_login>,
<django.db.models.fields.BooleanField: is_superuser>,
<django.db.models.fields.CharField: username>,
<django.db.models.fields.CharField: first_name>,
<django.db.models.fields.CharField: last_name>,
<django.db.models.fields.EmailField: email>,
<django.db.models.fields.BooleanField: is_staff>,
<django.db.models.fields.BooleanField: is_active>,
<django.db.models.fields.DateTimeField: date_joined>,
<django.db.models.fields.related.ManyToManyField: groups>,
<django.db.models.fields.related.ManyToManyField: user_permissions>)

Migrating from the old API

As part of the formalization of the Model._meta API (from the django.db.models.options.Options class), a number of methods and properties have been deprecated and will be removed in Django 1.10.

These old APIs can be replicated by either:

- invoking Options.get_field(), or;

- invoking Options.get_fields() to retrieve a list of all fields, and then filtering this list using the field attributes that describe (or retrieve, in the case of _with_model variants) the properties of the desired fields.

Although it’s possible to make strictly equivalent replacements of the old methods, that might not be the best approach. Taking the time to refactor any field loops to make better use of the new API - and possibly include fields that were previously excluded - will almost certainly result in better code.

Assuming you have a model named MyModel, the following substitutions can be made to convert your code to the new API:

- MyModel._meta.get_field(name) becomes:

f = MyModel._meta.get_field(name)

then check if:

- f.auto_created == False, because the new get_field() API will find “reverse” relations, and:

- f.is_relation and f.related_model is None, because the new get_field() API will find GenericForeignKey relations.

- MyModel._meta.get_field_by_name(name) returns a tuple of these four values with the following replacements:

- field can be found by MyModel._meta.get_field(name)

- model can be found through the model attribute on the field.

- direct can be found by: not field.auto_created or field.concrete

The auto_created check excludes all “forward” and “reverse” relations that are created by Django, but this also includes AutoField and OneToOneField on proxy models. We avoid filtering out these attributes using the concrete attribute.

- m2m can be found through the many_to_many attribute on the field.

- MyModel._meta.get_fields_with_model() becomes:

[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if not f.is_relation
or f.one_to_one
or (f.many_to_one and f.related_model)
]

- MyModel._meta.get_concrete_fields_with_model() becomes:

[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if f.concrete and (
not f.is_relation
or f.one_to_one
or (f.many_to_one and f.related_model)
)
]

- MyModel._meta.get_m2m_with_model() becomes:

[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if f.many_to_many and not f.auto_created
]

- MyModel._meta.get_all_related_objects() becomes:

[
f for f in MyModel._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]

- MyModel._meta.get_all_related_objects_with_model() becomes:

[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]

- MyModel._meta.get_all_related_many_to_many_objects() becomes:

[
f for f in MyModel._meta.get_fields(include_hidden=True)
if f.many_to_many and f.auto_created
]

- MyModel._meta.get_all_related_m2m_objects_with_model() becomes:

[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields(include_hidden=True)
if f.many_to_many and f.auto_created
]

- MyModel._meta.get_all_field_names() becomes:

from itertools import chain
list(set(chain.from_iterable(
(field.name, field.attname) if hasattr(field, 'attname') else (field.name,)
for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results.
if not (field.many_to_one and field.related_model is None)
)))

This provides a 100% backwards compatible replacement, ensuring that both field names and attribute names ForeignKeys are included, but fields associated with GenericForeignKeys are not. A simpler version would be:

[f.name for f in MyModel._meta.get_fields()]

While this isn’t 100% backwards compatible, it may be sufficient in many situations.

Related objects reference

class RelatedManager

A “related manager” is a manager used in a one-to-many or many-to-many related context. This happens in two cases:

- The “other side” of a ForeignKey relation. That is:

from django.db import models

class Reporter(models.Model):
# ...
pass

class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

In the above example, the methods below will be available on the manager reporter.article_set.

- Both sides of a ManyToManyField relation:

class Topping(models.Model):
# ...
pass

class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)

In this example, the methods below will be available both on topping.pizza_set and on pizza.toppings.

add(*objs, bulk=True)

Adds the specified model objects to the related object set.

Example:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.

In the example above, in the case of a ForeignKey relationship, QuerySet.update() is used to perform the update. This requires the objects to already be saved.

You can use the bulk=False argument to instead have the related manager perform the update by calling e.save().

Using add() with a many-to-many relationship, however, will not call any save() methods, but rather create the relationships using QuerySet.bulk_create(). If you need to execute some custom logic when a relationship is created, listen to the m2m_changed signal.

Changed in Django 1.9:
The bulk parameter was added. In older versions, foreign key updates were always done using save(). Use bulk=False if you require the old behavior.

create(**kwargs)

Creates a new object, saves it and puts it in the related object set. Returns the newly created object:

>>> b = Blog.objects.get(id=1)
>>> e = b.entry_set.create(
...     headline='Hello',
...     body_text='Hi',
...     pub_date=datetime.date(2005, 1, 1)
... )

# No need to call e.save() at this point -- it's already been saved.

This is equivalent to (but much simpler than):

>>> b = Blog.objects.get(id=1)
>>> e = Entry(
...     blog=b,
...     headline='Hello',
...     body_text='Hi',
...     pub_date=datetime.date(2005, 1, 1)
... )
>>> e.save(force_insert=True)

Note that there’s no need to specify the keyword argument of the model that defines the relationship. In the above example, we don’t pass the parameter blog to create(). Django figures out that the new Entry object’s blog field should be set to b.

remove(*objs)

Removes the specified model objects from the related object set:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.

Similar to add(), e.save() is called in the example above to perform the update. Using remove() with a many-to-many relationship, however, will delete the relationships using QuerySet.delete() which means no model save() methods are called; listen to the m2m_changed signal if you wish to execute custom code when a relationship is deleted.

For ForeignKey objects, this method only exists if null=True. If the related field can’t be set to None (NULL), then an object can’t be removed from a relation without being added to another. In the above example, removing e from b.entry_set() is equivalent to doing e.blog = None, and because the blog ForeignKey doesn’t have null=True, this is invalid.

For ForeignKey objects, this method accepts a bulk argument to control how to perform the operation. If True (the default), QuerySet.update() is used. If bulk=False, the save() method of each individual model instance is called instead. This triggers the pre_save and post_save signals and comes at the expense of performance.

clear()

Removes all objects from the related object set:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()

Note this doesn’t delete the related objects – it just disassociates them.

Just like remove(), clear() is only available on ForeignKeys where null=True and it also accepts the bulk keyword argument.

set(objs, bulk=True, clear=False)

New in Django 1.9.

Replace the set of related objects:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)

This method accepts a clear argument to control how to perform the operation. If False (the default), the elements missing from the new set are removed using remove() and only the new ones are added. If clear=True, the clear() method is called instead and the whole set is added at once.

The bulk argument is passed on to add().

Note that since set() is a compound operation, it is subject to race conditions. For instance, new objects may be added to the database in between the call to clear() and the call to add().

Note

Note that add(), create(), remove(), clear(), and set() all apply database changes immediately for all types of related fields. In other words, there is no need to call save() on either end of the relationship.

Also, if you are using an intermediate model for a many-to-many relationship, then the add(), create(), remove(), and set() methods are disabled.

Direct Assignment

A related object set can be replaced in bulk with one operation by assigning a new iterable of objects to it:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list

If the foreign key relationship has null=True, then the related manager will first disassociate any existing objects in the related set before adding the contents of new_list. Otherwise the objects in new_list will be added to the existing related object set.

Changed in Django 1.9:
In earlier versions, direct assignment used to perform clear() followed by add(). It now performs a set() with the keyword argument clear=False.

Model class reference

This document covers features of the Model class. For more information about models, see the complete list of Model reference guides.

Attributes

objects

Model.objects

Each non-abstract Model class must have a Manager instance added to it. Django ensures that in your model class you have at least a default Manager specified. If you don’t add your own Manager, Django will add an attribute objects containing default Manager instance. If you add your own Manager instance attribute, the default one does not appear. Consider the following example:

from django.db import models

class Person(models.Model):
# Add manager with another name
people = models.Manager()

For more details on model managers see Managers and Retrieving objects.

Model Meta options

This document explains all the possible metadata options that you can give your model in its internal class Meta.

Available Meta options

abstract

Options.abstract

If abstract = True, this model will be an abstract base class.

app_label

Options.app_label

If a model is defined outside of an application in INSTALLED_APPS, it must declare which app it belongs to:

app_label = 'myapp'

New in Django 1.9.

If you want to represent a model with the format app_label.object_name or app_label.model_name you can use model._meta.label or model._meta.label_lower respectively.

db_table

Options.db_table

The name of the database table to use for the model:

db_table = 'music_album'

Table names

To save you time, Django automatically derives the name of the database table from the name of your model class and the app that contains it. A model’s database table name is constructed by joining the model’s “app label” – the name you used in manage.py startapp – to the model’s class name, with an underscore between them.

For example, if you have an app bookstore (as created by manage.py startapp bookstore), a model defined as class Book will have a database table named bookstore_book.

To override the database table name, use the db_table parameter in class Meta.

If your database table name is an SQL reserved word, or contains characters that aren’t allowed in Python variable names – notably, the hyphen – that’s OK. Django quotes column and table names behind the scenes.

Use lowercase table names for MySQL

It is strongly advised that you use lowercase table names when you override the table name via db_table, particularly if you are using the MySQL backend. See the MySQL notes for more details.

Table name quoting for Oracle

In order to meet the 30-char limitation Oracle has on table names, and match the usual conventions for Oracle databases, Django may shorten table names and turn them all-uppercase. To prevent such transformations, use a quoted name as the value for db_table:

db_table = '"name_left_in_lowercase"'

Such quoted names can also be used with Django’s other supported database backends; except for Oracle, however, the quotes have no effect. See the Oracle notes for more details.

db_tablespace

Options.db_tablespace

The name of the database tablespace to use for this model. The default is the project’s DEFAULT_TABLESPACE setting, if set. If the backend doesn’t support tablespaces, this option is ignored.

default_related_name

Options.default_related_name

New in Django 1.8.

The name that will be used by default for the relation from a related object back to this one. The default is <model_name>_set.

As the reverse name for a field should be unique, be careful if you intend to subclass your model. To work around name collisions, part of the name should contain '%(app_label)s' and '%(model_name)s', which are replaced respectively by the name of the application the model is in, and the name of the model, both lowercased. See the paragraph on related names for abstract models.

get_latest_by

Options.get_latest_by

The name of an orderable field in the model, typically a DateField, DateTimeField, or IntegerField. This specifies the default field to use in your model Manager’s latest() and earliest() methods.

Example:

get_latest_by = "order_date"

See the latest() docs for more.

managed

Options.managed

Defaults to True, meaning Django will create the appropriate database tables in migrate or as part of migrations and remove them as part of a flush management command. That is, Django manages the database tables’ lifecycles.

If False, no database table creation or deletion operations will be performed for this model. This is useful if the model represents an existing table or a database view that has been created by some other means. This is the only difference when managed=False. All other aspects of model handling are exactly the same as normal. This includes

1. Adding an automatic primary key field to the model if you don’t declare it. To avoid confusion for later code readers, it’s recommended to specify all the columns from the database table you are modeling when using unmanaged models.

2. If a model with managed=False contains a ManyToManyField that points to another unmanaged model, then the intermediate table for the many-to-many join will also not be created. However, the intermediary table between one managed and one unmanaged model will be created.

If you need to change this default behavior, create the intermediary table as an explicit model (with managed set as needed) and use the ManyToManyField.through attribute to make the relation use your custom model.

For tests involving models with managed=False, it’s up to you to ensure the correct tables are created as part of the test setup.

If you’re interested in changing the Python-level behavior of a model class, you could use managed=False and create a copy of an existing model. However, there’s a better approach for that situation: Proxy models.

order_with_respect_to

Options.order_with_respect_to

Makes this object orderable with respect to the given field, usually a ForeignKey. This can be used to make related objects orderable with respect to a parent object. For example, if an Answer relates to a Question object, and a question has more than one answer, and the order of answers matters, you’d do this:

from django.db import models

class Question(models.Model):
text = models.TextField()
# ...

class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
# ...

class Meta:
order_with_respect_to = 'question'

When order_with_respect_to is set, two additional methods are provided to retrieve and to set the order of the related objects: get_RELATED_order() and set_RELATED_order(), where RELATED is the lowercased model name. For example, assuming that a Question object has multiple related Answer objects, the list returned contains the primary keys of the related Answer objects:

>>> question = Question.objects.get(id=1)
>>> question.get_answer_order()
[1, 2, 3]

The order of a Question object’s related Answer objects can be set by passing in a list of Answer primary keys:

>>> question.set_answer_order([3, 1, 2])

The related objects also get two methods, get_next_in_order() and get_previous_in_order(), which can be used to access those objects in their proper order. Assuming the Answer objects are ordered by id:

>>> answer = Answer.objects.get(id=2)
>>> answer.get_next_in_order()
<Answer: 3>
>>> answer.get_previous_in_order()
<Answer: 1>

order_with_respect_to implicitly sets the ordering option

Internally, order_with_respect_to adds an additional field/database column named _order and sets the model’s ordering option to this field. Consequently, order_with_respect_to and ordering cannot be used together, and the ordering added by order_with_respect_to will apply whenever you obtain a list of objects of this model.

Changing order_with_respect_to

Because order_with_respect_to adds a new database column, be sure to make and apply the appropriate migrations if you add or change order_with_respect_to after your initial migrate.

ordering

Options.ordering

The default ordering for the object, for use when obtaining lists of objects:

ordering = ['-order_date']

This is a tuple or list of strings. Each string is a field name with an optional “-” prefix, which indicates descending order. Fields without a leading “-” will be ordered ascending. Use the string ”?” to order randomly.

For example, to order by a pub_date field ascending, use this:

ordering = ['pub_date']

To order by pub_date descending, use this:

ordering = ['-pub_date']

To order by pub_date descending, then by author ascending, use this:

ordering = ['-pub_date', 'author']

Default ordering also affects aggregation queries.

Warning

Ordering is not a free operation. Each field you add to the ordering incurs a cost to your database. Each foreign key you add will implicitly include all of its default orderings as well.

permissions

Options.permissions

Extra permissions to enter into the permissions table when creating this object. Add, delete and change permissions are automatically created for each model. This example specifies an extra permission, can_deliver_pizzas:

permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)

This is a list or tuple of 2-tuples in the format (permission_code, human_readable_permission_name).

default_permissions

Options.default_permissions

Defaults to ('add', 'change', 'delete'). You may customize this list, for example, by setting this to an empty list if your app doesn’t require any of the default permissions. It must be specified on the model before the model is created by migrate in order to prevent any omitted permissions from being created.

proxy

Options.proxy

If proxy = True, a model which subclasses another model will be treated as a proxy model.

required_db_features

Options.required_db_features

New in Django 1.9.

List of database features that the current connection should have so that the model is considered during the migration phase. For example, if you set this list to ['gis_enabled'], the model will only be synchronized on GIS-enabled databases. It’s also useful to skip some models when testing with several database backends. Avoid relations between models that may or may not be created as the ORM doesn’t handle this.

required_db_vendor

Options.required_db_vendor

New in Django 1.9.

Name of a supported database vendor that this model is specific to. Current built-in vendor names are: sqlite, postgresql, mysql, oracle. If this attribute is not empty and the current connection vendor doesn’t match it, the model will not be synchronized.

select_on_save

Options.select_on_save

Determines if Django will use the pre-1.6 django.db.models.Model.save() algorithm. The old algorithm uses SELECT to determine if there is an existing row to be updated. The new algorithm tries an UPDATE directly. In some rare cases the UPDATE of an existing row isn’t visible to Django. An example is the PostgreSQL ON UPDATE trigger which returns NULL. In such cases the new algorithm will end up doing an INSERT even when a row exists in the database.

Usually there is no need to set this attribute. The default is False.

See django.db.models.Model.save() for more about the old and new saving algorithm.

unique_together

Options.unique_together

Sets of field names that, taken together, must be unique:

unique_together = (("driver", "restaurant"),)

This is a tuple of tuples that must be unique when considered together. It’s used in the Django admin and is enforced at the database level (i.e., the appropriate UNIQUE statements are included in the CREATE TABLE statement).

For convenience, unique_together can be a single tuple when dealing with a single set of fields:

unique_together = ("driver", "restaurant")

A ManyToManyField cannot be included in unique_together. (It’s not clear what that would even mean!) If you need to validate uniqueness related to a ManyToManyField, try using a signal or an explicit through model.

The ValidationError raised during model validation when the constraint is violated has the unique_together error code.

index_together

Options.index_together

Sets of field names that, taken together, are indexed:

index_together = [
["pub_date", "deadline"],
]

This list of fields will be indexed together (i.e. the appropriate CREATE INDEX statement will be issued.)

For convenience, index_together can be a single list when dealing with a single set of fields:

index_together = ["pub_date", "deadline"]

verbose_name

Options.verbose_name

A human-readable name for the object, singular:

verbose_name = "pizza"

If this isn’t given, Django will use a munged version of the class name: CamelCase becomes camel case.

verbose_name_plural

Options.verbose_name_plural

The plural name for the object:

verbose_name_plural = "stories"

If this isn’t given, Django will use verbose_name + "s".

Read-only Meta attributes

label

Options.label

New in Django 1.9.

Representation of the object, returns app_label.object_name, e.g. 'polls.Question'.

label_lower

Options.label_lower

New in Django 1.9.

Representation of the model, returns app_label.model_name, e.g. 'polls.question'.

Model instance reference

This document describes the details of the Model API. It builds on the material presented in the model and database query guides, so you’ll probably want to read and understand those documents before reading this one.

Throughout this reference we’ll use the example Weblog models presented in the database query guide.

Creating objects

To create a new instance of a model, just instantiate it like any other Python class:

class Model(**kwargs)[source]

The keyword arguments are simply the names of the fields you’ve defined on your model. Note that instantiating a model in no way touches your database; for that, you need to save().

Note

You may be tempted to customize the model by overriding the __init__ method. If you do so, however, take care not to change the calling signature as any change may prevent the model instance from being saved. Rather than overriding __init__, try using one of these approaches:

1. Add a classmethod on the model class:

from django.db import models

class Book(models.Model):
title = models.CharField(max_length=100)

@classmethod
def create(cls, title):
book = cls(title=title)
# do something with the book
return book

book = Book.create("Pride and Prejudice")

2. Add a method on a custom manager (usually preferred):

class BookManager(models.Manager):
def create_book(self, title):
book = self.create(title=title)
# do something with the book
return book

class Book(models.Model):
title = models.CharField(max_length=100)

objects = BookManager()

book = Book.objects.create_book("Pride and Prejudice")

Customizing model loading

classmethod Model.from_db(db, field_names, values)[source]

New in Django 1.8.

The from_db() method can be used to customize model instance creation when loading from the database.

The db argument contains the database alias for the database the model is loaded from, field_names contains the names of all loaded fields, and values contains the loaded values for each field in field_names. The field_names are in the same order as the values, so it is possible to use cls(**(zip(field_names, values))) to instantiate the object. If all of the model’s fields are present, then values are guaranteed to be in the order __init__() expects them. That is, the instance can be created by cls(*values). It is possible to check if all fields are present by consulting cls._deferred - if False, then all fields have been loaded from the database.

In addition to creating the new model, the from_db() method must set the adding and db flags in the new instance’s _state attribute.

Below is an example showing how to record the initial values of fields that are loaded from the database:

@classmethod
def from_db(cls, db, field_names, values):
# default implementation of from_db() (could be replaced
# with super())
if cls._deferred:
instance = cls(**zip(field_names, values))
else:
instance = cls(*values)
instance._state.adding = False
instance._state.db = db
# customization to store the original field values on the instance
instance._loaded_values = dict(zip(field_names, values))
return instance

def save(self, *args, **kwargs):
# Check how the current values differ from ._loaded_values. For example,
# prevent changing the creator_id of the model. (This example doesn't
# support cases where 'creator_id' is deferred).
if not self._state.adding and (
self.creator_id != self._loaded_values['creator_id']):
raise ValueError("Updating the value of creator isn't allowed")
super(...).save(*args, **kwargs)

The example above shows a full from_db() implementation to clarify how that is done. In this case it would of course be possible to just use super() call in the from_db() method.

Refreshing objects from database

Model.refresh_from_db(using=None, fields=None, **kwargs)[source]

New in Django 1.8.

If you need to reload a model’s values from the database, you can use the refresh_from_db() method. When this method is called without arguments the following is done:

1. All non-deferred fields of the model are updated to the values currently present in the database.

2. The previously loaded related instances for which the relation’s value is no longer valid are removed from the reloaded instance. For example, if you have a foreign key from the reloaded instance to another model with name Author, then if obj.author_id != obj.author.id, obj.author will be thrown away, and when next accessed it will be reloaded with the value of obj.author_id.

Note that only fields of the model are reloaded from the database. Other database dependent values such as annotations are not reloaded.

The reloading happens from the database the instance was loaded from, or from the default database if the instance wasn’t loaded from the database. The using argument can be used to force the database used for reloading.

It is possible to force the set of fields to be loaded by using the fields argument.

For example, to test that an update() call resulted in the expected update, you could write a test similar to this:

def test_update_result(self):
obj = MyModel.objects.create(val=1)
MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
# At this point obj.val is still 1, but the value in the database
# was updated to 2. The object's updated value needs to be reloaded
# from the database.
obj.refresh_from_db()
self.assertEqual(obj.val, 2)

Note that when deferred fields are accessed, the loading of the deferred field’s value happens through this method. Thus it is possible to customize the way deferred loading happens. The example below shows how one can reload all of the instance’s fields when a deferred field is reloaded:

class ExampleModel(models.Model):
def refresh_from_db(self, using=None, fields=None, **kwargs):
# fields contains the name of the deferred field to be
# loaded.
if fields is not None:
fields = set(fields)
deferred_fields = self.get_deferred_fields()
# If any deferred field is going to be loaded
if fields.intersection(deferred_fields):
# then load all of them
fields = fields.union(deferred_fields)
super(ExampleModel, self).refresh_from_db(using, fields, **kwargs)

Model.get_deferred_fields()[source]

New in Django 1.8.

A helper method that returns a set containing the attribute names of all those fields that are currently deferred for this model.

Validating objects

There are three steps involved in validating a model:

1. Validate the model fields - Model.clean_fields()

2. Validate the model as a whole - Model.clean()

3. Validate the field uniqueness - Model.validate_unique()

All three steps are performed when you call a model’s full_clean() method.

When you use a ModelForm, the call to is_valid() will perform these validation steps for all the fields that are included on the form. See the ModelForm documentation for more information. You should only need to call a model’s full_clean() method if you plan to handle validation errors yourself, or if you have excluded fields from the ModelForm that require validation.

Model.full_clean(exclude=None, validate_unique=True)[source]

This method calls Model.clean_fields(), Model.clean(), and Model.validate_unique() (if validate_unique is True), in that order and raises a ValidationError that has a message_dict attribute containing errors from all three stages.

The optional exclude argument can be used to provide a list of field names that can be excluded from validation and cleaning. ModelForm uses this argument to exclude fields that aren’t present on your form from being validated since any errors raised could not be corrected by the user.

Note that full_clean() will not be called automatically when you call your model’s save() method. You’ll need to call it manually when you want to run one-step model validation for your own manually created models. For example:

from django.core.exceptions import ValidationError
try:
article.full_clean()
except ValidationError as e:
# Do something based on the errors contained in e.message_dict.
# Display them to a user, or handle them programmatically.
pass

The first step full_clean() performs is to clean each individual field.

Model.clean_fields(exclude=None)[source]

This method will validate all fields on your model. The optional exclude argument lets you provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.

The second step full_clean() performs is to call Model.clean(). This method should be overridden to perform custom validation on your model.

Model.clean()[source]

This method should be used to provide custom model validation, and to modify attributes on your model if desired. For instance, you could use it to automatically provide a value for a field, or to do validation that requires access to more than a single field:

import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _

class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError(_('Draft entries may not have a publication date.'))
# Set the pub_date for published items if it hasn't been set already.
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.date.today()

Note, however, that like Model.full_clean(), a model’s clean() method is not invoked when you call your model’s save() method.

In the above example, the ValidationError exception raised by Model.clean() was instantiated with a string, so it will be stored in a special error dictionary key, NON_FIELD_ERRORS. This key is used for errors that are tied to the entire model instead of to a specific field:

from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
article.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]

To assign exceptions to a specific field, instantiate the ValidationError with a dictionary, where the keys are the field names. We could update the previous example to assign the error to the pub_date field:

class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
...

If you detect errors in multiple fields during Model.clean(), you can also pass a dictionary mapping field names to errors:

raise ValidationError({
'title': ValidationError(_('Missing title.'), code='required'),
'pub_date': ValidationError(_('Invalid date.'), code='invalid'),
})

Finally, full_clean() will check any unique constraints on your model.

Model.validate_unique(exclude=None)[source]

This method is similar to clean_fields(), but validates all uniqueness constraints on your model instead of individual field values. The optional exclude argument allows you to provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.

Note that if you provide an exclude argument to validate_unique(), any unique_together constraint involving one of the fields you provided will not be checked.

Saving objects

To save an object back to the database, call save():

Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)[source]

If you want customized saving behavior, you can override this save() method. See Overriding predefined model methods for more details.

The model save process also has some subtleties; see the sections below.

Auto-incrementing primary keys

If a model has an AutoField — an auto-incrementing primary key — then that auto-incremented value will be calculated and saved as an attribute on your object the first time you call save():

>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id     # Returns None, because b doesn't have an ID yet.
>>> b2.save()
>>> b2.id     # Returns the ID of your new object.

There’s no way to tell what the value of an ID will be before you call save(), because that value is calculated by your database, not by Django.

For convenience, each model has an AutoField named id by default unless you explicitly specify primary_key=True on a field in your model. See the documentation for AutoField for more details.

The pk property

Model.pk

Regardless of whether you define a primary key field yourself, or let Django supply one for you, each model will have a property called pk. It behaves like a normal attribute on the model, but is actually an alias for whichever attribute is the primary key field for the model. You can read and set this value, just as you would for any other attribute, and it will update the correct field in the model.

Explicitly specifying auto-primary-key values

If a model has an AutoField but you want to define a new object’s ID explicitly when saving, just define it explicitly before saving, rather than relying on the auto-assignment of the ID:

>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id     # Returns 3.
>>> b3.save()
>>> b3.id     # Returns 3.

If you assign auto-primary-key values manually, make sure not to use an already-existing primary-key value! If you create a new object with an explicit primary-key value that already exists in the database, Django will assume you’re changing the existing record rather than creating a new one.

Given the above 'Cheddar Talk' blog example, this example would override the previous record in the database:

b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save()  # Overrides the previous blog with ID=3!

See How Django knows to UPDATE vs. INSERT, below, for the reason this happens.

Explicitly specifying auto-primary-key values is mostly useful for bulk-saving objects, when you’re confident you won’t have primary-key collision.

What happens when you save?

When you save an object, Django performs the following steps:

1. Emit a pre-save signal. The signal django.db.models.signals.pre_save is sent, allowing any functions listening for that signal to take some customized action.

2. Pre-process the data. Each field on the object is asked to perform any automated data modification that the field may need to perform.

Most fields do no pre-processing — the field data is kept as-is. Pre-processing is only used on fields that have special behavior. For example, if your model has a DateField with auto_now=True, the pre-save phase will alter the data in the object to ensure that the date field contains the current date stamp. (Our documentation doesn’t yet include a list of all the fields with this “special behavior.”)

3. Prepare the data for the database. Each field is asked to provide its current value in a data type that can be written to the database.

Most fields require no data preparation. Simple data types, such as integers and strings, are ‘ready to write’ as a Python object. However, more complex data types often require some modification.

For example, DateField fields use a Python datetime object to store data. Databases don’t store datetime objects, so the field value must be converted into an ISO-compliant date string for insertion into the database.

4. Insert the data into the database. The pre-processed, prepared data is then composed into an SQL statement for insertion into the database.

5. Emit a post-save signal. The signal django.db.models.signals.post_save is sent, allowing any functions listening for that signal to take some customized action.

How Django knows to UPDATE vs. INSERT

You may have noticed Django database objects use the same save() method for creating and changing objects. Django abstracts the need to use INSERT or UPDATE SQL statements. Specifically, when you call save(), Django follows this algorithm:

- If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the empty string), Django executes an UPDATE.

- If the object’s primary key attribute is not set or if the UPDATE didn’t update anything, Django executes an INSERT.

The one gotcha here is that you should be careful not to specify a primary-key value explicitly when saving new objects, if you cannot guarantee the primary-key value is unused. For more on this nuance, see Explicitly specifying auto-primary-key values above and Forcing an INSERT or UPDATE below.

In Django 1.5 and earlier, Django did a SELECT when the primary key attribute was set. If the SELECT found a row, then Django did an UPDATE, otherwise it did an INSERT. The old algorithm results in one more query in the UPDATE case. There are some rare cases where the database doesn’t report that a row was updated even if the database contains a row for the object’s primary key value. An example is the PostgreSQL ON UPDATE trigger which returns NULL. In such cases it is possible to revert to the old algorithm by setting the select_on_save option to True.

Forcing an INSERT or UPDATE

In some rare circumstances, it’s necessary to be able to force the save() method to perform an SQL INSERT and not fall back to doing an UPDATE. Or vice-versa: update, if possible, but not insert a new row. In these cases you can pass the force_insert=True or force_update=True parameters to the save() method. Obviously, passing both parameters is an error: you cannot both insert and update at the same time!

It should be very rare that you’ll need to use these parameters. Django will almost always do the right thing and trying to override that will lead to errors that are difficult to track down. This feature is for advanced use only.

Using update_fields will force an update similarly to force_update.

Updating attributes based on existing fields

Sometimes you’ll need to perform a simple arithmetic task on a field, such as incrementing or decrementing the current value. The obvious way to achieve this is to do something like:

>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()

If the old number_sold value retrieved from the database was 10, then the value of 11 will be written back to the database.

The process can be made robust, avoiding a race condition, as well as slightly faster by expressing the update relative to the original field value, rather than as an explicit assignment of a new value. Django provides F expressions for performing this kind of relative update. Using F expressions, the previous example is expressed as:

>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()

For more details, see the documentation on F expressions and their use in update queries.

Specifying which fields to save

If save() is passed a list of field names in keyword argument update_fields, only the fields named in that list will be updated. This may be desirable if you want to update just one or a few fields on an object. There will be a slight performance benefit from preventing all of the model fields from being updated in the database. For example:

product.name = 'Name changed again'
product.save(update_fields=['name'])

The update_fields argument can be any iterable containing strings. An empty update_fields iterable will skip the save. A value of None will perform an update on all fields.

Specifying update_fields will force an update.

When saving a model fetched through deferred model loading (only() or defer()) only the fields loaded from the DB will get updated. In effect there is an automatic update_fields in this case. If you assign or change any deferred field value, the field will be added to the updated fields.

Deleting objects

Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False)[source]

Issues an SQL DELETE for the object. This only deletes the object in the database; the Python instance will still exist and will still have data in its fields. This method returns the number of objects deleted and a dictionary with the number of deletions per object type.

For more details, including how to delete objects in bulk, see Deleting objects.

If you want customized deletion behavior, you can override the delete() method. See Overriding predefined model methods for more details.

Sometimes with multi-table inheritance you may want to delete only a child model’s data. Specifying keep_parents=True will keep the parent model’s data.

Changed in Django 1.9:
The keep_parents parameter was added.

Changed in Django 1.9:
The return value describing the number of objects deleted was added.

Pickling objects

When you pickle a model, its current state is pickled. When you unpickle it, it’ll contain the model instance at the moment it was pickled, rather than the data that’s currently in the database.

You can’t share pickles between versions

Pickles of models are only valid for the version of Django that was used to generate them. If you generate a pickle using Django version N, there is no guarantee that pickle will be readable with Django version N+1. Pickles should not be used as part of a long-term archival strategy.

New in Django 1.8.

Since pickle compatibility errors can be difficult to diagnose, such as silently corrupted objects, a RuntimeWarning is raised when you try to unpickle a model in a Django version that is different than the one in which it was pickled.

Other model instance methods

A few object methods have special purposes.

__str__()

Model.__str__()[source]

The __str__() method is called whenever you call str() on an object. Django uses str(obj) in a number of places. Most notably, to display an object in the Django admin site and as the value inserted into a template when it displays an object. Thus, you should always return a nice, human-readable representation of the model from the __str__() method.

For example:

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible  # only if you need to support Python 2
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)

def __str__(self):
return '%s %s' % (self.first_name, self.last_name)

If you’d like compatibility with Python 2, you can decorate your model class with python_2_unicode_compatible() as shown above.

__eq__()

Model.__eq__()[source]

The equality method is defined such that instances with the same primary key value and the same concrete class are considered equal. For proxy models, concrete class is defined as the model’s first non-proxy parent; for all other models it is simply the model’s class.

For example:

from django.db import models

class MyModel(models.Model):
id = models.AutoField(primary_key=True)

class MyProxyModel(MyModel):
class Meta:
proxy = True

class MultitableInherited(MyModel):
pass

MyModel(id=1) == MyModel(id=1)
MyModel(id=1) == MyProxyModel(id=1)
MyModel(id=1) != MultitableInherited(id=1)
MyModel(id=1) != MyModel(id=2)

__hash__()

Model.__hash__()[source]

The __hash__() method is based on the instance’s primary key value. It is effectively hash(obj.pk). If the instance doesn’t have a primary key value then a TypeError will be raised (otherwise the __hash__() method would return different values before and after the instance is saved, but changing the __hash__() value of an instance is forbidden in Python.

get_absolute_url()

Model.get_absolute_url()

Define a get_absolute_url() method to tell Django how to calculate the canonical URL for an object. To callers, this method should appear to return a string that can be used to refer to the object over HTTP.

For example:

def get_absolute_url(self):
return "/people/%i/" % self.id

While this code is correct and simple, it may not be the most portable way to write this kind of method. The reverse() function is usually the best approach.

For example:

def get_absolute_url(self):
from django.core.urlresolvers import reverse
return reverse('people.views.details', args=[str(self.id)])

One place Django uses get_absolute_url() is in the admin app. If an object defines this method, the object-editing page will have a “View on site” link that will jump you directly to the object’s public view, as given by get_absolute_url().

Similarly, a couple of other bits of Django, such as the syndication feed framework, use get_absolute_url() when it is defined. If it makes sense for your model’s instances to each have a unique URL, you should define get_absolute_url().

Warning

You should avoid building the URL from unvalidated user input, in order to reduce possibilities of link or redirect poisoning:

def get_absolute_url(self):
return '/%s/' % self.name

If self.name is '/example.com' this returns '//example.com/' which, in turn, is a valid schema relative URL but not the expected '/%2Fexample.com/'.

It’s good practice to use get_absolute_url() in templates, instead of hard-coding your objects’ URLs. For example, this template code is bad:

<!-- BAD template code. Avoid! -->
<a href="/people/{{ object.id }}/">{{ object.name }}</a>

This template code is much better:

<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

The logic here is that if you change the URL structure of your objects, even for something simple such as correcting a spelling error, you don’t want to have to track down every place that the URL might be created. Specify it once, in get_absolute_url() and have all your other code call that one place.

Note

The string you return from get_absolute_url() must contain only ASCII characters (required by the URI specification, RFC 2396) and be URL-encoded, if necessary.

Code and templates calling get_absolute_url() should be able to use the result directly without any further processing. You may wish to use the django.utils.encoding.iri_to_uri() function to help with this if you are using unicode strings containing characters outside the ASCII range at all.

Extra instance methods

In addition to save(), delete(), a model object might have some of the following methods:

Model.get_FOO_display()

For every field that has choices set, the object will have a get_FOO_display() method, where FOO is the name of the field. This method returns the “human-readable” value of the field.

For example:

from django.db import models

class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)

>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'

Model.get_next_by_FOO(**kwargs)

Model.get_previous_by_FOO(**kwargs)

For every DateField and DateTimeField that does not have null=True, the object will have get_next_by_FOO() and get_previous_by_FOO() methods, where FOO is the name of the field. This returns the next and previous object with respect to the date field, raising a DoesNotExist exception when appropriate.

Both of these methods will perform their queries using the default manager for the model. If you need to emulate filtering used by a custom manager, or want to perform one-off custom filtering, both methods also accept optional keyword arguments, which should be in the format described in Field lookups.

Note that in the case of identical date values, these methods will use the primary key as a tie-breaker. This guarantees that no records are skipped or duplicated. That also means you cannot use those methods on unsaved objects.

Other attributes

DoesNotExist

exception Model.DoesNotExist

This exception is raised by the ORM in a couple places, for example by QuerySet.get() when an object is not found for the given query parameters.

Django provides a DoesNotExist exception as an attribute of each model class to identify the class of object that could not be found and to allow you to catch a particular model class with try/except. The exception is a subclass of django.core.exceptions.ObjectDoesNotExist.

QuerySet API reference

This document describes the details of the QuerySet API. It builds on the material presented in the model and database query guides, so you’ll probably want to read and understand those documents before reading this one.

Throughout this reference we’ll use the example Weblog models presented in the database query guide.

When QuerySets are evaluated

Internally, a QuerySet can be constructed, filtered, sliced, and generally passed around without actually hitting the database. No database activity actually occurs until you do something to evaluate the queryset.

You can evaluate a QuerySet in the following ways:

- Iteration. A QuerySet is iterable, and it executes its database query the first time you iterate over it. For example, this will print the headline of all entries in the database:

for e in Entry.objects.all():
print(e.headline)

Note: Don’t use this if all you want to do is determine if at least one result exists. It’s more efficient to use exists().

- Slicing. As explained in Limiting QuerySets, a QuerySet can be sliced, using Python’s array-slicing syntax. Slicing an unevaluated QuerySet usually returns another unevaluated QuerySet, but Django will execute the database query if you use the “step” parameter of slice syntax, and will return a list. Slicing a QuerySet that has been evaluated also returns a list.

Also note that even though slicing an unevaluated QuerySet returns another unevaluated QuerySet, modifying it further (e.g., adding more filters, or modifying ordering) is not allowed, since that does not translate well into SQL and it would not have a clear meaning either.

- Pickling/Caching. See the following section for details of what is involved when pickling QuerySets. The important thing for the purposes of this section is that the results are read from the database.

- repr(). A QuerySet is evaluated when you call repr() on it. This is for convenience in the Python interactive interpreter, so you can immediately see your results when using the API interactively.

- len(). A QuerySet is evaluated when you call len() on it. This, as you might expect, returns the length of the result list.

Note: If you only need to determine the number of records in the set (and don’t need the actual objects), it’s much more efficient to handle a count at the database level using SQL’s SELECT COUNT(*). Django provides a count() method for precisely this reason.

- list(). Force evaluation of a QuerySet by calling list() on it. For example:

entry_list = list(Entry.objects.all())

- bool(). Testing a QuerySet in a boolean context, such as using bool(), or, and or an if statement, will cause the query to be executed. If there is at least one result, the QuerySet is True, otherwise False. For example:

if Entry.objects.filter(headline="Test"):
print("There is at least one Entry with the headline Test")

Note: If you only want to determine if at least one result exists (and don’t need the actual objects), it’s more efficient to use exists().

Pickling QuerySets

If you pickle a QuerySet, this will force all the results to be loaded into memory prior to pickling. Pickling is usually used as a precursor to caching and when the cached queryset is reloaded, you want the results to already be present and ready for use (reading from the database can take some time, defeating the purpose of caching). This means that when you unpickle a QuerySet, it contains the results at the moment it was pickled, rather than the results that are currently in the database.

If you only want to pickle the necessary information to recreate the QuerySet from the database at a later time, pickle the query attribute of the QuerySet. You can then recreate the original QuerySet (without any results loaded) using some code like this:

>>> import pickle
>>> query = pickle.loads(s)     # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query            # Restore the original 'query'.

The query attribute is an opaque object. It represents the internals of the query construction and is not part of the public API. However, it is safe (and fully supported) to pickle and unpickle the attribute’s contents as described here.

You can’t share pickles between versions

Pickles of QuerySets are only valid for the version of Django that was used to generate them. If you generate a pickle using Django version N, there is no guarantee that pickle will be readable with Django version N+1. Pickles should not be used as part of a long-term archival strategy.

New in Django 1.8.

Since pickle compatibility errors can be difficult to diagnose, such as silently corrupted objects, a RuntimeWarning is raised when you try to unpickle a queryset in a Django version that is different than the one in which it was pickled.

QuerySet API

Here’s the formal declaration of a QuerySet:

class QuerySet(model=None, query=None, using=None)[source]

Usually when you’ll interact with a QuerySet you’ll use it by chaining filters. To make this work, most QuerySet methods return new querysets. These methods are covered in detail later in this section.

The QuerySet class has two public attributes you can use for introspection:

ordered

True if the QuerySet is ordered — i.e. has an order_by() clause or a default ordering on the model. False otherwise.

db

The database that will be used if this query is executed now.

Note

The query parameter to QuerySet exists so that specialized query subclasses such as GeoQuerySet can reconstruct internal query state. The value of the parameter is an opaque representation of that query state and is not part of a public API. To put it simply: if you need to ask, you don’t need to use it.

Methods that return new QuerySets

Django provides a range of QuerySet refinement methods that modify either the types of results returned by the QuerySet or the way its SQL query is executed.

filter()

filter(**kwargs)

Returns a new QuerySet containing objects that match the given lookup parameters.

The lookup parameters (**kwargs) should be in the format described in Field lookups below. Multiple parameters are joined via AND in the underlying SQL statement.

If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects.

exclude()

exclude(**kwargs)

Returns a new QuerySet containing objects that do not match the given lookup parameters.

The lookup parameters (**kwargs) should be in the format described in Field lookups below. Multiple parameters are joined via AND in the underlying SQL statement, and the whole thing is enclosed in a NOT().

This example excludes all entries whose pub_date is later than 2005-1-3 AND whose headline is “Hello”:

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

In SQL terms, that evaluates to:

SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

This example excludes all entries whose pub_date is later than 2005-1-3 OR whose headline is “Hello”:

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')

In SQL terms, that evaluates to:

SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'

Note the second example is more restrictive.

If you need to execute more complex queries (for example, queries with OR statements), you can use Q objects.

annotate()

annotate(*args, **kwargs)

Annotates each object in the QuerySet with the provided list of query expressions. An expression may be a simple value, a reference to a field on the model (or any related models), or an aggregate expression (averages, sums, etc.) that has been computed over the objects that are related to the objects in the QuerySet.

New in Django 1.8:
Previous versions of Django only allowed aggregate functions to be used as annotations. It is now possible to annotate a model with all kinds of expressions.

Each argument to annotate() is an annotation that will be added to each object in the QuerySet that is returned.

The aggregation functions that are provided by Django are described in Aggregation Functions below.

Annotations specified using keyword arguments will use the keyword as the alias for the annotation. Anonymous arguments will have an alias generated for them based upon the name of the aggregate function and the model field that is being aggregated. Only aggregate expressions that reference a single field can be anonymous arguments. Everything else must be a keyword argument.

For example, if you were manipulating a list of blogs, you may want to determine how many entries have been made in each blog:

>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count('entry'))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42

The Blog model doesn’t define an entry__count attribute by itself, but by using a keyword argument to specify the aggregate function, you can control the name of the annotation:

>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42

For an in-depth discussion of aggregation, see the topic guide on Aggregation.

order_by()

order_by(*fields)

By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the model’s Meta. You can override this on a per-QuerySet basis by using the order_by method.

Example:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

The result above will be ordered by pub_date descending, then by headline ascending. The negative sign in front of "-pub_date" indicates descending order. Ascending order is implied. To order randomly, use "?", like so:

Entry.objects.order_by('?')

Note: order_by('?') queries may be expensive and slow, depending on the database backend you’re using.

To order by a field in a different model, use the same syntax as when you are querying across model relations. That is, the name of the field, followed by a double underscore (__), followed by the name of the field in the new model, and so on for as many models as you want to join. For example:

Entry.objects.order_by('blog__name', 'headline')

If you try to order by a field that is a relation to another model, Django will use the default ordering on the related model, or order by the related model’s primary key if there is no Meta.ordering specified. For example, since the Blog model has no default ordering specified:

Entry.objects.order_by('blog')

...is identical to:

Entry.objects.order_by('blog__id')

If Blog had ordering = ['name'], then the first queryset would be identical to:

Entry.objects.order_by('blog__name')

It is also possible to order a queryset by a related field, without incurring the cost of a JOIN, by referring to the _id of the related field:

# No Join
Entry.objects.order_by('blog_id')

# Join
Entry.objects.order_by('blog__id')

You can also order by query expressions by calling asc() or desc() on the expression:

Entry.objects.order_by(Coalesce('summary', 'headline').desc())

New in Django 1.8:
Ordering by query expressions was added.

Be cautious when ordering by fields in related models if you are also using distinct(). See the note in distinct() for an explanation of how related model ordering can change the expected results.

Note

It is permissible to specify a multi-valued field to order the results by (for example, a ManyToManyField field, or the reverse relation of a ForeignKey field).

Consider this case:

class Event(Model):
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
related_name='children',
)
date = models.DateField()

Event.objects.order_by('children__date')

Here, there could potentially be multiple ordering data for each Event; each Event with multiple children will be returned multiple times into the new QuerySet that order_by() creates. In other words, using order_by() on the QuerySet could return more items than you were working on to begin with - which is probably neither expected nor useful.

Thus, take care when using multi-valued field to order the results. If you can be sure that there will only be one ordering piece of data for each of the items you’re ordering, this approach should not present problems. If not, make sure the results are what you expect.

There’s no way to specify whether ordering should be case sensitive. With respect to case-sensitivity, Django will order results however your database backend normally orders them.

You can order by a field converted to lowercase with Lower which will achieve case-consistent ordering:

Entry.objects.order_by(Lower('headline').desc())

New in Django 1.8:
The ability to order by expressions like Lower was added.

If you don’t want any ordering to be applied to a query, not even the default ordering, call order_by() with no parameters.

You can tell if a query is ordered or not by checking the QuerySet.ordered attribute, which will be True if the QuerySet has been ordered in any way.

Each order_by() call will clear any previous ordering. For example, this query will be ordered by pub_date and not headline:

Entry.objects.order_by('headline').order_by('pub_date')

Warning

Ordering is not a free operation. Each field you add to the ordering incurs a cost to your database. Each foreign key you add will implicitly include all of its default orderings as well.

reverse()

reverse()

Use the reverse() method to reverse the order in which a queryset’s elements are returned. Calling reverse() a second time restores the ordering back to the normal direction.

To retrieve the “last” five items in a queryset, you could do this:

my_queryset.reverse()[:5]

Note that this is not quite the same as slicing from the end of a sequence in Python. The above example will return the last item first, then the penultimate item and so on. If we had a Python sequence and looked at seq[-5:], we would see the fifth-last item first. Django doesn’t support that mode of access (slicing from the end), because it’s not possible to do it efficiently in SQL.

Also, note that reverse() should generally only be called on a QuerySet which has a defined ordering (e.g., when querying against a model which defines a default ordering, or when using order_by()). If no such ordering is defined for a given QuerySet, calling reverse() on it has no real effect (the ordering was undefined prior to calling reverse(), and will remain undefined afterward).

distinct()

distinct(*fields)

Returns a new QuerySet that uses SELECT DISTINCT in its SQL query. This eliminates duplicate rows from the query results.

By default, a QuerySet will not eliminate duplicate rows. In practice, this is rarely a problem, because simple queries such as Blog.objects.all() don’t introduce the possibility of duplicate result rows. However, if your query spans multiple tables, it’s possible to get duplicate results when a QuerySet is evaluated. That’s when you’d use distinct().

Note

Any fields used in an order_by() call are included in the SQL SELECT columns. This can sometimes lead to unexpected results when used in conjunction with distinct(). If you order by fields from a related model, those fields will be added to the selected columns and they may make otherwise duplicate rows appear to be distinct. Since the extra columns don’t appear in the returned results (they are only there to support ordering), it sometimes looks like non-distinct results are being returned.

Similarly, if you use a values() query to restrict the columns selected, the columns used in any order_by() (or default model ordering) will still be involved and may affect uniqueness of the results.

The moral here is that if you are using distinct() be careful about ordering by related models. Similarly, when using distinct() and values() together, be careful when ordering by fields not in the values() call.

On PostgreSQL only, you can pass positional arguments (*fields) in order to specify the names of fields to which the DISTINCT should apply. This translates to a SELECT DISTINCT ON SQL query. Here’s the difference. For a normal distinct() call, the database compares each field in each row when determining which rows are distinct. For a distinct() call with specified field names, the database will only compare the specified field names.

Note

When you specify field names, you must provide an order_by() in the QuerySet, and the fields in order_by() must start with the fields in distinct(), in the same order.

For example, SELECT DISTINCT ON (a) gives you the first row for each value in column a. If you don’t specify an order, you’ll get some arbitrary row.

Examples (those after the first will only work on PostgreSQL):

>>> Author.objects.distinct()
[...]

>>> Entry.objects.order_by('pub_date').distinct('pub_date')
[...]

>>> Entry.objects.order_by('blog').distinct('blog')
[...]

>>> Entry.objects.order_by('author', 'pub_date').distinct('author', 'pub_date')
[...]

>>> Entry.objects.order_by('blog__name', 'mod_date').distinct('blog__name', 'mod_date')
[...]

>>> Entry.objects.order_by('author', 'pub_date').distinct('author')
[...]

Note

Keep in mind that order_by() uses any default related model ordering that has been defined. You might have to explicitly order by the relation _id or referenced field to make sure the DISTINCT ON expressions match those at the beginning of the ORDER BY clause. For example, if the Blog model defined an ordering by name:

Entry.objects.order_by('blog').distinct('blog')

...wouldn’t work because the query would be ordered by blog__name thus mismatching the DISTINCT ON expression. You’d have to explicitly order by the relation _id field (blog_id in this case) or the referenced one (blog__pk) to make sure both expressions match.

values()

values(*fields)

Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable.

Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects.

This example compares the dictionaries of values() with the normal model objects:

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
[<Blog: Beatles Blog>]

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]

The values() method takes optional positional arguments, *fields, which specify field names to which the SELECT should be limited. If you specify the fields, each dictionary will contain only the field keys/values for the fields you specify. If you don’t specify the fields, each dictionary will contain a key and value for every field in the database table.

Example:

>>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]

A few subtleties that are worth mentioning:

- If you have a field called foo that is a ForeignKey, the default values() call will return a dictionary key called foo_id, since this is the name of the hidden model attribute that stores the actual value (the foo attribute refers to the related model). When you are calling values() and passing in field names, you can pass in either foo or foo_id and you will get back the same thing (the dictionary key will match the field name you passed in).

For example:

>>> Entry.objects.values()
[{'blog_id': 1, 'headline': 'First Entry', ...}, ...]

>>> Entry.objects.values('blog')
[{'blog': 1}, ...]

>>> Entry.objects.values('blog_id')
[{'blog_id': 1}, ...]

- When using values() together with distinct(), be aware that ordering can affect the results. See the note in distinct() for details.

- If you use a values() clause after an extra() call, any fields defined by a select argument in the extra() must be explicitly included in the values() call. Any extra() call made after a values() call will have its extra selected fields ignored.

- Calling only() and defer() after values() doesn’t make sense, so doing so will raise a NotImplementedError.

It is useful when you know you’re only going to need values from a small number of the available fields and you won’t need the functionality of a model instance object. It’s more efficient to select only the fields you need to use.

Finally, note that you can call filter(), order_by(), etc. after the values() call, that means that these two calls are identical:

Blog.objects.values().order_by('id')
Blog.objects.order_by('id').values()

The people who made Django prefer to put all the SQL-affecting methods first, followed (optionally) by any output-affecting methods (such as values()), but it doesn’t really matter. This is your chance to really flaunt your individualism.

You can also refer to fields on related models with reverse relations through OneToOneField, ForeignKey and ManyToManyField attributes:

Blog.objects.values('name', 'entry__headline')
[{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...]

Warning

Because ManyToManyField attributes and reverse relations can have multiple related rows, including these can have a multiplier effect on the size of your result set. This will be especially pronounced if you include multiple such fields in your values() query, in which case all possible combinations will be returned.

values_list()

values_list(*fields, flat=False)

This is similar to values() except that instead of returning dictionaries, it returns tuples when iterated over. Each tuple contains the value from the respective field passed into the values_list() call — so the first item is the first field, etc. For example:

>>> Entry.objects.values_list('id', 'headline')
[(1, 'First entry'), ...]

If you only pass in a single field, you can also pass in the flat parameter. If True, this will mean the returned results are single values, rather than one-tuples. An example should make the difference clearer:

>>> Entry.objects.values_list('id').order_by('id')
[(1,), (2,), (3,), ...]

>>> Entry.objects.values_list('id', flat=True).order_by('id')
[1, 2, 3, ...]

It is an error to pass in flat when there is more than one field.

If you don’t pass any values to values_list(), it will return all the fields in the model, in the order they were declared.

A common need is to get a specific field value of a certain model instance. To achieve that, use values_list() followed by a get() call:

>>> Entry.objects.values_list('headline', flat=True).get(pk=1)
'First entry'

values() and values_list() are both intended as optimizations for a specific use case: retrieving a subset of data without the overhead of creating a model instance. This metaphor falls apart when dealing with many-to-many and other multivalued relations (such as the one-to-many relation of a reverse foreign key) because the “one row, one object” assumption doesn’t hold.

For example, notice the behavior when querying across a ManyToManyField:

>>> Author.objects.values_list('name', 'entry__headline')
[('Noam Chomsky', 'Impressions of Gaza'),
('George Orwell', 'Why Socialists Do Not Believe in Fun'),
('George Orwell', 'In Defence of English Cooking'),
('Don Quixote', None)]

Authors with multiple entries appear multiple times and authors without any entries have None for the entry headline.

Similarly, when querying a reverse foreign key, None appears for entries not having any author:

>>> Entry.objects.values_list('authors')
[('Noam Chomsky',), ('George Orwell',), (None,)]

dates()

dates(field, kind, order='ASC')

Returns a QuerySet that evaluates to a list of datetime.date objects representing all available dates of a particular kind within the contents of the QuerySet.

field should be the name of a DateField of your model. kind should be either "year", "month" or "day". Each datetime.date object in the result list is “truncated” to the given type.

- "year" returns a list of all distinct year values for the field.

- "month" returns a list of all distinct year/month values for the field.

- "day" returns a list of all distinct year/month/day values for the field.

order, which defaults to 'ASC', should be either 'ASC' or 'DESC'. This specifies how to order the results.

Examples:

>>> Entry.objects.dates('pub_date', 'year')
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates('pub_date', 'month')
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates('pub_date', 'day')
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.date(2005, 3, 20)]

datetimes()

datetimes(field_name, kind, order='ASC', tzinfo=None)

Returns a QuerySet that evaluates to a list of datetime.datetime objects representing all available dates of a particular kind within the contents of the QuerySet.

field_name should be the name of a DateTimeField of your model.

kind should be either "year", "month", "day", "hour", "minute" or "second". Each datetime.datetime object in the result list is “truncated” to the given type.

order, which defaults to 'ASC', should be either 'ASC' or 'DESC'. This specifies how to order the results.

tzinfo defines the time zone to which datetimes are converted prior to truncation. Indeed, a given datetime has different representations depending on the time zone in use. This parameter must be a datetime.tzinfo object. If it’s None, Django uses the current time zone. It has no effect when USE_TZ is False.

Note

This function performs time zone conversions directly in the database. As a consequence, your database must be able to interpret the value of tzinfo.tzname(None). This translates into the following requirements:

- SQLite: install pytz — conversions are actually performed in Python.

- PostgreSQL: no requirements (see Time Zones).

- Oracle: no requirements (see Choosing a Time Zone File).

- MySQL: install pytz and load the time zone tables with mysql_tzinfo_to_sql.

none()

none()

Calling none() will create a queryset that never returns any objects and no query will be executed when accessing the results. A qs.none() queryset is an instance of EmptyQuerySet.

Examples:

>>> Entry.objects.none()
[]
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True

all()

all()

Returns a copy of the current QuerySet (or QuerySet subclass). This can be useful in situations where you might want to pass in either a model manager or a QuerySet and do further filtering on the result. After calling all() on either object, you’ll definitely have a QuerySet to work with.

When a QuerySet is evaluated, it typically caches its results. If the data in the database might have changed since a QuerySet was evaluated, you can get updated results for the same query by calling all() on a previously evaluated QuerySet.

select_related()

select_related(*fields)

Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query. This is a performance booster which results in a single more complex query but means later use of foreign-key relationships won’t require database queries.

The following examples illustrate the difference between plain lookups and select_related() lookups. Here’s standard lookup:

# Hits the database.
e = Entry.objects.get(id=5)

# Hits the database again to get the related Blog object.
b = e.blog

And here’s select_related lookup:

# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)

# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog

You can use select_related() with any queryset of objects:

from django.utils import timezone

# Find all the blogs with entries scheduled to be published in the future.
blogs = set()

for e in Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog'):
# Without select_related(), this would make a database query for each
# loop iteration in order to fetch the related blog for each entry.
blogs.add(e.blog)

The order of filter() and select_related() chaining isn’t important. These querysets are equivalent:

Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())

You can follow foreign keys in a similar way to querying them. If you have the following models:

from django.db import models

class City(models.Model):
# ...
pass

class Person(models.Model):
# ...
hometown = models.ForeignKey(
City,
on_delete=models.SET_NULL,
blank=True,
null=True,
)

class Book(models.Model):
# ...
author = models.ForeignKey(Person, on_delete=models.CASCADE)

... then a call to Book.objects.select_related('author__hometown').get(id=4) will cache the related Person and the related City:

b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author         # Doesn't hit the database.
c = p.hometown       # Doesn't hit the database.

b = Book.objects.get(id=4) # No select_related() in this example.
p = b.author         # Hits the database.
c = p.hometown       # Hits the database.

You can refer to any ForeignKey or OneToOneField relation in the list of fields passed to select_related().

You can also refer to the reverse direction of a OneToOneField in the list of fields passed to select_related — that is, you can traverse a OneToOneField back to the object on which the field is defined. Instead of specifying the field name, use the related_name for the field on the related object.

There may be some situations where you wish to call select_related() with a lot of related objects, or where you don’t know all of the relations. In these cases it is possible to call select_related() with no arguments. This will follow all non-null foreign keys it can find - nullable foreign keys must be specified. This is not recommended in most cases as it is likely to make the underlying query more complex, and return more data, than is actually needed.

If you need to clear the list of related fields added by past calls of select_related on a QuerySet, you can pass None as a parameter:

>>> without_relations = queryset.select_related(None)

Chaining select_related calls works in a similar way to other methods - that is that select_related('foo', 'bar') is equivalent to select_related('foo').select_related('bar').

prefetch_related()

prefetch_related(*lookups)

Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.

This has a similar purpose to select_related, in that both are designed to stop the deluge of database queries that is caused by accessing related objects, but the strategy is quite different.

select_related works by creating an SQL join and including the fields of the related object in the SELECT statement. For this reason, select_related gets the related objects in the same database query. However, to avoid the much larger result set that would result from joining across a ‘many’ relationship, select_related is limited to single-valued relationships - foreign key and one-to-one.

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related. It also supports prefetching of GenericRelation and GenericForeignKey, however, it must be restricted to a homogeneous set of results. For example, prefetching objects referenced by a GenericForeignKey is only supported if the query is restricted to one ContentType.

For example, suppose you have these models:

from django.db import models

class Topping(models.Model):
name = models.CharField(max_length=30)

class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)

def __str__(self):              # __unicode__ on Python 2
return "%s (%s)" % (
self.name,
", ".join(topping.name for topping in self.toppings.all()),
)

and run:

>>> Pizza.objects.all()
["Hawaiian (ham, pineapple)", "Seafood (prawns, smoked salmon)"...

The problem with this is that every time Pizza.__str__() asks for self.toppings.all() it has to query the database, so Pizza.objects.all() will run a query on the Toppings table for every item in the Pizza QuerySet.

We can reduce to just two queries using prefetch_related:

>>> Pizza.objects.all().prefetch_related('toppings')

This implies a self.toppings.all() for each Pizza; now each time self.toppings.all() is called, instead of having to go to the database for the items, it will find them in a prefetched QuerySet cache that was populated in a single query.

That is, all the relevant toppings will have been fetched in a single query, and used to make QuerySets that have a pre-filled cache of the relevant results; these QuerySets are then used in the self.toppings.all() calls.

The additional queries in prefetch_related() are executed after the QuerySet has begun to be evaluated and the primary query has been executed.

Note that the result cache of the primary QuerySet and all specified related objects will then be fully loaded into memory. This changes the typical behavior of QuerySets, which normally try to avoid loading all objects into memory before they are needed, even after a query has been executed in the database.

Note

Remember that, as always with QuerySets, any subsequent chained methods which imply a different database query will ignore previously cached results, and retrieve data using a fresh database query. So, if you write the following:

>>> pizzas = Pizza.objects.prefetch_related('toppings')
>>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]

...then the fact that pizza.toppings.all() has been prefetched will not help you. The prefetch_related('toppings') implied pizza.toppings.all(), but pizza.toppings.filter() is a new and different query. The prefetched cache can’t help here; in fact it hurts performance, since you have done a database query that you haven’t used. So use this feature with caution!

You can also use the normal join syntax to do related fields of related fields. Suppose we have an additional model to the example above:

class Restaurant(models.Model):
pizzas = models.ManyToManyField(Pizza, related_name='restaurants')
best_pizza = models.ForeignKey(Pizza, related_name='championed_by')

The following are all legal:

>>> Restaurant.objects.prefetch_related('pizzas__toppings')

This will prefetch all pizzas belonging to restaurants, and all toppings belonging to those pizzas. This will result in a total of 3 database queries - one for the restaurants, one for the pizzas, and one for the toppings.

>>> Restaurant.objects.prefetch_related('best_pizza__toppings')

This will fetch the best pizza and all the toppings for the best pizza for each restaurant. This will be done in 3 database queries - one for the restaurants, one for the ‘best pizzas’, and one for one for the toppings.

Of course, the best_pizza relationship could also be fetched using select_related to reduce the query count to 2:

>>> Restaurant.objects.select_related('best_pizza').prefetch_related('best_pizza__toppings')

Since the prefetch is executed after the main query (which includes the joins needed by select_related), it is able to detect that the best_pizza objects have already been fetched, and it will skip fetching them again.

Chaining prefetch_related calls will accumulate the lookups that are prefetched. To clear any prefetch_related behavior, pass None as a parameter:

>>> non_prefetched = qs.prefetch_related(None)

One difference to note when using prefetch_related is that objects created by a query can be shared between the different objects that they are related to i.e. a single Python model instance can appear at more than one point in the tree of objects that are returned. This will normally happen with foreign key relationships. Typically this behavior will not be a problem, and will in fact save both memory and CPU time.

While prefetch_related supports prefetching GenericForeignKey relationships, the number of queries will depend on the data. Since a GenericForeignKey can reference data in multiple tables, one query per table referenced is needed, rather than one query for all the items. There could be additional queries on the ContentType table if the relevant rows have not already been fetched.

prefetch_related in most cases will be implemented using an SQL query that uses the ‘IN’ operator. This means that for a large QuerySet a large ‘IN’ clause could be generated, which, depending on the database, might have performance problems of its own when it comes to parsing or executing the SQL query. Always profile for your use case!

Note that if you use iterator() to run the query, prefetch_related() calls will be ignored since these two optimizations do not make sense together.

You can use the Prefetch object to further control the prefetch operation.

In its simplest form Prefetch is equivalent to the traditional string based lookups:

>>> Restaurant.objects.prefetch_related(Prefetch('pizzas__toppings'))

You can provide a custom queryset with the optional queryset argument. This can be used to change the default ordering of the queryset:

>>> Restaurant.objects.prefetch_related(
...     Prefetch('pizzas__toppings', queryset=Toppings.objects.order_by('name')))

Or to call select_related() when applicable to reduce the number of queries even further:

>>> Pizza.objects.prefetch_related(
...     Prefetch('restaurants', queryset=Restaurant.objects.select_related('best_pizza')))

You can also assign the prefetched result to a custom attribute with the optional to_attr argument. The result will be stored directly in a list.

This allows prefetching the same relation multiple times with a different QuerySet; for instance:

>>> vegetarian_pizzas = Pizza.objects.filter(vegetarian=True)
>>> Restaurant.objects.prefetch_related(
...     Prefetch('pizzas', to_attr='menu'),
...     Prefetch('pizzas', queryset=vegetarian_pizzas, to_attr='vegetarian_menu'))

Lookups created with custom to_attr can still be traversed as usual by other lookups:

>>> vegetarian_pizzas = Pizza.objects.filter(vegetarian=True)
>>> Restaurant.objects.prefetch_related(
...     Prefetch('pizzas', queryset=vegetarian_pizzas, to_attr='vegetarian_menu'),
...     'vegetarian_menu__toppings')

Using to_attr is recommended when filtering down the prefetch result as it is less ambiguous than storing a filtered result in the related manager’s cache:

>>> queryset = Pizza.objects.filter(vegetarian=True)
>>>
>>> # Recommended:
>>> restaurants = Restaurant.objects.prefetch_related(
...     Prefetch('pizzas', queryset=queryset, to_attr='vegetarian_pizzas'))
>>> vegetarian_pizzas = restaurants[0].vegetarian_pizzas
>>>
>>> # Not recommended:
>>> restaurants = Restaurant.objects.prefetch_related(
...     Prefetch('pizzas', queryset=queryset))
>>> vegetarian_pizzas = restaurants[0].pizzas.all()

Custom prefetching also works with single related relations like forward ForeignKey or OneToOneField. Generally you’ll want to use select_related() for these relations, but there are a number of cases where prefetching with a custom QuerySet is useful:

- You want to use a QuerySet that performs further prefetching on related models.

- You want to prefetch only a subset of the related objects.

- You want to use performance optimization techniques like deferred fields:

>>> queryset = Pizza.objects.only('name')
>>>
>>> restaurants = Restaurant.objects.prefetch_related(
...     Prefetch('best_pizza', queryset=queryset))

Note

The ordering of lookups matters.

Take the following examples:

>>> prefetch_related('pizzas__toppings', 'pizzas')

This works even though it’s unordered because 'pizzas__toppings' already contains all the needed information, therefore the second argument 'pizzas' is actually redundant.

>>> prefetch_related('pizzas__toppings', Prefetch('pizzas', queryset=Pizza.objects.all()))

This will raise a ValueError because of the attempt to redefine the queryset of a previously seen lookup. Note that an implicit queryset was created to traverse 'pizzas' as part of the 'pizzas__toppings' lookup.

>>> prefetch_related('pizza_list__toppings', Prefetch('pizzas', to_attr='pizza_list'))

This will trigger an AttributeError because 'pizza_list' doesn’t exist yet when 'pizza_list__toppings' is being processed.

This consideration is not limited to the use of Prefetch objects. Some advanced techniques may require that the lookups be performed in a specific order to avoid creating extra queries; therefore it’s recommended to always carefully order prefetch_related arguments.

extra()

extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)

Sometimes, the Django query syntax by itself can’t easily express a complex WHERE clause. For these edge cases, Django provides the extra() QuerySet modifier — a hook for injecting specific clauses into the SQL generated by a QuerySet.

Use this method as a last resort

This is an old API that we aim to deprecate at some point in the future. Use it only if you cannot express your query using other queryset methods. If you do need to use it, please file a ticket using the QuerySet.extra keyword with your use case (please check the list of existing tickets first) so that we can enhance the QuerySet API to allow removing extra(). We are no longer improving or fixing bugs for this method.

For example, this use of extra():

>>> qs.extra(
...     select={'val': "select col from sometable where othercol = %s"},
...     select_params=(someparam,),
... )

is equivalent to:

>>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

The main benefit of using RawSQL is that you can set output_field if needed. The main downside is that if you refer to some table alias of the queryset in the raw SQL, then it is possible that Django might change that alias (for example, when the queryset is used as a subquery in yet another query).

Warning

You should be very careful whenever you use extra(). Every time you use it, you should escape any parameters that the user can control by using params in order to protect against SQL injection attacks . Please read more about SQL injection protection.

By definition, these extra lookups may not be portable to different database engines (because you’re explicitly writing SQL code) and violate the DRY principle, so you should avoid them if possible.

Specify one or more of params, select, where or tables. None of the arguments is required, but you should use at least one of them.

- select

The select argument lets you put extra fields in the SELECT clause. It should be a dictionary mapping attribute names to SQL clauses to use to calculate that attribute.

Example:

Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})

As a result, each Entry object will have an extra attribute, is_recent, a boolean representing whether the entry’s pub_date is greater than Jan. 1, 2006.

Django inserts the given SQL snippet directly into the SELECT statement, so the resulting SQL of the above example would be something like:

SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
FROM blog_entry;

The next example is more advanced; it does a subquery to give each resulting Blog object an entry_count attribute, an integer count of associated Entry objects:

Blog.objects.extra(
select={
'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
},
)

In this particular case, we’re exploiting the fact that the query will already contain the blog_blog table in its FROM clause.

The resulting SQL of the above example would be:

SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;

Note that the parentheses required by most database engines around subqueries are not required in Django’s select clauses. Also note that some database backends, such as some MySQL versions, don’t support subqueries.

In some rare cases, you might wish to pass parameters to the SQL fragments in extra(select=...). For this purpose, use the select_params parameter. Since select_params is a sequence and the select attribute is a dictionary, some care is required so that the parameters are matched up correctly with the extra select pieces. In this situation, you should use a collections.OrderedDict for the select value, not just a normal Python dictionary.

This will work, for example:

Blog.objects.extra(
select=OrderedDict([('a', '%s'), ('b', '%s')]),
select_params=('one', 'two'))

If you need to use a literal %s inside your select string, use the sequence %%s.

Changed in Django 1.8:
Prior to 1.8, you were unable to escape a literal %s.

- where / tables

You can define explicit SQL WHERE clauses — perhaps to perform non-explicit joins — by using where. You can manually add tables to the SQL FROM clause by using tables.

where and tables both take a list of strings. All where parameters are “AND”ed to any other search criteria.

Example:

Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])

...translates (roughly) into the following SQL:

SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')

Be careful when using the tables parameter if you’re specifying tables that are already used in the query. When you add extra tables via the tables parameter, Django assumes you want that table included an extra time, if it is already included. That creates a problem, since the table name will then be given an alias. If a table appears multiple times in an SQL statement, the second and subsequent occurrences must use aliases so the database can tell them apart. If you’re referring to the extra table you added in the extra where parameter this is going to cause errors.

Normally you’ll only be adding extra tables that don’t already appear in the query. However, if the case outlined above does occur, there are a few solutions. First, see if you can get by without including the extra table and use the one already in the query. If that isn’t possible, put your extra() call at the front of the queryset construction so that your table is the first use of that table. Finally, if all else fails, look at the query produced and rewrite your where addition to use the alias given to your extra table. The alias will be the same each time you construct the queryset in the same way, so you can rely upon the alias name to not change.

- order_by

If you need to order the resulting queryset using some of the new fields or tables you have included via extra() use the order_by parameter to extra() and pass in a sequence of strings. These strings should either be model fields (as in the normal order_by() method on querysets), of the form table_name.column_name or an alias for a column that you specified in the select parameter to extra().

For example:

q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
q = q.extra(order_by = ['-is_recent'])

This would sort all the items for which is_recent is true to the front of the result set (True sorts before False in a descending ordering).

This shows, by the way, that you can make multiple calls to extra() and it will behave as you expect (adding new constraints each time).

- params

The where parameter described above may use standard Python database string placeholders — '%s' to indicate parameters the database engine should automatically quote. The params argument is a list of any extra parameters to be substituted.

Example:

Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

Always use params instead of embedding values directly into where because params will ensure values are quoted correctly according to your particular backend. For example, quotes will be escaped correctly.

Bad:

Entry.objects.extra(where=["headline='Lennon'"])

Good:

Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

Warning

If you are performing queries on MySQL, note that MySQL’s silent type coercion may cause unexpected results when mixing types. If you query on a string type column, but with an integer value, MySQL will coerce the types of all values in the table to an integer before performing the comparison. For example, if your table contains the values 'abc', 'def' and you query for WHERE mycolumn=0, both rows will match. To prevent this, perform the correct typecasting before using the value in a query.

defer()

defer(*fields)

In some complex data-modeling situations, your models might contain a lot of fields, some of which could contain a lot of data (for example, text fields), or require expensive processing to convert them to Python objects. If you are using the results of a queryset in some situation where you don’t know if you need those particular fields when you initially fetch the data, you can tell Django not to retrieve them from the database.

This is done by passing the names of the fields to not load to defer():

Entry.objects.defer("headline", "body")

A queryset that has deferred fields will still return model instances. Each deferred field will be retrieved from the database if you access that field (one at a time, not all the deferred fields at once).

You can make multiple calls to defer(). Each call adds new fields to the deferred set:

# Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")

The order in which fields are added to the deferred set does not matter. Calling defer() with a field name that has already been deferred is harmless (the field will still be deferred).

You can defer loading of fields in related models (if the related models are loading via select_related()) by using the standard double-underscore notation to separate related fields:

Blog.objects.select_related().defer("entry__headline", "entry__body")

If you want to clear the set of deferred fields, pass None as a parameter to defer():

# Load all fields immediately.
my_queryset.defer(None)

Some fields in a model won’t be deferred, even if you ask for them. You can never defer the loading of the primary key. If you are using select_related() to retrieve related models, you shouldn’t defer the loading of the field that connects from the primary model to the related one, doing so will result in an error.

Note

The defer() method (and its cousin, only(), below) are only for advanced use-cases. They provide an optimization for when you have analyzed your queries closely and understand exactly what information you need and have measured that the difference between returning the fields you need and the full set of fields for the model will be significant.

Even if you think you are in the advanced use-case situation, only use defer() when you cannot, at queryset load time, determine if you will need the extra fields or not. If you are frequently loading and using a particular subset of your data, the best choice you can make is to normalize your models and put the non-loaded data into a separate model (and database table). If the columns must stay in the one table for some reason, create a model with Meta.managed = False (see the managed attribute documentation) containing just the fields you normally need to load and use that where you might otherwise call defer(). This makes your code more explicit to the reader, is slightly faster and consumes a little less memory in the Python process.

For example, both of these models use the same underlying database table:

class CommonlyUsedModel(models.Model):
f1 = models.CharField(max_length=10)

class Meta:
managed = False
db_table = 'app_largetable'

class ManagedModel(models.Model):
f1 = models.CharField(max_length=10)
f2 = models.CharField(max_length=10)

class Meta:
db_table = 'app_largetable'

# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.all().defer('f2')

If many fields need to be duplicated in the unmanaged model, it may be best to create an abstract model with the shared fields and then have the unmanaged and managed models inherit from the abstract model.

Note

When calling save() for instances with deferred fields, only the loaded fields will be saved. See save() for more details.

only()

only(*fields)

The only() method is more or less the opposite of defer(). You call it with the fields that should not be deferred when retrieving a model. If you have a model where almost all the fields need to be deferred, using only() to specify the complementary set of fields can result in simpler code.

Suppose you have a model with fields name, age and biography. The following two querysets are the same, in terms of deferred fields:

Person.objects.defer("age", "biography")
Person.objects.only("name")

Whenever you call only() it replaces the set of fields to load immediately. The method’s name is mnemonic: only those fields are loaded immediately; the remainder are deferred. Thus, successive calls to only() result in only the final fields being considered:

# This will defer all fields except the headline.
Entry.objects.only("body", "rating").only("headline")

Since defer() acts incrementally (adding fields to the deferred list), you can combine calls to only() and defer() and things will behave logically:

# Final result is that everything except "headline" is deferred.
Entry.objects.only("headline", "body").defer("body")

# Final result loads headline and body immediately (only() replaces any
# existing set of fields).
Entry.objects.defer("body").only("headline", "body")

All of the cautions in the note for the defer() documentation apply to only() as well. Use it cautiously and only after exhausting your other options.

Using only() and omitting a field requested using select_related() is an error as well.

Note

When calling save() for instances with deferred fields, only the loaded fields will be saved. See save() for more details.

using()

using(alias)

This method is for controlling which database the QuerySet will be evaluated against if you are using more than one database. The only argument this method takes is the alias of a database, as defined in DATABASES.

For example:

# queries the database with the 'default' alias.
>>> Entry.objects.all()

# queries the database with the 'backup' alias
>>> Entry.objects.using('backup')

select_for_update()

select_for_update(nowait=False)

Returns a queryset that will lock rows until the end of the transaction, generating a SELECT ... FOR UPDATE SQL statement on supported databases.

For example:

entries = Entry.objects.select_for_update().filter(author=request.user)

All matched entries will be locked until the end of the transaction block, meaning that other transactions will be prevented from changing or acquiring locks on them.

Usually, if another transaction has already acquired a lock on one of the selected rows, the query will block until the lock is released. If this is not the behavior you want, call select_for_update(nowait=True). This will make the call non-blocking. If a conflicting lock is already acquired by another transaction, DatabaseError will be raised when the queryset is evaluated.

Currently, the postgresql, oracle, and mysql database backends support select_for_update(). However, MySQL has no support for the nowait argument. Obviously, users of external third-party backends should check with their backend’s documentation for specifics in those cases.

Passing nowait=True to select_for_update() using database backends that do not support nowait, such as MySQL, will cause a DatabaseError to be raised. This is in order to prevent code unexpectedly blocking.

Evaluating a queryset with select_for_update() in autocommit mode on backends which support SELECT ... FOR UPDATE is a TransactionManagementError error because the rows are not locked in that case. If allowed, this would facilitate data corruption and could easily be caused by calling code that expects to be run in a transaction outside of one.

Using select_for_update() on backends which do not support SELECT ... FOR UPDATE (such as SQLite) will have no effect. SELECT ... FOR UPDATE will not be added to the query, and an error isn’t raised if select_for_update() is used in autocommit mode.

Warning

Although select_for_update() normally fails in autocommit mode, since TestCase automatically wraps each test in a transaction, calling select_for_update() in a TestCase even outside an atomic() block will (perhaps unexpectedly) pass without raising a TransactionManagementError. To properly test select_for_update() you should use TransactionTestCase.

raw()

raw(raw_query, params=None, translations=None)

Takes a raw SQL query, executes it, and returns a django.db.models.query.RawQuerySet instance. This RawQuerySet instance can be iterated over just like an normal QuerySet to provide object instances.

See the Performing raw SQL queries for more information.

Warning

raw() always triggers a new query and doesn’t account for previous filtering. As such, it should generally be called from the Manager or from a fresh QuerySet instance.

Methods that do not return QuerySets

The following QuerySet methods evaluate the QuerySet and return something other than a QuerySet.

These methods do not use a cache (see Caching and QuerySets). Rather, they query the database each time they’re called.

get()

get(**kwargs)

Returns the object matching the given lookup parameters, which should be in the format described in Field lookups.

get() raises MultipleObjectsReturned if more than one object was found. The MultipleObjectsReturned exception is an attribute of the model class.

get() raises a DoesNotExist exception if an object wasn’t found for the given parameters. This exception is an attribute of the model class. Example:

Entry.objects.get(id='foo') # raises Entry.DoesNotExist

The DoesNotExist exception inherits from django.core.exceptions.ObjectDoesNotExist, so you can target multiple DoesNotExist exceptions. Example:

from django.core.exceptions import ObjectDoesNotExist
try:
e = Entry.objects.get(id=3)
b = Blog.objects.get(id=1)
except ObjectDoesNotExist:
print("Either the entry or blog doesn't exist.")

create()

create(**kwargs)

A convenience method for creating an object and saving it all in one step. Thus:

p = Person.objects.create(first_name="Bruce", last_name="Springsteen")

and:

p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)

are equivalent.

The force_insert parameter is documented elsewhere, but all it means is that a new object will always be created. Normally you won’t need to worry about this. However, if your model contains a manual primary key value that you set and if that value already exists in the database, a call to create() will fail with an IntegrityError since primary keys must be unique. Be prepared to handle the exception if you are using manual primary keys.

get_or_create()

get_or_create(defaults=None, **kwargs)

A convenience method for looking up an object with the given kwargs (may be empty if your model has defaults for all fields), creating one if necessary.

Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.

This is meant as a shortcut to boilerplatish code. For example:

try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
obj.save()

This pattern gets quite unwieldy as the number of fields in a model goes up. The above example can be rewritten using get_or_create() like so:

obj, created = Person.objects.get_or_create(
first_name='John',
last_name='Lennon',
defaults={'birthday': date(1940, 10, 9)},
)

Any keyword arguments passed to get_or_create() — except an optional one called defaults — will be used in a get() call. If an object is found, get_or_create() returns a tuple of that object and False. If multiple objects are found, get_or_create raises MultipleObjectsReturned. If an object is not found, get_or_create() will instantiate and save a new object, returning a tuple of the new object and True. The new object will be created roughly according to this algorithm:

params = {k: v for k, v in kwargs.items() if '__' not in k}
params.update(defaults)
obj = self.model(**params)
obj.save()

In English, that means start with any non-'defaults' keyword argument that doesn’t contain a double underscore (which would indicate a non-exact lookup). Then add the contents of defaults, overriding any keys if necessary, and use the result as the keyword arguments to the model class. As hinted at above, this is a simplification of the algorithm that is used, but it contains all the pertinent details. The internal implementation has some more error-checking than this and handles some extra edge-conditions; if you’re interested, read the code.

If you have a field named defaults and want to use it as an exact lookup in get_or_create(), just use 'defaults__exact', like so:

Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})

The get_or_create() method has similar error behavior to create() when you’re using manually specified primary keys. If an object needs to be created and the key already exists in the database, an IntegrityError will be raised.

This method is atomic assuming correct usage, correct database configuration, and correct behavior of the underlying database. However, if uniqueness is not enforced at the database level for the kwargs used in a get_or_create call (see unique or unique_together), this method is prone to a race-condition which can result in multiple rows with the same parameters being inserted simultaneously.

If you are using MySQL, be sure to use the READ COMMITTED isolation level rather than REPEATABLE READ (the default), otherwise you may see cases where get_or_create will raise an IntegrityError but the object won’t appear in a subsequent get() call.

Finally, a word on using get_or_create() in Django views. Please make sure to use it only in POST requests unless you have a good reason not to. GET requests shouldn’t have any effect on data. Instead, use POST whenever a request to a page has a side effect on your data. For more, see Safe methods in the HTTP spec.

Warning

You can use get_or_create() through ManyToManyField attributes and reverse relations. In that case you will restrict the queries inside the context of that relation. That could lead you to some integrity problems if you don’t use it consistently.

Being the following models:

class Chapter(models.Model):
title = models.CharField(max_length=255, unique=True)

class Book(models.Model):
title = models.CharField(max_length=256)
chapters = models.ManyToManyField(Chapter)

You can use get_or_create() through Book’s chapters field, but it only fetches inside the context of that book:

>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError

This is happening because it’s trying to get or create “Chapter 1” through the book “Ulysses”, but it can’t do any of them: the relation can’t fetch that chapter because it isn’t related to that book, but it can’t create it either because title field should be unique.

update_or_create()

update_or_create(defaults=None, **kwargs)

A convenience method for updating an object with the given kwargs, creating a new one if necessary. The defaults is a dictionary of (field, value) pairs used to update the object.

Returns a tuple of (object, created), where object is the created or updated object and created is a boolean specifying whether a new object was created.

The update_or_create method tries to fetch an object from database based on the given kwargs. If a match is found, it updates the fields passed in the defaults dictionary.

This is meant as a shortcut to boilerplatish code. For example:

try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
for key, value in updated_values.iteritems():
setattr(obj, key, value)
obj.save()
except Person.DoesNotExist:
updated_values.update({'first_name': 'John', 'last_name': 'Lennon'})
obj = Person(**updated_values)
obj.save()

This pattern gets quite unwieldy as the number of fields in a model goes up. The above example can be rewritten using update_or_create() like so:

obj, created = Person.objects.update_or_create(
first_name='John', last_name='Lennon', defaults=updated_values)

For detailed description how names passed in kwargs are resolved see get_or_create().

As described above in get_or_create(), this method is prone to a race-condition which can result in multiple rows being inserted simultaneously if uniqueness is not enforced at the database level.

bulk_create()

bulk_create(objs, batch_size=None)

This method inserts the provided list of objects into the database in an efficient manner (generally only 1 query, no matter how many objects there are):

>>> Entry.objects.bulk_create([
...     Entry(headline="Django 1.0 Released"),
...     Entry(headline="Django 1.1 Announced"),
...     Entry(headline="Breaking: Django is awesome")
... ])

This has a number of caveats though:

- The model’s save() method will not be called, and the pre_save and post_save signals will not be sent.

- It does not work with child models in a multi-table inheritance scenario.

- If the model’s primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does.

- It does not work with many-to-many relationships.

Changed in Django 1.9:
Support for using bulk_create() with proxy models was added.

The batch_size parameter controls how many objects are created in single query. The default is to create all objects in one batch, except for SQLite where the default is such that at most 999 variables per query are used.

count()

count()

Returns an integer representing the number of objects in the database matching the QuerySet. The count() method never raises exceptions.

Example:

# Returns the total number of entries in the database.
Entry.objects.count()

# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains='Lennon').count()

A count() call performs a SELECT COUNT(*) behind the scenes, so you should always use count() rather than loading all of the record into Python objects and calling len() on the result (unless you need to load the objects into memory anyway, in which case len() will be faster).

Depending on which database you’re using (e.g. PostgreSQL vs. MySQL), count() may return a long integer instead of a normal Python integer. This is an underlying implementation quirk that shouldn’t pose any real-world problems.

Note that if you want the number of items in a QuerySet and are also retrieving model instances from it (for example, by iterating over it), it’s probably more efficient to use len(queryset) which won’t cause an extra database query like count() would.

in_bulk()

in_bulk(id_list)

Takes a list of primary-key values and returns a dictionary mapping each primary-key value to an instance of the object with the given ID.

Example:

>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}

If you pass in_bulk() an empty list, you’ll get an empty dictionary.

iterator()

iterator()

Evaluates the QuerySet (by performing the query) and returns an iterator (see PEP 234) over the results. A QuerySet typically caches its results internally so that repeated evaluations do not result in additional queries. In contrast, iterator() will read results directly, without doing any caching at the QuerySet level (internally, the default iterator calls iterator() and caches the return value). For a QuerySet which returns a large number of objects that you only need to access once, this can result in better performance and a significant reduction in memory.

Note that using iterator() on a QuerySet which has already been evaluated will force it to evaluate again, repeating the query.

Also, use of iterator() causes previous prefetch_related() calls to be ignored since these two optimizations do not make sense together.

Warning

Some Python database drivers like psycopg2 perform caching if using client side cursors (instantiated with connection.cursor() and what Django’s ORM uses). Using iterator() does not affect caching at the database driver level. To disable this caching, look at server side cursors.

latest()

latest(field_name=None)

Returns the latest object in the table, by date, using the field_name provided as the date field.

This example returns the latest Entry in the table, according to the pub_date field:

Entry.objects.latest('pub_date')

If your model’s Meta specifies get_latest_by, you can leave off the field_name argument to earliest() or latest(). Django will use the field specified in get_latest_by by default.

Like get(), earliest() and latest() raise DoesNotExist if there is no object with the given parameters.

Note that earliest() and latest() exist purely for convenience and readability.

earliest() and latest() may return instances with null dates.

Since ordering is delegated to the database, results on fields that allow null values may be ordered differently if you use different databases. For example, PostgreSQL and MySQL sort null values as if they are higher than non-null values, while SQLite does the opposite.

You may want to filter out null values:

Entry.objects.filter(pub_date__isnull=False).latest('pub_date')

earliest()

earliest(field_name=None)

Works otherwise like latest() except the direction is changed.

first()

first()

Returns the first object matched by the queryset, or None if there is no matching object. If the QuerySet has no ordering defined, then the queryset is automatically ordered by the primary key.

Example:

p = Article.objects.order_by('title', 'pub_date').first()

Note that first() is a convenience method, the following code sample is equivalent to the above example:

try:
p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
p = None

last()

last()

Works like first(), but returns the last object in the queryset.

aggregate()

aggregate(*args, **kwargs)

Returns a dictionary of aggregate values (averages, sums, etc.) calculated over the QuerySet. Each argument to aggregate() specifies a value that will be included in the dictionary that is returned.

The aggregation functions that are provided by Django are described in Aggregation Functions below. Since aggregates are also query expressions, you may combine aggregates with other aggregates or values to create complex aggregates.

Aggregates specified using keyword arguments will use the keyword as the name for the annotation. Anonymous arguments will have a name generated for them based upon the name of the aggregate function and the model field that is being aggregated. Complex aggregates cannot use anonymous arguments and must specify a keyword argument as an alias.

For example, when you are working with blog entries, you may want to know the number of authors that have contributed blog entries:

>>> from django.db.models import Count
>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}

By using a keyword argument to specify the aggregate function, you can control the name of the aggregation value that is returned:

>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}

For an in-depth discussion of aggregation, see the topic guide on Aggregation.

exists()

exists()

Returns True if the QuerySet contains any results, and False if not. This tries to perform the query in the simplest and fastest way possible, but it does execute nearly the same query as a normal QuerySet query.

exists() is useful for searches relating to both object membership in a QuerySet and to the existence of any objects in a QuerySet, particularly in the context of a large QuerySet.

The most efficient method of finding whether a model with a unique field (e.g. primary_key) is a member of a QuerySet is:

entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
print("Entry contained in queryset")

Which will be faster than the following which requires evaluating and iterating through the entire queryset:

if entry in some_queryset:
print("Entry contained in QuerySet")

And to find whether a queryset contains any items:

if some_queryset.exists():
print("There is at least one object in some_queryset")

Which will be faster than:

if some_queryset:
print("There is at least one object in some_queryset")

... but not by a large degree (hence needing a large queryset for efficiency gains).

Additionally, if a some_queryset has not yet been evaluated, but you know that it will be at some point, then using some_queryset.exists() will do more overall work (one query for the existence check plus an extra one to later retrieve the results) than simply using bool(some_queryset), which retrieves the results and then checks if any were returned.

update()

update(**kwargs)

Performs an SQL update query for the specified fields, and returns the number of rows matched (which may not be equal to the number of rows updated if some rows already have the new value).

For example, to turn comments off for all blog entries published in 2010, you could do this:

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)

(This assumes your Entry model has fields pub_date and comments_on.)

You can update multiple fields — there’s no limit on how many. For example, here we update the comments_on and headline fields:

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old')

The update() method is applied instantly, and the only restriction on the QuerySet that is updated is that it can only update columns in the model’s main table, not on related models. You can’t do this, for example:

>>> Entry.objects.update(blog__name='foo') # Won't work!

Filtering based on related fields is still possible, though:

>>> Entry.objects.filter(blog__id=1).update(comments_on=True)

You cannot call update() on a QuerySet that has had a slice taken or can otherwise no longer be filtered.

The update() method returns the number of affected rows:

>>> Entry.objects.filter(id=64).update(comments_on=True)
1

>>> Entry.objects.filter(slug='nonexistent-slug').update(comments_on=True)
0

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
132

If you’re just updating a record and don’t need to do anything with the model object, the most efficient approach is to call update(), rather than loading the model object into memory. For example, instead of doing this:

e = Entry.objects.get(id=10)
e.comments_on = False
e.save()

...do this:

Entry.objects.filter(id=10).update(comments_on=False)

Using update() also prevents a race condition wherein something might change in your database in the short period of time between loading the object and calling save().

Finally, realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals (which are a consequence of calling Model.save()). If you want to update a bunch of records for a model that has a custom save() method, loop over them and call save(), like this:

for e in Entry.objects.filter(pub_date__year=2010):
e.comments_on = False
e.save()

delete()

delete()

Performs an SQL delete query on all rows in the QuerySet and returns the number of objects deleted and a dictionary with the number of deletions per object type.

The delete() is applied instantly. You cannot call delete() on a QuerySet that has had a slice taken or can otherwise no longer be filtered.

For example, to delete all the entries in a particular blog:

>>> b = Blog.objects.get(pk=1)

# Delete all the entries belonging to this Blog.
>>> Entry.objects.filter(blog=b).delete()
(4, {'weblog.Entry': 2, 'weblog.Entry_authors': 2})

Changed in Django 1.9:
The return value describing the number of objects deleted was added.

By default, Django’s ForeignKey emulates the SQL constraint ON DELETE CASCADE — in other words, any objects with foreign keys pointing at the objects to be deleted will be deleted along with them. For example:

>>> blogs = Blog.objects.all()

# This will delete all Blogs and all of their Entry objects.
>>> blogs.delete()
(5, {'weblog.Blog': 1, 'weblog.Entry': 2, 'weblog.Entry_authors': 2})

This cascade behavior is customizable via the on_delete argument to the ForeignKey.

The delete() method does a bulk delete and does not call any delete() methods on your models. It does, however, emit the pre_delete and post_delete signals for all deleted objects (including cascaded deletions).

Django needs to fetch objects into memory to send signals and handle cascades. However, if there are no cascades and no signals, then Django may take a fast-path and delete objects without fetching into memory. For large deletes this can result in significantly reduced memory usage. The amount of executed queries can be reduced, too.

ForeignKeys which are set to on_delete DO_NOTHING do not prevent taking the fast-path in deletion.

Note that the queries generated in object deletion is an implementation detail subject to change.

as_manager()

classmethod as_manager()

Class method that returns an instance of Manager with a copy of the QuerySet’s methods. See Creating a manager with QuerySet methods for more details.

Field lookups

Field lookups are how you specify the meat of an SQL WHERE clause. They’re specified as keyword arguments to the QuerySet methods filter(), exclude() and get().

For an introduction, see models and database queries documentation.

Django’s built-in lookups are listed below. It is also possible to write custom lookups for model fields.

As a convenience when no lookup type is provided (like in Entry.objects.get(id=14)) the lookup type is assumed to be exact.

exact

Exact match. If the value provided for comparison is None, it will be interpreted as an SQL NULL (see isnull for more details).

Examples:

Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)

SQL equivalents:

SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;

MySQL comparisons

In MySQL, a database table’s “collation” setting determines whether exact comparisons are case-sensitive. This is a database setting, not a Django setting. It’s possible to configure your MySQL tables to use case-sensitive comparisons, but some trade-offs are involved. For more information about this, see the collation section in the databases documentation.

iexact

Case-insensitive exact match. If the value provided for comparison is None, it will be interpreted as an SQL NULL (see isnull for more details).

Example:

Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)

SQL equivalents:

SELECT ... WHERE name ILIKE 'beatles blog';
SELECT ... WHERE name IS NULL;

Note the first query will match 'Beatles Blog', 'beatles blog', 'BeAtLes BLoG', etc.

SQLite users

When using the SQLite backend and Unicode (non-ASCII) strings, bear in mind the database note about string comparisons. SQLite does not do case-insensitive matching for Unicode strings.

contains

Case-sensitive containment test.

Example:

Entry.objects.get(headline__contains='Lennon')

SQL equivalent:

SELECT ... WHERE headline LIKE '%Lennon%';

Note this will match the headline 'Lennon honored today' but not 'lennon honored today'.

SQLite users

SQLite doesn’t support case-sensitive LIKE statements; contains acts like icontains for SQLite. See the database note for more information.

icontains

Case-insensitive containment test.

Example:

Entry.objects.get(headline__icontains='Lennon')

SQL equivalent:

SELECT ... WHERE headline ILIKE '%Lennon%';

SQLite users

When using the SQLite backend and Unicode (non-ASCII) strings, bear in mind the database note about string comparisons.

in

In a given list.

Example:

Entry.objects.filter(id__in=[1, 3, 4])

SQL equivalent:

SELECT ... WHERE id IN (1, 3, 4);

You can also use a queryset to dynamically evaluate the list of values instead of providing a list of literal values:

inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)

This queryset will be evaluated as subselect statement:

SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

If you pass in a QuerySet resulting from values() or values_list() as the value to an __in lookup, you need to ensure you are only extracting one field in the result. For example, this will work (filtering on the blog names):

inner_qs = Blog.objects.filter(name__contains='Ch').values('name')
entries = Entry.objects.filter(blog__name__in=inner_qs)

This example will raise an exception, since the inner query is trying to extract two field values, where only one is expected:

# Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains='Ch').values('name', 'id')
entries = Entry.objects.filter(blog__name__in=inner_qs)

Performance considerations

Be cautious about using nested queries and understand your database server’s performance characteristics (if in doubt, benchmark!). Some database backends, most notably MySQL, don’t optimize nested queries very well. It is more efficient, in those cases, to extract a list of values and then pass that into the second query. That is, execute two queries instead of one:

values = Blog.objects.filter(
name__contains='Cheddar').values_list('pk', flat=True)
entries = Entry.objects.filter(blog__in=list(values))

Note the list() call around the Blog QuerySet to force execution of the first query. Without it, a nested query would be executed, because QuerySets are lazy.

gt

Greater than.

Example:

Entry.objects.filter(id__gt=4)

SQL equivalent:

SELECT ... WHERE id > 4;

gte

Greater than or equal to.

lt

Less than.

lte

Less than or equal to.

startswith

Case-sensitive starts-with.

Example:

Entry.objects.filter(headline__startswith='Will')

SQL equivalent:

SELECT ... WHERE headline LIKE 'Will%';

SQLite doesn’t support case-sensitive LIKE statements; startswith acts like istartswith for SQLite.

istartswith

Case-insensitive starts-with.

Example:

Entry.objects.filter(headline__istartswith='will')

SQL equivalent:

SELECT ... WHERE headline ILIKE 'Will%';

SQLite users

When using the SQLite backend and Unicode (non-ASCII) strings, bear in mind the database note about string comparisons.

endswith

Case-sensitive ends-with.

Example:

Entry.objects.filter(headline__endswith='cats')

SQL equivalent:

SELECT ... WHERE headline LIKE '%cats';

SQLite users

SQLite doesn’t support case-sensitive LIKE statements; endswith acts like iendswith for SQLite. Refer to the database note documentation for more.

iendswith

Case-insensitive ends-with.

Example:

Entry.objects.filter(headline__iendswith='will')

SQL equivalent:

SELECT ... WHERE headline ILIKE '%will'

SQLite users

When using the SQLite backend and Unicode (non-ASCII) strings, bear in mind the database note about string comparisons.

range

Range test (inclusive).

Example:

import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

SQL equivalent:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

You can use range anywhere you can use BETWEEN in SQL — for dates, numbers and even characters.

Warning

Filtering a DateTimeField with dates won’t include items on the last day, because the bounds are interpreted as “0am on the given date”. If pub_date was a DateTimeField, the above expression would be turned into this SQL:

SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';

Generally speaking, you can’t mix dates and datetimes.

date

New in Django 1.9.

For datetime fields, casts the value as date. Allows chaining additional field lookups. Takes a date value.

Example:

Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

(No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.)

When USE_TZ is True, fields are converted to the current time zone before filtering.

year

For date and datetime fields, an exact year match. Allows chaining additional field lookups. Takes an integer year.

Example:

Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)

SQL equivalent:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';

(The exact SQL syntax varies for each database engine.)

When USE_TZ is True, datetime fields are converted to the current time zone before filtering.

Changed in Django 1.9:
Allowed chaining additional field lookups.

month

For date and datetime fields, an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December).

Example:

Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)

SQL equivalent:

SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';

(The exact SQL syntax varies for each database engine.)

When USE_TZ is True, datetime fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

Changed in Django 1.9:
Allowed chaining additional field lookups.

day

For date and datetime fields, an exact day match. Allows chaining additional field lookups. Takes an integer day.

Example:

Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)

SQL equivalent:

SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';

(The exact SQL syntax varies for each database engine.)

Note this will match any record with a pub_date on the third day of the month, such as January 3, July 3, etc.

When USE_TZ is True, datetime fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

Changed in Django 1.9:
Allowed chaining additional field lookups.

week_day

For date and datetime fields, a ‘day of the week’ match. Allows chaining additional field lookups.

Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday).

Example:

Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)

(No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.)

Note this will match any record with a pub_date that falls on a Monday (day 2 of the week), regardless of the month or year in which it occurs. Week days are indexed with day 1 being Sunday and day 7 being Saturday.

When USE_TZ is True, datetime fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

Changed in Django 1.9:
Allowed chaining additional field lookups.

hour

For datetime and time fields, an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23.

Example:

Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)

SQL equivalent:

SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';

(The exact SQL syntax varies for each database engine.)

For datetime fields, when USE_TZ is True, values are converted to the current time zone before filtering.

Changed in Django 1.9:
Added support for TimeField on SQLite (other databases supported it as of 1.7).

Changed in Django 1.9:
Allowed chaining additional field lookups.

minute

For datetime and time fields, an exact minute match. Allows chaining additional field lookups. Takes an integer between 0 and 59.

Example:

Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)

SQL equivalent:

SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';

(The exact SQL syntax varies for each database engine.)

For datetime fields, When USE_TZ is True, values are converted to the current time zone before filtering.

Changed in Django 1.9:
Added support for TimeField on SQLite (other databases supported it as of 1.7).

Changed in Django 1.9:
Allowed chaining additional field lookups.

second

For datetime and time fields, an exact second match. Allows chaining additional field lookups. Takes an integer between 0 and 59.

Example:

Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)

SQL equivalent:

SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';

(The exact SQL syntax varies for each database engine.)

For datetime fields, when USE_TZ is True, values are converted to the current time zone before filtering.

Changed in Django 1.9:
Added support for TimeField on SQLite (other databases supported it as of 1.7).

Changed in Django 1.9:
Allowed chaining additional field lookups.

isnull

Takes either True or False, which correspond to SQL queries of IS NULL and IS NOT NULL, respectively.

Example:

Entry.objects.filter(pub_date__isnull=True)

SQL equivalent:

SELECT ... WHERE pub_date IS NULL;

search

A boolean full-text search, taking advantage of full-text indexing. This is like contains but is significantly faster due to full-text indexing.

Example:

Entry.objects.filter(headline__search="+Django -jazz Python")

SQL equivalent:

SELECT ... WHERE MATCH(tablename, headline) AGAINST (+Django -jazz Python IN BOOLEAN MODE);

Note this is only available in MySQL and requires direct manipulation of the database to add the full-text index. By default Django uses BOOLEAN MODE for full text searches. See the MySQL documentation for additional details.

regex

Case-sensitive regular expression match.

The regular expression syntax is that of the database backend in use. In the case of SQLite, which has no built in regular expression support, this feature is provided by a (Python) user-defined REGEXP function, and the regular expression syntax is therefore that of Python’s re module.

Example:

Entry.objects.get(title__regex=r'^(An?|The) +')

SQL equivalents:

SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL

SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle

SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL

SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite

Using raw strings (e.g., r'foo' instead of 'foo') for passing in the regular expression syntax is recommended.

iregex

Case-insensitive regular expression match.

Example:

Entry.objects.get(title__iregex=r'^(an?|the) +')

SQL equivalents:

SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL

SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle

SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL

SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite

Aggregation functions

Django provides the following aggregation functions in the django.db.models module. For details on how to use these aggregate functions, see the topic guide on aggregation. See the Aggregate documentation to learn how to create your aggregates.

Warning

SQLite can’t handle aggregation on date/time fields out of the box. This is because there are no native date/time fields in SQLite and Django currently emulates these features using a text field. Attempts to use aggregation on date/time fields in SQLite will raise NotImplementedError.

Note

Aggregation functions return None when used with an empty QuerySet. For example, the Sum aggregation function returns None instead of 0 if the QuerySet contains no entries. An exception is Count, which does return 0 if the QuerySet is empty.

All aggregates have the following parameters in common:

expression

A string that references a field on the model, or a query expression.

New in Django 1.8:
Aggregate functions are now able to reference multiple fields in complex computations.

output_field

An optional argument that represents the model field of the return value

New in Django 1.8:
The output_field argument was added.

Note

When combining multiple field types, Django can only determine the output_field if all fields are of the same type. Otherwise, you must provide the output_field yourself.

**extra

Keyword arguments that can provide extra context for the SQL generated by the aggregate.

Avg

class Avg(expression, output_field=FloatField(), **extra)[source]

Returns the mean value of the given expression, which must be numeric unless you specify a different output_field.

- Default alias: <field>__avg

- Return type: float (or the type of whatever output_field is specified)

Changed in Django 1.9:
The output_field parameter was added to allow aggregating over non-numeric columns, such as DurationField.

Count

class Count(expression, distinct=False, **extra)[source]

Returns the number of objects that are related through the provided expression.

- Default alias: <field>__count

- Return type: int

Has one optional argument:

distinct

If distinct=True, the count will only include unique instances. This is the SQL equivalent of COUNT(DISTINCT <field>). The default value is False.

Max

class Max(expression, output_field=None, **extra)[source]

Returns the maximum value of the given expression.

- Default alias: <field>__max

- Return type: same as input field, or output_field if supplied

Min

class Min(expression, output_field=None, **extra)[source]

Returns the minimum value of the given expression.

- Default alias: <field>__min

- Return type: same as input field, or output_field if supplied

StdDev

class StdDev(expression, sample=False, **extra)[source]

Returns the standard deviation of the data in the provided expression.

- Default alias: <field>__stddev

- Return type: float

Has one optional argument:

sample

By default, StdDev returns the population standard deviation. However, if sample=True, the return value will be the sample standard deviation.

SQLite

SQLite doesn’t provide StdDev out of the box. An implementation is available as an extension module for SQLite. Consult the SQlite documentation for instructions on obtaining and installing this extension.

Sum

class Sum(expression, output_field=None, **extra)[source]

Computes the sum of all values of the given expression.

- Default alias: <field>__sum

- Return type: same as input field, or output_field if supplied

Variance

class Variance(expression, sample=False, **extra)[source]

Returns the variance of the data in the provided expression.

- Default alias: <field>__variance

- Return type: float

Has one optional argument:

sample

By default, Variance returns the population variance. However, if sample=True, the return value will be the sample variance.

SQLite

SQLite doesn’t provide Variance out of the box. An implementation is available as an extension module for SQLite. Consult the SQlite documentation for instructions on obtaining and installing this extension.

Query-related classes

This section provides reference material for query-related tools not documented elsewhere.

Q() objects

class Q[source]

A Q() object, like an F object, encapsulates a SQL expression in a Python object that can be used in database-related operations.

In general, Q() objects make it possible to define and reuse conditions. This permits the construction of complex database queries using | (OR) and & (AND) operators; in particular, it is not otherwise possible to use OR in QuerySets.

Prefetch() objects

class Prefetch(lookup, queryset=None, to_attr=None)[source]

The Prefetch() object can be used to control the operation of prefetch_related().

The lookup argument describes the relations to follow and works the same as the string based lookups passed to prefetch_related(). For example:

>>> Question.objects.prefetch_related(Prefetch('choice_set')).get().choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
# This will only execute two queries regardless of the number of Question
# and Choice objects.
>>> Question.objects.prefetch_related(Prefetch('choice_set')).all()
[<Question: Question object>]

The queryset argument supplies a base QuerySet for the given lookup. This is useful to further filter down the prefetch operation, or to call select_related() from the prefetched relation, hence reducing the number of queries even further:

>>> voted_choices = Choice.objects.filter(votes__gt=0)
>>> voted_choices
[<Choice: The sky>]
>>> prefetch = Prefetch('choice_set', queryset=voted_choices)
>>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
[<Choice: The sky>]

The to_attr argument sets the result of the prefetch operation to a custom attribute:

>>> prefetch = Prefetch('choice_set', queryset=voted_choices, to_attr='voted_choices')
>>> Question.objects.prefetch_related(prefetch).get().voted_choices
[<Choice: The sky>]
>>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

Note

When using to_attr the prefetched result is stored in a list. This can provide a significant speed improvement over traditional prefetch_related calls which store the cached result within a QuerySet instance.

Lookup API reference

This document has the API references of lookups, the Django API for building the WHERE clause of a database query. To learn how to use lookups, see Making queries; to learn how to create new lookups, see Custom Lookups.

The lookup API has two components: a RegisterLookupMixin class that registers lookups, and the Query Expression API, a set of methods that a class has to implement to be registrable as a lookup.

Django has two base classes that follow the query expression API and from where all Django builtin lookups are derived:

- Lookup: to lookup a field (e.g. the exact of field_name__exact)

- Transform: to transform a field

A lookup expression consists of three parts:

- Fields part (e.g. Book.objects.filter(author__best_friends__first_name...);

- Transforms part (may be omitted) (e.g. __lower__first3chars__reversed);

- A lookup (e.g. __icontains) that, if omitted, defaults to __exact.

Registration API

Django uses RegisterLookupMixin to give a class the interface to register lookups on itself. The two prominent examples are Field, the base class of all model fields, and Aggregate, the base class of all Django aggregates.

class lookups.RegisterLookupMixin

A mixin that implements the lookup API on a class.

classmethod register_lookup(lookup, lookup_name=None)

Registers a new lookup in the class. For example DateField.register_lookup(YearExact) will register YearExact lookup on DateField. It overrides a lookup that already exists with the same name. lookup_name will be used for this lookup if provided, otherwise lookup.lookup_name will be used.

Changed in Django 1.9:
The lookup_name parameter was added.

get_lookup(lookup_name)

Returns the Lookup named lookup_name registered in the class. The default implementation looks recursively on all parent classes and checks if any has a registered lookup named lookup_name, returning the first match.

get_transform(transform_name)

Returns a Transform named transform_name. The default implementation looks recursively on all parent classes to check if any has the registered transform named transform_name, returning the first match.

For a class to be a lookup, it must follow the Query Expression API. Lookup and Transform naturally follow this API.

The Query Expression API

The query expression API is a common set of methods that classes define to be usable in query expressions to translate themselves into SQL expressions. Direct field references, aggregates, and Transform are examples that follow this API. A class is said to follow the query expression API when it implements the following methods:

as_sql(self, compiler, connection)

Responsible for producing the query string and parameters for the expression. The compiler is an SQLCompiler object, which has a compile() method that can be used to compile other expressions. The connection is the connection used to execute the query.

Calling expression.as_sql() is usually incorrect - instead compiler.compile(expression) should be used. The compiler.compile() method will take care of calling vendor-specific methods of the expression.

as_vendorname(self, compiler, connection)

Works like as_sql() method. When an expression is compiled by compiler.compile(), Django will first try to call as_vendorname(), where vendorname is the vendor name of the backend used for executing the query. The vendorname is one of postgresql, oracle, sqlite, or mysql for Django’s built-in backends.

get_lookup(lookup_name)

Must return the lookup named lookup_name. For instance, by returning self.output_field.get_lookup(lookup_name).

get_transform(transform_name)

Must return the lookup named transform_name. For instance, by returning self.output_field.get_transform(transform_name).

output_field

Defines the type of class returned by the get_lookup() method. It must be a Field instance.

Transform reference

class Transform[source]

A Transform is a generic class to implement field transformations. A prominent example is __year that transforms a DateField into a IntegerField.

The notation to use a Transform in an lookup expression is <expression>__<transformation> (e.g. date__year).

This class follows the Query Expression API, which implies that you can use <expression>__<transform1>__<transform2>. It’s a specialized Func() expression that only accepts one argument. It can also be used on the right hand side of a filter or directly as an annotation.

Changed in Django 1.9:
Transform is now a subclass of Func.

bilateral

New in Django 1.8.

A boolean indicating whether this transformation should apply to both lhs and rhs. Bilateral transformations will be applied to rhs in the same order as they appear in the lookup expression. By default it is set to False. For example usage, see Custom Lookups.

lhs

The left-hand side - what is being transformed. It must follow the Query Expression API.

lookup_name

The name of the lookup, used for identifying it on parsing query expressions. It cannot contain the string "__".

output_field

Defines the class this transformation outputs. It must be a Field instance. By default is the same as its lhs.output_field.

Lookup reference

class Lookup[source]

A Lookup is a generic class to implement lookups. A lookup is a query expression with a left-hand side, lhs; a right-hand side, rhs; and a lookup_name that is used to produce a boolean comparison between lhs and rhs such as lhs in rhs or lhs > rhs.

The notation to use a lookup in an expression is <lhs>__<lookup_name>=<rhs>.

This class doesn’t follow the Query Expression API since it has =<rhs> on its construction: lookups are always the end of a lookup expression.

lhs

The left-hand side - what is being looked up. The object must follow the Query Expression API.

rhs

The right-hand side - what lhs is being compared against. It can be a plain value, or something that compiles into SQL, typically an F() object or a QuerySet.

lookup_name

The name of this lookup, used to identify it on parsing query expressions. It cannot contain the string "__".

process_lhs(compiler, connection, lhs=None)[source]

Returns a tuple (lhs_string, lhs_params), as returned by compiler.compile(lhs). This method can be overridden to tune how the lhs is processed.

compiler is an SQLCompiler object, to be used like compiler.compile(lhs) for compiling lhs. The connection can be used for compiling vendor specific SQL. If lhs is not None, use it as the processed lhs instead of self.lhs.

process_rhs(compiler, connection)[source]

Behaves the same way as process_lhs(), for the right-hand side.

Query Expressions

Query expressions describe a value or a computation that can be used as part of an update, create, filter, order by, annotation, or aggregate. There are a number of built-in expressions (documented below) that can be used to help you write queries. Expressions can be combined, or in some cases nested, to form more complex computations.

Changed in Django 1.9:
Support for using expressions when creating new model instances was added.

Supported arithmetic

Django supports addition, subtraction, multiplication, division, modulo arithmetic, and the power operator on query expressions, using Python constants, variables, and even other expressions.

Some examples

Changed in Django 1.8:
Some of the examples rely on functionality that is new in Django 1.8.

from django.db.models import F, Count
from django.db.models.functions import Length, Upper, Value

# Find companies that have more employees than chairs.
Company.objects.filter(num_employees__gt=F('num_chairs'))

# Find companies that have at least twice as many employees
# as chairs. Both the querysets below are equivalent.
Company.objects.filter(num_employees__gt=F('num_chairs') * 2)
Company.objects.filter(
num_employees__gt=F('num_chairs') + F('num_chairs'))

# How many chairs are needed for each company to seat all employees?
>>> company = Company.objects.filter(
...    num_employees__gt=F('num_chairs')).annotate(
...    chairs_needed=F('num_employees') - F('num_chairs')).first()
>>> company.num_employees
120
>>> company.num_chairs
50
>>> company.chairs_needed
70

# Create a new company using expressions.
>>> company = Company.objects.create(name='Google', ticker=Upper(Value('goog')))
# Be sure to refresh it if you need to access the field.
>>> company.refresh_from_db()
>>> company.ticker
'GOOG'

# Annotate models with an aggregated value. Both forms
# below are equivalent.
Company.objects.annotate(num_products=Count('products'))
Company.objects.annotate(num_products=Count(F('products')))

# Aggregates can contain complex computations also
Company.objects.annotate(num_offerings=Count(F('products') + F('services')))

# Expressions can also be used in order_by()
Company.objects.order_by(Length('name').asc())
Company.objects.order_by(Length('name').desc())

Built-in Expressions

Note

These expressions are defined in django.db.models.expressions and django.db.models.aggregates, but for convenience they’re available and usually imported from django.db.models.

F() expressions

class F[source]

An F() object represents the value of a model field or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.

Instead, Django uses the F() object to generate an SQL expression that describes the required operation at the database level.

This is easiest to understand through an example. Normally, one might do something like this:

# Tintin filed a news story!
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()

Here, we have pulled the value of reporter.stories_filed from the database into memory and manipulated it using familiar Python operators, and then saved the object back to the database. But instead we could also have done:

from django.db.models import F

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

Although reporter.stories_filed = F('stories_filed') + 1 looks like a normal Python assignment of value to an instance attribute, in fact it’s an SQL construct describing an operation on the database.

When Django encounters an instance of F(), it overrides the standard Python operators to create an encapsulated SQL expression; in this case, one which instructs the database to increment the database field represented by reporter.stories_filed.

Whatever value is or was on reporter.stories_filed, Python never gets to know about it - it is dealt with entirely by the database. All Python does, through Django’s F() class, is create the SQL syntax to refer to the field and describe the operation.

Note

In order to access the new value that has been saved in this way, the object will need to be reloaded:

reporter = Reporters.objects.get(pk=reporter.pk)
# Or, more succinctly:
reporter.refresh_from_db()

As well as being used in operations on single instances as above, F() can be used on QuerySets of object instances, with update(). This reduces the two queries we were using above - the get() and the save() - to just one:

reporter = Reporters.objects.filter(name='Tintin')
reporter.update(stories_filed=F('stories_filed') + 1)

We can also use update() to increment the field value on multiple objects - which could be very much faster than pulling them all into Python from the database, looping over them, incrementing the field value of each one, and saving each one back to the database:

Reporter.objects.all().update(stories_filed=F('stories_filed') + 1)

F() therefore can offer performance advantages by:

- getting the database, rather than Python, to do work

- reducing the number of queries some operations require

Avoiding race conditions using F()

Another useful benefit of F() is that having the database - rather than Python - update a field’s value avoids a race condition.

If two Python threads execute the code in the first example above, one thread could retrieve, increment, and save a field’s value after the other has retrieved it from the database. The value that the second thread saves will be based on the original value; the work of the first thread will simply be lost.

If the database is responsible for updating the field, the process is more robust: it will only ever update the field based on the value of the field in the database when the save() or update() is executed, rather than based on its value when the instance was retrieved.

F() assignments persist after Model.save()

F() objects assigned to model fields persist after saving the model instance and will be applied on each save(). For example:

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

reporter.name = 'Tintin Jr.'
reporter.save()

stories_filed will be updated twice in this case. If it’s initially 1, the final value will be 3.

Using F() in filters

F() is also very useful in QuerySet filters, where they make it possible to filter a set of objects against criteria based on their field values, rather than on Python values.

This is documented in using F() expressions in queries.

Using F() with annotations

F() can be used to create dynamic fields on your models by combining different fields with arithmetic:

company = Company.objects.annotate(
chairs_needed=F('num_employees') - F('num_chairs'))

If the fields that you’re combining are of different types you’ll need to tell Django what kind of field will be returned. Since F() does not directly support output_field you will need to wrap the expression with ExpressionWrapper:

from django.db.models import DateTimeField, ExpressionWrapper, F

Ticket.objects.annotate(
expires=ExpressionWrapper(
F('active_at') + F('duration'), output_field=DateTimeField()))

Func() expressions

New in Django 1.8.

Func() expressions are the base type of all expressions that involve database functions like COALESCE and LOWER, or aggregates like SUM. They can be used directly:

from django.db.models import Func, F

queryset.annotate(field_lower=Func(F('field'), function='LOWER'))

or they can be used to build a library of database functions:

class Lower(Func):
function = 'LOWER'

queryset.annotate(field_lower=Lower('field'))

But both cases will result in a queryset where each model is annotated with an extra attribute field_lower produced, roughly, from the following SQL:

SELECT
...
LOWER("db_table"."field") as "field_lower"

See Database Functions for a list of built-in database functions.

The Func API is as follows:

class Func(*expressions, **extra)[source]

function

A class attribute describing the function that will be generated. Specifically, the function will be interpolated as the function placeholder within template. Defaults to None.

template

A class attribute, as a format string, that describes the SQL that is generated for this function. Defaults to '%(function)s(%(expressions)s)'.

arg_joiner

A class attribute that denotes the character used to join the list of expressions together. Defaults to ', '.

The *expressions argument is a list of positional expressions that the function will be applied to. The expressions will be converted to strings, joined together with arg_joiner, and then interpolated into the template as the expressions placeholder.

Positional arguments can be expressions or Python values. Strings are assumed to be column references and will be wrapped in F() expressions while other values will be wrapped in Value() expressions.

The **extra kwargs are key=value pairs that can be interpolated into the template attribute. Note that the keywords function and template can be used to replace the function and template attributes respectively, without having to define your own class. output_field can be used to define the expected return type.

Aggregate() expressions

An aggregate expression is a special case of a Func() expression that informs the query that a GROUP BY clause is required. All of the aggregate functions, like Sum() and Count(), inherit from Aggregate().

Since Aggregates are expressions and wrap expressions, you can represent some complex computations:

from django.db.models import Count

Company.objects.annotate(
managers_required=(Count('num_employees') / 4) + Count('num_managers'))

The Aggregate API is as follows:

class Aggregate(expression, output_field=None, **extra)[source]

template

A class attribute, as a format string, that describes the SQL that is generated for this aggregate. Defaults to '%(function)s( %(expressions)s )'.

function

A class attribute describing the aggregate function that will be generated. Specifically, the function will be interpolated as the function placeholder within template. Defaults to None.

The expression argument can be the name of a field on the model, or another expression. It will be converted to a string and used as the expressions placeholder within the template.

The output_field argument requires a model field instance, like IntegerField() or BooleanField(), into which Django will load the value after it’s retrieved from the database. Usually no arguments are needed when instantiating the model field as any arguments relating to data validation (max_length, max_digits, etc.) will not be enforced on the expression’s output value.

Note that output_field is only required when Django is unable to determine what field type the result should be. Complex expressions that mix field types should define the desired output_field. For example, adding an IntegerField() and a FloatField() together should probably have output_field=FloatField() defined.

Changed in Django 1.8:
output_field is a new parameter.

The **extra kwargs are key=value pairs that can be interpolated into the template attribute.

New in Django 1.8:
Aggregate functions can now use arithmetic and reference multiple model fields in a single function.

Creating your own Aggregate Functions

Creating your own aggregate is extremely easy. At a minimum, you need to define function, but you can also completely customize the SQL that is generated. Here’s a brief example:

from django.db.models import Aggregate

class Count(Aggregate):
# supports COUNT(distinct field)
function = 'COUNT'
template = '%(function)s(%(distinct)s%(expressions)s)'

def __init__(self, expression, distinct=False, **extra):
super(Count, self).__init__(
expression,
distinct='DISTINCT ' if distinct else '',
output_field=IntegerField(),
**extra
)

Value() expressions

class Value(value, output_field=None)[source]

A Value() object represents the smallest possible component of an expression: a simple value. When you need to represent the value of an integer, boolean, or string within an expression, you can wrap that value within a Value().

You will rarely need to use Value() directly. When you write the expression F('field') + 1, Django implicitly wraps the 1 in a Value(), allowing simple values to be used in more complex expressions. You will need to use Value() when you want to pass a string to an expression. Most expressions interpret a string argument as the name of a field, like Lower('name').

The value argument describes the value to be included in the expression, such as 1, True, or None. Django knows how to convert these Python values into their corresponding database type.

The output_field argument should be a model field instance, like IntegerField() or BooleanField(), into which Django will load the value after it’s retrieved from the database. Usually no arguments are needed when instantiating the model field as any arguments relating to data validation (max_length, max_digits, etc.) will not be enforced on the expression’s output value.

ExpressionWrapper() expressions

class ExpressionWrapper(expression, output_field)[source]

New in Django 1.8.

ExpressionWrapper simply surrounds another expression and provides access to properties, such as output_field, that may not be available on other expressions. ExpressionWrapper is necessary when using arithmetic on F() expressions with different types as described in Using F() with annotations.

Conditional expressions

New in Django 1.8.

Conditional expressions allow you to use if ... elif ... else logic in queries. Django natively supports SQL CASE expressions. For more details see Conditional Expressions.

Raw SQL expressions

New in Django 1.8.

class RawSQL(sql, params, output_field=None)[source]

Sometimes database expressions can’t easily express a complex WHERE clause. In these edge cases, use the RawSQL expression. For example:

>>> from django.db.models.expressions import RawSQL
>>> queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

These extra lookups may not be portable to different database engines (because you’re explicitly writing SQL code) and violate the DRY principle, so you should avoid them if possible.

Warning

You should be very careful to escape any parameters that the user can control by using params in order to protect against SQL injection attacks. params is a required argument to force you to acknowledge that you’re not interpolating your SQL with user provided data.

Technical Information

Below you’ll find technical implementation details that may be useful to library authors. The technical API and examples below will help with creating generic query expressions that can extend the built-in functionality that Django provides.

Expression API

Query expressions implement the query expression API, but also expose a number of extra methods and attributes listed below. All query expressions must inherit from Expression() or a relevant subclass.

When a query expression wraps another expression, it is responsible for calling the appropriate methods on the wrapped expression.

class Expression[source]

contains_aggregate

Tells Django that this expression contains an aggregate and that a GROUP BY clause needs to be added to the query.

resolve_expression(query=None, allow_joins=True, reuse=None, summarize=False, for_save=False)

Provides the chance to do any pre-processing or validation of the expression before it’s added to the query. resolve_expression() must also be called on any nested expressions. A copy() of self should be returned with any necessary transformations.

query is the backend query implementation.

allow_joins is a boolean that allows or denies the use of joins in the query.

reuse is a set of reusable joins for multi-join scenarios.

summarize is a boolean that, when True, signals that the query being computed is a terminal aggregate query.

get_source_expressions()

Returns an ordered list of inner expressions. For example:

>>> Sum(F('foo')).get_source_expressions()
[F('foo')]

set_source_expressions(expressions)

Takes a list of expressions and stores them such that get_source_expressions() can return them.

relabeled_clone(change_map)

Returns a clone (copy) of self, with any column aliases relabeled. Column aliases are renamed when subqueries are created. relabeled_clone() should also be called on any nested expressions and assigned to the clone.

change_map is a dictionary mapping old aliases to new aliases.

Example:

def relabeled_clone(self, change_map):
clone = copy.copy(self)
clone.expression = self.expression.relabeled_clone(change_map)
return clone

convert_value(self, value, expression, connection, context)

A hook allowing the expression to coerce value into a more appropriate type.

refs_aggregate(existing_aggregates)

Returns a tuple containing the (aggregate, lookup_path) of the first aggregate that this expression (or any nested expression) references, or (False, ()) if no aggregate is referenced. For example:

queryset.filter(num_chairs__gt=F('sum__employees'))

The F() expression here references a previous Sum() computation which means that this filter expression should be added to the HAVING clause rather than the WHERE clause.

In the majority of cases, returning the result of refs_aggregate on any nested expression should be appropriate, as the necessary built-in expressions will return the correct values.

get_group_by_cols()

Responsible for returning the list of columns references by this expression. get_group_by_cols() should be called on any nested expressions. F() objects, in particular, hold a reference to a column.

asc()

Returns the expression ready to be sorted in ascending order.

desc()

Returns the expression ready to be sorted in descending order.

reverse_ordering()

Returns self with any modifications required to reverse the sort order within an order_by call. As an example, an expression implementing NULLS LAST would change its value to be NULLS FIRST. Modifications are only required for expressions that implement sort order like OrderBy. This method is called when reverse() is called on a queryset.

Writing your own Query Expressions

You can write your own query expression classes that use, and can integrate with, other query expressions. Let’s step through an example by writing an implementation of the COALESCE SQL function, without using the built-in Func() expressions.

The COALESCE SQL function is defined as taking a list of columns or values. It will return the first column or value that isn’t NULL.

We’ll start by defining the template to be used for SQL generation and an __init__() method to set some attributes:

import copy
from django.db.models import Expression

class Coalesce(Expression):
template = 'COALESCE( %(expressions)s )'

def __init__(self, expressions, output_field, **extra):
super(Coalesce, self).__init__(output_field=output_field)
if len(expressions) < 2:
raise ValueError('expressions must have at least 2 elements')
for expression in expressions:
if not hasattr(expression, 'resolve_expression'):
raise TypeError('%r is not an Expression' % expression)
self.expressions = expressions
self.extra = extra

We do some basic validation on the parameters, including requiring at least 2 columns or values, and ensuring they are expressions. We are requiring output_field here so that Django knows what kind of model field to assign the eventual result to.

Now we implement the pre-processing and validation. Since we do not have any of our own validation at this point, we just delegate to the nested expressions:

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = self.copy()
c.is_summary = summarize
for pos, expression in enumerate(self.expressions):
c.expressions[pos] = expression.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c

Next, we write the method responsible for generating the SQL:

def as_sql(self, compiler, connection):
sql_expressions, sql_params = [], []
for expression in self.expressions:
sql, params = compiler.compile(expression)
sql_expressions.append(sql)
sql_params.extend(params)
self.extra['expressions'] = ','.join(sql_expressions)
return self.template % self.extra, sql_params

def as_oracle(self, compiler, connection):
"""
Example of vendor specific handling (Oracle in this case).
Let's make the function name lowercase.
"""
self.template = 'coalesce( %(expressions)s )'
return self.as_sql(compiler, connection)

We generate the SQL for each of the expressions by using the compiler.compile() method, and join the result together with commas. Then the template is filled out with our data and the SQL and parameters are returned.

We’ve also defined a custom implementation that is specific to the Oracle backend. The as_oracle() function will be called instead of as_sql() if the Oracle backend is in use.

Finally, we implement the rest of the methods that allow our query expression to play nice with other query expressions:

def get_source_expressions(self):
return self.expressions

def set_source_expressions(self, expressions):
self.expressions = expressions

Let’s see how it works:

>>> from django.db.models import F, Value, CharField
>>> qs = Company.objects.annotate(
...    tagline=Coalesce([
...        F('motto'),
...        F('ticker_name'),
...        F('description'),
...        Value('No Tagline')
...        ], output_field=CharField()))
>>> for c in qs:
...     print("%s: %s" % (c.name, c.tagline))
...
Google: Do No Evil
Apple: AAPL
Yahoo: Internet Company
Django Software Foundation: No Tagline

Adding support in third-party database backends

If you’re using a database backend that uses a different SQL syntax for a certain function, you can add support for it by monkey patching a new method onto the function’s class.

Let’s say we’re writing a backend for Microsoft’s SQL Server which uses the SQL LEN instead of LENGTH for the Length function. We’ll monkey patch a new method called as_sqlserver() onto the Length class:

from django.db.models.functions import Length

def sqlserver_length(self, compiler, connection):
return self.as_sql(compiler, connection, function='LEN')

Length.as_sqlserver = sqlserver_length

You can also customize the SQL using the template parameter of as_sql().

We use as_sqlserver() because django.db.connection.vendor returns sqlserver for the backend.

Third-party backends can register their functions in the top level __init__.py file of the backend package or in a top level expressions.py file (or package) that is imported from the top level __init__.py.

For user projects wishing to patch the backend that they’re using, this code should live in an AppConfig.ready() method.

Conditional Expressions

New in Django 1.8.

Conditional expressions let you use if ... elif ... else logic within filters, annotations, aggregations, and updates. A conditional expression evaluates a series of conditions for each row of a table and returns the matching result expression. Conditional expressions can also be combined and nested like other expressions.

The conditional expression classes

We’ll be using the following model in the subsequent examples:

from django.db import models

class Client(models.Model):
REGULAR = 'R'
GOLD = 'G'
PLATINUM = 'P'
ACCOUNT_TYPE_CHOICES = (
(REGULAR, 'Regular'),
(GOLD, 'Gold'),
(PLATINUM, 'Platinum'),
)
name = models.CharField(max_length=50)
registered_on = models.DateField()
account_type = models.CharField(
max_length=1,
choices=ACCOUNT_TYPE_CHOICES,
default=REGULAR,
)

When

class When(condition=None, then=None, **lookups)[source]

A When() object is used to encapsulate a condition and its result for use in the conditional expression. Using a When() object is similar to using the filter() method. The condition can be specified using field lookups or Q objects. The result is provided using the then keyword.

Some examples:

>>> from django.db.models import When, F, Q
>>> # String arguments refer to fields; the following two examples are equivalent:
>>> When(account_type=Client.GOLD, then='name')
>>> When(account_type=Client.GOLD, then=F('name'))
>>> # You can use field lookups in the condition
>>> from datetime import date
>>> When(registered_on__gt=date(2014, 1, 1),
...      registered_on__lt=date(2015, 1, 1),
...      then='account_type')
>>> # Complex conditions can be created using Q objects
>>> When(Q(name__startswith="John") | Q(name__startswith="Paul"),
...      then='name')

Keep in mind that each of these values can be an expression.

Note

Since the then keyword argument is reserved for the result of the When(), there is a potential conflict if a Model has a field named then. This can be resolved in two ways:

>>> When(then__exact=0, then=1)
>>> When(Q(then=0), then=1)

Case

class Case(*cases, **extra)[source]

A Case() expression is like the if ... elif ... else statement in Python. Each condition in the provided When() objects is evaluated in order, until one evaluates to a truthful value. The result expression from the matching When() object is returned.

A simple example:

>>>
>>> from datetime import date, timedelta
>>> from django.db.models import CharField, Case, Value, When
>>> Client.objects.create(
...     name='Jane Doe',
...     account_type=Client.REGULAR,
...     registered_on=date.today() - timedelta(days=36))
>>> Client.objects.create(
...     name='James Smith',
...     account_type=Client.GOLD,
...     registered_on=date.today() - timedelta(days=5))
>>> Client.objects.create(
...     name='Jack Black',
...     account_type=Client.PLATINUM,
...     registered_on=date.today() - timedelta(days=10 * 365))
>>> # Get the discount for each Client based on the account type
>>> Client.objects.annotate(
...     discount=Case(
...         When(account_type=Client.GOLD, then=Value('5%')),
...         When(account_type=Client.PLATINUM, then=Value('10%')),
...         default=Value('0%'),
...         output_field=CharField(),
...     ),
... ).values_list('name', 'discount')
[('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')]

Case() accepts any number of When() objects as individual arguments. Other options are provided using keyword arguments. If none of the conditions evaluate to TRUE, then the expression given with the default keyword argument is returned. If a default argument isn’t provided, None is used.

If we wanted to change our previous query to get the discount based on how long the Client has been with us, we could do so using lookups:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Get the discount for each Client based on the registration date
>>> Client.objects.annotate(
...     discount=Case(
...         When(registered_on__lte=a_year_ago, then=Value('10%')),
...         When(registered_on__lte=a_month_ago, then=Value('5%')),
...         default=Value('0%'),
...         output_field=CharField(),
...     )
... ).values_list('name', 'discount')
[('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]

Note

Remember that the conditions are evaluated in order, so in the above example we get the correct result even though the second condition matches both Jane Doe and Jack Black. This works just like an if ... elif ... else statement in Python.

Advanced queries

Conditional expressions can be used in annotations, aggregations, lookups, and updates. They can also be combined and nested with other expressions. This allows you to make powerful conditional queries.

Conditional update

Let’s say we want to change the account_type for our clients to match their registration dates. We can do this using a conditional expression and the update() method:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Update the account_type for each Client from the registration date
>>> Client.objects.update(
...     account_type=Case(
...         When(registered_on__lte=a_year_ago,
...              then=Value(Client.PLATINUM)),
...         When(registered_on__lte=a_month_ago,
...              then=Value(Client.GOLD)),
...         default=Value(Client.REGULAR)
...     ),
... )
>>> Client.objects.values_list('name', 'account_type')
[('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')]

Conditional aggregation

What if we want to find out how many clients there are for each account_type? We can nest conditional expression within aggregate functions to achieve this:

>>> # Create some more Clients first so we can have something to count
>>> Client.objects.create(
...     name='Jean Grey',
...     account_type=Client.REGULAR,
...     registered_on=date.today())
>>> Client.objects.create(
...     name='James Bond',
...     account_type=Client.PLATINUM,
...     registered_on=date.today())
>>> Client.objects.create(
...     name='Jane Porter',
...     account_type=Client.PLATINUM,
...     registered_on=date.today())
>>> # Get counts for each value of account_type
>>> from django.db.models import IntegerField, Sum
>>> Client.objects.aggregate(
...     regular=Sum(
...         Case(When(account_type=Client.REGULAR, then=1),
...              output_field=IntegerField())
...     ),
...     gold=Sum(
...         Case(When(account_type=Client.GOLD, then=1),
...              output_field=IntegerField())
...     ),
...     platinum=Sum(
...         Case(When(account_type=Client.PLATINUM, then=1),
...              output_field=IntegerField())
...     )
... )
{'regular': 2, 'gold': 1, 'platinum': 3}

Database Functions

New in Django 1.8.

The classes documented below provide a way for users to use functions provided by the underlying database as annotations, aggregations, or filters in Django. Functions are also expressions, so they can be used and combined with other expressions like aggregate functions.

We’ll be using the following model in examples of each function:

class Author(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveIntegerField(null=True, blank=True)
alias = models.CharField(max_length=50, null=True, blank=True)
goes_by = models.CharField(max_length=50, null=True, blank=True)

We don’t usually recommend allowing null=True for CharField since this allows the field to have two “empty values”, but it’s important for the Coalesce example below.

Coalesce

class Coalesce(*expressions, **extra)[source]

Accepts a list of at least two field names or expressions and returns the first non-null value (note that an empty string is not considered a null value). Each argument must be of a similar type, so mixing text and numbers will result in a database error.

Usage examples:

>>> # Get a screen name from least to most public
>>> from django.db.models import Sum, Value as V
>>> from django.db.models.functions import Coalesce
>>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
>>> author = Author.objects.annotate(
...    screen_name=Coalesce('alias', 'goes_by', 'name')).get()
>>> print(author.screen_name)
Maggie

>>> # Prevent an aggregate Sum() from returning None
>>> aggregated = Author.objects.aggregate(
...    combined_age=Coalesce(Sum('age'), V(0)),
...    combined_age_default=Sum('age'))
>>> print(aggregated['combined_age'])
0
>>> print(aggregated['combined_age_default'])
None

Warning

A Python value passed to Coalesce on MySQL may be converted to an incorrect type unless explicitly cast to the correct database type:

>>> from django.db.models.expressions import RawSQL
>>> from django.utils import timezone
>>> now = timezone.now()
>>> now_sql = RawSQL("cast(%s as datetime)", (now,))
>>> Coalesce('updated', now_sql)

Concat

class Concat(*expressions, **extra)[source]

Accepts a list of at least two text fields or expressions and returns the concatenated text. Each argument must be of a text or char type. If you want to concatenate a TextField() with a CharField(), then be sure to tell Django that the output_field should be a TextField(). This is also required when concatenating a Value as in the example below.

This function will never have a null result. On backends where a null argument results in the entire expression being null, Django will ensure that each null part is converted to an empty string first.

Usage example:

>>> # Get the display name as "name (goes_by)"
>>> from django.db.models import CharField, Value as V
>>> from django.db.models.functions import Concat
>>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
>>> author = Author.objects.annotate(
...    screen_name=Concat('name', V(' ('), 'goes_by', V(')'),
...    output_field=CharField())).get()
>>> print(author.screen_name)
Margaret Smith (Maggie)

Greatest

class Greatest(*expressions, **extra)[source]

New in Django 1.9.

Accepts a list of at least two field names or expressions and returns the greatest value. Each argument must be of a similar type, so mixing text and numbers will result in a database error.

Usage example:

class Blog(models.Model):
body = models.TextField()
modified = models.DateTimeField(auto_now=True)

class Comment(models.Model):
body = models.TextField()
modified = models.DateTimeField(auto_now=True)
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)

>>> from django.db.models.functions import Greatest
>>> blog = Blog.objects.create(body='Greatest is the best.')
>>> comment = Comment.objects.create(body='No, Least is better.', blog=blog)
>>> comments = Comment.objects.annotate(last_updated=Greatest('modified', 'blog__modified'))
>>> annotated_comment = comments.get()

annotated_comment.last_updated will be the most recent of blog.modified and comment.modified.

Warning

The behavior of Greatest when one or more expression may be null varies between databases:

- PostgreSQL: Greatest will return the largest non-null expression, or null if all expressions are null.

- SQLite, Oracle, and MySQL: If any expression is null, Greatest will return null.

The PostgreSQL behavior can be emulated using Coalesce if you know a sensible minimum value to provide as a default.

Least

class Least(*expressions, **extra)[source]

New in Django 1.9.

Accepts a list of at least two field names or expressions and returns the least value. Each argument must be of a similar type, so mixing text and numbers will result in a database error.

Warning

The behavior of Least when one or more expression may be null varies between databases:

- PostgreSQL: Least will return the smallest non-null expression, or null if all expressions are null.

- SQLite, Oracle, and MySQL: If any expression is null, Least will return null.

The PostgreSQL behavior can be emulated using Coalesce if you know a sensible maximum value to provide as a default.

Length

class Length(expression, **extra)[source]

Accepts a single text field or expression and returns the number of characters the value has. If the expression is null, then the length will also be null.

Usage example:

>>> # Get the length of the name and goes_by fields
>>> from django.db.models.functions import Length
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(
...    name_length=Length('name'),
...    goes_by_length=Length('goes_by')).get()
>>> print(author.name_length, author.goes_by_length)
(14, None)

It can also be registered as a transform. For example:

>>> from django.db.models import CharField
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length, 'length')
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)

Changed in Django 1.9:
The ability to register the function as a transform was added.

Lower

class Lower(expression, **extra)[source]

Accepts a single text field or expression and returns the lowercase representation.

It can also be registered as a transform as described in Length.

Usage example:

>>> from django.db.models.functions import Lower
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(name_lower=Lower('name')).get()
>>> print(author.name_lower)
margaret smith

Changed in Django 1.9:
The ability to register the function as a transform was added.

Now

class Now[source]

New in Django 1.9.

Returns the database server’s current date and time when the query is executed, typically using the SQL CURRENT_TIMESTAMP.

Usage example:

>>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now())
[<Article: How to Django>]

PostgreSQL considerations

On PostgreSQL, the SQL CURRENT_TIMESTAMP returns the time that the current transaction started. Therefore for cross-database compatibility, Now() uses STATEMENT_TIMESTAMP instead. If you need the transaction timestamp, use django.contrib.postgres.functions.TransactionNow.

Substr

class Substr(expression, pos, length=None, **extra)[source]

Returns a substring of length length from the field or expression starting at position pos. The position is 1-indexed, so the position must be greater than 0. If length is None, then the rest of the string will be returned.

Usage example:

>>> # Set the alias to the first 5 characters of the name as lowercase
>>> from django.db.models.functions import Substr, Lower
>>> Author.objects.create(name='Margaret Smith')
>>> Author.objects.update(alias=Lower(Substr('name', 1, 5)))
1
>>> print(Author.objects.get(name='Margaret Smith').alias)
marga

Upper

class Upper(expression, **extra)[source]

Accepts a single text field or expression and returns the uppercase representation.

It can also be registered as a transform as described in Length.

Usage example:

>>> from django.db.models.functions import Upper
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(name_upper=Upper('name')).get()
>>> print(author.name_upper)
MARGARET SMITH

Changed in Django 1.9:
The ability to register the function as a transform was added.

Request and response objects

Quick overview

Django uses request and response objects to pass state through the system.

When a page is requested, Django creates an HttpRequest object that contains metadata about the request. Then Django loads the appropriate view, passing the HttpRequest as the first argument to the view function. Each view is responsible for returning an HttpResponse object.

This document explains the APIs for HttpRequest and HttpResponse objects, which are defined in the django.http module.

HttpRequest objects

class HttpRequest[source]

Attributes

All attributes should be considered read-only, unless stated otherwise.

HttpRequest.scheme

A string representing the scheme of the request (http or https usually).

HttpRequest.body

The raw HTTP request body as a byte string. This is useful for processing data in different ways than conventional HTML forms: binary images, XML payload etc. For processing conventional form data, use HttpRequest.POST.

You can also read from an HttpRequest using a file-like interface. See HttpRequest.read().

HttpRequest.path

A string representing the full path to the requested page, not including the scheme or domain.

Example: "/music/bands/the_beatles/"

HttpRequest.path_info

Under some Web server configurations, the portion of the URL after the host name is split up into a script prefix portion and a path info portion. The path_info attribute always contains the path info portion of the path, no matter what Web server is being used. Using this instead of path can make your code easier to move between test and deployment servers.

For example, if the WSGIScriptAlias for your application is set to "/minfo", then path might be "/minfo/music/bands/the_beatles/" and path_info would be "/music/bands/the_beatles/".

HttpRequest.method

A string representing the HTTP method used in the request. This is guaranteed to be uppercase. Example:

if request.method == 'GET':
do_something()
elif request.method == 'POST':
do_something_else()

HttpRequest.encoding

A string representing the current encoding used to decode form submission data (or None, which means the DEFAULT_CHARSET setting is used). You can write to this attribute to change the encoding used when accessing the form data. Any subsequent attribute accesses (such as reading from GET or POST) will use the new encoding value. Useful if you know the form data is not in the DEFAULT_CHARSET encoding.

HttpRequest.GET

A dictionary-like object containing all given HTTP GET parameters. See the QueryDict documentation below.

HttpRequest.POST

A dictionary-like object containing all given HTTP POST parameters, providing that the request contains form data. See the QueryDict documentation below. If you need to access raw or non-form data posted in the request, access this through the HttpRequest.body attribute instead.

It’s possible that a request can come in via POST with an empty POST dictionary – if, say, a form is requested via the POST HTTP method but does not include form data. Therefore, you shouldn’t use if request.POST to check for use of the POST method; instead, use if request.method == "POST" (see above).

Note: POST does not include file-upload information. See FILES.

HttpRequest.COOKIES

A standard Python dictionary containing all cookies. Keys and values are strings.

HttpRequest.FILES

A dictionary-like object containing all uploaded files. Each key in FILES is the name from the <input type="file" name="" />. Each value in FILES is an UploadedFile.

See Managing files for more information.

Note that FILES will only contain data if the request method was POST and the <form> that posted to the request had enctype="multipart/form-data". Otherwise, FILES will be a blank dictionary-like object.

HttpRequest.META

A standard Python dictionary containing all available HTTP headers. Available headers depend on the client and server, but here are some examples:

- CONTENT_LENGTH – The length of the request body (as a string).

- CONTENT_TYPE – The MIME type of the request body.

- HTTP_ACCEPT – Acceptable content types for the response.

- HTTP_ACCEPT_ENCODING – Acceptable encodings for the response.

- HTTP_ACCEPT_LANGUAGE – Acceptable languages for the response.

- HTTP_HOST – The HTTP Host header sent by the client.

- HTTP_REFERER – The referring page, if any.

- HTTP_USER_AGENT – The client’s user-agent string.

- QUERY_STRING – The query string, as a single (unparsed) string.

- REMOTE_ADDR – The IP address of the client.

- REMOTE_HOST – The hostname of the client.

- REMOTE_USER – The user authenticated by the Web server, if any.

- REQUEST_METHOD – A string such as "GET" or "POST".

- SERVER_NAME – The hostname of the server.

- SERVER_PORT – The port of the server (as a string).

With the exception of CONTENT_LENGTH and CONTENT_TYPE, as given above, any HTTP headers in the request are converted to META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name. So, for example, a header called X-Bender would be mapped to the META key HTTP_X_BENDER.

Note that runserver strips all headers with underscores in the name, so you won’t see them in META. This prevents header-spoofing based on ambiguity between underscores and dashes both being normalizing to underscores in WSGI environment variables. It matches the behavior of Web servers like Nginx and Apache 2.4+.

HttpRequest.resolver_match

An instance of ResolverMatch representing the resolved url. This attribute is only set after url resolving took place, which means it’s available in all views but not in middleware methods which are executed before url resolving takes place (like process_request, you can use process_view instead).

Attributes set by application code

Django doesn’t set these attributes itself but makes use of them if set by your application.

HttpRequest.current_app

New in Django 1.8.

The url template tag will use its value as the current_app argument to reverse().

HttpRequest.urlconf

This will be used as the root URLconf for the current request, overriding the ROOT_URLCONF setting. See How Django processes a request for details.

urlconf can be set to None to revert any changes made by previous middleware and return to using the ROOT_URLCONF.

Changed in Django 1.9:
Setting urlconf=None raised ImproperlyConfigured in older versions.

Attributes set by middleware

Some of the middleware included in Django’s contrib apps set attributes on the request. If you don’t see the attribute on a request, be sure the appropriate middleware class is listed in MIDDLEWARE_CLASSES.

HttpRequest.session

From the SessionMiddleware: A readable and writable, dictionary-like object that represents the current session.

HttpRequest.site

From the CurrentSiteMiddleware: An instance of Site or RequestSite as returned by get_current_site() representing the current site.

HttpRequest.user

From the AuthenticationMiddleware: An instance of AUTH_USER_MODEL representing the currently logged-in user. If the user isn’t currently logged in, user will be set to an instance of AnonymousUser. You can tell them apart with is_authenticated(), like so:

if request.user.is_authenticated():
... # Do something for logged-in users.
else:
... # Do something for anonymous users.

Methods

HttpRequest.get_host()[source]

Returns the originating host of the request using information from the HTTP_X_FORWARDED_HOST (if USE_X_FORWARDED_HOST is enabled) and HTTP_HOST headers, in that order. If they don’t provide a value, the method uses a combination of SERVER_NAME and SERVER_PORT as detailed in PEP 3333.

Example: "127.0.0.1:8000"

Note

The get_host() method fails when the host is behind multiple proxies. One solution is to use middleware to rewrite the proxy headers, as in the following example:

class MultipleProxyMiddleware(object):
FORWARDED_FOR_FIELDS = [
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED_HOST',
'HTTP_X_FORWARDED_SERVER',
]

def process_request(self, request):
"""
Rewrites the proxy headers so that only the most
recent proxy is used.
"""
for field in self.FORWARDED_FOR_FIELDS:
if field in request.META:
if ',' in request.META[field]:
parts = request.META[field].split(',')
request.META[field] = parts[-1].strip()

This middleware should be positioned before any other middleware that relies on the value of get_host() – for instance, CommonMiddleware or CsrfViewMiddleware.

HttpRequest.get_port()[source]

New in Django 1.9.

Returns the originating port of the request using information from the HTTP_X_FORWARDED_PORT (if USE_X_FORWARDED_PORT is enabled) and SERVER_PORT META variables, in that order.

HttpRequest.get_full_path()[source]

Returns the path, plus an appended query string, if applicable.

Example: "/music/bands/the_beatles/?print=true"

HttpRequest.build_absolute_uri(location)[source]

Returns the absolute URI form of location. If no location is provided, the location will be set to request.get_full_path().

If the location is already an absolute URI, it will not be altered. Otherwise the absolute URI is built using the server variables available in this request.

Example: "https://example.com/music/bands/the_beatles/?print=true"

Note

Mixing HTTP and HTTPS on the same site is discouraged, therefore build_absolute_uri() will always generate an absolute URI with the same scheme the current request has. If you need to redirect users to HTTPS, it’s best to let your webserver redirect all HTTP traffic to HTTPS.

HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)[source]

Returns a cookie value for a signed cookie, or raises a django.core.signing.BadSignature exception if the signature is no longer valid. If you provide the default argument the exception will be suppressed and that default value will be returned instead.

The optional salt argument can be used to provide extra protection against brute force attacks on your secret key. If supplied, the max_age argument will be checked against the signed timestamp attached to the cookie value to ensure the cookie is not older than max_age seconds.

For example:

>>> request.get_signed_cookie('name')
'Tony'
>>> request.get_signed_cookie('name', salt='name-salt')
'Tony' # assuming cookie was set using the same salt
>>> request.get_signed_cookie('non-existing-cookie')
...
KeyError: 'non-existing-cookie'
>>> request.get_signed_cookie('non-existing-cookie', False)
False
>>> request.get_signed_cookie('cookie-that-was-tampered-with')
...
BadSignature: ...
>>> request.get_signed_cookie('name', max_age=60)
...
SignatureExpired: Signature age 1677.3839159 > 60 seconds
>>> request.get_signed_cookie('name', False, max_age=60)
False

See cryptographic signing for more information.

HttpRequest.is_secure()[source]

Returns True if the request is secure; that is, if it was made with HTTPS.

HttpRequest.is_ajax()[source]

Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. Most modern JavaScript libraries send this header. If you write your own XMLHttpRequest call (on the browser side), you’ll have to set this header manually if you want is_ajax() to work.

If a response varies on whether or not it’s requested via AJAX and you are using some form of caching like Django’s cache middleware, you should decorate the view with vary_on_headers('HTTP_X_REQUESTED_WITH') so that the responses are properly cached.

HttpRequest.read(size=None)[source]

HttpRequest.readline()[source]

HttpRequest.readlines()[source]

HttpRequest.xreadlines()[source]

HttpRequest.__iter__()

Methods implementing a file-like interface for reading from an HttpRequest instance. This makes it possible to consume an incoming request in a streaming fashion. A common use-case would be to process a big XML payload with an iterative parser without constructing a whole XML tree in memory.

Given this standard interface, an HttpRequest instance can be passed directly to an XML parser such as ElementTree:

import xml.etree.ElementTree as ET
for element in ET.iterparse(request):
process(element)

QueryDict objects

class QueryDict[source]

In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict, a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably <select multiple>, pass multiple values for the same key.

The QueryDicts at request.POST and request.GET will be immutable when accessed in a normal request/response cycle. To get a mutable version you need to use .copy().

Methods

QueryDict implements all the standard dictionary methods because it’s a subclass of dictionary. Exceptions are outlined here:

QueryDict.__init__(query_string=None, mutable=False, encoding=None)[source]

Instantiates a QueryDict object based on query_string.

>>> QueryDict('a=1&a=2&c=3')
<QueryDict: {'a': ['1', '2'], 'c': ['3']}>

If query_string is not passed in, the resulting QueryDict will be empty (it will have no keys or values).

Most QueryDicts you encounter, and in particular those at request.POST and request.GET, will be immutable. If you are instantiating one yourself, you can make it mutable by passing mutable=True to its __init__().

Strings for setting both keys and values will be converted from encoding to unicode. If encoding is not set, it defaults to DEFAULT_CHARSET.

Changed in Django 1.8:
In previous versions, query_string was a required positional argument.

QueryDict.__getitem__(key)

Returns the value for the given key. If the key has more than one value, __getitem__() returns the last value. Raises django.utils.datastructures.MultiValueDictKeyError if the key does not exist. (This is a subclass of Python’s standard KeyError, so you can stick to catching KeyError.)

QueryDict.__setitem__(key, value)[source]

Sets the given key to [value] (a Python list whose single element is value). Note that this, as other dictionary functions that have side effects, can only be called on a mutable QueryDict (such as one that was created via copy()).

QueryDict.__contains__(key)

Returns True if the given key is set. This lets you do, e.g., if "foo" in request.GET.

QueryDict.get(key, default=None)

Uses the same logic as __getitem__() above, with a hook for returning a default value if the key doesn’t exist.

QueryDict.setdefault(key, default=None)[source]

Just like the standard dictionary setdefault() method, except it uses __setitem__() internally.

QueryDict.update(other_dict)

Takes either a QueryDict or standard dictionary. Just like the standard dictionary update() method, except it appends to the current dictionary items rather than replacing them. For example:

>>> q = QueryDict('a=1', mutable=True)
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # returns the last
'2'

QueryDict.items()

Just like the standard dictionary items() method, except this uses the same last-value logic as __getitem__(). For example:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.items()
[('a', '3')]

QueryDict.iteritems()

Just like the standard dictionary iteritems() method. Like QueryDict.items() this uses the same last-value logic as QueryDict.__getitem__().

QueryDict.iterlists()

Like QueryDict.iteritems() except it includes all values, as a list, for each member of the dictionary.

QueryDict.values()

Just like the standard dictionary values() method, except this uses the same last-value logic as __getitem__(). For example:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.values()
['3']

QueryDict.itervalues()

Just like QueryDict.values(), except an iterator.

In addition, QueryDict has the following methods:

QueryDict.copy()[source]

Returns a copy of the object, using copy.deepcopy() from the Python standard library. This copy will be mutable even if the original was not.

QueryDict.getlist(key, default=None)

Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn’t exist and no default value was provided. It’s guaranteed to return a list of some sort unless the default value provided is not a list.

QueryDict.setlist(key, list_)[source]

Sets the given key to list_ (unlike __setitem__()).

QueryDict.appendlist(key, item)[source]

Appends an item to the internal list associated with key.

QueryDict.setlistdefault(key, default_list=None)[source]

Just like setdefault, except it takes a list of values instead of a single value.

QueryDict.lists()

Like items(), except it includes all values, as a list, for each member of the dictionary. For example:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[('a', ['1', '2', '3'])]

QueryDict.pop(key)[source]

Returns a list of values for the given key and removes them from the dictionary. Raises KeyError if the key does not exist. For example:

>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
>>> q.pop('a')
['1', '2', '3']

QueryDict.popitem()[source]

Removes an arbitrary member of the dictionary (since there’s no concept of ordering), and returns a two value tuple containing the key and a list of all values for the key. Raises KeyError when called on an empty dictionary. For example:

>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
>>> q.popitem()
('a', ['1', '2', '3'])

QueryDict.dict()

Returns dict representation of QueryDict. For every (key, list) pair in QueryDict, dict will have (key, item), where item is one element of the list, using same logic as QueryDict.__getitem__():

>>> q = QueryDict('a=1&a=3&a=5')
>>> q.dict()
{'a': '5'}

QueryDict.urlencode(safe=None)[source]

Returns a string of the data in query-string format. Example:

>>> q = QueryDict('a=2&b=3&b=5')
>>> q.urlencode()
'a=2&b=3&b=5'

Optionally, urlencode can be passed characters which do not require encoding. For example:

>>> q = QueryDict(mutable=True)
>>> q['next'] = '/a&b/'
>>> q.urlencode(safe='/')
'next=/a%26b/'

HttpResponse objects

class HttpResponse[source]

In contrast to HttpRequest objects, which are created automatically by Django, HttpResponse objects are your responsibility. Each view you write is responsible for instantiating, populating and returning an HttpResponse.

The HttpResponse class lives in the django.http module.

Usage

Passing strings

Typical usage is to pass the contents of the page, as a string, to the HttpResponse constructor:

>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")

But if you want to add content incrementally, you can use response as a file-like object:

>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")

Passing iterators

Finally, you can pass HttpResponse an iterator rather than strings. HttpResponse will consume the iterator immediately, store its content as a string, and discard it.

If you need the response to be streamed from the iterator to the client, you must use the StreamingHttpResponse class instead.

Setting header fields

To set or remove a header field in your response, treat it like a dictionary:

>>> response = HttpResponse()
>>> response['Age'] = 120
>>> del response['Age']

Note that unlike a dictionary, del doesn’t raise KeyError if the header field doesn’t exist.

For setting the Cache-Control and Vary header fields, it is recommended to use the patch_cache_control() and patch_vary_headers() methods from django.utils.cache, since these fields can have multiple, comma-separated values. The “patch” methods ensure that other values, e.g. added by a middleware, are not removed.

HTTP header fields cannot contain newlines. An attempt to set a header field containing a newline character (CR or LF) will raise BadHeaderError

Telling the browser to treat the response as a file attachment

To tell the browser to treat the response as a file attachment, use the content_type argument and set the Content-Disposition header. For example, this is how you might return a Microsoft Excel spreadsheet:

>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'

There’s nothing Django-specific about the Content-Disposition header, but it’s easy to forget the syntax, so we’ve included it here.

Attributes

HttpResponse.content

A bytestring representing the content, encoded from a Unicode object if necessary.

HttpResponse.charset

New in Django 1.8.

A string denoting the charset in which the response will be encoded. If not given at HttpResponse instantiation time, it will be extracted from content_type and if that is unsuccessful, the DEFAULT_CHARSET setting will be used.

HttpResponse.status_code

The HTTP status code for the response.

Changed in Django 1.9:
Unless reason_phrase is explicitly set, modifying the value of status_code outside the constructor will also modify the value of reason_phrase.

HttpResponse.reason_phrase

The HTTP reason phrase for the response.

Changed in Django 1.9:
reason_phrase no longer defaults to all capital letters. It now uses the HTTP standard’s default reason phrases.

Unless explicitly set, reason_phrase is determined by the current value of status_code.

HttpResponse.streaming

This is always False.

This attribute exists so middleware can treat streaming responses differently from regular responses.

HttpResponse.closed

New in Django 1.8.

True if the response has been closed.

Methods

HttpResponse.__init__(content='', content_type=None, status=200, reason=None, charset=None)[source]

Instantiates an HttpResponse object with the given page content and content type.

content should be an iterator or a string. If it’s an iterator, it should return strings, and those strings will be joined together to form the content of the response. If it is not an iterator or a string, it will be converted to a string when accessed.

content_type is the MIME type optionally completed by a character set encoding and is used to fill the HTTP Content-Type header. If not specified, it is formed by the DEFAULT_CONTENT_TYPE and DEFAULT_CHARSET settings, by default: “text/html; charset=utf-8”.

status is the HTTP status code for the response.

reason is the HTTP response phrase. If not provided, a default phrase will be used.

charset is the charset in which the response will be encoded. If not given it will be extracted from content_type, and if that is unsuccessful, the DEFAULT_CHARSET setting will be used.

New in Django 1.8:
The charset parameter was added.

HttpResponse.__setitem__(header, value)

Sets the given header name to the given value. Both header and value should be strings.

HttpResponse.__delitem__(header)

Deletes the header with the given name. Fails silently if the header doesn’t exist. Case-insensitive.

HttpResponse.__getitem__(header)

Returns the value for the given header name. Case-insensitive.

HttpResponse.has_header(header)

Returns True or False based on a case-insensitive check for a header with the given name.

HttpResponse.setdefault(header, value)

New in Django 1.8.

Sets a header unless it has already been set.

HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)

Sets a cookie. The parameters are the same as in the Morsel cookie object in the Python standard library.

- max_age should be a number of seconds, or None (default) if the cookie should last only as long as the client’s browser session. If expires is not specified, it will be calculated.

- expires should either be a string in the format "Wdy, DD-Mon-YY HH:MM:SS GMT" or a datetime.datetime object in UTC. If expires is a datetime object, the max_age will be calculated.

- Use domain if you want to set a cross-domain cookie. For example, domain=".lawrence.com" will set a cookie that is readable by the domains www.lawrence.com, blogs.lawrence.com and calendars.lawrence.com. Otherwise, a cookie will only be readable by the domain that set it.

- Use httponly=True if you want to prevent client-side JavaScript from having access to the cookie.

HTTPOnly is a flag included in a Set-Cookie HTTP response header. It is not part of the RFC 2109 standard for cookies, and it isn’t honored consistently by all browsers. However, when it is honored, it can be a useful way to mitigate the risk of a client-side script from accessing the protected cookie data.

Warning

Both RFC 2109 and RFC 6265 state that user agents should support cookies of at least 4096 bytes. For many browsers this is also the maximum size. Django will not raise an exception if there’s an attempt to store a cookie of more than 4096 bytes, but many browsers will not set the cookie correctly.

HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)

Like set_cookie(), but cryptographic signing the cookie before setting it. Use in conjunction with HttpRequest.get_signed_cookie(). You can use the optional salt argument for added key strength, but you will need to remember to pass it to the corresponding HttpRequest.get_signed_cookie() call.

HttpResponse.delete_cookie(key, path='/', domain=None)

Deletes the cookie with the given key. Fails silently if the key doesn’t exist.

Due to the way cookies work, path and domain should be the same values you used in set_cookie() – otherwise the cookie may not be deleted.

HttpResponse.write(content)[source]

This method makes an HttpResponse instance a file-like object.

HttpResponse.flush()

This method makes an HttpResponse instance a file-like object.

HttpResponse.tell()[source]

This method makes an HttpResponse instance a file-like object.

HttpResponse.getvalue()[source]

New in Django 1.8.

Returns the value of HttpResponse.content. This method makes an HttpResponse instance a stream-like object.

HttpResponse.writable()[source]

New in Django 1.8.

Always True. This method makes an HttpResponse instance a stream-like object.

HttpResponse.writelines(lines)[source]

New in Django 1.8.

Writes a list of lines to the response. Line separators are not added. This method makes an HttpResponse instance a stream-like object.

HttpResponse subclasses

Django includes a number of HttpResponse subclasses that handle different types of HTTP responses. Like HttpResponse, these subclasses live in django.http.

class HttpResponseRedirect[source]

The first argument to the constructor is required – the path to redirect to. This can be a fully qualified URL (e.g. 'https://www.yahoo.com/search/'), an absolute path with no domain (e.g. '/search/'), or even a relative path (e.g. 'search/'). In that last case, the client browser will reconstruct the full URL itself according to the current path. See HttpResponse for other optional constructor arguments. Note that this returns an HTTP status code 302.

url

This read-only attribute represents the URL the response will redirect to (equivalent to the Location response header).

class HttpResponsePermanentRedirect[source]

Like HttpResponseRedirect, but it returns a permanent redirect (HTTP status code 301) instead of a “found” redirect (status code 302).

class HttpResponseNotModified[source]

The constructor doesn’t take any arguments and no content should be added to this response. Use this to designate that a page hasn’t been modified since the user’s last request (status code 304).

class HttpResponseBadRequest[source]

Acts just like HttpResponse but uses a 400 status code.

class HttpResponseNotFound[source]

Acts just like HttpResponse but uses a 404 status code.

class HttpResponseForbidden[source]

Acts just like HttpResponse but uses a 403 status code.

class HttpResponseNotAllowed[source]

Like HttpResponse, but uses a 405 status code. The first argument to the constructor is required: a list of permitted methods (e.g. ['GET', 'POST']).

class HttpResponseGone[source]

Acts just like HttpResponse but uses a 410 status code.

class HttpResponseServerError[source]

Acts just like HttpResponse but uses a 500 status code.

Note

If a custom subclass of HttpResponse implements a render method, Django will treat it as emulating a SimpleTemplateResponse, and the render method must itself return a valid response object.

JsonResponse objects

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs)[source]

An HttpResponse subclass that helps to create a JSON-encoded response. It inherits most behavior from its superclass with a couple differences:

Its default Content-Type header is set to application/json.

The first parameter, data, should be a dict instance. If the safe parameter is set to False (see below) it can be any JSON-serializable object.

The encoder, which defaults to django.core.serializers.json.DjangoJSONEncoder, will be used to serialize the data. See JSON serialization for more details about this serializer.

The safe boolean parameter defaults to True. If it’s set to False, any object can be passed for serialization (otherwise only dict instances are allowed). If safe is True and a non-dict object is passed as the first argument, a TypeError will be raised.

The json_dumps_params parameter is a dictionary of keyword arguments to pass to the json.dumps() call used to generate the response.

Changed in Django 1.9:
The json_dumps_params argument was added.

Usage

Typical usage could look like:

>>> from django.http import JsonResponse
>>> response = JsonResponse({'foo': 'bar'})
>>> response.content
b'{"foo": "bar"}'

Serializing non-dictionary objects

In order to serialize objects other than dict you must set the safe parameter to False:

>>> response = JsonResponse([1, 2, 3], safe=False)

Without passing safe=False, a TypeError will be raised.

Warning

Before the 5th edition of ECMAScript it was possible to poison the JavaScript Array constructor. For this reason, Django does not allow passing non-dict objects to the JsonResponse constructor by default. However, most modern browsers implement EcmaScript 5 which removes this attack vector. Therefore it is possible to disable this security precaution.

Changing the default JSON encoder

If you need to use a different JSON encoder class you can pass the encoder parameter to the constructor method:

>>> response = JsonResponse(data, encoder=MyJSONEncoder)

StreamingHttpResponse objects

class StreamingHttpResponse[source]

The StreamingHttpResponse class is used to stream a response from Django to the browser. You might want to do this if generating the response takes too long or uses too much memory. For instance, it’s useful for generating large CSV files.

Performance considerations

Django is designed for short-lived requests. Streaming responses will tie a worker process for the entire duration of the response. This may result in poor performance.

Generally speaking, you should perform expensive tasks outside of the request-response cycle, rather than resorting to a streamed response.

The StreamingHttpResponse is not a subclass of HttpResponse, because it features a slightly different API. However, it is almost identical, with the following notable differences:

- It should be given an iterator that yields strings as content.

- You cannot access its content, except by iterating the response object itself. This should only occur when the response is returned to the client.

- It has no content attribute. Instead, it has a streaming_content attribute.

- You cannot use the file-like object tell() or write() methods. Doing so will raise an exception.

StreamingHttpResponse should only be used in situations where it is absolutely required that the whole content isn’t iterated before transferring the data to the client. Because the content can’t be accessed, many middlewares can’t function normally. For example the ETag and Content- Length headers can’t be generated for streaming responses.

Attributes

StreamingHttpResponse.streaming_content

An iterator of strings representing the content.

StreamingHttpResponse.status_code

The HTTP status code for the response.

Changed in Django 1.9:
Unless reason_phrase is explicitly set, modifying the value of status_code outside the constructor will also modify the value of reason_phrase.

StreamingHttpResponse.reason_phrase

The HTTP reason phrase for the response.

Changed in Django 1.9:
reason_phrase no longer defaults to all capital letters. It now uses the HTTP standard’s default reason phrases.

Unless explicitly set, reason_phrase is determined by the current value of status_code.

StreamingHttpResponse.streaming

This is always True.

FileResponse objects

class FileResponse[source]

FileResponse is a subclass of StreamingHttpResponse optimized for binary files. It uses wsgi.file_wrapper if provided by the wsgi server, otherwise it streams the file out in small chunks.

FileResponse expects a file open in binary mode like so:

>>> from django.http import FileResponse
>>> response = FileResponse(open('myfile.png', 'rb'))

SchemaEditor

class BaseDatabaseSchemaEditor[source]

Django’s migration system is split into two parts; the logic for calculating and storing what operations should be run (django.db.migrations), and the database abstraction layer that turns things like “create a model” or “delete a field” into SQL - which is the job of the SchemaEditor.

It’s unlikely that you will want to interact directly with SchemaEditor as a normal developer using Django, but if you want to write your own migration system, or have more advanced needs, it’s a lot nicer than writing SQL.

Each database backend in Django supplies its own version of SchemaEditor, and it’s always accessible via the connection.schema_editor() context manager:

with connection.schema_editor() as schema_editor:
schema_editor.delete_model(MyModel)

It must be used via the context manager as this allows it to manage things like transactions and deferred SQL (like creating ForeignKey constraints).

It exposes all possible operations as methods, that should be called in the order you wish changes to be applied. Some possible operations or types of change are not possible on all databases - for example, MyISAM does not support foreign key constraints.

If you are writing or maintaining a third-party database backend for Django, you will need to provide a SchemaEditor implementation in order to work with 1.7’s migration functionality - however, as long as your database is relatively standard in its use of SQL and relational design, you should be able to subclass one of the built-in Django SchemaEditor classes and just tweak the syntax a little. Also note that there are a few new database features that migrations will look for: can_rollback_ddl and supports_combined_alters are the most important.

Methods

execute()

BaseDatabaseSchemaEditor.execute(sql, params=[])[source]

Executes the SQL statement passed in, with parameters if supplied. This is a simple wrapper around the normal database cursors that allows capture of the SQL to a .sql file if the user wishes.

create_model()

BaseDatabaseSchemaEditor.create_model(model)[source]

Creates a new table in the database for the provided model, along with any unique constraints or indexes it requires.

delete_model()

BaseDatabaseSchemaEditor.delete_model(model)[source]

Drops the model’s table in the database along with any unique constraints or indexes it has.

alter_unique_together()

BaseDatabaseSchemaEditor.alter_unique_together(model, old_unique_together, new_unique_together)[source]

Changes a model’s unique_together value; this will add or remove unique constraints from the model’s table until they match the new value.

alter_index_together()

BaseDatabaseSchemaEditor.alter_index_together(model, old_index_together, new_index_together)[source]

Changes a model’s index_together value; this will add or remove indexes from the model’s table until they match the new value.

alter_db_table()

BaseDatabaseSchemaEditor.alter_db_table(model, old_db_table, new_db_table)[source]

Renames the model’s table from old_db_table to new_db_table.

alter_db_tablespace()

BaseDatabaseSchemaEditor.alter_db_tablespace(model, old_db_tablespace, new_db_tablespace)[source]

Moves the model’s table from one tablespace to another.

add_field()

BaseDatabaseSchemaEditor.add_field(model, field)[source]

Adds a column (or sometimes multiple) to the model’s table to represent the field. This will also add indexes or a unique constraint if the field has db_index=True or unique=True.

If the field is a ManyToManyField without a value for through, instead of creating a column, it will make a table to represent the relationship. If through is provided, it is a no-op.

If the field is a ForeignKey, this will also add the foreign key constraint to the column.

remove_field()

BaseDatabaseSchemaEditor.remove_field(model, field)[source]

Removes the column(s) representing the field from the model’s table, along with any unique constraints, foreign key constraints, or indexes caused by that field.

If the field is a ManyToManyField without a value for through, it will remove the table created to track the relationship. If through is provided, it is a no-op.

alter_field()

BaseDatabaseSchemaEditor.alter_field(model, old_field, new_field, strict=False)[source]

This transforms the field on the model from the old field to the new one. This includes changing the name of the column (the db_column attribute), changing the type of the field (if the field class changes), changing the NULL status of the field, adding or removing field-only unique constraints and indexes, changing primary key, and changing the destination of ForeignKey constraints.

The most common transformation this cannot do is transforming a ManyToManyField into a normal Field or vice-versa; Django cannot do this without losing data, and so it will refuse to do it. Instead, remove_field() and add_field() should be called separately.

If the database has the supports_combined_alters, Django will try and do as many of these in a single database call as possible; otherwise, it will issue a separate ALTER statement for each change, but will not issue ALTERs where no change is required (as South often did).

Attributes

All attributes should be considered read-only unless stated otherwise.

connection

SchemaEditor.connection

A connection object to the database. A useful attribute of the connection is alias which can be used to determine the name of the database being accessed.

This is useful when doing data migrations for migrations with multiple databases.

Settings

- Core Settings

- Auth

- Messages

- Sessions

- Sites

- Static Files

- Core Settings Topical Index

Warning

Be careful when you override settings, especially when the default value is a non-empty list or dictionary, such as MIDDLEWARE_CLASSES and STATICFILES_FINDERS. Make sure you keep the components required by the features of Django you wish to use.

Core Settings

Here’s a list of settings available in Django core and their default values. Settings provided by contrib apps are listed below, followed by a topical index of the core settings. For introductory material, see the settings topic guide.

ABSOLUTE_URL_OVERRIDES

Default: {} (Empty dictionary)

A dictionary mapping "app_label.model_name" strings to functions that take a model object and return its URL. This is a way of inserting or overriding get_absolute_url() methods on a per-installation basis. Example:

ABSOLUTE_URL_OVERRIDES = {
'blogs.weblog': lambda o: "/blogs/%s/" % o.slug,
'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
}

Note that the model name used in this setting should be all lower-case, regardless of the case of the actual model class name.

ADMINS

Default: [] (Empty list)

A list of all the people who get code error notifications. When DEBUG=False and a view raises an exception, Django will email these people with the full exception information. Each item in the list should be a tuple of (Full name, email address). Example:

[('John', 'john@example.com'), ('Mary', 'mary@example.com')]

Note that Django will email all of these people whenever an error happens. See Error reporting for more information.

ALLOWED_HOSTS

Default: [] (Empty list)

A list of strings representing the host/domain names that this Django site can serve. This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.

Values in this list can be fully qualified names (e.g. 'www.example.com'), in which case they will be matched against the request’s Host header exactly (case-insensitive, not including port). A value beginning with a period can be used as a subdomain wildcard: '.example.com' will match example.com, www.example.com, and any other subdomain of example.com. A value of '*' will match anything; in this case you are responsible to provide your own validation of the Host header (perhaps in a middleware; if so this middleware must be listed first in MIDDLEWARE_CLASSES).

Django also allows the fully qualified domain name (FQDN) of any entries. Some browsers include a trailing dot in the Host header which Django strips when performing host validation.

If the Host header (or X-Forwarded-Host if USE_X_FORWARDED_HOST is enabled) does not match any value in this list, the django.http.HttpRequest.get_host() method will raise SuspiciousOperation.

When DEBUG is True or when running tests, host validation is disabled; any host will be accepted. Thus it’s usually only necessary to set it in production.

This validation only applies via get_host(); if your code accesses the Host header directly from request.META you are bypassing this security protection.

ALLOWED_INCLUDE_ROOTS

Default: [] (Empty list)

Deprecated since version 1.8: This setting, along with the ssi template tag, is deprecated and will be removed in Django 1.10.

Changed in Django 1.8:
You can also set the 'allowed_include_roots' option in the OPTIONS of a DjangoTemplates backend instead.

A list of strings representing allowed prefixes for the {% ssi %} template tag. This is a security measure, so that template authors can’t access files that they shouldn’t be accessing.

For example, if ALLOWED_INCLUDE_ROOTS is ['/home/html', '/var/www'], then {% ssi /home/html/foo.txt %} would work, but {% ssi /etc/passwd %} wouldn’t.

APPEND_SLASH

Default: True

When set to True, if the request URL does not match any of the patterns in the URLconf and it doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note that the redirect may cause any data submitted in a POST request to be lost.

The APPEND_SLASH setting is only used if CommonMiddleware is installed (see Middleware). See also PREPEND_WWW.

CACHES

Default:

{
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}

A dictionary containing the settings for all caches to be used with Django. It is a nested dictionary whose contents maps cache aliases to a dictionary containing the options for an individual cache.

The CACHES setting must configure a default cache; any number of additional caches may also be specified. If you are using a cache backend other than the local memory cache, or you need to define multiple caches, other options will be required. The following cache options are available.

BACKEND

Default: '' (Empty string)

The cache backend to use. The built-in cache backends are:

- 'django.core.cache.backends.db.DatabaseCache'

- 'django.core.cache.backends.dummy.DummyCache'

- 'django.core.cache.backends.filebased.FileBasedCache'

- 'django.core.cache.backends.locmem.LocMemCache'

- 'django.core.cache.backends.memcached.MemcachedCache'

- 'django.core.cache.backends.memcached.PyLibMCCache'

You can use a cache backend that doesn’t ship with Django by setting BACKEND to a fully-qualified path of a cache backend class (i.e. mypackage.backends.whatever.WhateverCache).

KEY_FUNCTION

A string containing a dotted path to a function (or any callable) that defines how to compose a prefix, version and key into a final cache key. The default implementation is equivalent to the function:

def make_key(key, key_prefix, version):
return ':'.join([key_prefix, str(version), key])

You may use any key function you want, as long as it has the same argument signature.

See the cache documentation for more information.

KEY_PREFIX

Default: '' (Empty string)

A string that will be automatically included (prepended by default) to all cache keys used by the Django server.

See the cache documentation for more information.

LOCATION

Default: '' (Empty string)

The location of the cache to use. This might be the directory for a file system cache, a host and port for a memcache server, or simply an identifying name for a local memory cache. e.g.:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}

OPTIONS

Default: None

Extra parameters to pass to the cache backend. Available parameters vary depending on your cache backend.

Some information on available parameters can be found in the Cache Backends documentation. For more information, consult your backend module’s own documentation.

TIMEOUT

Default: 300

The number of seconds before a cache entry is considered stale. If the value of this settings is None, cache entries will not expire.

VERSION

Default: 1

The default version number for cache keys generated by the Django server.

See the cache documentation for more information.

CACHE_MIDDLEWARE_ALIAS

Default: default

The cache connection to use for the cache middleware.

CACHE_MIDDLEWARE_KEY_PREFIX

Default: '' (Empty string)

A string which will be prefixed to the cache keys generated by the cache middleware. This prefix is combined with the KEY_PREFIX setting; it does not replace it.

See Django’s cache framework.

CACHE_MIDDLEWARE_SECONDS

Default: 600

The default number of seconds to cache a page for the cache middleware.

See Django’s cache framework.

CSRF_COOKIE_AGE

Default: 31449600 (approximately 1 year, in seconds)

The age of CSRF cookies, in seconds.

The reason for setting a long-lived expiration time is to avoid problems in the case of a user closing a browser or bookmarking a page and then loading that page from a browser cache. Without persistent cookies, the form submission would fail in this case.

Some browsers (specifically Internet Explorer) can disallow the use of persistent cookies or can have the indexes to the cookie jar corrupted on disk, thereby causing CSRF protection checks to (sometimes intermittently) fail. Change this setting to None to use session-based CSRF cookies, which keep the cookies in-memory instead of on persistent storage.

CSRF_COOKIE_DOMAIN

Default: None

The domain to be used when setting the CSRF cookie. This can be useful for easily allowing cross-subdomain requests to be excluded from the normal cross site request forgery protection. It should be set to a string such as ".example.com" to allow a POST request from a form on one subdomain to be accepted by a view served from another subdomain.

Please note that the presence of this setting does not imply that Django’s CSRF protection is safe from cross-subdomain attacks by default - please see the CSRF limitations section.

CSRF_COOKIE_HTTPONLY

Default: False

Whether to use HttpOnly flag on the CSRF cookie. If this is set to True, client-side JavaScript will not to be able to access the CSRF cookie.

This can help prevent malicious JavaScript from bypassing CSRF protection. If you enable this and need to send the value of the CSRF token with Ajax requests, your JavaScript will need to pull the value from a hidden CSRF token form input on the page instead of from the cookie.

See SESSION_COOKIE_HTTPONLY for details on HttpOnly.

CSRF_COOKIE_NAME

Default: 'csrftoken'

The name of the cookie to use for the CSRF authentication token. This can be whatever you want (as long as it’s different from the other cookie names in your application). See Cross Site Request Forgery protection.

CSRF_COOKIE_PATH

Default: '/'

The path set on the CSRF cookie. This should either match the URL path of your Django installation or be a parent of that path.

This is useful if you have multiple Django instances running under the same hostname. They can use different cookie paths, and each instance will only see its own CSRF cookie.

CSRF_COOKIE_SECURE

Default: False

Whether to use a secure cookie for the CSRF cookie. If this is set to True, the cookie will be marked as “secure,” which means browsers may ensure that the cookie is only sent with an HTTPS connection.

CSRF_FAILURE_VIEW

Default: 'django.views.csrf.csrf_failure'

A dotted path to the view function to be used when an incoming request is rejected by the CSRF protection. The function should have this signature:

def csrf_failure(request, reason=""):
...

where reason is a short message (intended for developers or logging, not for end users) indicating the reason the request was rejected. It should return an HttpResponseForbidden.

CSRF_HEADER_NAME

New in Django 1.9.

Default: 'HTTP_X_CSRFTOKEN'

The name of the request header used for CSRF authentication.

As with other HTTP headers in request.META, the header name received from the server is normalized by converting all characters to uppercase, replacing any hyphens with underscores, and adding an 'HTTP_' prefix to the name. For example, if your client sends a 'X-XSRF-TOKEN' header, the setting should be 'HTTP_X_XSRF_TOKEN'.

CSRF_TRUSTED_ORIGINS

New in Django 1.9.

Default: [] (Empty list)

A list of hosts which are trusted origins for unsafe requests (e.g. POST). For a secure unsafe request, Django’s CSRF protection requires that the request have a Referer header that matches the origin present in the Host header. This prevents, for example, a POST request from subdomain.example.com from succeeding against api.example.com. If you need cross-origin unsafe requests over HTTPS, continuing the example, add "subdomain.example.com" to this list. The setting also supports subdomains, so you could add ".example.com", for example, to allow access from all subdomains of example.com.

DATABASES

Default: {} (Empty dictionary)

A dictionary containing the settings for all databases to be used with Django. It is a nested dictionary whose contents map a database alias to a dictionary containing the options for an individual database.

The DATABASES setting must configure a default database; any number of additional databases may also be specified.

The simplest possible settings file is for a single-database setup using SQLite. This can be configured using the following:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase',
}
}

When connecting to other database backends, such as MySQL, Oracle, or PostgreSQL, additional connection parameters will be required. See the ENGINE setting below on how to specify other database types. This example is for PostgreSQL:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}

The following inner options that may be required for more complex configurations are available:

ATOMIC_REQUESTS

Default: False

Set this to True to wrap each view in a transaction on this database. See Tying transactions to HTTP requests.

AUTOCOMMIT

Default: True

Set this to False if you want to disable Django’s transaction management and implement your own.

ENGINE

Default: '' (Empty string)

The database backend to use. The built-in database backends are:

- 'django.db.backends.postgresql'

- 'django.db.backends.mysql'

- 'django.db.backends.sqlite3'

- 'django.db.backends.oracle'

You can use a database backend that doesn’t ship with Django by setting ENGINE to a fully-qualified path (i.e. mypackage.backends.whatever).

Changed in Django 1.9:
The django.db.backends.postgresql backend is named django.db.backends.postgresql_psycopg2 in older releases. For backwards compatibility, the old name still works in newer versions.

HOST

Default: '' (Empty string)

Which host to use when connecting to the database. An empty string means localhost. Not used with SQLite.

If this value starts with a forward slash ('/') and you’re using MySQL, MySQL will connect via a Unix socket to the specified socket. For example:

"HOST": '/var/run/mysql'

If you’re using MySQL and this value doesn’t start with a forward slash, then this value is assumed to be the host.

If you’re using PostgreSQL, by default (empty HOST), the connection to the database is done through UNIX domain sockets (‘local’ lines in pg_hba.conf). If your UNIX domain socket is not in the standard location, use the same value of unix_socket_directory from postgresql.conf. If you want to connect through TCP sockets, set HOST to ‘localhost’ or ‘127.0.0.1’ (‘host’ lines in pg_hba.conf). On Windows, you should always define HOST, as UNIX domain sockets are not available.

NAME

Default: '' (Empty string)

The name of the database to use. For SQLite, it’s the full path to the database file. When specifying the path, always use forward slashes, even on Windows (e.g. C:/homes/user/mysite/sqlite3.db).

CONN_MAX_AGE

Default: 0

The lifetime of a database connection, in seconds. Use 0 to close database connections at the end of each request — Django’s historical behavior — and None for unlimited persistent connections.

OPTIONS

Default: {} (Empty dictionary)

Extra parameters to use when connecting to the database. Available parameters vary depending on your database backend.

Some information on available parameters can be found in the Database Backends documentation. For more information, consult your backend module’s own documentation.

PASSWORD

Default: '' (Empty string)

The password to use when connecting to the database. Not used with SQLite.

PORT

Default: '' (Empty string)

The port to use when connecting to the database. An empty string means the default port. Not used with SQLite.

TIME_ZONE

New in Django 1.9.

Default: None

A string representing the time zone for datetimes stored in this database (assuming that it doesn’t support time zones) or None. The same values are accepted as in the general TIME_ZONE setting.

This allows interacting with third-party databases that store datetimes in local time rather than UTC. To avoid issues around DST changes, you shouldn’t set this option for databases managed by Django.

Setting this option requires installing pytz.

When USE_TZ is True and the database doesn’t support time zones (e.g. SQLite, MySQL, Oracle), Django reads and writes datetimes in local time according to this option if it is set and in UTC if it isn’t.

When USE_TZ is True and the database supports time zones (e.g. PostgreSQL), it is an error to set this option.

Changed in Django 1.9:
Before Django 1.9, the PostgreSQL database backend accepted an undocumented TIME_ZONE option, which caused data corruption.

When USE_TZ is False, it is an error to set this option.

USER

Default: '' (Empty string)

The username to use when connecting to the database. Not used with SQLite.

TEST

Default: {} (Empty dictionary)

A dictionary of settings for test databases; for more details about the creation and use of test databases, see The test database.

Here’s an example with a test database configuration:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'USER': 'mydatabaseuser',
'NAME': 'mydatabase',
'TEST': {
'NAME': 'mytestdatabase',
},
},
}

The following keys in the TEST dictionary are available:

CHARSET

Default: None

The character set encoding used to create the test database. The value of this string is passed directly through to the database, so its format is backend-specific.

Supported by the PostgreSQL (postgresql) and MySQL (mysql) backends.

COLLATION

Default: None

The collation order to use when creating the test database. This value is passed directly to the backend, so its format is backend-specific.

Only supported for the mysql backend (see the MySQL manual for details).

DEPENDENCIES

Default: ['default'], for all databases other than default, which has no dependencies.

The creation-order dependencies of the database. See the documentation on controlling the creation order of test databases for details.

MIRROR

Default: None

The alias of the database that this database should mirror during testing.

This setting exists to allow for testing of primary/replica (referred to as master/slave by some databases) configurations of multiple databases. See the documentation on testing primary/replica configurations for details.

NAME

Default: None

The name of database to use when running the test suite.

If the default value (None) is used with the SQLite database engine, the tests will use a memory resident database. For all other database engines the test database will use the name 'test_' + DATABASE_NAME.

See The test database.

SERIALIZE

Boolean value to control whether or not the default test runner serializes the database into an in-memory JSON string before running tests (used to restore the database state between tests if you don’t have transactions). You can set this to False to speed up creation time if you don’t have any test classes with serialized_rollback=True.

CREATE_DB

Default: True

This is an Oracle-specific setting.

If it is set to False, the test tablespaces won’t be automatically created at the beginning of the tests or dropped at the end.

CREATE_USER

Default: True

This is an Oracle-specific setting.

If it is set to False, the test user won’t be automatically created at the beginning of the tests and dropped at the end.

USER

Default: None

This is an Oracle-specific setting.

The username to use when connecting to the Oracle database that will be used when running tests. If not provided, Django will use 'test_' + USER.

PASSWORD

Default: None

This is an Oracle-specific setting.

The password to use when connecting to the Oracle database that will be used when running tests. If not provided, Django will use a hardcoded default value.

TBLSPACE

Default: None

This is an Oracle-specific setting.

The name of the tablespace that will be used when running tests. If not provided, Django will use 'test_' + USER.

Changed in Django 1.8:
Previously Django used 'test_' + NAME if not provided.

TBLSPACE_TMP

Default: None

This is an Oracle-specific setting.

The name of the temporary tablespace that will be used when running tests. If not provided, Django will use 'test_' + USER + '_temp'.

Changed in Django 1.8:
Previously Django used 'test_' + NAME + '_temp' if not provided.

DATAFILE

New in Django 1.8.

Default: None

This is an Oracle-specific setting.

The name of the datafile to use for the TBLSPACE. If not provided, Django will use TBLSPACE + '.dbf'.

DATAFILE_TMP

New in Django 1.8.

Default: None

This is an Oracle-specific setting.

The name of the datafile to use for the TBLSPACE_TMP. If not provided, Django will use TBLSPACE_TMP + '.dbf'.

DATAFILE_MAXSIZE

New in Django 1.8.

Default: '500M'

Changed in Django 1.8:
The previous value was 200M and was not user customizable.

This is an Oracle-specific setting.

The maximum size that the DATAFILE is allowed to grow to.

DATAFILE_TMP_MAXSIZE

New in Django 1.8.

Default: '500M'

Changed in Django 1.8:
The previous value was 200M and was not user customizable.

This is an Oracle-specific setting.

The maximum size that the DATAFILE_TMP is allowed to grow to.

DATABASE_ROUTERS

Default: [] (Empty list)

The list of routers that will be used to determine which database to use when performing a database query.

See the documentation on automatic database routing in multi database configurations.

DATE_FORMAT

Default: 'N j, Y' (e.g. Feb. 4, 2003)

The default formatting to use for displaying date fields in any part of the system. Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead. See allowed date format strings.

See also DATETIME_FORMAT, TIME_FORMAT and SHORT_DATE_FORMAT.

DATE_INPUT_FORMATS

Default:

[
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
'%b %d %Y', '%b %d, %Y',            # 'Oct 25 2006', 'Oct 25, 2006'
'%d %b %Y', '%d %b, %Y',            # '25 Oct 2006', '25 Oct, 2006'
'%B %d %Y', '%B %d, %Y',            # 'October 25 2006', 'October 25, 2006'
'%d %B %Y', '%d %B, %Y',            # '25 October 2006', '25 October, 2006'
]

A list of formats that will be accepted when inputting data on a date field. Formats will be tried in order, using the first valid one. Note that these format strings use Python’s datetime module syntax, not the format strings from the date template filter.

When USE_L10N is True, the locale-dictated format has higher precedence and will be applied instead.

See also DATETIME_INPUT_FORMATS and TIME_INPUT_FORMATS.

DATETIME_FORMAT

Default: 'N j, Y, P' (e.g. Feb. 4, 2003, 4 p.m.)

The default formatting to use for displaying datetime fields in any part of the system. Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead. See allowed date format strings.

See also DATE_FORMAT, TIME_FORMAT and SHORT_DATETIME_FORMAT.

DATETIME_INPUT_FORMATS

Default:

[
'%Y-%m-%d %H:%M:%S',     # '2006-10-25 14:30:59'
'%Y-%m-%d %H:%M:%S.%f',  # '2006-10-25 14:30:59.000200'
'%Y-%m-%d %H:%M',        # '2006-10-25 14:30'
'%Y-%m-%d',              # '2006-10-25'
'%m/%d/%Y %H:%M:%S',     # '10/25/2006 14:30:59'
'%m/%d/%Y %H:%M:%S.%f',  # '10/25/2006 14:30:59.000200'
'%m/%d/%Y %H:%M',        # '10/25/2006 14:30'
'%m/%d/%Y',              # '10/25/2006'
'%m/%d/%y %H:%M:%S',     # '10/25/06 14:30:59'
'%m/%d/%y %H:%M:%S.%f',  # '10/25/06 14:30:59.000200'
'%m/%d/%y %H:%M',        # '10/25/06 14:30'
'%m/%d/%y',              # '10/25/06'
]

A list of formats that will be accepted when inputting data on a datetime field. Formats will be tried in order, using the first valid one. Note that these format strings use Python’s datetime module syntax, not the format strings from the date template filter.

When USE_L10N is True, the locale-dictated format has higher precedence and will be applied instead.

See also DATE_INPUT_FORMATS and TIME_INPUT_FORMATS.

DEBUG

Default: False

A boolean that turns on/off debug mode.

Never deploy a site into production with DEBUG turned on.

Did you catch that? NEVER deploy a site into production with DEBUG turned on.

One of the main features of debug mode is the display of detailed error pages. If your app raises an exception when DEBUG is True, Django will display a detailed traceback, including a lot of metadata about your environment, such as all the currently defined Django settings (from settings.py).

As a security measure, Django will not include settings that might be sensitive, such as SECRET_KEY. Specifically, it will exclude any setting whose name includes any of the following:

- 'API'

- 'KEY'

- 'PASS'

- 'SECRET'

- 'SIGNATURE'

- 'TOKEN'

Note that these are partial matches. 'PASS' will also match PASSWORD, just as 'TOKEN' will also match TOKENIZED and so on.

Still, note that there are always going to be sections of your debug output that are inappropriate for public consumption. File paths, configuration options and the like all give attackers extra information about your server.

It is also important to remember that when running with DEBUG turned on, Django will remember every SQL query it executes. This is useful when you’re debugging, but it’ll rapidly consume memory on a production server.

Finally, if DEBUG is False, you also need to properly set the ALLOWED_HOSTS setting. Failing to do so will result in all requests being returned as “Bad Request (400)”.

Note

The default settings.py file created by django-admin startproject sets DEBUG = True for convenience.

DEBUG_PROPAGATE_EXCEPTIONS

Default: False

If set to True, Django’s normal exception handling of view functions will be suppressed, and exceptions will propagate upwards. This can be useful for some test setups, and should never be used on a live site.

DECIMAL_SEPARATOR

Default: '.' (Dot)

Default decimal separator used when formatting decimal numbers.

Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead.

See also NUMBER_GROUPING, THOUSAND_SEPARATOR and USE_THOUSAND_SEPARATOR.

DEFAULT_CHARSET

Default: 'utf-8'

Default charset to use for all HttpResponse objects, if a MIME type isn’t manually specified. Used with DEFAULT_CONTENT_TYPE to construct the Content-Type header.

DEFAULT_CONTENT_TYPE

Default: 'text/html'

Default content type to use for all HttpResponse objects, if a MIME type isn’t manually specified. Used with DEFAULT_CHARSET to construct the Content-Type header.

DEFAULT_EXCEPTION_REPORTER_FILTER

Default: 'django.views.debug.SafeExceptionReporterFilter'

Default exception reporter filter class to be used if none has been assigned to the HttpRequest instance yet. See Filtering error reports.

DEFAULT_FILE_STORAGE

Default: 'django.core.files.storage.FileSystemStorage'

Default file storage class to be used for any file-related operations that don’t specify a particular storage system. See Managing files.

DEFAULT_FROM_EMAIL

Default: 'webmaster@localhost'

Default email address to use for various automated correspondence from the site manager(s). This doesn’t include error messages sent to ADMINS and MANAGERS; for that, see SERVER_EMAIL.

DEFAULT_INDEX_TABLESPACE

Default: '' (Empty string)

Default tablespace to use for indexes on fields that don’t specify one, if the backend supports it (see Tablespaces).

DEFAULT_TABLESPACE

Default: '' (Empty string)

Default tablespace to use for models that don’t specify one, if the backend supports it (see Tablespaces).

DISALLOWED_USER_AGENTS

Default: [] (Empty list)

List of compiled regular expression objects representing User-Agent strings that are not allowed to visit any page, systemwide. Use this for bad robots/crawlers. This is only used if CommonMiddleware is installed (see Middleware).

EMAIL_BACKEND

Default: 'django.core.mail.backends.smtp.EmailBackend'

The backend to use for sending emails. For the list of available backends see Sending email.

EMAIL_FILE_PATH

Default: Not defined

The directory used by the file email backend to store output files.

EMAIL_HOST

Default: 'localhost'

The host to use for sending email.

See also EMAIL_PORT.

EMAIL_HOST_PASSWORD

Default: '' (Empty string)

Password to use for the SMTP server defined in EMAIL_HOST. This setting is used in conjunction with EMAIL_HOST_USER when authenticating to the SMTP server. If either of these settings is empty, Django won’t attempt authentication.

See also EMAIL_HOST_USER.

EMAIL_HOST_USER

Default: '' (Empty string)

Username to use for the SMTP server defined in EMAIL_HOST. If empty, Django won’t attempt authentication.

See also EMAIL_HOST_PASSWORD.

EMAIL_PORT

Default: 25

Port to use for the SMTP server defined in EMAIL_HOST.

EMAIL_SUBJECT_PREFIX

Default: '[Django] '

Subject-line prefix for email messages sent with django.core.mail.mail_admins or django.core.mail.mail_managers. You’ll probably want to include the trailing space.

EMAIL_USE_TLS

Default: False

Whether to use a TLS (secure) connection when talking to the SMTP server. This is used for explicit TLS connections, generally on port 587. If you are experiencing hanging connections, see the implicit TLS setting EMAIL_USE_SSL.

EMAIL_USE_SSL

Default: False

Whether to use an implicit TLS (secure) connection when talking to the SMTP server. In most email documentation this type of TLS connection is referred to as SSL. It is generally used on port 465. If you are experiencing problems, see the explicit TLS setting EMAIL_USE_TLS.

Note that EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so only set one of those settings to True.

EMAIL_SSL_CERTFILE

New in Django 1.8.

Default: None

If EMAIL_USE_SSL or EMAIL_USE_TLS is True, you can optionally specify the path to a PEM-formatted certificate chain file to use for the SSL connection.

EMAIL_SSL_KEYFILE

New in Django 1.8.

Default: None

If EMAIL_USE_SSL or EMAIL_USE_TLS is True, you can optionally specify the path to a PEM-formatted private key file to use for the SSL connection.

Note that setting EMAIL_SSL_CERTFILE and EMAIL_SSL_KEYFILE doesn’t result in any certificate checking. They’re passed to the underlying SSL connection. Please refer to the documentation of Python’s ssl.wrap_socket() function for details on how the certificate chain file and private key file are handled.

EMAIL_TIMEOUT

New in Django 1.8.

Default: None

Specifies a timeout in seconds for blocking operations like the connection attempt.

FILE_CHARSET

Default: 'utf-8'

The character encoding used to decode any files read from disk. This includes template files and initial SQL data files.

FILE_UPLOAD_HANDLERS

Default:

[
'django.core.files.uploadhandler.MemoryFileUploadHandler',
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]

A list of handlers to use for uploading. Changing this setting allows complete customization – even replacement – of Django’s upload process.

See Managing files for details.

FILE_UPLOAD_MAX_MEMORY_SIZE

Default: 2621440 (i.e. 2.5 MB).

The maximum size (in bytes) that an upload will be before it gets streamed to the file system. See Managing files for details.

FILE_UPLOAD_DIRECTORY_PERMISSIONS

Default: None

The numeric mode to apply to directories created in the process of uploading files.

This setting also determines the default permissions for collected static directories when using the collectstatic management command. See collectstatic for details on overriding it.

This value mirrors the functionality and caveats of the FILE_UPLOAD_PERMISSIONS setting.

FILE_UPLOAD_PERMISSIONS

Default: None

The numeric mode (i.e. 0o644) to set newly uploaded files to. For more information about what these modes mean, see the documentation for os.chmod().

If this isn’t given or is None, you’ll get operating-system dependent behavior. On most platforms, temporary files will have a mode of 0o600, and files saved from memory will be saved using the system’s standard umask.

For security reasons, these permissions aren’t applied to the temporary files that are stored in FILE_UPLOAD_TEMP_DIR.

This setting also determines the default permissions for collected static files when using the collectstatic management command. See collectstatic for details on overriding it.

Warning

Always prefix the mode with a 0.

If you’re not familiar with file modes, please note that the leading 0 is very important: it indicates an octal number, which is the way that modes must be specified. If you try to use 644, you’ll get totally incorrect behavior.

FILE_UPLOAD_TEMP_DIR

Default: None

The directory to store data to (typically files larger than FILE_UPLOAD_MAX_MEMORY_SIZE) temporarily while uploading files. If None, Django will use the standard temporary directory for the operating system. For example, this will default to /tmp on *nix-style operating systems.

See Managing files for details.

FIRST_DAY_OF_WEEK

Default: 0 (Sunday)

A number representing the first day of the week. This is especially useful when displaying a calendar. This value is only used when not using format internationalization, or when a format cannot be found for the current locale.

The value must be an integer from 0 to 6, where 0 means Sunday, 1 means Monday and so on.

FIXTURE_DIRS

Default: [] (Empty list)

List of directories searched for fixture files, in addition to the fixtures directory of each application, in search order.

Note that these paths should use Unix-style forward slashes, even on Windows.

See Providing initial data with fixtures and Fixture loading.

FORCE_SCRIPT_NAME

Default: None

If not None, this will be used as the value of the SCRIPT_NAME environment variable in any HTTP request. This setting can be used to override the server-provided value of SCRIPT_NAME, which may be a rewritten version of the preferred value or not supplied at all.

FORMAT_MODULE_PATH

Default: None

A full Python path to a Python package that contains format definitions for project locales. If not None, Django will check for a formats.py file, under the directory named as the current locale, and will use the formats defined in this file.

For example, if FORMAT_MODULE_PATH is set to mysite.formats, and current language is en (English), Django will expect a directory tree like:

mysite/
formats/
__init__.py
en/
__init__.py
formats.py

Changed in Django 1.8:
You can also set this setting to a list of Python paths, for example:

FORMAT_MODULE_PATH = [
'mysite.formats',
'some_app.formats',
]

When Django searches for a certain format, it will go through all given Python paths until it finds a module that actually defines the given format. This means that formats defined in packages farther up in the list will take precedence over the same formats in packages farther down.

Available formats are DATE_FORMAT, TIME_FORMAT, DATETIME_FORMAT, YEAR_MONTH_FORMAT, MONTH_DAY_FORMAT, SHORT_DATE_FORMAT, SHORT_DATETIME_FORMAT, FIRST_DAY_OF_WEEK, DECIMAL_SEPARATOR, THOUSAND_SEPARATOR and NUMBER_GROUPING.

IGNORABLE_404_URLS

Default: [] (Empty list)

List of compiled regular expression objects describing URLs that should be ignored when reporting HTTP 404 errors via email (see Error reporting). Regular expressions are matched against request's full paths (including query string, if any). Use this if your site does not provide a commonly requested file such as favicon.ico or robots.txt, or if it gets hammered by script kiddies.

This is only used if BrokenLinkEmailsMiddleware is enabled (see Middleware).

INSTALLED_APPS

Default: [] (Empty list)

A list of strings designating all applications that are enabled in this Django installation. Each string should be a dotted Python path to:

- an application configuration class (preferred), or

- a package containing an application.

Learn more about application configurations.

Use the application registry for introspection

Your code should never access INSTALLED_APPS directly. Use django.apps.apps instead.

Application names and labels must be unique in INSTALLED_APPS

Application names — the dotted Python path to the application package — must be unique. There is no way to include the same application twice, short of duplicating its code under another name.

Application labels — by default the final part of the name — must be unique too. For example, you can’t include both django.contrib.auth and myproject.auth. However, you can relabel an application with a custom configuration that defines a different label.

These rules apply regardless of whether INSTALLED_APPS references application configuration classes or application packages.

When several applications provide different versions of the same resource (template, static file, management command, translation), the application listed first in INSTALLED_APPS has precedence.

INTERNAL_IPS

Default: [] (Empty list)

A list of IP addresses, as strings, that:

- Allow the debug() context processor to add some variables to the template context.

- Can use the admindocs bookmarklets even if not logged in as a staff user.

- Are marked as “internal” (as opposed to “EXTERNAL”) in AdminEmailHandler emails.

LANGUAGE_CODE

Default: 'en-us'

A string representing the language code for this installation. This should be in standard language ID format. For example, U.S. English is "en-us". See also the list of language identifiers and Internationalization and localization.

USE_I18N must be active for this setting to have any effect.

It serves two purposes:

- If the locale middleware isn’t in use, it decides which translation is served to all users.

- If the locale middleware is active, it provides a fallback language in case the user’s preferred language can’t be determined or is not supported by the website. It also provides the fallback translation when a translation for a given literal doesn’t exist for the user’s preferred language.

Changed in Django 1.8:
The fallback for translation literals was added.

See How Django discovers language preference for more details.

LANGUAGE_COOKIE_AGE

Default: None (expires at browser close)

The age of the language cookie, in seconds.

LANGUAGE_COOKIE_DOMAIN

Default: None

The domain to use for the language cookie. Set this to a string such as ".example.com" (note the leading dot!) for cross-domain cookies, or use None for a standard domain cookie.

Be cautious when updating this setting on a production site. If you update this setting to enable cross-domain cookies on a site that previously used standard domain cookies, existing user cookies that have the old domain will not be updated. This will result in site users being unable to switch the language as long as these cookies persist. The only safe and reliable option to perform the switch is to change the language cookie name permanently (via the LANGUAGE_COOKIE_NAME setting) and to add a middleware that copies the value from the old cookie to a new one and then deletes the old one.

LANGUAGE_COOKIE_NAME

Default: 'django_language'

The name of the cookie to use for the language cookie. This can be whatever you want (as long as it’s different from the other cookie names in your application). See Internationalization and localization.

LANGUAGE_COOKIE_PATH

Default: '/'

The path set on the language cookie. This should either match the URL path of your Django installation or be a parent of that path.

This is useful if you have multiple Django instances running under the same hostname. They can use different cookie paths and each instance will only see its own language cookie.

Be cautious when updating this setting on a production site. If you update this setting to use a deeper path than it previously used, existing user cookies that have the old path will not be updated. This will result in site users being unable to switch the language as long as these cookies persist. The only safe and reliable option to perform the switch is to change the language cookie name permanently (via the LANGUAGE_COOKIE_NAME setting), and to add a middleware that copies the value from the old cookie to a new one and then deletes the one.

LANGUAGES

Default: A list of all available languages. This list is continually growing and including a copy here would inevitably become rapidly out of date. You can see the current list of translated languages by looking in django/conf/global_settings.py (or view the online source).

The list is a list of two-tuples in the format (language code, language name) – for example, ('ja', 'Japanese'). This specifies which languages are available for language selection. See Internationalization and localization.

Generally, the default value should suffice. Only set this setting if you want to restrict language selection to a subset of the Django-provided languages.

If you define a custom LANGUAGES setting, you can mark the language names as translation strings using the ugettext_lazy() function.

Here’s a sample settings file:

from django.utils.translation import ugettext_lazy as _

LANGUAGES = [
('de', _('German')),
('en', _('English')),
]

LOCALE_PATHS

Default: [] (Empty list)

A list of directories where Django looks for translation files. See How Django discovers translations.

Example:

LOCALE_PATHS = [
'/home/www/project/common_files/locale',
'/var/local/translations/locale',
]

Django will look within each of these paths for the <locale_code>/LC_MESSAGES directories containing the actual translation files.

LOGGING

Default: A logging configuration dictionary.

A data structure containing configuration information. The contents of this data structure will be passed as the argument to the configuration method described in LOGGING_CONFIG.

Among other things, the default logging configuration passes HTTP 500 server errors to an email log handler when DEBUG is False. See also Configuring logging.

You can see the default logging configuration by looking in django/utils/log.py (or view the online source).

LOGGING_CONFIG

Default: 'logging.config.dictConfig'

A path to a callable that will be used to configure logging in the Django project. Points at a instance of Python’s dictConfig configuration method by default.

If you set LOGGING_CONFIG to None, the logging configuration process will be skipped.

MANAGERS

Default: [] (Empty list)

A list in the same format as ADMINS that specifies who should get broken link notifications when BrokenLinkEmailsMiddleware is enabled.

MEDIA_ROOT

Default: '' (Empty string)

Absolute filesystem path to the directory that will hold user-uploaded files.

Example: "/var/www/example.com/media/"

See also MEDIA_URL.

Warning

MEDIA_ROOT and STATIC_ROOT must have different values. Before STATIC_ROOT was introduced, it was common to rely or fallback on MEDIA_ROOT to also serve static files; however, since this can have serious security implications, there is a validation check to prevent it.

MEDIA_URL

Default: '' (Empty string)

URL that handles the media served from MEDIA_ROOT, used for managing stored files. It must end in a slash if set to a non-empty value. You will need to configure these files to be served in both development and production environments.

If you want to use {{ MEDIA_URL }} in your templates, add 'django.template.context_processors.media' in the 'context_processors' option of TEMPLATES.

Example: "http://media.example.com/"

Warning

There are security risks if you are accepting uploaded content from untrusted users! See the security guide’s topic on User-uploaded content for mitigation details.

Warning

MEDIA_URL and STATIC_URL must have different values. See MEDIA_ROOT for more details.

MIDDLEWARE_CLASSES

Default:

[
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
]

A list of middleware classes to use. See Middleware.

MIGRATION_MODULES

Default: {} (Empty dictionary)

A dictionary specifying the package where migration modules can be found on a per-app basis. The default value of this setting is an empty dictionary, but the default package name for migration modules is migrations.

Example:

{'blog': 'blog.db_migrations'}

In this case, migrations pertaining to the blog app will be contained in the blog.db_migrations package.

If you provide the app_label argument, makemigrations will automatically create the package if it doesn’t already exist.

New in Django 1.9.

When you supply None as a value for an app, Django will consider the app as an app without migrations regardless of an existing migrations submodule. This can be used, for example, in a test settings file to skip migrations while testing (tables will still be created for the apps’ models). If this is used in your general project settings, remember to use the migrate --run-syncdb option if you want to create tables for the app.

MONTH_DAY_FORMAT

Default: 'F j'

The default formatting to use for date fields on Django admin change-list pages – and, possibly, by other parts of the system – in cases when only the month and day are displayed.

For example, when a Django admin change-list page is being filtered by a date drilldown, the header for a given day displays the day and month. Different locales have different formats. For example, U.S. English would say “January 1,” whereas Spanish might say “1 Enero.”

Note that if USE_L10N is set to True, then the corresponding locale-dictated format has higher precedence and will be applied.

See allowed date format strings. See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT and YEAR_MONTH_FORMAT.

NUMBER_GROUPING

Default: 0

Number of digits grouped together on the integer part of a number.

Common use is to display a thousand separator. If this setting is 0, then no grouping will be applied to the number. If this setting is greater than 0, then THOUSAND_SEPARATOR will be used as the separator between those groups.

Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead.

See also DECIMAL_SEPARATOR, THOUSAND_SEPARATOR and USE_THOUSAND_SEPARATOR.

PREPEND_WWW

Default: False

Whether to prepend the “www.” subdomain to URLs that don’t have it. This is only used if CommonMiddleware is installed (see Middleware). See also APPEND_SLASH.

ROOT_URLCONF

Default: Not defined

A string representing the full Python import path to your root URLconf. For example: "mydjangoapps.urls". Can be overridden on a per-request basis by setting the attribute urlconf on the incoming HttpRequest object. See How Django processes a request for details.

SECRET_KEY

Default: '' (Empty string)

A secret key for a particular Django installation. This is used to provide cryptographic signing, and should be set to a unique, unpredictable value.

django-admin startproject automatically adds a randomly-generated SECRET_KEY to each new project.

Django will refuse to start if SECRET_KEY is not set.

Warning

Keep this value secret.

Running Django with a known SECRET_KEY defeats many of Django’s security protections, and can lead to privilege escalation and remote code execution vulnerabilities.

The secret key is used for:

- All sessions if you are using any other session backend than django.contrib.sessions.backends.cache, or if you use SessionAuthenticationMiddleware and are using the default get_session_auth_hash().

- All messages if you are using CookieStorage or FallbackStorage.

- All password_reset() tokens.

- Any usage of cryptographic signing, unless a different key is provided.

If you rotate your secret key, all of the above will be invalidated. Secret keys are not used for passwords of users and key rotation will not affect them.

Note

The default settings.py file created by django-admin startproject creates a unique SECRET_KEY for convenience.

SECURE_BROWSER_XSS_FILTER

New in Django 1.8.

Default: False

If True, the SecurityMiddleware sets the X-XSS-Protection: 1; mode=block header on all responses that do not already have it.

SECURE_CONTENT_TYPE_NOSNIFF

New in Django 1.8.

Default: False

If True, the SecurityMiddleware sets the X-Content-Type-Options: nosniff header on all responses that do not already have it.

SECURE_HSTS_INCLUDE_SUBDOMAINS

New in Django 1.8.

Default: False

If True, the SecurityMiddleware adds the includeSubDomains tag to the HTTP Strict Transport Security header. It has no effect unless SECURE_HSTS_SECONDS is set to a non-zero value.

Warning

Setting this incorrectly can irreversibly (for the value of SECURE_HSTS_SECONDS) break your site. Read the HTTP Strict Transport Security documentation first.

SECURE_HSTS_SECONDS

New in Django 1.8.

Default: 0

If set to a non-zero integer value, the SecurityMiddleware sets the HTTP Strict Transport Security header on all responses that do not already have it.

Warning

Setting this incorrectly can irreversibly (for some time) break your site. Read the HTTP Strict Transport Security documentation first.

SECURE_PROXY_SSL_HEADER

Default: None

A tuple representing a HTTP header/value combination that signifies a request is secure. This controls the behavior of the request object’s is_secure() method.

This takes some explanation. By default, is_secure() is able to determine whether a request is secure by looking at whether the requested URL uses “https://”. This is important for Django’s CSRF protection, and may be used by your own code or third-party apps.

If your Django app is behind a proxy, though, the proxy may be “swallowing” the fact that a request is HTTPS, using a non-HTTPS connection between the proxy and Django. In this case, is_secure() would always return False – even for requests that were made via HTTPS by the end user.

In this situation, you’ll want to configure your proxy to set a custom HTTP header that tells Django whether the request came in via HTTPS, and you’ll want to set SECURE_PROXY_SSL_HEADER so that Django knows what header to look for.

You’ll need to set a tuple with two elements – the name of the header to look for and the required value. For example:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Here, we’re telling Django that we trust the X-Forwarded-Proto header that comes from our proxy, and any time its value is 'https', then the request is guaranteed to be secure (i.e., it originally came in via HTTPS). Obviously, you should only set this setting if you control your proxy or have some other guarantee that it sets/strips this header appropriately.

Note that the header needs to be in the format as used by request.META – all caps and likely starting with HTTP_. (Remember, Django automatically adds 'HTTP_' to the start of x-header names before making the header available in request.META.)

Warning

You will probably open security holes in your site if you set this without knowing what you’re doing. And if you fail to set it when you should. Seriously.

Make sure ALL of the following are true before setting this (assuming the values from the example above):

- Your Django app is behind a proxy.

- Your proxy strips the X-Forwarded-Proto header from all incoming requests. In other words, if end users include that header in their requests, the proxy will discard it.

- Your proxy sets the X-Forwarded-Proto header and sends it to Django, but only for requests that originally come in via HTTPS.

If any of those are not true, you should keep this setting set to None and find another way of determining HTTPS, perhaps via custom middleware.

SECURE_REDIRECT_EXEMPT

New in Django 1.8.

Default: [] (Empty list)

If a URL path matches a regular expression in this list, the request will not be redirected to HTTPS. If SECURE_SSL_REDIRECT is False, this setting has no effect.

SECURE_SSL_HOST

New in Django 1.8.

Default: None

If a string (e.g. secure.example.com), all SSL redirects will be directed to this host rather than the originally-requested host (e.g. www.example.com). If SECURE_SSL_REDIRECT is False, this setting has no effect.

SECURE_SSL_REDIRECT

New in Django 1.8.

Default: False

If True, the SecurityMiddleware redirects all non-HTTPS requests to HTTPS (except for those URLs matching a regular expression listed in SECURE_REDIRECT_EXEMPT).

Note

If turning this to True causes infinite redirects, it probably means your site is running behind a proxy and can’t tell which requests are secure and which are not. Your proxy likely sets a header to indicate secure requests; you can correct the problem by finding out what that header is and configuring the SECURE_PROXY_SSL_HEADER setting accordingly.

SERIALIZATION_MODULES

Default: Not defined

A dictionary of modules containing serializer definitions (provided as strings), keyed by a string identifier for that serialization type. For example, to define a YAML serializer, use:

SERIALIZATION_MODULES = {'yaml': 'path.to.yaml_serializer'}

SERVER_EMAIL

Default: 'root@localhost'

The email address that error messages come from, such as those sent to ADMINS and MANAGERS.

Why are my emails sent from a different address?

This address is used only for error messages. It is not the address that regular email messages sent with send_mail() come from; for that, see DEFAULT_FROM_EMAIL.

SHORT_DATE_FORMAT

Default: 'm/d/Y' (e.g. 12/31/2003)

An available formatting that can be used for displaying date fields on templates. Note that if USE_L10N is set to True, then the corresponding locale-dictated format has higher precedence and will be applied. See allowed date format strings.

See also DATE_FORMAT and SHORT_DATETIME_FORMAT.

SHORT_DATETIME_FORMAT

Default: 'm/d/Y P' (e.g. 12/31/2003 4 p.m.)

An available formatting that can be used for displaying datetime fields on templates. Note that if USE_L10N is set to True, then the corresponding locale-dictated format has higher precedence and will be applied. See allowed date format strings.

See also DATE_FORMAT and SHORT_DATE_FORMAT.

SIGNING_BACKEND

Default: 'django.core.signing.TimestampSigner'

The backend used for signing cookies and other data.

See also the Cryptographic signing documentation.

SILENCED_SYSTEM_CHECKS

Default: [] (Empty list)

A list of identifiers of messages generated by the system check framework (i.e. ["models.W001"]) that you wish to permanently acknowledge and ignore. Silenced checks will not be output to the console.

Changed in Django 1.9:
In older versions, silenced messages of ERROR level or higher were printed to the console.

See also the System check framework documentation.

TEMPLATES

New in Django 1.8.

Default: [] (Empty list)

A list containing the settings for all template engines to be used with Django. Each item of the list is a dictionary containing the options for an individual engine.

Here’s a simple setup that tells the Django template engine to load templates from the templates subdirectory inside each installed application:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
},
]

The following options are available for all backends.

BACKEND

Default: Not defined

The template backend to use. The built-in template backends are:

- 'django.template.backends.django.DjangoTemplates'

- 'django.template.backends.jinja2.Jinja2'

You can use a template backend that doesn’t ship with Django by setting BACKEND to a fully-qualified path (i.e. 'mypackage.whatever.Backend').

NAME

Default: see below

The alias for this particular template engine. It’s an identifier that allows selecting an engine for rendering. Aliases must be unique across all configured template engines.

It defaults to the name of the module defining the engine class, i.e. the next to last piece of BACKEND, when it isn’t provided. For example if the backend is 'mypackage.whatever.Backend' then its default name is 'whatever'.

DIRS

Default: [] (Empty list)

Directories where the engine should look for template source files, in search order.

APP_DIRS

Default: False

Whether the engine should look for template source files inside installed applications.

Note

The default settings.py file created by django-admin startproject sets 'APP_DIRS': True.

OPTIONS

Default: {} (Empty dict)

Extra parameters to pass to the template backend. Available parameters vary depending on the template backend. See DjangoTemplates and Jinja2 for the options of the built-in backends.

TEMPLATE_CONTEXT_PROCESSORS

Default:

["django.contrib.auth.context_processors.auth",
"django.template.context_processors.debug",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
"django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages"]

Deprecated since version 1.8: Set the 'context_processors' option in the OPTIONS of a DjangoTemplates backend instead.

A list of callables that are used to populate the context in RequestContext. These callables take a request object as their argument and return a dictionary of items to be merged into the context.

Changed in Django 1.8:
Built-in template context processors were moved from django.core.context_processors to django.template.context_processors in Django 1.8.

TEMPLATE_DEBUG

Default: False

Deprecated since version 1.8: Set the 'debug' option in the OPTIONS of a DjangoTemplates backend instead.

A boolean that turns on/off template debug mode. If this is True, the fancy error page will display a detailed report for any exception raised during template rendering. This report contains the relevant snippet of the template, with the appropriate line highlighted.

Note that Django only displays fancy error pages if DEBUG is True, so you’ll want to set that to take advantage of this setting.

See also DEBUG.

TEMPLATE_DIRS

Default: [] (Empty list)

Deprecated since version 1.8: Set the DIRS option of a DjangoTemplates backend instead.

List of locations of the template source files searched by django.template.loaders.filesystem.Loader, in search order.

Note that these paths should use Unix-style forward slashes, even on Windows.

See The Django template language.

TEMPLATE_LOADERS

Default:

['django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader']

Deprecated since version 1.8: Set the 'loaders' option in the OPTIONS of a DjangoTemplates backend instead.

A list of template loader classes, specified as strings. Each Loader class knows how to import templates from a particular source. Optionally, a tuple can be used instead of a string. The first item in the tuple should be the Loader’s module, subsequent items are passed to the Loader during initialization. See The Django template language: for Python programmers.

TEMPLATE_STRING_IF_INVALID

Default: '' (Empty string)

Deprecated since version 1.8: Set the 'string_if_invalid' option in the OPTIONS of a DjangoTemplates backend instead.

Output, as a string, that the template system should use for invalid (e.g. misspelled) variables. See How invalid variables are handled.

TEST_RUNNER

Default: 'django.test.runner.DiscoverRunner'

The name of the class to use for starting the test suite. See Using different testing frameworks.

TEST_NON_SERIALIZED_APPS

Default: [] (Empty list)

In order to restore the database state between tests for TransactionTestCases and database backends without transactions, Django will serialize the contents of all apps when it starts the test run so it can then reload from that copy before running tests that need it.

This slows down the startup time of the test runner; if you have apps that you know don’t need this feature, you can add their full names in here (e.g. 'django.contrib.contenttypes') to exclude them from this serialization process.

THOUSAND_SEPARATOR

Default: ',' (Comma)

Default thousand separator used when formatting numbers. This setting is used only when USE_THOUSAND_SEPARATOR is True and NUMBER_GROUPING is greater than 0.

Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead.

See also NUMBER_GROUPING, DECIMAL_SEPARATOR and USE_THOUSAND_SEPARATOR.

TIME_FORMAT

Default: 'P' (e.g. 4 p.m.)

The default formatting to use for displaying time fields in any part of the system. Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead. See allowed date format strings.

See also DATE_FORMAT and DATETIME_FORMAT.

TIME_INPUT_FORMATS

Default:

[
'%H:%M:%S',     # '14:30:59'
'%H:%M:%S.%f',  # '14:30:59.000200'
'%H:%M',        # '14:30'
]

A list of formats that will be accepted when inputting data on a time field. Formats will be tried in order, using the first valid one. Note that these format strings use Python’s datetime module syntax, not the format strings from the date template filter.

When USE_L10N is True, the locale-dictated format has higher precedence and will be applied instead.

See also DATE_INPUT_FORMATS and DATETIME_INPUT_FORMATS.

TIME_ZONE

Default: 'America/Chicago'

A string representing the time zone for this installation, or None. See the list of time zones.

Note

Since Django was first released with the TIME_ZONE set to 'America/Chicago', the global setting (used if nothing is defined in your project’s settings.py) remains 'America/Chicago' for backwards compatibility. New project templates default to 'UTC'.

Note that this isn’t necessarily the time zone of the server. For example, one server may serve multiple Django-powered sites, each with a separate time zone setting.

When USE_TZ is False, this is the time zone in which Django will store all datetimes. When USE_TZ is True, this is the default time zone that Django will use to display datetimes in templates and to interpret datetimes entered in forms.

Django sets the os.environ['TZ'] variable to the time zone you specify in the TIME_ZONE setting. Thus, all your views and models will automatically operate in this time zone. However, Django won’t set the TZ environment variable under the following conditions:

- If you’re using the manual configuration option as described in manually configuring settings, or

- If you specify TIME_ZONE = None. This will cause Django to fall back to using the system timezone. However, this is discouraged when USE_TZ = True, because it makes conversions between local time and UTC less reliable.

If Django doesn’t set the TZ environment variable, it’s up to you to ensure your processes are running in the correct environment.

Note

Django cannot reliably use alternate time zones in a Windows environment. If you’re running Django on Windows, TIME_ZONE must be set to match the system time zone.

USE_ETAGS

Default: False

A boolean that specifies whether to output the “Etag” header. This saves bandwidth but slows down performance. This is used by the CommonMiddleware (see Middleware) and in the``Cache Framework`` (see Django’s cache framework).

USE_I18N

Default: True

A boolean that specifies whether Django’s translation system should be enabled. This provides an easy way to turn it off, for performance. If this is set to False, Django will make some optimizations so as not to load the translation machinery.

See also LANGUAGE_CODE, USE_L10N and USE_TZ.

Note

The default settings.py file created by django-admin startproject includes USE_I18N = True for convenience.

USE_L10N

Default: False

A boolean that specifies if localized formatting of data will be enabled by default or not. If this is set to True, e.g. Django will display numbers and dates using the format of the current locale.

See also LANGUAGE_CODE, USE_I18N and USE_TZ.

Note

The default settings.py file created by django-admin startproject includes USE_L10N = True for convenience.

USE_THOUSAND_SEPARATOR

Default: False

A boolean that specifies whether to display numbers using a thousand separator. When USE_L10N is set to True and if this is also set to True, Django will use the values of THOUSAND_SEPARATOR and NUMBER_GROUPING to format numbers unless the locale already has an existing thousands separator. If there is a thousands separator in the locale format, it will have higher precedence and will be applied instead.

See also DECIMAL_SEPARATOR, NUMBER_GROUPING and THOUSAND_SEPARATOR.

USE_TZ

Default: False

A boolean that specifies if datetimes will be timezone-aware by default or not. If this is set to True, Django will use timezone-aware datetimes internally. Otherwise, Django will use naive datetimes in local time.

See also TIME_ZONE, USE_I18N and USE_L10N.

Note

The default settings.py file created by django-admin startproject includes USE_TZ = True for convenience.

USE_X_FORWARDED_HOST

Default: False

A boolean that specifies whether to use the X-Forwarded-Host header in preference to the Host header. This should only be enabled if a proxy which sets this header is in use.

This setting takes priority over USE_X_FORWARDED_PORT. Per RFC 7239#page-7, the X-Forwarded-Host header can include the port number, in which case you shouldn’t use USE_X_FORWARDED_PORT.

USE_X_FORWARDED_PORT

New in Django 1.9.

Default: False

A boolean that specifies whether to use the X-Forwarded-Port header in preference to the SERVER_PORT META variable. This should only be enabled if a proxy which sets this header is in use.

USE_X_FORWARDED_HOST takes priority over this setting.

WSGI_APPLICATION

Default: None

The full Python path of the WSGI application object that Django’s built-in servers (e.g. runserver) will use. The django-admin startproject management command will create a simple wsgi.py file with an application callable in it, and point this setting to that application.

If not set, the return value of django.core.wsgi.get_wsgi_application() will be used. In this case, the behavior of runserver will be identical to previous Django versions.

YEAR_MONTH_FORMAT

Default: 'F Y'

The default formatting to use for date fields on Django admin change-list pages – and, possibly, by other parts of the system – in cases when only the year and month are displayed.

For example, when a Django admin change-list page is being filtered by a date drilldown, the header for a given month displays the month and the year. Different locales have different formats. For example, U.S. English would say “January 2006,” whereas another locale might say “2006/January.”

Note that if USE_L10N is set to True, then the corresponding locale-dictated format has higher precedence and will be applied.

See allowed date format strings. See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT and MONTH_DAY_FORMAT.

X_FRAME_OPTIONS

Default: 'SAMEORIGIN'

The default value for the X-Frame-Options header used by XFrameOptionsMiddleware. See the clickjacking protection documentation.

Auth

Settings for django.contrib.auth.

AUTHENTICATION_BACKENDS

Default: ['django.contrib.auth.backends.ModelBackend']

A list of authentication backend classes (as strings) to use when attempting to authenticate a user. See the authentication backends documentation for details.

AUTH_USER_MODEL

Default: 'auth.User'

The model to use to represent a User. See Substituting a custom User model.

Warning

You cannot change the AUTH_USER_MODEL setting during the lifetime of a project (i.e. once you have made and migrated models that depend on it) without serious effort. It is intended to be set at the project start, and the model it refers to must be available in the first migration of the app that it lives in. See Substituting a custom User model for more details.

LOGIN_REDIRECT_URL

Default: '/accounts/profile/'

The URL where requests are redirected after login when the contrib.auth.login view gets no next parameter.

This is used by the login_required() decorator, for example.

This setting also accepts named URL patterns which can be used to reduce configuration duplication since you don’t have to define the URL in two places (settings and URLconf).

Deprecated since version 1.8: The setting may also be a dotted Python path to a view function. Support for this will be removed in Django 1.10.

LOGIN_URL

Default: '/accounts/login/'

The URL where requests are redirected for login, especially when using the login_required() decorator.

This setting also accepts named URL patterns which can be used to reduce configuration duplication since you don’t have to define the URL in two places (settings and URLconf).

Deprecated since version 1.8: The setting may also be a dotted Python path to a view function. Support for this will be removed in Django 1.10.

PASSWORD_RESET_TIMEOUT_DAYS

Default: 3

The number of days a password reset link is valid for. Used by the django.contrib.auth password reset mechanism.

PASSWORD_HASHERS

See How Django stores passwords.

Default:

[
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]

AUTH_PASSWORD_VALIDATORS

New in Django 1.9.

Default: [] (Empty list)

The list of validators that are used to check the strength of user’s passwords. See Password validation for more details. By default, no validation is performed and all passwords are accepted.

Messages

Settings for django.contrib.messages.

MESSAGE_LEVEL

Default: messages.INFO

Sets the minimum message level that will be recorded by the messages framework. See message levels for more details.

Important

If you override MESSAGE_LEVEL in your settings file and rely on any of the built-in constants, you must import the constants module directly to avoid the potential for circular imports, e.g.:

from django.contrib.messages import constants as message_constants
MESSAGE_LEVEL = message_constants.DEBUG

If desired, you may specify the numeric values for the constants directly according to the values in the above constants table.

MESSAGE_STORAGE

Default: 'django.contrib.messages.storage.fallback.FallbackStorage'

Controls where Django stores message data. Valid values are:

- 'django.contrib.messages.storage.fallback.FallbackStorage'

- 'django.contrib.messages.storage.session.SessionStorage'

- 'django.contrib.messages.storage.cookie.CookieStorage'

See message storage backends for more details.

The backends that use cookies – CookieStorage and FallbackStorage – use the value of SESSION_COOKIE_DOMAIN, SESSION_COOKIE_SECURE and SESSION_COOKIE_HTTPONLY when setting their cookies.

MESSAGE_TAGS

Default:

{
messages.DEBUG: 'debug',
messages.INFO: 'info',
messages.SUCCESS: 'success',
messages.WARNING: 'warning',
messages.ERROR: 'error',
}

This sets the mapping of message level to message tag, which is typically rendered as a CSS class in HTML. If you specify a value, it will extend the default. This means you only have to specify those values which you need to override. See Displaying messages above for more details.

Important

If you override MESSAGE_TAGS in your settings file and rely on any of the built-in constants, you must import the constants module directly to avoid the potential for circular imports, e.g.:

from django.contrib.messages import constants as message_constants
MESSAGE_TAGS = {message_constants.INFO: ''}

If desired, you may specify the numeric values for the constants directly according to the values in the above constants table.

Sessions

Settings for django.contrib.sessions.

SESSION_CACHE_ALIAS

Default: 'default'

If you’re using cache-based session storage, this selects the cache to use.

SESSION_COOKIE_AGE

Default: 1209600 (2 weeks, in seconds)

The age of session cookies, in seconds.

SESSION_COOKIE_DOMAIN

Default: None

The domain to use for session cookies. Set this to a string such as ".example.com" (note the leading dot!) for cross-domain cookies, or use None for a standard domain cookie.

Be cautious when updating this setting on a production site. If you update this setting to enable cross-domain cookies on a site that previously used standard domain cookies, existing user cookies will be set to the old domain. This may result in them being unable to log in as long as these cookies persist.

This setting also affects cookies set by django.contrib.messages.

SESSION_COOKIE_HTTPONLY

Default: True

Whether to use HTTPOnly flag on the session cookie. If this is set to True, client-side JavaScript will not to be able to access the session cookie.

HTTPOnly is a flag included in a Set-Cookie HTTP response header. It is not part of the RFC 2109 standard for cookies, and it isn’t honored consistently by all browsers. However, when it is honored, it can be a useful way to mitigate the risk of client side script accessing the protected cookie data.

Turning it on makes it less trivial for an attacker to escalate a cross-site scripting vulnerability into full hijacking of a user’s session. There’s not much excuse for leaving this off, either: if your code depends on reading session cookies from JavaScript, you’re probably doing it wrong.

SESSION_COOKIE_NAME

Default: 'sessionid'

The name of the cookie to use for sessions. This can be whatever you want (as long as it’s different from the other cookie names in your application).

SESSION_COOKIE_PATH

Default: '/'

The path set on the session cookie. This should either match the URL path of your Django installation or be parent of that path.

This is useful if you have multiple Django instances running under the same hostname. They can use different cookie paths, and each instance will only see its own session cookie.

SESSION_COOKIE_SECURE

Default: False

Whether to use a secure cookie for the session cookie. If this is set to True, the cookie will be marked as “secure,” which means browsers may ensure that the cookie is only sent under an HTTPS connection.

Since it’s trivial for a packet sniffer (e.g. Firesheep) to hijack a user’s session if the session cookie is sent unencrypted, there’s really no good excuse to leave this off. It will prevent you from using sessions on insecure requests and that’s a good thing.

SESSION_ENGINE

Default: 'django.contrib.sessions.backends.db'

Controls where Django stores session data. Included engines are:

- 'django.contrib.sessions.backends.db'

- 'django.contrib.sessions.backends.file'

- 'django.contrib.sessions.backends.cache'

- 'django.contrib.sessions.backends.cached_db'

- 'django.contrib.sessions.backends.signed_cookies'

See Configuring the session engine for more details.

SESSION_EXPIRE_AT_BROWSER_CLOSE

Default: False

Whether to expire the session when the user closes their browser. See Browser-length sessions vs. persistent sessions.

SESSION_FILE_PATH

Default: None

If you’re using file-based session storage, this sets the directory in which Django will store session data. When the default value (None) is used, Django will use the standard temporary directory for the system.

SESSION_SAVE_EVERY_REQUEST

Default: False

Whether to save the session data on every request. If this is False (default), then the session data will only be saved if it has been modified – that is, if any of its dictionary values have been assigned or deleted. Empty sessions won’t be created, even if this setting is active.

SESSION_SERIALIZER

Default: 'django.contrib.sessions.serializers.JSONSerializer'

Full import path of a serializer class to use for serializing session data. Included serializers are:

- 'django.contrib.sessions.serializers.PickleSerializer'

- 'django.contrib.sessions.serializers.JSONSerializer'

See Session serialization for details, including a warning regarding possible remote code execution when using PickleSerializer.

Sites

Settings for django.contrib.sites.

SITE_ID

Default: Not defined

The ID, as an integer, of the current site in the django_site database table. This is used so that application data can hook into specific sites and a single database can manage content for multiple sites.

Static Files

Settings for django.contrib.staticfiles.

STATIC_ROOT

Default: None

The absolute path to the directory where collectstatic will collect static files for deployment.

Example: "/var/www/example.com/static/"

If the staticfiles contrib app is enabled (default) the collectstatic management command will collect static files into this directory. See the howto on managing static files for more details about usage.

Warning

This should be an initially empty destination directory for collecting your static files from their permanent locations into one directory for ease of deployment; it is not a place to store your static files permanently. You should do that in directories that will be found by staticfiles’s finders, which by default, are 'static/' app sub-directories and any directories you include in STATICFILES_DIRS).

STATIC_URL

Default: None

URL to use when referring to static files located in STATIC_ROOT.

Example: "/static/" or "http://static.example.com/"

If not None, this will be used as the base path for asset definitions (the Media class) and the staticfiles app.

It must end in a slash if set to a non-empty value.

You may need to configure these files to be served in development and will definitely need to do so in production.

STATICFILES_DIRS

Default: [] (Empty list)

This setting defines the additional locations the staticfiles app will traverse if the FileSystemFinder finder is enabled, e.g. if you use the collectstatic or findstatic management command or use the static file serving view.

This should be set to a list of strings that contain full paths to your additional files directory(ies) e.g.:

STATICFILES_DIRS = [
"/home/special.polls.com/polls/static",
"/home/polls.com/polls/static",
"/opt/webfiles/common",
]

Note that these paths should use Unix-style forward slashes, even on Windows (e.g. "C:/Users/user/mysite/extra_static_content").

Prefixes (optional)

In case you want to refer to files in one of the locations with an additional namespace, you can optionally provide a prefix as (prefix, path) tuples, e.g.:

STATICFILES_DIRS = [
# ...
("downloads", "/opt/webfiles/stats"),
]

For example, assuming you have STATIC_URL set to '/static/', the collectstatic management command would collect the “stats” files in a 'downloads' subdirectory of STATIC_ROOT.

This would allow you to refer to the local file '/opt/webfiles/stats/polls_20101022.tar.gz' with '/static/downloads/polls_20101022.tar.gz' in your templates, e.g.:

<a href="{% static "downloads/polls_20101022.tar.gz" %}">

STATICFILES_STORAGE

Default: 'django.contrib.staticfiles.storage.StaticFilesStorage'

The file storage engine to use when collecting static files with the collectstatic management command.

A ready-to-use instance of the storage backend defined in this setting can be found at django.contrib.staticfiles.storage.staticfiles_storage.

For an example, see Serving static files from a cloud service or CDN.

STATICFILES_FINDERS

Default:

[
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

The list of finder backends that know how to find static files in various locations.

The default will find files stored in the STATICFILES_DIRS setting (using django.contrib.staticfiles.finders.FileSystemFinder) and in a static subdirectory of each app (using django.contrib.staticfiles.finders.AppDirectoriesFinder). If multiple files with the same name are present, the first file that is found will be used.

One finder is disabled by default: django.contrib.staticfiles.finders.DefaultStorageFinder. If added to your STATICFILES_FINDERS setting, it will look for static files in the default file storage as defined by the DEFAULT_FILE_STORAGE setting.

Note

When using the AppDirectoriesFinder finder, make sure your apps can be found by staticfiles. Simply add the app to the INSTALLED_APPS setting of your site.

Static file finders are currently considered a private interface, and this interface is thus undocumented.

Core Settings Topical Index

Cache

- CACHES

- CACHE_MIDDLEWARE_ALIAS

- CACHE_MIDDLEWARE_KEY_PREFIX

- CACHE_MIDDLEWARE_SECONDS

Database

- DATABASES

- DATABASE_ROUTERS

- DEFAULT_INDEX_TABLESPACE

- DEFAULT_TABLESPACE

Debugging

- DEBUG

- DEBUG_PROPAGATE_EXCEPTIONS

Email

- ADMINS

- DEFAULT_CHARSET

- DEFAULT_FROM_EMAIL

- EMAIL_BACKEND

- EMAIL_FILE_PATH

- EMAIL_HOST

- EMAIL_HOST_PASSWORD

- EMAIL_HOST_USER

- EMAIL_PORT

- EMAIL_SSL_CERTFILE

- EMAIL_SSL_KEYFILE

- EMAIL_SUBJECT_PREFIX

- EMAIL_TIMEOUT

- EMAIL_USE_TLS

- MANAGERS

- SERVER_EMAIL

Error reporting

- DEFAULT_EXCEPTION_REPORTER_FILTER

- IGNORABLE_404_URLS

- MANAGERS

- SILENCED_SYSTEM_CHECKS

File uploads

- DEFAULT_FILE_STORAGE

- FILE_CHARSET

- FILE_UPLOAD_HANDLERS

- FILE_UPLOAD_MAX_MEMORY_SIZE

- FILE_UPLOAD_PERMISSIONS

- FILE_UPLOAD_TEMP_DIR

- MEDIA_ROOT

- MEDIA_URL

Globalization (i18n/l10n)

- DATE_FORMAT

- DATE_INPUT_FORMATS

- DATETIME_FORMAT

- DATETIME_INPUT_FORMATS

- DECIMAL_SEPARATOR

- FIRST_DAY_OF_WEEK

- FORMAT_MODULE_PATH

- LANGUAGE_CODE

- LANGUAGE_COOKIE_AGE

- LANGUAGE_COOKIE_DOMAIN

- LANGUAGE_COOKIE_NAME

- LANGUAGE_COOKIE_PATH

- LANGUAGES

- LOCALE_PATHS

- MONTH_DAY_FORMAT

- NUMBER_GROUPING

- SHORT_DATE_FORMAT

- SHORT_DATETIME_FORMAT

- THOUSAND_SEPARATOR

- TIME_FORMAT

- TIME_INPUT_FORMATS

- TIME_ZONE

- USE_I18N

- USE_L10N

- USE_THOUSAND_SEPARATOR

- USE_TZ

- YEAR_MONTH_FORMAT

HTTP

- DEFAULT_CHARSET

- DEFAULT_CONTENT_TYPE

- DISALLOWED_USER_AGENTS

- FORCE_SCRIPT_NAME

- INTERNAL_IPS

- MIDDLEWARE_CLASSES

- Security

- SECURE_BROWSER_XSS_FILTER

- SECURE_CONTENT_TYPE_NOSNIFF

- SECURE_HSTS_INCLUDE_SUBDOMAINS

- SECURE_HSTS_SECONDS

- SECURE_PROXY_SSL_HEADER

- SECURE_REDIRECT_EXEMPT

- SECURE_SSL_HOST

- SECURE_SSL_REDIRECT

- SIGNING_BACKEND

- USE_ETAGS

- USE_X_FORWARDED_HOST

- USE_X_FORWARDED_PORT

- WSGI_APPLICATION

Logging

- LOGGING

- LOGGING_CONFIG

Models

- ABSOLUTE_URL_OVERRIDES

- FIXTURE_DIRS

- INSTALLED_APPS

Security

- Cross Site Request Forgery Protection

- CSRF_COOKIE_DOMAIN

- CSRF_COOKIE_NAME

- CSRF_COOKIE_PATH

- CSRF_COOKIE_SECURE

- CSRF_FAILURE_VIEW

- CSRF_HEADER_NAME

- CSRF_TRUSTED_ORIGINS

- SECRET_KEY

- X_FRAME_OPTIONS

Serialization

- DEFAULT_CHARSET

- SERIALIZATION_MODULES

Templates

- ALLOWED_INCLUDE_ROOTS

- TEMPLATES

- TEMPLATE_CONTEXT_PROCESSORS

- TEMPLATE_DEBUG

- TEMPLATE_DIRS

- TEMPLATE_LOADERS

- TEMPLATE_STRING_IF_INVALID

Testing

- Database: TEST

- TEST_NON_SERIALIZED_APPS

- TEST_RUNNER

URLs

- APPEND_SLASH

- PREPEND_WWW

- ROOT_URLCONF

Signals

A list of all the signals that Django sends. All built-in signals are sent using the send() method.

See also

See the documentation on the signal dispatcher for information regarding how to register for and receive signals.

The authentication framework sends signals when a user is logged in / out.

Model signals

The django.db.models.signals module defines a set of signals sent by the model system.

Warning

Many of these signals are sent by various model methods like __init__() or save() that you can override in your own code.

If you override these methods on your model, you must call the parent class’ methods for this signals to be sent.

Note also that Django stores signal handlers as weak references by default, so if your handler is a local function, it may be garbage collected. To prevent this, pass weak=False when you call the signal’s connect().

Note

Model signals sender model can be lazily referenced when connecting a receiver by specifying its full application label. For example, an Answer model defined in the polls application could be referenced as 'polls.Answer'. This sort of reference can be quite handy when dealing with circular import dependencies and swappable models.

pre_init

django.db.models.signals.pre_init

Whenever you instantiate a Django model, this signal is sent at the beginning of the model’s __init__() method.

Arguments sent with this signal:

sender

The model class that just had an instance created.

args

A list of positional arguments passed to __init__():

kwargs

A dictionary of keyword arguments passed to __init__():

For example, the tutorial has this line:

p = Poll(question="What's up?", pub_date=datetime.now())

The arguments sent to a pre_init handler would be:

Argument

Value

sender

Poll (the class itself)

args

[] (an empty list because there were no positional arguments passed to __init__().)

kwargs

{'question': "What's up?", 'pub_date': datetime.now()}

post_init

django.db.models.signals.post_init

Like pre_init, but this one is sent when the __init__() method finishes.

Arguments sent with this signal:

sender

As above: the model class that just had an instance created.

instance

The actual instance of the model that’s just been created.

pre_save

django.db.models.signals.pre_save

This is sent at the beginning of a model’s save() method.

Arguments sent with this signal:

sender

The model class.

instance

The actual instance being saved.

raw

A boolean; True if the model is saved exactly as presented (i.e. when loading a fixture). One should not query/modify other records in the database as the database might not be in a consistent state yet.

using

The database alias being used.

update_fields

The set of fields to update as passed to Model.save(), or None if update_fields wasn’t passed to save().

post_save

django.db.models.signals.post_save

Like pre_save, but sent at the end of the save() method.

Arguments sent with this signal:

sender

The model class.

instance

The actual instance being saved.

created

A boolean; True if a new record was created.

raw

A boolean; True if the model is saved exactly as presented (i.e. when loading a fixture). One should not query/modify other records in the database as the database might not be in a consistent state yet.

using

The database alias being used.

update_fields

The set of fields to update as passed to Model.save(), or None if update_fields wasn’t passed to save().

pre_delete

django.db.models.signals.pre_delete

Sent at the beginning of a model’s delete() method and a queryset’s delete() method.

Arguments sent with this signal:

sender

The model class.

instance

The actual instance being deleted.

using

The database alias being used.

post_delete

django.db.models.signals.post_delete

Like pre_delete, but sent at the end of a model’s delete() method and a queryset’s delete() method.

Arguments sent with this signal:

sender

The model class.

instance

The actual instance being deleted.

Note that the object will no longer be in the database, so be very careful what you do with this instance.

using

The database alias being used.

m2m_changed

django.db.models.signals.m2m_changed

Sent when a ManyToManyField is changed on a model instance. Strictly speaking, this is not a model signal since it is sent by the ManyToManyField, but since it complements the pre_save/post_save and pre_delete/post_delete when it comes to tracking changes to models, it is included here.

Arguments sent with this signal:

sender

The intermediate model class describing the ManyToManyField. This class is automatically created when a many-to-many field is defined; you can access it using the through attribute on the many-to-many field.

instance

The instance whose many-to-many relation is updated. This can be an instance of the sender, or of the class the ManyToManyField is related to.

action

A string indicating the type of update that is done on the relation. This can be one of the following:

"pre_add"

Sent before one or more objects are added to the relation.

"post_add"

Sent after one or more objects are added to the relation.

"pre_remove"

Sent before one or more objects are removed from the relation.

"post_remove"

Sent after one or more objects are removed from the relation.

"pre_clear"

Sent before the relation is cleared.

"post_clear"

Sent after the relation is cleared.

reverse Indicates which side of the relation is updated (i.e., if it is the forward or reverse relation that is being modified). model The class of the objects that are added to, removed from or cleared from the relation. pk_set
For the pre_add, post_add, pre_remove and post_remove actions, this is a set of primary key values that have been added to or removed from the relation.

For the pre_clear and post_clear actions, this is None.
using The database alias being used.
For example, if a Pizza can have multiple Topping objects, modeled like this:

class Topping(models.Model):
# ...
pass

class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)

If we connected a handler like this:

from django.db.models.signals import m2m_changed

def toppings_changed(sender, **kwargs):
# Do something
pass

m2m_changed.connect(toppings_changed, sender=Pizza.toppings.through)

and then did something like this:

>>> p = Pizza.objects.create(...)
>>> t = Topping.objects.create(...)
>>> p.toppings.add(t)

the arguments sent to a m2m_changed handler (toppings_changed in the example above) would be:

Argument

Value

sender

Pizza.toppings.through (the intermediate m2m class)

instance

p (the Pizza instance being modified)

action

"pre_add" (followed by a separate signal with "post_add")

reverse

False (Pizza contains the ManyToManyField, so this call modifies the forward relation)

model

Topping (the class of the objects added to the Pizza)

pk_set

{t.id} (since only Topping t was added to the relation)

using

"default" (since the default router sends writes here)

And if we would then do something like this:

>>> t.pizza_set.remove(p)

the arguments sent to a m2m_changed handler would be:

Argument

Value

sender

Pizza.toppings.through (the intermediate m2m class)

instance

t (the Topping instance being modified)

action

"pre_remove" (followed by a separate signal with "post_remove")

reverse

True (Pizza contains the ManyToManyField, so this call modifies the reverse relation)

model

Pizza (the class of the objects removed from the Topping)

pk_set

{p.id} (since only Pizza p was removed from the relation)

using

"default" (since the default router sends writes here)

class_prepared

django.db.models.signals.class_prepared

Sent whenever a model class has been “prepared” – that is, once model has been defined and registered with Django’s model system. Django uses this signal internally; it’s not generally used in third-party applications.

Since this signal is sent during the app registry population process, and AppConfig.ready() runs after the app registry is fully populated, receivers cannot be connected in that method. One possibility is to connect them AppConfig.__init__() instead, taking care not to import models or trigger calls to the app registry.

Arguments that are sent with this signal:

sender

The model class which was just prepared.

Management signals

Signals sent by django-admin.

pre_migrate

django.db.models.signals.pre_migrate

Sent by the migrate command before it starts to install an application. It’s not emitted for applications that lack a models module.

Arguments sent with this signal:

sender

An AppConfig instance for the application about to be migrated/synced.

app_config

Same as sender.

verbosity

Indicates how much information manage.py is printing on screen. See the --verbosity flag for details.

Functions which listen for pre_migrate should adjust what they output to the screen based on the value of this argument.

interactive

If interactive is True, it’s safe to prompt the user to input things on the command line. If interactive is False, functions which listen for this signal should not try to prompt for anything.

For example, the django.contrib.auth app only prompts to create a superuser when interactive is True.

using

The alias of database on which a command will operate.

post_migrate

django.db.models.signals.post_migrate

Sent by the migrate command after it installs an application, and the flush command. It’s not emitted for applications that lack a models module.

It is important that handlers of this signal perform idempotent changes (e.g. no database alterations) as this may cause the flush management command to fail if it also ran during the migrate command.

Arguments sent with this signal:

sender

An AppConfig instance for the application that was just installed.

app_config

Same as sender.

verbosity

Indicates how much information manage.py is printing on screen. See the --verbosity flag for details.

Functions which listen for post_migrate should adjust what they output to the screen based on the value of this argument.

interactive

If interactive is True, it’s safe to prompt the user to input things on the command line. If interactive is False, functions which listen for this signal should not try to prompt for anything.

For example, the django.contrib.auth app only prompts to create a superuser when interactive is True.

using

The database alias used for synchronization. Defaults to the default database.

For example, you could register a callback in an AppConfig like this:

from django.apps import AppConfig
from django.db.models.signals import post_migrate

def my_callback(sender, **kwargs):
# Your specific logic here
pass

class MyAppConfig(AppConfig):
...

def ready(self):
post_migrate.connect(my_callback, sender=self)

Note

If you provide an AppConfig instance as the sender argument, please ensure that the signal is registered in ready(). AppConfigs are recreated for tests that run with a modified set of INSTALLED_APPS (such as when settings are overridden) and such signals should be connected for each new AppConfig instance.

Request/response signals

Signals sent by the core framework when processing a request.

request_started

django.core.signals.request_started

Sent when Django begins processing an HTTP request.

Arguments sent with this signal:

sender

The handler class – e.g. django.core.handlers.wsgi.WsgiHandler – that handled the request.

environ

The environ dictionary provided to the request.

Changed in Django 1.8:
The environ argument was added.

request_finished

django.core.signals.request_finished

Sent when Django finishes delivering an HTTP response to the client.

Note

Some WSGI servers and middleware do not always call close on the response object after handling a request, most notably uWSGI prior to 1.2.6 and Sentry’s error reporting middleware up to 2.0.7. In those cases this signal isn’t sent at all. This can result in idle connections to database and memcache servers.

Arguments sent with this signal:

sender

The handler class, as above.

got_request_exception

django.core.signals.got_request_exception

This signal is sent whenever Django encounters an exception while processing an incoming HTTP request.

Arguments sent with this signal:

sender

The handler class, as above.

request

The HttpRequest object.

Test signals

Signals only sent when running tests.

setting_changed

django.test.signals.setting_changed

This signal is sent when the value of a setting is changed through the django.test.TestCase.settings() context manager or the django.test.override_settings() decorator/context manager.

It’s actually sent twice: when the new value is applied (“setup”) and when the original value is restored (“teardown”). Use the enter argument to distinguish between the two.

You can also import this signal from django.core.signals to avoid importing from django.test in non-test situations.

Changed in Django 1.8:
The signal was moved to django.core.signals as described above.

Arguments sent with this signal:

sender

The settings handler.

setting

The name of the setting.

value

The value of the setting after the change. For settings that initially don’t exist, in the “teardown” phase, value is None.

enter

A boolean; True if the setting is applied, False if restored.

template_rendered

django.test.signals.template_rendered

Sent when the test system renders a template. This signal is not emitted during normal operation of a Django server – it is only available during testing.

Arguments sent with this signal:

sender

The Template object which was rendered.

template

Same as sender

context

The Context with which the template was rendered.

Database Wrappers

Signals sent by the database wrapper when a database connection is initiated.

connection_created

django.db.backends.signals.connection_created

Sent when the database wrapper makes the initial connection to the database. This is particularly useful if you’d like to send any post connection commands to the SQL backend.

Arguments sent with this signal:

sender

The database wrapper class – i.e. django.db.backends.postgresql.DatabaseWrapper or django.db.backends.mysql.DatabaseWrapper, etc.

connection

The database connection that was opened. This can be used in a multiple-database configuration to differentiate connection signals from different databases.

Templates

Django’s template engine provides a powerful mini-language for defining the user-facing layer of your application, encouraging a clean separation of application and presentation logic. Templates can be maintained by anyone with an understanding of HTML; no knowledge of Python is required. For introductory material, see Templates topic guide.

- The Django template language

- Templates

- Variables

- Filters

- Tags

- Comments

- Template inheritance

- Automatic HTML escaping

- Accessing method calls

- Custom tag and filter libraries

- Built-in template tags and filters

- Built-in tag reference

- Built-in filter reference

- Internationalization tags and filters

- Other tags and filters libraries

- The Django template language: for Python programmers

- Overview

- Configuring an engine

- Loading a template

- Rendering a context

- Playing with Context objects

- Loading templates

- Custom loaders

- Template origin

- Upgrading templates to Django 1.8

- The TEMPLATES settings

- django.template.loader

- Template()

See also

For information on writing your own custom tags and filters, see Custom template tags and filters.

The Django template language

This document explains the language syntax of the Django template system. If you’re looking for a more technical perspective on how it works and how to extend it, see The Django template language: for Python programmers.

Django’s template language is designed to strike a balance between power and ease. It’s designed to feel comfortable to those used to working with HTML. If you have any exposure to other text-based template languages, such as Smarty or Jinja2, you should feel right at home with Django’s templates.

Philosophy

If you have a background in programming, or if you’re used to languages which mix programming code directly into HTML, you’ll want to bear in mind that the Django template system is not simply Python embedded into HTML. This is by design: the template system is meant to express presentation, not program logic.

The Django template system provides tags which function similarly to some programming constructs – an if tag for boolean tests, a for tag for looping, etc. – but these are not simply executed as the corresponding Python code, and the template system will not execute arbitrary Python expressions. Only the tags, filters and syntax listed below are supported by default (although you can add your own extensions to the template language as needed).

Templates

A template is simply a text file. It can generate any text-based format (HTML, XML, CSV, etc.).

A template contains variables, which get replaced with values when the template is evaluated, and tags, which control the logic of the template.

Below is a minimal template that illustrates a few basics. Each element will be explained later in this document.

{% extends "base_generic.html" %}

{% block title %}{{ section.title }}{% endblock %}

{% block content %}
<h1>{{ section.title }}</h1>

{% for story in story_list %}
<h2>
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

Philosophy

Why use a text-based template instead of an XML-based one (like Zope’s TAL)? We wanted Django’s template language to be usable for more than just XML/HTML templates. At World Online, we use it for emails, JavaScript and CSV. You can use the template language for any text-based format.

Oh, and one more thing: making humans edit XML is sadistic!

Variables

Variables look like this: {{ variable }}. When the template engine encounters a variable, it evaluates that variable and replaces it with the result. Variable names consist of any combination of alphanumeric characters and the underscore ("_"). The dot (".") also appears in variable sections, although that has a special meaning, as indicated below. Importantly, you cannot have spaces or punctuation characters in variable names.

Use a dot (.) to access attributes of a variable.

Behind the scenes

Technically, when the template system encounters a dot, it tries the following lookups, in this order:

- Dictionary lookup

- Attribute or method lookup

- Numeric index lookup

If the resulting value is callable, it is called with no arguments. The result of the call becomes the template value.

This lookup order can cause some unexpected behavior with objects that override dictionary lookup. For example, consider the following code snippet that attempts to loop over a collections.defaultdict:

{% for k, v in defaultdict.iteritems %}
Do something with k and v here...
{% endfor %}

Because dictionary lookup happens first, that behavior kicks in and provides a default value instead of using the intended .iteritems() method. In this case, consider converting to a dictionary first.

In the above example, {{ section.title }} will be replaced with the title attribute of the section object.

If you use a variable that doesn’t exist, the template system will insert the value of the string_if_invalid option, which is set to '' (the empty string) by default.

Note that “bar” in a template expression like {{ foo.bar }} will be interpreted as a literal string and not using the value of the variable “bar”, if one exists in the template context.

Filters

You can modify variables for display by using filters.

Filters look like this: {{ name|lower }}. This displays the value of the {{ name }} variable after being filtered through the lower filter, which converts text to lowercase. Use a pipe (|) to apply a filter.

Filters can be “chained.” The output of one filter is applied to the next. {{ text|escape|linebreaks }} is a common idiom for escaping text contents, then converting line breaks to <p> tags.

Some filters take arguments. A filter argument looks like this: {{ bio|truncatewords:30 }}. This will display the first 30 words of the bio variable.

Filter arguments that contain spaces must be quoted; for example, to join a list with commas and spaces you’d use {{ list|join:", " }}.

Django provides about sixty built-in template filters. You can read all about them in the built-in filter reference. To give you a taste of what’s available, here are some of the more commonly used template filters:

default

If a variable is false or empty, use given default. Otherwise, use the value of the variable. For example:

{{ value|default:"nothing" }}

If value isn’t provided or is empty, the above will display “nothing”.

length

Returns the length of the value. This works for both strings and lists. For example:

{{ value|length }}

If value is ['a', 'b', 'c', 'd'], the output will be 4.

filesizeformat

Formats the value like a “human-readable” file size (i.e. '13 KB', '4.1 MB', '102 bytes', etc.). For example:

{{ value|filesizeformat }}

If value is 123456789, the output would be 117.7 MB.

Again, these are just a few examples; see the built-in filter reference for the complete list.

You can also create your own custom template filters; see Custom template tags and filters.

See also

Django’s admin interface can include a complete reference of all template tags and filters available for a given site. See The Django admin documentation generator.

Tags

Tags look like this: {% tag %}. Tags are more complex than variables: Some create text in the output, some control flow by performing loops or logic, and some load external information into the template to be used by later variables.

Some tags require beginning and ending tags (i.e. {% tag %} ... tag contents ... {% endtag %}).

Django ships with about two dozen built-in template tags. You can read all about them in the built-in tag reference. To give you a taste of what’s available, here are some of the more commonly used tags:

for

Loop over each item in an array. For example, to display a list of athletes provided in athlete_list:

<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>

if, elif, and else

Evaluates a variable, and if that variable is “true” the contents of the block are displayed:

{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}

In the above, if athlete_list is not empty, the number of athletes will be displayed by the {{ athlete_list|length }} variable. Otherwise, if athlete_in_locker_room_list is not empty, the message “Athletes should be out...” will be displayed. If both lists are empty, “No athletes.” will be displayed.

You can also use filters and various operators in the if tag:

{% if athlete_list|length > 1 %}
Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
Athlete: {{ athlete_list.0.name }}
{% endif %}

While the above example works, be aware that most template filters return strings, so mathematical comparisons using filters will generally not work as you expect. length is an exception.

block and extends

Set up template inheritance (see below), a powerful way of cutting down on “boilerplate” in templates.

Again, the above is only a selection of the whole list; see the built-in tag reference for the complete list.

You can also create your own custom template tags; see Custom template tags and filters.

See also

Django’s admin interface can include a complete reference of all template tags and filters available for a given site. See The Django admin documentation generator.

Comments

To comment-out part of a line in a template, use the comment syntax: {# #}.

For example, this template would render as 'hello':

{# greeting #}hello

A comment can contain any template code, invalid or not. For example:

{# {% if foo %}bar{% else %} #}

This syntax can only be used for single-line comments (no newlines are permitted between the {# and #} delimiters). If you need to comment out a multiline portion of the template, see the comment tag.

Template inheritance

The most powerful – and thus the most complex – part of Django’s template engine is template inheritance. Template inheritance allows you to build a base “skeleton” template that contains all the common elements of your site and defines blocks that child templates can override.

It’s easiest to understand template inheritance by starting with an example:

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>

<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>

<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>

This template, which we’ll call base.html, defines a simple HTML skeleton document that you might use for a simple two-column page. It’s the job of “child” templates to fill the empty blocks with content.

In this example, the block tag defines three blocks that child templates can fill in. All the block tag does is to tell the template engine that a child template may override those portions of the template.

A child template might look like this:

{% extends "base.html" %}

{% block title %}My amazing blog{% endblock %}

{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}

The extends tag is the key here. It tells the template engine that this template “extends” another template. When the template system evaluates this template, first it locates the parent – in this case, “base.html”.

At that point, the template engine will notice the three block tags in base.html and replace those blocks with the contents of the child template. Depending on the value of blog_entries, the output might look like:

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>My amazing blog</title>
</head>

<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
</div>

<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>

<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>

Note that since the child template didn’t define the sidebar block, the value from the parent template is used instead. Content within a {% block %} tag in a parent template is always used as a fallback.

You can use as many levels of inheritance as needed. One common way of using inheritance is the following three-level approach:

- Create a base.html template that holds the main look-and-feel of your site.

- Create a base_SECTIONNAME.html template for each “section” of your site. For example, base_news.html, base_sports.html. These templates all extend base.html and include section-specific styles/design.

- Create individual templates for each type of page, such as a news article or blog entry. These templates extend the appropriate section template.

This approach maximizes code reuse and makes it easy to add items to shared content areas, such as section-wide navigation.

Here are some tips for working with inheritance:

- If you use {% extends %} in a template, it must be the first template tag in that template. Template inheritance won’t work, otherwise.

- More {% block %} tags in your base templates are better. Remember, child templates don’t have to define all parent blocks, so you can fill in reasonable defaults in a number of blocks, then only define the ones you need later. It’s better to have more hooks than fewer hooks.

- If you find yourself duplicating content in a number of templates, it probably means you should move that content to a {% block %} in a parent template.

- If you need to get the content of the block from the parent template, the {{ block.super }} variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }} will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.

- For extra readability, you can optionally give a name to your {% endblock %} tag. For example:

{% block content %}
...
{% endblock content %}

In larger templates, this technique helps you see which {% block %} tags are being closed.

Finally, note that you can’t define multiple block tags with the same name in the same template. This limitation exists because a block tag works in “both” directions. That is, a block tag doesn’t just provide a hole to fill – it also defines the content that fills the hole in the parent. If there were two similarly-named block tags in a template, that template’s parent wouldn’t know which one of the blocks’ content to use.

Automatic HTML escaping

When generating HTML from templates, there’s always a risk that a variable will include characters that affect the resulting HTML. For example, consider this template fragment:

Hello, {{ name }}

At first, this seems like a harmless way to display a user’s name, but consider what would happen if the user entered their name as this:

<script>alert('hello')</script>

With this name value, the template would be rendered as:

Hello, <script>alert('hello')</script>

...which means the browser would pop-up a JavaScript alert box!

Similarly, what if the name contained a '<' symbol, like this?

<b>username

That would result in a rendered template like this:

Hello, <b>username

...which, in turn, would result in the remainder of the Web page being bolded!

Clearly, user-submitted data shouldn’t be trusted blindly and inserted directly into your Web pages, because a malicious user could use this kind of hole to do potentially bad things. This type of security exploit is called a Cross Site Scripting (XSS) attack.

To avoid this problem, you have two options:

- One, you can make sure to run each untrusted variable through the escape filter (documented below), which converts potentially harmful HTML characters to unharmful ones. This was the default solution in Django for its first few years, but the problem is that it puts the onus on you, the developer / template author, to ensure you’re escaping everything. It’s easy to forget to escape data.

- Two, you can take advantage of Django’s automatic HTML escaping. The remainder of this section describes how auto-escaping works.

By default in Django, every template automatically escapes the output of every variable tag. Specifically, these five characters are escaped:

- < is converted to &lt;

- > is converted to &gt;

- ' (single quote) is converted to &#39;

- " (double quote) is converted to &quot;

- & is converted to &amp;

Again, we stress that this behavior is on by default. If you’re using Django’s template system, you’re protected.

How to turn it off

If you don’t want data to be auto-escaped, on a per-site, per-template level or per-variable level, you can turn it off in several ways.

Why would you want to turn it off? Because sometimes, template variables contain data that you intend to be rendered as raw HTML, in which case you don’t want their contents to be escaped. For example, you might store a blob of HTML in your database and want to embed that directly into your template. Or, you might be using Django’s template system to produce text that is not HTML – like an email message, for instance.

For individual variables

To disable auto-escaping for an individual variable, use the safe filter:

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

Think of safe as shorthand for safe from further escaping or can be safely interpreted as HTML. In this example, if data contains '<b>', the output will be:

This will be escaped: &lt;b&gt;
This will not be escaped: <b>

For template blocks

To control auto-escaping for a template, wrap the template (or just a particular section of the template) in the autoescape tag, like so:

{% autoescape off %}
Hello {{ name }}
{% endautoescape %}

The autoescape tag takes either on or off as its argument. At times, you might want to force auto-escaping when it would otherwise be disabled. Here is an example template:

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
This will not be auto-escaped: {{ data }}.

Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}

The auto-escaping tag passes its effect onto templates that extend the current one as well as templates included via the include tag, just like all block tags. For example:

base.html

{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}

child.html

{% extends "base.html" %}
{% block title %}This &amp; that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}

Because auto-escaping is turned off in the base template, it will also be turned off in the child template, resulting in the following rendered HTML when the greeting variable contains the string <b>Hello!</b>:

<h1>This &amp; that</h1>
<b>Hello!</b>

Notes

Generally, template authors don’t need to worry about auto-escaping very much. Developers on the Python side (people writing views and custom filters) need to think about the cases in which data shouldn’t be escaped, and mark data appropriately, so things Just Work in the template.

If you’re creating a template that might be used in situations where you’re not sure whether auto-escaping is enabled, then add an escape filter to any variable that needs escaping. When auto-escaping is on, there’s no danger of the escape filter double-escaping data – the escape filter does not affect auto-escaped variables.

String literals and automatic escaping

As we mentioned earlier, filter arguments can be strings:

{{ data|default:"This is a string literal." }}

All string literals are inserted without any automatic escaping into the template – they act as if they were all passed through the safe filter. The reasoning behind this is that the template author is in control of what goes into the string literal, so they can make sure the text is correctly escaped when the template is written.

This means you would write

{{ data|default:"3 &lt; 2" }}

...rather than:

{{ data|default:"3 < 2" }}  {# Bad! Don't do this. #}

This doesn’t affect what happens to data coming from the variable itself. The variable’s contents are still automatically escaped, if necessary, because they’re beyond the control of the template author.

Accessing method calls

Most method calls attached to objects are also available from within templates. This means that templates have access to much more than just class attributes (like field names) and variables passed in from views. For example, the Django ORM provides the “entry_set” syntax for finding a collection of objects related on a foreign key. Therefore, given a model called “comment” with a foreign key relationship to a model called “task” you can loop through all comments attached to a given task like this:

{% for comment in task.comment_set.all %}
{{ comment }}
{% endfor %}

Similarly, QuerySets provide a count() method to count the number of objects they contain. Therefore, you can obtain a count of all comments related to the current task with:

{{ task.comment_set.all.count }}

And of course you can easily access methods you’ve explicitly defined on your own models:

models.py

class Task(models.Model):
def foo(self):
return "bar"

template.html

{{ task.foo }}

Because Django intentionally limits the amount of logic processing available in the template language, it is not possible to pass arguments to method calls accessed from within templates. Data should be calculated in views, then passed to templates for display.

Custom tag and filter libraries

Certain applications provide custom tag and filter libraries. To access them in a template, ensure the application is in INSTALLED_APPS (we’d add 'django.contrib.humanize' for this example), and then use the load tag in a template:

{% load humanize %}

{{ 45000|intcomma }}

In the above, the load tag loads the humanize tag library, which then makes the intcomma filter available for use. If you’ve enabled django.contrib.admindocs, you can consult the documentation area in your admin to find the list of custom libraries in your installation.

The load tag can take multiple library names, separated by spaces. Example:

{% load humanize i18n %}

See Custom template tags and filters for information on writing your own custom template libraries.

Custom libraries and template inheritance

When you load a custom tag or filter library, the tags/filters are only made available to the current template – not any parent or child templates along the template-inheritance path.

For example, if a template foo.html has {% load humanize %}, a child template (e.g., one that has {% extends "foo.html" %}) will not have access to the humanize template tags and filters. The child template is responsible for its own {% load humanize %}.

This is a feature for the sake of maintainability and sanity.

See also

The Templates Reference

Covers built-in tags, built-in filters, using an alternative template, language, and more.

Built-in template tags and filters

This document describes Django’s built-in template tags and filters. It is recommended that you use the automatic documentation, if available, as this will also include documentation for any custom tags or filters installed.

Built-in tag reference

autoescape

Controls the current auto-escaping behavior. This tag takes either on or off as an argument and that determines whether auto-escaping is in effect inside the block. The block is closed with an endautoescape ending tag.

When auto-escaping is in effect, all variable content has HTML escaping applied to it before placing the result into the output (but after any filters have been applied). This is equivalent to manually applying the escape filter to each variable.

The only exceptions are variables that are already marked as “safe” from escaping, either by the code that populated the variable, or because it has had the safe or escape filters applied.

Sample usage:

{% autoescape on %}
{{ body }}
{% endautoescape %}

block

Defines a block that can be overridden by child templates. See Template inheritance for more information.

comment

Ignores everything between {% comment %} and {% endcomment %}. An optional note may be inserted in the first tag. For example, this is useful when commenting out code for documenting why the code was disabled.

Sample usage:

<p>Rendered text with {{ pub_date|date:"c" }}</p>
{% comment "Optional note" %}
<p>Commented out text with {{ create_date|date:"c" }}</p>
{% endcomment %}

comment tags cannot be nested.

csrf_token

This tag is used for CSRF protection, as described in the documentation for Cross Site Request Forgeries.

cycle

Produces one of its arguments each time this tag is encountered. The first argument is produced on the first encounter, the second argument on the second encounter, and so forth. Once all arguments are exhausted, the tag cycles to the first argument and produces it again.

This tag is particularly useful in a loop:

{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}

The first iteration produces HTML that refers to class row1, the second to row2, the third to row1 again, and so on for each iteration of the loop.

You can use variables, too. For example, if you have two template variables, rowvalue1 and rowvalue2, you can alternate between their values like this:

{% for o in some_list %}
<tr class="{% cycle rowvalue1 rowvalue2 %}">
...
</tr>
{% endfor %}

Variables included in the cycle will be escaped. You can disable auto-escaping with:

{% for o in some_list %}
<tr class="{% autoescape off %}{% cycle rowvalue1 rowvalue2 %}{% endautoescape %}">
...
</tr>
{% endfor %}

You can mix variables and strings:

{% for o in some_list %}
<tr class="{% cycle 'row1' rowvalue2 'row3' %}">
...
</tr>
{% endfor %}

In some cases you might want to refer to the current value of a cycle without advancing to the next value. To do this, just give the {% cycle %} tag a name, using “as”, like this:

{% cycle 'row1' 'row2' as rowcolors %}

From then on, you can insert the current value of the cycle wherever you’d like in your template by referencing the cycle name as a context variable. If you want to move the cycle to the next value independently of the original cycle tag, you can use another cycle tag and specify the name of the variable. So, the following template:

<tr>
<td class="{% cycle 'row1' 'row2' as rowcolors %}">...</td>
<td class="{{ rowcolors }}">...</td>
</tr>
<tr>
<td class="{% cycle rowcolors %}">...</td>
<td class="{{ rowcolors }}">...</td>
</tr>

would output:

<tr>
<td class="row1">...</td>
<td class="row1">...</td>
</tr>
<tr>
<td class="row2">...</td>
<td class="row2">...</td>
</tr>

You can use any number of values in a cycle tag, separated by spaces. Values enclosed in single quotes (') or double quotes (") are treated as string literals, while values without quotes are treated as template variables.

By default, when you use the as keyword with the cycle tag, the usage of {% cycle %} that initiates the cycle will itself produce the first value in the cycle. This could be a problem if you want to use the value in a nested loop or an included template. If you only want to declare the cycle but not produce the first value, you can add a silent keyword as the last keyword in the tag. For example:

{% for obj in some_list %}
{% cycle 'row1' 'row2' as rowcolors silent %}
<tr class="{{ rowcolors }}">{% include "subtemplate.html" %}</tr>
{% endfor %}

This will output a list of <tr> elements with class alternating between row1 and row2. The subtemplate will have access to rowcolors in its context and the value will match the class of the <tr> that encloses it. If the silent keyword were to be omitted, row1 and row2 would be emitted as normal text, outside the <tr> element.

When the silent keyword is used on a cycle definition, the silence automatically applies to all subsequent uses of that specific cycle tag. The following template would output nothing, even though the second call to {% cycle %} doesn’t specify silent:

{% cycle 'row1' 'row2' as rowcolors silent %}
{% cycle rowcolors %}

Deprecated since version 1.9: The {% cycle %} tag supports the much inferior old syntax from previous Django versions. You shouldn’t use this in any new projects, but for the sake of the people who are still using it, here’s what it looks like:

{% cycle row1,row2,row3 %}

In this syntax, each value gets interpreted as a literal string, and there’s no way to specify variable values, literal commas, or spaces. Support for this syntax will be removed in Django 1.10.

debug

Outputs a whole load of debugging information, including the current context and imported modules.

extends

Signals that this template extends a parent template.

This tag can be used in two ways:

- {% extends "base.html" %} (with quotes) uses the literal value "base.html" as the name of the parent template to extend.

- {% extends variable %} uses the value of variable. If the variable evaluates to a string, Django will use that string as the name of the parent template. If the variable evaluates to a Template object, Django will use that object as the parent template.

See Template inheritance for more information.

filter

Filters the contents of the block through one or more filters. Multiple filters can be specified with pipes and filters can have arguments, just as in variable syntax.

Note that the block includes all the text between the filter and endfilter tags.

Sample usage:

{% filter force_escape|lower %}
This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}

Note

The escape and safe filters are not acceptable arguments. Instead, use the autoescape tag to manage autoescaping for blocks of template code.

firstof

Outputs the first argument variable that is not False. Outputs nothing if all the passed variables are False.

Sample usage:

{% firstof var1 var2 var3 %}

This is equivalent to:

{% if var1 %}
{{ var1 }}
{% elif var2 %}
{{ var2 }}
{% elif var3 %}
{{ var3 }}
{% endif %}

You can also use a literal string as a fallback value in case all passed variables are False:

{% firstof var1 var2 var3 "fallback value" %}

This tag auto-escapes variable values. You can disable auto-escaping with:

{% autoescape off %}
{% firstof var1 var2 var3 "<strong>fallback value</strong>" %}
{% endautoescape %}

Or if only some variables should be escaped, you can use:

{% firstof var1 var2|safe var3 "<strong>fallback value</strong>"|safe %}

You can use the syntax {% firstof var1 var2 var3 as value %} to store the output inside a variable.

New in Django 1.9:
The “as” syntax was added.

for

Loops over each item in an array, making the item available in a context variable. For example, to display a list of athletes provided in athlete_list:

<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>

You can loop over a list in reverse by using {% for obj in list reversed %}.

If you need to loop over a list of lists, you can unpack the values in each sublist into individual variables. For example, if your context contains a list of (x,y) coordinates called points, you could use the following to output the list of points:

{% for x, y in points %}
There is a point at {{ x }},{{ y }}
{% endfor %}

This can also be useful if you need to access the items in a dictionary. For example, if your context contained a dictionary data, the following would display the keys and values of the dictionary:

{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}

Keep in mind that for the dot operator, dictionary key lookup takes precedence over method lookup. Therefore if the data dictionary contains a key named 'items', data.items will return data['items'] instead of data.items(). Avoid adding keys that are named like dictionary methods if you want to use those methods in a template (items, values, keys, etc.). Read more about the lookup order of the dot operator in the documentation of template variables.

The for loop sets a number of variables available within the loop:

Variable

Description

forloop.counter

The current iteration of the loop (1-indexed)

forloop.counter0

The current iteration of the loop (0-indexed)

forloop.revcounter

The number of iterations from the end of the loop (1-indexed)

forloop.revcounter0

The number of iterations from the end of the loop (0-indexed)

forloop.first

True if this is the first time through the loop

forloop.last

True if this is the last time through the loop

forloop.parentloop

For nested loops, this is the loop surrounding the current one

for ... empty

The for tag can take an optional {% empty %} clause whose text is displayed if the given array is empty or could not be found:

<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>

The above is equivalent to – but shorter, cleaner, and possibly faster than – the following:

<ul>
{% if athlete_list %}
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
{% else %}
<li>Sorry, no athletes in this list.</li>
{% endif %}
</ul>

if

The {% if %} tag evaluates a variable, and if that variable is “true” (i.e. exists, is not empty, and is not a false boolean value) the contents of the block are output:

{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}

In the above, if athlete_list is not empty, the number of athletes will be displayed by the {{ athlete_list|length }} variable.

As you can see, the if tag may take one or several {% elif %} clauses, as well as an {% else %} clause that will be displayed if all previous conditions fail. These clauses are optional.

Boolean operators

if tags may use and, or or not to test a number of variables or to negate a given variable:

{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% endif %}

{% if not athlete_list %}
There are no athletes.
{% endif %}

{% if athlete_list or coach_list %}
There are some athletes or some coaches.
{% endif %}

{% if not athlete_list or coach_list %}
There are no athletes or there are some coaches.
{% endif %}

{% if athlete_list and not coach_list %}
There are some athletes and absolutely no coaches.
{% endif %}

Use of both and and or clauses within the same tag is allowed, with and having higher precedence than or e.g.:

{% if athlete_list and coach_list or cheerleader_list %}

will be interpreted like:

if (athlete_list and coach_list) or cheerleader_list

Use of actual parentheses in the if tag is invalid syntax. If you need them to indicate precedence, you should use nested if tags.

if tags may also use the operators ==, !=, <, >, <=, >= and in which work as follows:

== operator

Equality. Example:

{% if somevar == "x" %}
This appears if variable somevar equals the string "x"
{% endif %}

!= operator

Inequality. Example:

{% if somevar != "x" %}
This appears if variable somevar does not equal the string "x",
or if somevar is not found in the context
{% endif %}

< operator

Less than. Example:

{% if somevar < 100 %}
This appears if variable somevar is less than 100.
{% endif %}

> operator

Greater than. Example:

{% if somevar > 0 %}
This appears if variable somevar is greater than 0.
{% endif %}

<= operator

Less than or equal to. Example:

{% if somevar <= 100 %}
This appears if variable somevar is less than 100 or equal to 100.
{% endif %}

>= operator

Greater than or equal to. Example:

{% if somevar >= 1 %}
This appears if variable somevar is greater than 1 or equal to 1.
{% endif %}

in operator

Contained within. This operator is supported by many Python containers to test whether the given value is in the container. The following are some examples of how x in y will be interpreted:

{% if "bc" in "abcdef" %}
This appears since "bc" is a substring of "abcdef"
{% endif %}

{% if "hello" in greetings %}
If greetings is a list or set, one element of which is the string
"hello", this will appear.
{% endif %}

{% if user in users %}
If users is a QuerySet, this will appear if user is an
instance that belongs to the QuerySet.
{% endif %}

not in operator

Not contained within. This is the negation of the in operator.

The comparison operators cannot be ‘chained’ like in Python or in mathematical notation. For example, instead of using:

{% if a > b > c %}  (WRONG)

you should use:

{% if a > b and b > c %}

Filters

You can also use filters in the if expression. For example:

{% if messages|length >= 100 %}
You have lots of messages today!
{% endif %}

Complex expressions

All of the above can be combined to form complex expressions. For such expressions, it can be important to know how the operators are grouped when the expression is evaluated - that is, the precedence rules. The precedence of the operators, from lowest to highest, is as follows:

- or

- and

- not

- in

- ==, !=, <, >, <=, >=

(This follows Python exactly). So, for example, the following complex if tag:

{% if a == b or c == d and e %}

...will be interpreted as:

(a == b) or ((c == d) and e)

If you need different precedence, you will need to use nested if tags. Sometimes that is better for clarity anyway, for the sake of those who do not know the precedence rules.

ifequal and ifnotequal

{% ifequal a b %} ... {% endifequal %} is an obsolete way to write {% if a == b %} ... {% endif %}. Likewise, {% ifnotequal a b %} ... {% endifnotequal %} is superseded by {% if a != b %} ... {% endif %}. The ifequal and ifnotequal tags will be deprecated in a future release.

ifchanged

Check if a value has changed from the last iteration of a loop.

The {% ifchanged %} block tag is used within a loop. It has two possible uses.

1. Checks its own rendered contents against its previous state and only displays the content if it has changed. For example, this displays a list of days, only displaying the month if it changes:

<h1>Archive for {{ year }}</h1>

{% for date in days %}
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}

2. If given one or more variables, check whether any variable has changed. For example, the following shows the date every time it changes, while showing the hour if either the hour or the date has changed:

{% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
{% ifchanged date.hour date.date %}
{{ date.hour }}
{% endifchanged %}
{% endfor %}

The ifchanged tag can also take an optional {% else %} clause that will be displayed if the value has not changed:

{% for match in matches %}
<div style="background-color:
{% ifchanged match.ballot_id %}
{% cycle "red" "blue" %}
{% else %}
gray
{% endifchanged %}
">{{ match }}</div>
{% endfor %}

include

Loads a template and renders it with the current context. This is a way of “including” other templates within a template.

The template name can either be a variable or a hard-coded (quoted) string, in either single or double quotes.

This example includes the contents of the template "foo/bar.html":

{% include "foo/bar.html" %}

This example includes the contents of the template whose name is contained in the variable template_name:

{% include template_name %}

The variable may also be any object with a render() method that accepts a context. This allows you to reference a compiled Template in your context.

An included template is rendered within the context of the template that includes it. This example produces the output "Hello, John!":

- Context: variable person is set to "John" and variable greeting is set to "Hello".

- Template:

{% include "name_snippet.html" %}

- The name_snippet.html template:

{{ greeting }}, {{ person|default:"friend" }}!

You can pass additional context to the template using keyword arguments:

{% include "name_snippet.html" with person="Jane" greeting="Hello" %}

If you want to render the context only with the variables provided (or even no variables at all), use the only option. No other variables are available to the included template:

{% include "name_snippet.html" with greeting="Hi" only %}

If the included template causes an exception while it’s rendered (including if it’s missing or has syntax errors), the behavior varies depending on the template engine's debug option (if not set, this option defaults to the value of DEBUG). When debug mode is turned on, an exception like TemplateDoesNotExist or TemplateSyntaxError will be raised. When debug mode is turned off, {% include %} logs a warning to the django.template logger with the exception that happens while rendering the included template and returns an empty string.

Changed in Django 1.9:
Template logging now includes the warning logging mentioned above.

Note

The include tag should be considered as an implementation of “render this subtemplate and include the HTML”, not as “parse this subtemplate and include its contents as if it were part of the parent”. This means that there is no shared state between included templates – each include is a completely independent rendering process.

Blocks are evaluated before they are included. This means that a template that includes blocks from another will contain blocks that have already been evaluated and rendered - not blocks that can be overridden by, for example, an extending template.

load

Loads a custom template tag set.

For example, the following template would load all the tags and filters registered in somelibrary and otherlibrary located in package package:

{% load somelibrary package.otherlibrary %}

You can also selectively load individual filters or tags from a library, using the from argument. In this example, the template tags/filters named foo and bar will be loaded from somelibrary:

{% load foo bar from somelibrary %}

See Custom tag and filter libraries for more information.

lorem

New in Django 1.8:
The tag was previously located in django.contrib.webdesign.

Displays random “lorem ipsum” Latin text. This is useful for providing sample data in templates.

Usage:

{% lorem [count] [method] [random] %}

The {% lorem %} tag can be used with zero, one, two or three arguments. The arguments are:

Argument

Description

count

A number (or variable) containing the number of paragraphs or words to generate (default is 1).

method

Either w for words, p for HTML paragraphs or b for plain-text paragraph blocks (default is b).

random

The word random, which if given, does not use the common paragraph (“Lorem ipsum dolor sit amet...”) when generating text.

Examples:

- {% lorem %} will output the common “lorem ipsum” paragraph.

- {% lorem 3 p %} will output the common “lorem ipsum” paragraph and two random paragraphs each wrapped in HTML <p> tags.

- {% lorem 2 w random %} will output two random Latin words.

now

Displays the current date and/or time, using a format according to the given string. Such string can contain format specifiers characters as described in the date filter section.

Example:

It is {% now "jS F Y H:i" %}

Note that you can backslash-escape a format string if you want to use the “raw” value. In this example, both “o” and “f” are backslash-escaped, because otherwise each is a format string that displays the year and the time, respectively:

It is the {% now "jS \o\f F" %}

This would display as “It is the 4th of September”.

Note

The format passed can also be one of the predefined ones DATE_FORMAT, DATETIME_FORMAT, SHORT_DATE_FORMAT or SHORT_DATETIME_FORMAT. The predefined formats may vary depending on the current locale and if Format localization is enabled, e.g.:

It is {% now "SHORT_DATETIME_FORMAT" %}

You can also use the syntax {% now "Y" as current_year %} to store the output (as a string) inside a variable. This is useful if you want to use {% now %} inside a template tag like blocktrans for example:

{% now "Y" as current_year %}
{% blocktrans %}Copyright {{ current_year }}{% endblocktrans %}

New in Django 1.8.

The ability to use the “as” syntax was added.

regroup

Regroups a list of alike objects by a common attribute.

This complex tag is best illustrated by way of an example: say that “places” is a list of cities represented by dictionaries containing "name", "population", and "country" keys:

cities = [
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]

...and you’d like to display a hierarchical list that is ordered by country, like this:

- India

- Mumbai: 19,000,000

- Calcutta: 15,000,000

- USA

- New York: 20,000,000

- Chicago: 7,000,000

- Japan

- Tokyo: 33,000,000

You can use the {% regroup %} tag to group the list of cities by country. The following snippet of template code would accomplish this:

{% regroup cities by country as country_list %}

<ul>
{% for country in country_list %}
<li>{{ country.grouper }}
<ul>
{% for item in country.list %}
<li>{{ item.name }}: {{ item.population }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>

Let’s walk through this example. {% regroup %} takes three arguments: the list you want to regroup, the attribute to group by, and the name of the resulting list. Here, we’re regrouping the cities list by the country attribute and calling the result country_list.

{% regroup %} produces a list (in this case, country_list) of group objects. Each group object has two attributes:

- grouper – the item that was grouped by (e.g., the string “India” or “Japan”).

- list – a list of all items in this group (e.g., a list of all cities with country=’India’).

Note that {% regroup %} does not order its input! Our example relies on the fact that the cities list was ordered by country in the first place. If the cities list did not order its members by country, the regrouping would naively display more than one group for a single country. For example, say the cities list was set to this (note that the countries are not grouped together):

cities = [
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]

With this input for cities, the example {% regroup %} template code above would result in the following output:

- India

- Mumbai: 19,000,000

- USA

- New York: 20,000,000

- India

- Calcutta: 15,000,000

- USA

- Chicago: 7,000,000

- Japan

- Tokyo: 33,000,000

The easiest solution to this gotcha is to make sure in your view code that the data is ordered according to how you want to display it.

Another solution is to sort the data in the template using the dictsort filter, if your data is in a list of dictionaries:

{% regroup cities|dictsort:"country" by country as country_list %}

Grouping on other properties

Any valid template lookup is a legal grouping attribute for the regroup tag, including methods, attributes, dictionary keys and list items. For example, if the “country” field is a foreign key to a class with an attribute “description,” you could use:

{% regroup cities by country.description as country_list %}

Or, if country is a field with choices, it will have a get_FOO_display() method available as an attribute, allowing you to group on the display string rather than the choices key:

{% regroup cities by get_country_display as country_list %}

{{ country.grouper }} will now display the value fields from the choices set rather than the keys.

spaceless

Removes whitespace between HTML tags. This includes tab characters and newlines.

Example usage:

{% spaceless %}
<p>
<a href="foo/">Foo</a>
</p>
{% endspaceless %}

This example would return this HTML:

<p><a href="foo/">Foo</a></p>

Only space between tags is removed – not space between tags and text. In this example, the space around Hello won’t be stripped:

{% spaceless %}
<strong>
Hello
</strong>
{% endspaceless %}

ssi

Deprecated since version 1.8: This tag has been deprecated and will be removed in Django 1.10. Use the include tag instead.

Outputs the contents of a given file into the page.

Like a simple include tag, {% ssi %} includes the contents of another file – which must be specified using an absolute path – in the current page:

{% ssi '/home/html/ljworld.com/includes/right_generic.html' %}

The first parameter of ssi can be a quoted literal or any other context variable.

If the optional parsed parameter is given, the contents of the included file are evaluated as template code, within the current context:

{% ssi '/home/html/ljworld.com/includes/right_generic.html' parsed %}

Note that if you use {% ssi %}, you’ll need to define 'allowed_include_roots' in the OPTIONS of your template engine, as a security measure.

Note

With the ssi tag and the parsed parameter there is no shared state between files – each include is a completely independent rendering process. This means it’s not possible for example to define blocks or alter the context in the current page using the included file.

See also: {% include %}.

templatetag

Outputs one of the syntax characters used to compose template tags.

Since the template system has no concept of “escaping”, to display one of the bits used in template tags, you must use the {% templatetag %} tag.

The argument tells which template bit to output:

Argument

Outputs

openblock

{%

closeblock

%}

openvariable

{{

closevariable

}}

openbrace

{

closebrace

}

opencomment

{#

closecomment

#}

Sample usage:

{% templatetag openblock %} url 'entry_list' {% templatetag closeblock %}

url

Returns an absolute path reference (a URL without the domain name) matching a given view and optional parameters. Any special characters in the resulting path will be encoded using iri_to_uri().

This is a way to output links without violating the DRY principle by having to hard-code URLs in your templates:

{% url 'some-url-name' v1 v2 %}

The first argument is a url() name. It can be a quoted literal or any other context variable. Additional arguments are optional and should be space-separated values that will be used as arguments in the URL. The example above shows passing positional arguments. Alternatively you may use keyword syntax:

{% url 'some-url-name' arg1=v1 arg2=v2 %}

Do not mix both positional and keyword syntax in a single call. All arguments required by the URLconf should be present.

For example, suppose you have a view, app_views.client, whose URLconf takes a client ID (here, client() is a method inside the views file app_views.py). The URLconf line might look like this:

('^client/([0-9]+)/$', app_views.client, name='app-views-client')

If this app’s URLconf is included into the project’s URLconf under a path such as this:

('^clients/', include('project_name.app_name.urls'))

...then, in a template, you can create a link to this view like this:

{% url 'app-views-client' client.id %}

The template tag will output the string /clients/client/123/.

Note that if the URL you’re reversing doesn’t exist, you’ll get an NoReverseMatch exception raised, which will cause your site to display an error page.

If you’d like to retrieve a URL without displaying it, you can use a slightly different call:

{% url 'some-url-name' arg arg2 as the_url %}

<a href="{{ the_url }}">I'm linking to {{ the_url }}</a>

The scope of the variable created by the as var syntax is the {% block %} in which the {% url %} tag appears.

This {% url ... as var %} syntax will not cause an error if the view is missing. In practice you’ll use this to link to views that are optional:

{% url 'some-url-name' as the_url %}
{% if the_url %}
<a href="{{ the_url }}">Link to optional stuff</a>
{% endif %}

If you’d like to retrieve a namespaced URL, specify the fully qualified name:

{% url 'myapp:view-name' %}

This will follow the normal namespaced URL resolution strategy, including using any hints provided by the context as to the current application.

Deprecated since version 1.8: You can also pass a dotted Python path to a view function, but this syntax is deprecated and will be removed in Django 1.10:

{% url 'path.to.some_view' v1 v2 %}

Warning

Don’t forget to put quotes around the url() name, otherwise the value will be interpreted as a context variable!

verbatim

Stops the template engine from rendering the contents of this block tag.

A common use is to allow a JavaScript template layer that collides with Django’s syntax. For example:

{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}

You can also designate a specific closing tag, allowing the use of {% endverbatim %} as part of the unrendered contents:

{% verbatim myblock %}
Avoid template rendering via the {% verbatim %}{% endverbatim %} block.
{% endverbatim myblock %}

widthratio

For creating bar charts and such, this tag calculates the ratio of a given value to a maximum value, and then applies that ratio to a constant.

For example:

<img src="bar.png" alt="Bar"
height="10" width="{% widthratio this_value max_value max_width %}" />

If this_value is 175, max_value is 200, and max_width is 100, the image in the above example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5 which is rounded up to 88).

In some cases you might want to capture the result of widthratio in a variable. It can be useful, for instance, in a blocktrans like this:

{% widthratio this_value max_value max_width as width %}
{% blocktrans %}The width is: {{ width }}{% endblocktrans %}

with

Caches a complex variable under a simpler name. This is useful when accessing an “expensive” method (e.g., one that hits the database) multiple times.

For example:

{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}

The populated variable (in the example above, total) is only available between the {% with %} and {% endwith %} tags.

You can assign more than one context variable:

{% with alpha=1 beta=2 %}
...
{% endwith %}

Note

The previous more verbose format is still supported: {% with business.employees.count as total %}

Built-in filter reference

add

Adds the argument to the value.

For example:

{{ value|add:"2" }}

If value is 4, then the output will be 6.

This filter will first try to coerce both values to integers. If this fails, it’ll attempt to add the values together anyway. This will work on some data types (strings, list, etc.) and fail on others. If it fails, the result will be an empty string.

For example, if we have:

{{ first|add:second }}

and first is [1, 2, 3] and second is [4, 5, 6], then the output will be [1, 2, 3, 4, 5, 6].

Warning

Strings that can be coerced to integers will be summed, not concatenated, as in the first example above.

addslashes

Adds slashes before quotes. Useful for escaping strings in CSV, for example.

For example:

{{ value|addslashes }}

If value is "I'm using Django", the output will be "I\'m using Django".

capfirst

Capitalizes the first character of the value. If the first character is not a letter, this filter has no effect.

For example:

{{ value|capfirst }}

If value is "django", the output will be "Django".

center

Centers the value in a field of a given width.

For example:

"{{ value|center:"15" }}"

If value is "Django", the output will be "     Django    ".

cut

Removes all values of arg from the given string.

For example:

{{ value|cut:" " }}

If value is "String with spaces", the output will be "Stringwithspaces".

date

Formats a date according to the given format.

Uses a similar format as PHP’s date() function (https://php.net/date) with some differences.

Note

These format characters are not used in Django outside of templates. They were designed to be compatible with PHP to ease transitioning for designers.

Available format strings:

Format character

Description

Example output

a

'a.m.' or 'p.m.' (Note that this is slightly different than PHP’s output, because this includes periods to match Associated Press style.)

'a.m.'

A

'AM' or 'PM'.

'AM'

b

Month, textual, 3 letters, lowercase.

'jan'

B

Not implemented.

c

ISO 8601 format. (Note: unlike others formatters, such as “Z”, “O” or “r”, the “c” formatter will not add timezone offset if value is a naive datetime (see datetime.tzinfo).

2008-01-02T10:30:00.000123+02:00, or 2008-01-02T10:30:00.000123 if the datetime is naive

d

Day of the month, 2 digits with leading zeros.

'01' to '31'

D

Day of the week, textual, 3 letters.

'Fri'

e

Timezone name. Could be in any format, or might return an empty string, depending on the datetime.

'', 'GMT', '-500', 'US/Eastern', etc.

E

Month, locale specific alternative representation usually used for long date representation.

'listopada' (for Polish locale, as opposed to 'Listopad')

f

Time, in 12-hour hours and minutes, with minutes left off if they’re zero. Proprietary extension.

'1', '1:30'

F

Month, textual, long.

'January'

g

Hour, 12-hour format without leading zeros.

'1' to '12'

G

Hour, 24-hour format without leading zeros.

'0' to '23'

h

Hour, 12-hour format.

'01' to '12'

H

Hour, 24-hour format.

'00' to '23'

i

Minutes.

'00' to '59'

I

Daylight Savings Time, whether it’s in effect or not.

'1' or '0'

j

Day of the month without leading zeros.

'1' to '31'

l

Day of the week, textual, long.

'Friday'

L

Boolean for whether it’s a leap year.

True or False

m

Month, 2 digits with leading zeros.

'01' to '12'

M

Month, textual, 3 letters.

'Jan'

n

Month without leading zeros.

'1' to '12'

N

Month abbreviation in Associated Press style. Proprietary extension.

'Jan.', 'Feb.', 'March', 'May'

o

ISO-8601 week-numbering year, corresponding to the ISO-8601 week number (W) which uses leap weeks. See Y for the more common year format.

'1999'

O

Difference to Greenwich time in hours.

'+0200'

P

Time, in 12-hour hours, minutes and ‘a.m.’/’p.m.’, with minutes left off if they’re zero and the special-case strings ‘midnight’ and ‘noon’ if appropriate. Proprietary extension.

'1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'

r

RFC 2822 formatted date.

'Thu, 21 Dec 2000 16:01:07 +0200'

s

Seconds, 2 digits with leading zeros.

'00' to '59'

S

English ordinal suffix for day of the month, 2 characters.

'st', 'nd', 'rd' or 'th'

t

Number of days in the given month.

28 to 31

T

Time zone of this machine.

'EST', 'MDT'

u

Microseconds.

000000 to 999999

U

Seconds since the Unix Epoch (January 1 1970 00:00:00 UTC).

w

Day of the week, digits without leading zeros.

'0' (Sunday) to '6' (Saturday)

W

ISO-8601 week number of year, with weeks starting on Monday.

1, 53

y

Year, 2 digits.

'99'

Y

Year, 4 digits.

'1999'

z

Day of the year.

0 to 365

Z

Time zone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.

-43200 to 43200

For example:

{{ value|date:"D d M Y" }}

If value is a datetime object (e.g., the result of datetime.datetime.now()), the output will be the string 'Wed 09 Jan 2008'.

The format passed can be one of the predefined ones DATE_FORMAT, DATETIME_FORMAT, SHORT_DATE_FORMAT or SHORT_DATETIME_FORMAT, or a custom format that uses the format specifiers shown in the table above. Note that predefined formats may vary depending on the current locale.

Assuming that USE_L10N is True and LANGUAGE_CODE is, for example, "es", then for:

{{ value|date:"SHORT_DATE_FORMAT" }}

the output would be the string "09/01/2008" (the "SHORT_DATE_FORMAT" format specifier for the es locale as shipped with Django is "d/m/Y").

When used without a format string:

{{ value|date }}

...the formatting string defined in the DATE_FORMAT setting will be used, without applying any localization.

You can combine date with the time filter to render a full representation of a datetime value. E.g.:

{{ value|date:"D d M Y" }} {{ value|time:"H:i" }}

default

If value evaluates to False, uses the given default. Otherwise, uses the value.

For example:

{{ value|default:"nothing" }}

If value is "" (the empty string), the output will be nothing.

default_if_none

If (and only if) value is None, uses the given default. Otherwise, uses the value.

Note that if an empty string is given, the default value will not be used. Use the default filter if you want to fallback for empty strings.

For example:

{{ value|default_if_none:"nothing" }}

If value is None, the output will be the string "nothing".

dictsort

Takes a list of dictionaries and returns that list sorted by the key given in the argument.

For example:

{{ value|dictsort:"name" }}

If value is:

[
{'name': 'zed', 'age': 19},
{'name': 'amy', 'age': 22},
{'name': 'joe', 'age': 31},
]

then the output would be:

[
{'name': 'amy', 'age': 22},
{'name': 'joe', 'age': 31},
{'name': 'zed', 'age': 19},
]

You can also do more complicated things like:

{% for book in books|dictsort:"author.age" %}
* {{ book.title }} ({{ book.author.name }})
{% endfor %}

If books is:

[
{'title': '1984', 'author': {'name': 'George', 'age': 45}},
{'title': 'Timequake', 'author': {'name': 'Kurt', 'age': 75}},
{'title': 'Alice', 'author': {'name': 'Lewis', 'age': 33}},
]

then the output would be:

* Alice (Lewis)
* 1984 (George)
* Timequake (Kurt)

dictsortreversed

Takes a list of dictionaries and returns that list sorted in reverse order by the key given in the argument. This works exactly the same as the above filter, but the returned value will be in reverse order.

divisibleby

Returns True if the value is divisible by the argument.

For example:

{{ value|divisibleby:"3" }}

If value is 21, the output would be True.

escape

Escapes a string’s HTML. Specifically, it makes these replacements:

- < is converted to &lt;

- > is converted to &gt;

- ' (single quote) is converted to &#39;

- " (double quote) is converted to &quot;

- & is converted to &amp;

The escaping is only applied when the string is output, so it does not matter where in a chained sequence of filters you put escape: it will always be applied as though it were the last filter. If you want escaping to be applied immediately, use the force_escape filter.

Applying escape to a variable that would normally have auto-escaping applied to the result will only result in one round of escaping being done. So it is safe to use this function even in auto-escaping environments. If you want multiple escaping passes to be applied, use the force_escape filter.

For example, you can apply escape to fields when autoescape is off:

{% autoescape off %}
{{ title|escape }}
{% endautoescape %}

escapejs

Escapes characters for use in JavaScript strings. This does not make the string safe for use in HTML, but does protect you from syntax errors when using templates to generate JavaScript/JSON.

For example:

{{ value|escapejs }}

If value is "testing\r\njavascript \'string" <b>escaping</b>", the output will be "testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E".

filesizeformat

Formats the value like a ‘human-readable’ file size (i.e. '13 KB', '4.1 MB', '102 bytes', etc.).

For example:

{{ value|filesizeformat }}

If value is 123456789, the output would be 117.7 MB.

File sizes and SI units

Strictly speaking, filesizeformat does not conform to the International System of Units which recommends using KiB, MiB, GiB, etc. when byte sizes are calculated in powers of 1024 (which is the case here). Instead, Django uses traditional unit names (KB, MB, GB, etc.) corresponding to names that are more commonly used.

first

Returns the first item in a list.

For example:

{{ value|first }}

If value is the list ['a', 'b', 'c'], the output will be 'a'.

floatformat

When used without an argument, rounds a floating-point number to one decimal place – but only if there’s a decimal part to be displayed. For example:

value

Template

Output

34.23234

{{ value|floatformat }}

34.2

34.00000

{{ value|floatformat }}

34

34.26000

{{ value|floatformat }}

34.3

If used with a numeric integer argument, floatformat rounds a number to that many decimal places. For example:

value

Template

Output

34.23234

{{ value|floatformat:3 }}

34.232

34.00000

{{ value|floatformat:3 }}

34.000

34.26000

{{ value|floatformat:3 }}

34.260

Particularly useful is passing 0 (zero) as the argument which will round the float to the nearest integer.

value

Template

Output

34.23234

{{ value|floatformat:"0" }}

34

34.00000

{{ value|floatformat:"0" }}

34

39.56000

{{ value|floatformat:"0" }}

40

If the argument passed to floatformat is negative, it will round a number to that many decimal places – but only if there’s a decimal part to be displayed. For example:

value

Template

Output

34.23234

{{ value|floatformat:"-3" }}

34.232

34.00000

{{ value|floatformat:"-3" }}

34

34.26000

{{ value|floatformat:"-3" }}

34.260

Using floatformat with no argument is equivalent to using floatformat with an argument of -1.

force_escape

Applies HTML escaping to a string (see the escape filter for details). This filter is applied immediately and returns a new, escaped string. This is useful in the rare cases where you need multiple escaping or want to apply other filters to the escaped results. Normally, you want to use the escape filter.

For example, if you want to catch the <p> HTML elements created by the linebreaks filter:

{% autoescape off %}
{{ body|linebreaks|force_escape }}
{% endautoescape %}

get_digit

Given a whole number, returns the requested digit, where 1 is the right-most digit, 2 is the second-right-most digit, etc. Returns the original value for invalid input (if input or argument is not an integer, or if argument is less than 1). Otherwise, output is always an integer.

For example:

{{ value|get_digit:"2" }}

If value is 123456789, the output will be 8.

iriencode

Converts an IRI (Internationalized Resource Identifier) to a string that is suitable for including in a URL. This is necessary if you’re trying to use strings containing non-ASCII characters in a URL.

It’s safe to use this filter on a string that has already gone through the urlencode filter.

For example:

{{ value|iriencode }}

If value is "?test=1&me=2", the output will be "?test=1&amp;me=2".

join

Joins a list with a string, like Python’s str.join(list)

For example:

{{ value|join:" // " }}

If value is the list ['a', 'b', 'c'], the output will be the string "a // b // c".

last

Returns the last item in a list.

For example:

{{ value|last }}

If value is the list ['a', 'b', 'c', 'd'], the output will be the string "d".

length

Returns the length of the value. This works for both strings and lists.

For example:

{{ value|length }}

If value is ['a', 'b', 'c', 'd'] or "abcd", the output will be 4.

Changed in Django 1.8:
The filter returns 0 for an undefined variable. Previously, it returned an empty string.

length_is

Returns True if the value’s length is the argument, or False otherwise.

For example:

{{ value|length_is:"4" }}

If value is ['a', 'b', 'c', 'd'] or "abcd", the output will be True.

linebreaks

Replaces line breaks in plain text with appropriate HTML; a single newline becomes an HTML line break (<br />) and a new line followed by a blank line becomes a paragraph break (</p>).

For example:

{{ value|linebreaks }}

If value is Joel\nis a slug, the output will be <p>Joel<br />is a slug</p>.

linebreaksbr

Converts all newlines in a piece of plain text to HTML line breaks (<br />).

For example:

{{ value|linebreaksbr }}

If value is Joel\nis a slug, the output will be Joel<br />is a slug.

linenumbers

Displays text with line numbers.

For example:

{{ value|linenumbers }}

If value is:

one
two
three

the output will be:

1. one
2. two
3. three

ljust

Left-aligns the value in a field of a given width.

Argument: field size

For example:

"{{ value|ljust:"10" }}"

If value is Django, the output will be "Django    ".

lower

Converts a string into all lowercase.

For example:

{{ value|lower }}

If value is Totally LOVING this Album!, the output will be totally loving this album!.

make_list

Returns the value turned into a list. For a string, it’s a list of characters. For an integer, the argument is cast into an unicode string before creating a list.

For example:

{{ value|make_list }}

If value is the string "Joel", the output would be the list ['J', 'o', 'e', 'l']. If value is 123, the output will be the list ['1', '2', '3'].

phone2numeric

Converts a phone number (possibly containing letters) to its numerical equivalent.

The input doesn’t have to be a valid phone number. This will happily convert any string.

For example:

{{ value|phone2numeric }}

If value is 800-COLLECT, the output will be 800-2655328.

pluralize

Returns a plural suffix if the value is not 1. By default, this suffix is 's'.

Example:

You have {{ num_messages }} message{{ num_messages|pluralize }}.

If num_messages is 1, the output will be You have 1 message. If num_messages is 2 the output will be You have 2 messages.

For words that require a suffix other than 's', you can provide an alternate suffix as a parameter to the filter.

Example:

You have {{ num_walruses }} walrus{{ num_walruses|pluralize:"es" }}.

For words that don’t pluralize by simple suffix, you can specify both a singular and plural suffix, separated by a comma.

Example:

You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}.

Note

Use blocktrans to pluralize translated strings.

pprint

A wrapper around pprint.pprint() – for debugging, really.

random

Returns a random item from the given list.

For example:

{{ value|random }}

If value is the list ['a', 'b', 'c', 'd'], the output could be "b".

removetags

Deprecated since version 1.8: removetags cannot guarantee HTML safe output and has been deprecated due to security concerns. Consider using bleach instead.

Removes a space-separated list of [X]HTML tags from the output.

For example:

{{ value|removetags:"b span" }}

If value is "<b>Joel</b> <button>is</button> a <span>slug</span>" the unescaped output will be "Joel <button>is</button> a slug".

Note that this filter is case-sensitive.

If value is "<B>Joel</B> <button>is</button> a <span>slug</span>" the unescaped output will be "<B>Joel</B> <button>is</button> a slug".

No safety guarantee

Note that removetags doesn’t give any guarantee about its output being HTML safe. In particular, it doesn’t work recursively, so an input like "<sc<script>ript>alert('XSS')</sc</script>ript>" won’t be safe even if you apply |removetags:"script". So if the input is user provided, NEVER apply the safe filter to a removetags output. If you are looking for something more robust, you can use the bleach Python library, notably its clean method.

rjust

Right-aligns the value in a field of a given width.

Argument: field size

For example:

"{{ value|rjust:"10" }}"

If value is Django, the output will be "    Django".

safe

Marks a string as not requiring further HTML escaping prior to output. When autoescaping is off, this filter has no effect.

Note

If you are chaining filters, a filter applied after safe can make the contents unsafe again. For example, the following code prints the variable as is, unescaped:

{{ var|safe|escape }}

safeseq

Applies the safe filter to each element of a sequence. Useful in conjunction with other filters that operate on sequences, such as join. For example:

{{ some_list|safeseq|join:", " }}

You couldn’t use the safe filter directly in this case, as it would first convert the variable into a string, rather than working with the individual elements of the sequence.

slice

Returns a slice of the list.

Uses the same syntax as Python’s list slicing. See http://www.diveintopython3.net/native-datatypes.html#slicinglists for an introduction.

Example:

{{ some_list|slice:":2" }}

If some_list is ['a', 'b', 'c'], the output will be ['a', 'b'].

slugify

Converts to ASCII. Converts spaces to hyphens. Removes characters that aren’t alphanumerics, underscores, or hyphens. Converts to lowercase. Also strips leading and trailing whitespace.

For example:

{{ value|slugify }}

If value is "Joel is a slug", the output will be "joel-is-a-slug".

stringformat

Formats the variable according to the argument, a string formatting specifier. This specifier uses the printf-style String Formatting syntax, with the exception that the leading “%” is dropped.

For example:

{{ value|stringformat:"E" }}

If value is 10, the output will be 1.000000E+01.

striptags

Makes all possible efforts to strip all [X]HTML tags.

For example:

{{ value|striptags }}

If value is "<b>Joel</b> <button>is</button> a <span>slug</span>", the output will be "Joel is a slug".

No safety guarantee

Note that striptags doesn’t give any guarantee about its output being HTML safe, particularly with non valid HTML input. So NEVER apply the safe filter to a striptags output. If you are looking for something more robust, you can use the bleach Python library, notably its clean method.

time

Formats a time according to the given format.

Given format can be the predefined one TIME_FORMAT, or a custom format, same as the date filter. Note that the predefined format is locale-dependent.

For example:

{{ value|time:"H:i" }}

If value is equivalent to datetime.datetime.now(), the output will be the string "01:23".

Another example:

Assuming that USE_L10N is True and LANGUAGE_CODE is, for example, "de", then for:

{{ value|time:"TIME_FORMAT" }}

the output will be the string "01:23:00" (The "TIME_FORMAT" format specifier for the de locale as shipped with Django is "H:i:s").

The time filter will only accept parameters in the format string that relate to the time of day, not the date (for obvious reasons). If you need to format a date value, use the date filter instead (or along time if you need to render a full datetime value).

There is one exception the above rule: When passed a datetime value with attached timezone information (a time-zone-aware datetime instance) the time filter will accept the timezone-related format specifiers 'e', 'O' , 'T' and 'Z'.

When used without a format string:

{{ value|time }}

...the formatting string defined in the TIME_FORMAT setting will be used, without applying any localization.

timesince

Formats a date as the time since that date (e.g., “4 days, 6 hours”).

Takes an optional argument that is a variable containing the date to use as the comparison point (without the argument, the comparison point is now). For example, if blog_date is a date instance representing midnight on 1 June 2006, and comment_date is a date instance for 08:00 on 1 June 2006, then the following would return “8 hours”:

{{ blog_date|timesince:comment_date }}

Comparing offset-naive and offset-aware datetimes will return an empty string.

Minutes is the smallest unit used, and “0 minutes” will be returned for any date that is in the future relative to the comparison point.

timeuntil

Similar to timesince, except that it measures the time from now until the given date or datetime. For example, if today is 1 June 2006 and conference_date is a date instance holding 29 June 2006, then {{ conference_date|timeuntil }} will return “4 weeks”.

Takes an optional argument that is a variable containing the date to use as the comparison point (instead of now). If from_date contains 22 June 2006, then the following will return “1 week”:

{{ conference_date|timeuntil:from_date }}

Comparing offset-naive and offset-aware datetimes will return an empty string.

Minutes is the smallest unit used, and “0 minutes” will be returned for any date that is in the past relative to the comparison point.

title

Converts a string into titlecase by making words start with an uppercase character and the remaining characters lowercase. This tag makes no effort to keep “trivial words” in lowercase.

For example:

{{ value|title }}

If value is "my FIRST post", the output will be "My First Post".

truncatechars

Truncates a string if it is longer than the specified number of characters. Truncated strings will end with a translatable ellipsis sequence (”...”).

Argument: Number of characters to truncate to

For example:

{{ value|truncatechars:9 }}

If value is "Joel is a slug", the output will be "Joel i...".

truncatechars_html

Similar to truncatechars, except that it is aware of HTML tags. Any tags that are opened in the string and not closed before the truncation point are closed immediately after the truncation.

For example:

{{ value|truncatechars_html:9 }}

If value is "<p>Joel is a slug</p>", the output will be "<p>Joel i...</p>".

Newlines in the HTML content will be preserved.

truncatewords

Truncates a string after a certain number of words.

Argument: Number of words to truncate after

For example:

{{ value|truncatewords:2 }}

If value is "Joel is a slug", the output will be "Joel is ...".

Newlines within the string will be removed.

truncatewords_html

Similar to truncatewords, except that it is aware of HTML tags. Any tags that are opened in the string and not closed before the truncation point, are closed immediately after the truncation.

This is less efficient than truncatewords, so should only be used when it is being passed HTML text.

For example:

{{ value|truncatewords_html:2 }}

If value is "<p>Joel is a slug</p>", the output will be "<p>Joel is ...</p>".

Newlines in the HTML content will be preserved.

unordered_list

Recursively takes a self-nested list and returns an HTML unordered list – WITHOUT opening and closing <ul> tags.

The list is assumed to be in the proper format. For example, if var contains ['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']], then {{ var|unordered_list }} would return:

<li>States
<ul>
<li>Kansas
<ul>
<li>Lawrence</li>
<li>Topeka</li>
</ul>
</li>
<li>Illinois</li>
</ul>
</li>

Deprecated since version 1.8: An older, more restrictive and verbose input format is also supported: ['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]. Support for this syntax will be removed in Django 1.10.

upper

Converts a string into all uppercase.

For example:

{{ value|upper }}

If value is "Joel is a slug", the output will be "JOEL IS A SLUG".

urlencode

Escapes a value for use in a URL.

For example:

{{ value|urlencode }}

If value is "https://www.example.org/foo?a=b&c=d", the output will be "https%3A//www.example.org/foo%3Fa%3Db%26c%3Dd".

An optional argument containing the characters which should not be escaped can be provided.

If not provided, the ‘/’ character is assumed safe. An empty string can be provided when all characters should be escaped. For example:

{{ value|urlencode:"" }}

If value is "https://www.example.org/", the output will be "https%3A%2F%2Fwww.example.org%2F".

urlize

Converts URLs and email addresses in text into clickable links.

This template tag works on links prefixed with http://, https://, or www.. For example, https://goo.gl/aia1t will get converted but goo.gl/aia1t won’t.

It also supports domain-only links ending in one of the original top level domains (.com, .edu, .gov, .int, .mil, .net, and .org). For example, djangoproject.com gets converted.

Changed in Django 1.8:
Support for domain-only links that include characters after the top-level domain (e.g. djangoproject.com/ and djangoproject.com/download/) was added.

Links can have trailing punctuation (periods, commas, close-parens) and leading punctuation (opening parens), and urlize will still do the right thing.

Links generated by urlize have a rel="nofollow" attribute added to them.

For example:

{{ value|urlize }}

If value is "Check out www.djangoproject.com", the output will be "Check out <a href="http://www.djangoproject.com" rel="nofollow">www.djangoproject.com</a>".

In addition to web links, urlize also converts email addresses into mailto: links. If value is "Send questions to foo@example.com", the output will be "Send questions to <a href="mailto:foo@example.com">foo@example.com</a>".

The urlize filter also takes an optional parameter autoescape. If autoescape is True, the link text and URLs will be escaped using Django’s built-in escape filter. The default value for autoescape is True.

Note

If urlize is applied to text that already contains HTML markup, things won’t work as expected. Apply this filter only to plain text.

urlizetrunc

Converts URLs and email addresses into clickable links just like urlize, but truncates URLs longer than the given character limit.

Argument: Number of characters that link text should be truncated to, including the ellipsis that’s added if truncation is necessary.

For example:

{{ value|urlizetrunc:15 }}

If value is "Check out www.djangoproject.com", the output would be 'Check out <a href="http://www.djangoproject.com" rel="nofollow">www.djangopr...</a>'.

As with urlize, this filter should only be applied to plain text.

wordcount

Returns the number of words.

For example:

{{ value|wordcount }}

If value is "Joel is a slug", the output will be 4.

wordwrap

Wraps words at specified line length.

Argument: number of characters at which to wrap the text

For example:

{{ value|wordwrap:5 }}

If value is Joel is a slug, the output would be:

Joel
is a
slug

yesno

Maps values for True, False, and (optionally) None, to the strings “yes”, “no”, “maybe”, or a custom mapping passed as a comma-separated list, and returns one of those strings according to the value:

For example:

{{ value|yesno:"yeah,no,maybe" }}

Value

Argument

Outputs

True

yes

True

"yeah,no,maybe"

yeah

False

"yeah,no,maybe"

no

None

"yeah,no,maybe"

maybe

None

"yeah,no"

no (converts None to False if no mapping for None is given)

Internationalization tags and filters

Django provides template tags and filters to control each aspect of internationalization in templates. They allow for granular control of translations, formatting, and time zone conversions.

i18n

This library allows specifying translatable text in templates. To enable it, set USE_I18N to True, then load it with {% load i18n %}.

See Internationalization: in template code.

l10n

This library provides control over the localization of values in templates. You only need to load the library using {% load l10n %}, but you’ll often set USE_L10N to True so that localization is active by default.

See Controlling localization in templates.

tz

This library provides control over time zone conversions in templates. Like l10n, you only need to load the library using {% load tz %}, but you’ll usually also set USE_TZ to True so that conversion to local time happens by default.

See Time zone aware output in templates.

Other tags and filters libraries

Django comes with a couple of other template-tag libraries that you have to enable explicitly in your INSTALLED_APPS setting and enable in your template with the {% load %} tag.

django.contrib.humanize

A set of Django template filters useful for adding a “human touch” to data. See django.contrib.humanize.

static

static

To link to static files that are saved in STATIC_ROOT Django ships with a static template tag. You can use this regardless if you’re using RequestContext or not. For example:

{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

It is also able to consume standard context variables, e.g. assuming a user_stylesheet variable is passed to the template:

{% load static %}
<link rel="stylesheet" href="{% static user_stylesheet %}" type="text/css" media="screen" />

If you’d like to retrieve a static URL without displaying it, you can use a slightly different call:

{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

Note

The staticfiles contrib app also ships with a static template tag which uses staticfiles' STATICFILES_STORAGE to build the URL of the given path (rather than simply using urllib.parse.urljoin() with the STATIC_URL setting and the given path). Use that instead if you have an advanced use case such as using a cloud service to serve static files:

{% load static from staticfiles %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

get_static_prefix

You should prefer the static template tag, but if you need more control over exactly where and how STATIC_URL is injected into the template, you can use the get_static_prefix template tag:

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

There’s also a second form you can use to avoid extra processing if you need the value multiple times:

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

get_media_prefix

Similar to the get_static_prefix, get_media_prefix populates a template variable with the media prefix MEDIA_URL, e.g.:

{% load static %}
<body data-media-url="{% get_media_prefix %}">

By storing the value in a data attribute, we ensure it’s escaped appropriately if we want to use it in a JavaScript context.

The Django template language: for Python programmers

This document explains the Django template system from a technical perspective – how it works and how to extend it. If you’re just looking for reference on the language syntax, see The Django template language.

It assumes an understanding of templates, contexts, variables, tags, and rendering. Start with the introduction to the Django template language if you aren’t familiar with these concepts.

Overview

Using the template system in Python is a three-step process:

1. You configure an Engine.

2. You compile template code into a Template.

3. You render the template with a Context.

Django projects generally rely on the high level, backend agnostic APIs for each of these steps instead of the template system’s lower level APIs:

1. For each DjangoTemplates backend in the TEMPLATES setting, Django instantiates an Engine. DjangoTemplates wraps Engine and adapts it to the common template backend API.

2. The django.template.loader module provides functions such as get_template() for loading templates. They return a django.template.backends.django.Template which wraps the actual django.template.Template.

3. The Template obtained in the previous step has a render() method which marshals a context and possibly a request into a Context and delegates the rendering to the underlying Template.

Configuring an engine

If you are simply using the DjangoTemplates backend, this probably isn’t the documentation you’re looking for. An instance of the Engine class described below is accessible using the engine attribute of that backend and any attribute defaults mentioned below are overridden by what’s passed by DjangoTemplates.

class Engine(dirs=None, app_dirs=False, allowed_include_roots=None, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None)[source]

New in Django 1.8.

When instantiating an Engine all arguments must be passed as keyword arguments:

- dirs is a list of directories where the engine should look for template source files. It is used to configure filesystem.Loader.

It defaults to an empty list.

- app_dirs only affects the default value of loaders. See below.

It defaults to False.

- allowed_include_roots is a list of strings representing allowed prefixes for the {% ssi %} template tag. This is a security measure, so that template authors can’t access files that they shouldn’t be accessing.

For example, if 'allowed_include_roots' is ['/home/html', '/var/www'], then {% ssi /home/html/foo.txt %} would work, but {% ssi /etc/passwd %} wouldn’t.

It defaults to an empty list.

Deprecated since version 1.8: allowed_include_roots is deprecated.

- context_processors is a list of dotted Python paths to callables that are used to populate the context when a template is rendered with a request. These callables take a request object as their argument and return a dict of items to be merged into the context.

It defaults to an empty list.

See RequestContext for more information.

- debug is a boolean that turns on/off template debug mode. If it is True, the template engine will store additional debug information which can be used to display a detailed report for any exception raised during template rendering.

It defaults to False.

- loaders is a list of template loader classes, specified as strings. Each Loader class knows how to import templates from a particular source. Optionally, a tuple can be used instead of a string. The first item in the tuple should be the Loader class name, subsequent items are passed to the Loader during initialization.

It defaults to a list containing:

- 'django.template.loaders.filesystem.Loader'

- 'django.template.loaders.app_directories.Loader' if and only if app_dirs is True.

See Loader types for details.

- string_if_invalid is the output, as a string, that the template system should use for invalid (e.g. misspelled) variables.

It defaults to the empty string.

See How invalid variables are handled for details.

- file_charset is the charset used to read template files on disk.

It defaults to 'utf-8'.

- 'libraries': A dictionary of labels and dotted Python paths of template tag modules to register with the template engine. This is used to add new libraries or provide alternate labels for existing ones. For example:

Engine(
libraries={
'myapp_tags': 'path.to.myapp.tags',
'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
},
)

Libraries can be loaded by passing the corresponding dictionary key to the {% load %} tag.

- 'builtins': A list of dotted Python paths of template tag modules to add to built-ins. For example:

Engine(
builtins=['myapp.builtins'],
)

Tags and filters from built-in libraries can be used without first calling the {% load %} tag.

New in Django 1.9:
The libraries and builtins arguments were added.

static Engine.get_default()[source]

When a Django project configures one and only one DjangoTemplates engine, this method returns the underlying Engine. In other circumstances it will raise ImproperlyConfigured.

It’s required for preserving APIs that rely on a globally available, implicitly configured engine. Any other use is strongly discouraged.

Engine.from_string(template_code)[source]

Compiles the given template code and returns a Template object.

Engine.get_template(template_name)[source]

Loads a template with the given name, compiles it and returns a Template object.

Engine.select_template(self, template_name_list)[source]

Like get_template(), except it takes a list of names and returns the first template that was found.

Loading a template

The recommended way to create a Template is by calling the factory methods of the Engine: get_template(), select_template() and from_string().

In a Django project where the TEMPLATES setting defines exactly one DjangoTemplates engine, it’s possible to instantiate a Template directly.

class Template[source]

This class lives at django.template.Template. The constructor takes one argument — the raw template code:

from django.template import Template

template = Template("My name is {{ my_name }}.")

Behind the scenes

The system only parses your raw template code once – when you create the Template object. From then on, it’s stored internally as a tree structure for performance.

Even the parsing itself is quite fast. Most of the parsing happens via a single call to a single, short, regular expression.

Rendering a context

Once you have a compiled Template object, you can render a context with it. You can reuse the same template to render it several times with different contexts.

class Context(dict_=None, current_app=_current_app_undefined)[source]

This class lives at django.template.Context. The constructor takes two optional arguments:

- A dictionary mapping variable names to variable values.

- The name of the current application. This application name is used to help resolve namespaced URLs. If you’re not using namespaced URLs, you can ignore this argument.

Deprecated since version 1.8: The current_app argument is deprecated. If you need it, you must now use a RequestContext instead of a Context.

For details, see Playing with Context objects below.

Template.render(context)[source]

Call the Template object’s render() method with a Context to “fill” the template:

>>> from django.template import Context, Template
>>> template = Template("My name is {{ my_name }}.")

>>> context = Context({"my_name": "Adrian"})
>>> template.render(context)
"My name is Adrian."

>>> context = Context({"my_name": "Dolores"})
>>> template.render(context)
"My name is Dolores."

Variables and lookups

Variable names must consist of any letter (A-Z), any digit (0-9), an underscore (but they must not start with an underscore) or a dot.

Dots have a special meaning in template rendering. A dot in a variable name signifies a lookup. Specifically, when the template system encounters a dot in a variable name, it tries the following lookups, in this order:

- Dictionary lookup. Example: foo["bar"]

- Attribute lookup. Example: foo.bar

- List-index lookup. Example: foo[bar]

Note that “bar” in a template expression like {{ foo.bar }} will be interpreted as a literal string and not using the value of the variable “bar”, if one exists in the template context.

The template system uses the first lookup type that works. It’s short-circuit logic. Here are a few examples:

>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."

>>> class PersonClass: pass
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."

>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."

If any part of the variable is callable, the template system will try calling it. Example:

>>> class PersonClass2:
...     def name(self):
...         return "Samantha"
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."

Callable variables are slightly more complex than variables which only require straight lookups. Here are some things to keep in mind:

- If the variable raises an exception when called, the exception will be propagated, unless the exception has an attribute silent_variable_failure whose value is True. If the exception does have a silent_variable_failure attribute whose value is True, the variable will render as the value of the engine’s string_if_invalid configuration option (an empty string, by default). Example:

>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClass3:
...     def first_name(self):
...         raise AssertionError("foo")
>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
...
AssertionError: foo

>>> class SilentAssertionError(Exception):
...     silent_variable_failure = True
>>> class PersonClass4:
...     def first_name(self):
...         raise SilentAssertionError
>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
"My name is ."

Note that django.core.exceptions.ObjectDoesNotExist, which is the base class for all Django database API DoesNotExist exceptions, has silent_variable_failure = True. So if you’re using Django templates with Django model objects, any DoesNotExist exception will fail silently.

- A variable can only be called if it has no required arguments. Otherwise, the system will return the value of the engine’s string_if_invalid option.

- Obviously, there can be side effects when calling some variables, and it’d be either foolish or a security hole to allow the template system to access them.

A good example is the delete() method on each Django model object. The template system shouldn’t be allowed to do something like this:

I will now delete this valuable data. {{ data.delete }}

To prevent this, set an alters_data attribute on the callable variable. The template system won’t call a variable if it has alters_data=True set, and will instead replace the variable with string_if_invalid, unconditionally. The dynamically-generated delete() and save() methods on Django model objects get alters_data=True automatically. Example:

def sensitive_function(self):
self.database_record.delete()
sensitive_function.alters_data = True

- Occasionally you may want to turn off this feature for other reasons, and tell the template system to leave a variable uncalled no matter what. To do so, set a do_not_call_in_templates attribute on the callable with the value True. The template system then will act as if your variable is not callable (allowing you to access attributes of the callable, for example).

How invalid variables are handled

Generally, if a variable doesn’t exist, the template system inserts the value of the engine’s string_if_invalid configuration option, which is set to '' (the empty string) by default.

Filters that are applied to an invalid variable will only be applied if string_if_invalid is set to '' (the empty string). If string_if_invalid is set to any other value, variable filters will be ignored.

This behavior is slightly different for the if, for and regroup template tags. If an invalid variable is provided to one of these template tags, the variable will be interpreted as None. Filters are always applied to invalid variables within these template tags.

If string_if_invalid contains a '%s', the format marker will be replaced with the name of the invalid variable.

For debug purposes only!

While string_if_invalid can be a useful debugging tool, it is a bad idea to turn it on as a ‘development default’.

Many templates, including those in the Admin site, rely upon the silence of the template system when a non-existent variable is encountered. If you assign a value other than '' to string_if_invalid, you will experience rendering problems with these templates and sites.

Generally, string_if_invalid should only be enabled in order to debug a specific template problem, then cleared once debugging is complete.

Built-in variables

Every context contains True, False and None. As you would expect, these variables resolve to the corresponding Python objects.

Limitations with string literals

Django’s template language has no way to escape the characters used for its own syntax. For example, the templatetag tag is required if you need to output character sequences like {% and %}.

A similar issue exists if you want to include these sequences in template filter or tag arguments. For example, when parsing a block tag, Django’s template parser looks for the first occurrence of %} after a {%. This prevents the use of "%}" as a string literal. For example, a TemplateSyntaxError will be raised for the following expressions:

{% include "template.html" tvar="Some string literal with %} in it." %}

{% with tvar="Some string literal with %} in it." %}{% endwith %}

The same issue can be triggered by using a reserved sequence in filter arguments:

{{ some.variable|default:"}}" }}

If you need to use strings with these sequences, store them in template variables or use a custom template tag or filter to workaround the limitation.

Playing with Context objects

Most of the time, you’ll instantiate Context objects by passing in a fully-populated dictionary to Context(). But you can add and delete items from a Context object once it’s been instantiated, too, using standard dictionary syntax:

>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'

Context.get(key, otherwise=None)

Returns the value for key if key is in the context, else returns otherwise.

Context.setdefault(key, default=None)

New in Django 1.9.

If key is in the context, returns its value. Otherwise inserts key with a value of default and returns default.

Context.pop()

Context.push()

exception ContextPopException[source]

A Context object is a stack. That is, you can push() and pop() it. If you pop() too much, it’ll raise django.template.ContextPopException:

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.push()
{}
>>> c['foo'] = 'second level'
>>> c['foo']
'second level'
>>> c.pop()
{'foo': 'second level'}
>>> c['foo']
'first level'
>>> c['foo'] = 'overwritten'
>>> c['foo']
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
ContextPopException

You can also use push() as a context manager to ensure a matching pop() is called.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.push():
...     c['foo'] = 'second level'
...     c['foo']
'second level'
>>> c['foo']
'first level'

All arguments passed to push() will be passed to the dict constructor used to build the new context level.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.push(foo='second level'):
...     c['foo']
'second level'
>>> c['foo']
'first level'

Context.update(other_dict)[source]

In addition to push() and pop(), the Context object also defines an update() method. This works like push() but takes a dictionary as an argument and pushes that dictionary onto the stack instead of an empty one.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'foo': 'updated'})
{'foo': 'updated'}
>>> c['foo']
'updated'
>>> c.pop()
{'foo': 'updated'}
>>> c['foo']
'first level'

Like push(), you can use update() as a context manager to ensure a matching pop() is called.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.update({'foo': 'second level'}):
...     c['foo']
'second level'
>>> c['foo']
'first level'

New in Django 1.9:
The ability to use update() as a context manager was added.

Using a Context as a stack comes in handy in some custom template tags.

Context.flatten()

Using flatten() method you can get whole Context stack as one dictionary including builtin variables.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'bar': 'second level'})
{'bar': 'second level'}
>>> c.flatten()
{'True': True, 'None': None, 'foo': 'first level', 'False': False, 'bar': 'second level'}

A flatten() method is also internally used to make Context objects comparable.

>>> c1 = Context()
>>> c1['foo'] = 'first level'
>>> c1['bar'] = 'second level'
>>> c2 = Context()
>>> c2.update({'bar': 'second level', 'foo': 'first level'})
{'foo': 'first level', 'bar': 'second level'}
>>> c1 == c2
True

Result from flatten() can be useful in unit tests to compare Context against dict:

class ContextTest(unittest.TestCase):
def test_against_dictionary(self):
c1 = Context()
c1['update'] = 'value'
self.assertEqual(c1.flatten(), {
'True': True,
'None': None,
'False': False,
'update': 'value',
})

Subclassing Context: RequestContext

class RequestContext(request, dict_=None, processors=None)[source]

Django comes with a special Context class, django.template.RequestContext, that acts slightly differently from the normal django.template.Context. The first difference is that it takes an HttpRequest as its first argument. For example:

c = RequestContext(request, {
'foo': 'bar',
})

The second difference is that it automatically populates the context with a few variables, according to the engine’s context_processors configuration option.

The context_processors option is a list of callables – called context processors – that take a request object as their argument and return a dictionary of items to be merged into the context. In the default generated settings file, the default template engine contains the following context processors:

[
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
]

Changed in Django 1.8:
Built-in template context processors were moved from django.core.context_processors to django.template.context_processors in Django 1.8.

In addition to these, RequestContext always enables 'django.template.context_processors.csrf'. This is a security related context processor required by the admin and other contrib apps, and, in case of accidental misconfiguration, it is deliberately hardcoded in and cannot be turned off in the context_processors option.

Each processor is applied in order. That means, if one processor adds a variable to the context and a second processor adds a variable with the same name, the second will override the first. The default processors are explained below.

When context processors are applied

Context processors are applied on top of context data. This means that a context processor may overwrite variables you’ve supplied to your Context or RequestContext, so take care to avoid variable names that overlap with those supplied by your context processors.

If you want context data to take priority over context processors, use the following pattern:

from django.template import RequestContext

request_context = RequestContext(request)
request_context.push({"my_name": "Adrian"})

Django does this to allow context data to override context processors in APIs such as render() and TemplateResponse.

Also, you can give RequestContext a list of additional processors, using the optional, third positional argument, processors. In this example, the RequestContext instance gets a ip_address variable:

from django.http import HttpResponse
from django.template import RequestContext

def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']}

def some_view(request):
# ...
c = RequestContext(request, {
'foo': 'bar',
}, [ip_address_processor])
return HttpResponse(t.render(c))

Built-in template context processors

Here’s what each of the built-in processors does:

django.contrib.auth.context_processors.auth

auth()[source]

If this processor is enabled, every RequestContext will contain these variables:

- user – An auth.User instance representing the currently logged-in user (or an AnonymousUser instance, if the client isn’t logged in).

- perms – An instance of django.contrib.auth.context_processors.PermWrapper, representing the permissions that the currently logged-in user has.

django.template.context_processors.debug

debug()[source]

If this processor is enabled, every RequestContext will contain these two variables – but only if your DEBUG setting is set to True and the request’s IP address (request.META['REMOTE_ADDR']) is in the INTERNAL_IPS setting:

- debug – True. You can use this in templates to test whether you’re in DEBUG mode.

- sql_queries – A list of {'sql': ..., 'time': ...} dictionaries, representing every SQL query that has happened so far during the request and how long it took. The list is in order by query and lazily generated on access.

django.template.context_processors.i18n

If this processor is enabled, every RequestContext will contain these two variables:

- LANGUAGES – The value of the LANGUAGES setting.

- LANGUAGE_CODE – request.LANGUAGE_CODE, if it exists. Otherwise, the value of the LANGUAGE_CODE setting.

See Internationalization and localization for more.

django.template.context_processors.media

If this processor is enabled, every RequestContext will contain a variable MEDIA_URL, providing the value of the MEDIA_URL setting.

django.template.context_processors.static

static()[source]

If this processor is enabled, every RequestContext will contain a variable STATIC_URL, providing the value of the STATIC_URL setting.

django.template.context_processors.csrf

This processor adds a token that is needed by the csrf_token template tag for protection against Cross Site Request Forgeries.

django.template.context_processors.request

If this processor is enabled, every RequestContext will contain a variable request, which is the current HttpRequest.

django.template.context_processors.tz

tz()[source]

If this processor is enabled, every RequestContext will contain a variable TIME_ZONE, providing the name of the currently active time zone.

django.contrib.messages.context_processors.messages

If this processor is enabled, every RequestContext will contain these two variables:

- messages – A list of messages (as strings) that have been set via the messages framework.

- DEFAULT_MESSAGE_LEVELS – A mapping of the message level names to their numeric value.

Writing your own context processors

A context processor has a very simple interface: It’s just a Python function that takes one argument, an HttpRequest object, and returns a dictionary that gets added to the template context. Each context processor must return a dictionary.

Custom context processors can live anywhere in your code base. All Django cares about is that your custom context processors are pointed to by the 'context_processors' option in your TEMPLATES setting — or the context_processors argument of Engine if you’re using it directly.

Loading templates

Generally, you’ll store templates in files on your filesystem rather than using the low-level Template API yourself. Save templates in a directory specified as a template directory.

Django searches for template directories in a number of places, depending on your template loading settings (see “Loader types” below), but the most basic way of specifying template directories is by using the DIRS option.

The DIRS option

Changed in Django 1.8:
This value used to be defined by the TEMPLATE_DIRS setting.

Tell Django what your template directories are by using the DIRS option in the TEMPLATES setting in your settings file — or the dirs argument of Engine. This should be set to a list of strings that contain full paths to your template directories:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
'/home/html/templates/lawrence.com',
'/home/html/templates/default',
],
},
]

Your templates can go anywhere you want, as long as the directories and templates are readable by the Web server. They can have any extension you want, such as .html or .txt, or they can have no extension at all.

Note that these paths should use Unix-style forward slashes, even on Windows.

Loader types

By default, Django uses a filesystem-based template loader, but Django comes with a few other template loaders, which know how to load templates from other sources.

Some of these other loaders are disabled by default, but you can activate them by adding a 'loaders' option to your DjangoTemplates backend in the TEMPLATES setting or passing a loaders argument to Engine. loaders should be a list of strings or tuples, where each represents a template loader class. Here are the template loaders that come with Django:

django.template.loaders.filesystem.Loader

class filesystem.Loader

Loads templates from the filesystem, according to DIRS.

This loader is enabled by default. However it won’t find any templates until you set DIRS to a non-empty list:

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
}]

django.template.loaders.app_directories.Loader

class app_directories.Loader

Loads templates from Django apps on the filesystem. For each app in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates in there.

This means you can store templates with your individual apps. This also makes it easy to distribute Django apps with default templates.

For example, for this setting:

INSTALLED_APPS = ['myproject.polls', 'myproject.music']

...then get_template('foo.html') will look for foo.html in these directories, in this order:

- /path/to/myproject/polls/templates/

- /path/to/myproject/music/templates/

... and will use the one it finds first.

The order of INSTALLED_APPS is significant! For example, if you want to customize the Django admin, you might choose to override the standard admin/base_site.html template, from django.contrib.admin, with your own admin/base_site.html in myproject.polls. You must then make sure that your myproject.polls comes before django.contrib.admin in INSTALLED_APPS, otherwise django.contrib.admin’s will be loaded first and yours will be ignored.

Note that the loader performs an optimization when it first runs: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.

You can enable this loader simply by setting APP_DIRS to True:

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
}]

django.template.loaders.eggs.Loader

class eggs.Loader

Deprecated since version 1.9: Distributing applications as eggs is not recommended.

Just like app_directories above, but it loads templates from Python eggs rather than from the filesystem.

This loader is disabled by default.

django.template.loaders.cached.Loader

class cached.Loader

By default, the templating system will read and compile your templates every time they need to be rendered. While the Django templating system is quite fast, the overhead from reading and compiling templates can add up.

The cached template loader is a class-based loader that you configure with a list of other loaders that it should wrap. The wrapped loaders are used to locate unknown templates when they are first encountered. The cached loader then stores the compiled Template in memory. The cached Template instance is returned for subsequent requests to load the same template.

For example, to enable template caching with the filesystem and app_directories template loaders you might use the following settings:

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'OPTIONS': {
'loaders': [
('django.template.loaders.cached.Loader', [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]),
],
},
}]

Note

All of the built-in Django template tags are safe to use with the cached loader, but if you’re using custom template tags that come from third party packages, or that you wrote yourself, you should ensure that the Node implementation for each tag is thread-safe. For more information, see template tag thread safety considerations.

This loader is disabled by default.

django.template.loaders.locmem.Loader

New in Django 1.8.

class locmem.Loader

Loads templates from a Python dictionary. This is useful for testing.

This loader takes a dictionary of templates as its first argument:

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {
'loaders': [
('django.template.loaders.locmem.Loader', {
'index.html': 'content here',
}),
],
},
}]

This loader is disabled by default.

Django uses the template loaders in order according to the 'loaders' option. It uses each loader until a loader finds a match.

Custom loaders

It’s possible to load templates from additional sources using custom template loaders. Custom Loader classes should inherit from django.template.loaders.base.Loader and define the get_contents() and get_template_sources() methods.

Changed in Django 1.8:
django.template.loaders.base.Loader used to be defined at django.template.loader.BaseLoader.

Changed in Django 1.9:
In previous versions of Django, custom loaders defined a single method: load_template_source().

Loader methods

class Loader[source]

Loads templates from a given source, such as the filesystem or a database.

get_template_sources(template_name)[source]

A method that takes a template_name and yields Origin instances for each possible source.

For example, the filesystem loader may receive 'index.html' as a template_name argument. This method would yield origins for the full path of index.html as it appears in each template directory the loader looks at.

The method doesn’t need to verify that the template exists at a given path, but it should ensure the path is valid. For instance, the filesystem loader makes sure the path lies under a valid template directory.

get_contents(origin)

Returns the contents for a template given a Origin instance.

This is where a filesystem loader would read contents from the filesystem, or a database loader would read from the database. If a matching template doesn’t exist, this should raise a TemplateDoesNotExist error.

get_template(template_name, skip=None)[source]

Returns a Template object for a given template_name by looping through results from get_template_sources() and calling get_contents(). This returns the first matching template. If no template is found, TemplateDoesNotExist is raised.

The optional skip argument is a list of origins to ignore when extending templates. This allow templates to extend other templates of the same name. It also used to avoid recursion errors.

In general, it is enough to define get_template_sources() and get_contents() for custom template loaders. get_template() will usually not need to be overridden.

load_template_source(template_name, template_dirs=None)[source]

Returns a tuple of (template_string, template_origin), where template_string is a string containing the template contents, and template_origin is a string identifying the template source. A filesystem-based loader may return the full path to the file as the template_origin, for example.

template_dirs is an optional argument used to control which directories the loader will search.

This method is called automatically by load_template() and should be overridden when writing custom template loaders.

Deprecated since version 1.9: Custom loaders should use get_template() and get_contents() instead.

load_template(template_name, template_dirs=None)[source]

Returns a tuple of (template, template_origin), where template is a Template object and template_origin is a string identifying the template source. A filesystem-based loader may return the full path to the file as the template_origin, for example.

Deprecated since version 1.9: Custom loaders should use get_template() and get_contents() instead.

Building your own

For examples, read the source code for Django’s built-in loaders.

Template origin

Templates have an origin containing attributes depending on the source they are loaded from.

Changed in Django 1.9:
Django used to create an origin based on django.template.loader.LoaderOrigin or django.template.base.StringOrigin. These have been replaced by django.template.base.Origin.

class Origin[source]

name

The path to the template as returned by the template loader. For loaders that read from the file system, this is the full path to the template.

If the template is instantiated directly rather than through a template loader, this is a string value of <unknown_source>.

template_name

The relative path to the template as passed into the template loader.

If the template is instantiated directly rather than through a template loader, this is None.

Upgrading templates to Django 1.8

Django’s template system was overhauled in Django 1.8 when it gained support for multiple template engines. This document complements the release notes with detailed upgrade instructions on some topics.

The TEMPLATES settings

A new setting was introduced in Django 1.8: TEMPLATES. All existing template-related settings were deprecated.

During the deprecation period, Django will create a backwards-compatible TEMPLATES based on the TEMPLATE_* settings if you don’t define it yourself.

Here’s how to define TEMPLATES in your settings module.

If you’re using the default value of TEMPLATE_LOADERS, that is, if it isn’t defined in your settings file or if it’s set to:

['django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader']

then you should define TEMPLATES as follows:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
# insert your TEMPLATE_DIRS here
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]

If you aren’t using the default value of TEMPLATE_LOADERS, then you should define TEMPLATES as follows:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
# insert your TEMPLATE_DIRS here
],
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
'loaders': [
# insert your TEMPLATE_LOADERS here
]
},
},
]

Furthermore you should replace django.core.context_processors with django.template.context_processors in the names of context processors.

If your settings module defines ALLOWED_INCLUDE_ROOTS or TEMPLATE_STRING_IF_INVALID, include their values under the 'allowed_include_roots' and 'string_if_invalid' keys in the 'OPTIONS' dictionary.

If it sets TEMPLATE_DEBUG to a value that differs from DEBUG, include that value under the 'debug' key in 'OPTIONS'.

Once you have defined TEMPLATES, you can safely remove ALLOWED_INCLUDE_ROOTS, TEMPLATE_CONTEXT_PROCESSORS, TEMPLATE_DEBUG, TEMPLATE_DIRS, TEMPLATE_LOADERS, and TEMPLATE_STRING_IF_INVALID.

If you are overriding some of these settings in tests, you should override the entire TEMPLATES setting instead.

django.template.loader

get_template() and select_template()

In Django 1.8 get_template() and select_template() return a backend-dependent Template instead of a django.template.Template.

For example, if get_template() loads a template with a DjangoTemplates backend, then it returns a django.template.backends.django.Template.

Template objects must provide a render() method whose signature differs slightly from the Django template language’s render().

Instead of:

from django.template import Context
from django.template.loader import get_template

template = get_template('hello.html')
html = template.render(Context({'name': 'world'}))

You should write:

from django.template.loader import get_template

template = get_template('hello.html')
html = template.render({'name': 'world'})

And instead of:

from django.template import RequestContext
from django.template.loader import get_template

template = get_template('hello.html')
html = template.render(RequestContext(request, {'name': 'world'}))

You should write:

from django.template.loader import get_template

template = get_template('hello.html')
html = template.render({'name': 'world'}, request)

Passing a Context or a RequestContext is still possible when the template is loaded by a DjangoTemplates backend but it’s deprecated and won’t be supported in Django 1.10.

If you’re loading a template while you’re rendering another template with the Django template language and you have access to the current context, for instance in the render() method of a template tag, you can use the current Engine directly. Instead of:

from django.template.loader import get_template
template = get_template('included.html')

You can write:

template = context.template.engine.get_template('included.html')

This will load the template with the current engine without triggering the multiple template engines machinery, which is usually the desired behavior. Unlike previous solutions, this returns a django.template.Template, like get_template() used to in Django 1.7 and earlier, avoiding all backwards-compatibility problems.

get_template_from_string()

Private API get_template_from_string(template_code) was removed in Django 1.8 because it had no way to choose an engine to compile the template.

Three alternatives are available.

If you control the project’s setting, you can use one of the configured engines:

from django.template import engines

template = engines['django'].from_string(template_code)

This returns a backend-dependent Template object.

For trivial templates that don’t need context processors nor anything else, you can create a bare-bones engine and use its from_string() method:

from django.template import Engine

template = Engine().from_string(template_code)

This returns a django.template.Template because Engine is part of the Django template language’s APIs. The multiple template engines machinery isn’t involved here.

Finally, if you have access to the current context, you can use the same trick as above:

template = context.template.engine.from_string(template_code)

Template()

To a lesser extent, instantiating a template with Template(template_code) suffers from the same issue as get_template_from_string().

It still works when the TEMPLATES setting defines exactly one DjangoTemplates backend, but pluggable applications can’t control this requirement.

The last two solutions described in the previous section are recommended in that case.

TemplateResponse and SimpleTemplateResponse

Standard HttpResponse objects are static structures. They are provided with a block of pre-rendered content at time of construction, and while that content can be modified, it isn’t in a form that makes it easy to perform modifications.

However, it can sometimes be beneficial to allow decorators or middleware to modify a response after it has been constructed by the view. For example, you may want to change the template that is used, or put additional data into the context.

TemplateResponse provides a way to do just that. Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the template and context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.

SimpleTemplateResponse objects

class SimpleTemplateResponse[source]

Attributes

SimpleTemplateResponse.template_name

The name of the template to be rendered. Accepts a backend-dependent template object (such as those returned by get_template()), the name of a template, or a list of template names.

Example: ['foo.html', 'path/to/bar.html']

Deprecated since version 1.8: template_name used to accept a Template.

SimpleTemplateResponse.context_data

The context data to be used when rendering the template. It must be a dict.

Example: {'foo': 123}

Deprecated since version 1.8: context_data used to accept a Context.

SimpleTemplateResponse.rendered_content

The current rendered value of the response content, using the current template and context data.

SimpleTemplateResponse.is_rendered

A boolean indicating whether the response content has been rendered.

Methods

SimpleTemplateResponse.__init__(template, context=None, content_type=None, status=None, charset=None, using=None)[source]

Instantiates a SimpleTemplateResponse object with the given template, context, content type, HTTP status, and charset.

template

A backend-dependent template object (such as those returned by get_template()), the name of a template, or a list of template names.

Deprecated since version 1.8: template used to accept a Template.

context

A dict of values to add to the template context. By default, this is an empty dictionary.

Deprecated since version 1.8: context used to accept a Context.

content_type

The value included in the HTTP Content-Type header, including the MIME type specification and the character set encoding. If content_type is specified, then its value is used. Otherwise, DEFAULT_CONTENT_TYPE is used.

status

The HTTP status code for the response.

charset

The charset in which the response will be encoded. If not given it will be extracted from content_type, and if that is unsuccessful, the DEFAULT_CHARSET setting will be used.

using

The NAME of a template engine to use for loading the template.

Changed in Django 1.8:
The charset and using parameters were added.

SimpleTemplateResponse.resolve_context(context)[source]

Preprocesses context data that will be used for rendering a template. Accepts a dict of context data. By default, returns the same dict.

Override this method in order to customize the context.

Changed in Django 1.8:
resolve_context returns a dict. It used to return a Context.

Deprecated since version 1.8: resolve_context no longer accepts a Context.

SimpleTemplateResponse.resolve_template(template)[source]

Resolves the template instance to use for rendering. Accepts a backend-dependent template object (such as those returned by get_template()), the name of a template, or a list of template names.

Returns the backend-dependent template object instance to be rendered.

Override this method in order to customize template loading.

Changed in Django 1.8:
resolve_template returns backend-dependent template object. It used to return a Template.

Deprecated since version 1.8: resolve_template no longer accepts a Template.

SimpleTemplateResponse.add_post_render_callback()[source]

Add a callback that will be invoked after rendering has taken place. This hook can be used to defer certain processing operations (such as caching) until after rendering has occurred.

If the SimpleTemplateResponse has already been rendered, the callback will be invoked immediately.

When called, callbacks will be passed a single argument – the rendered SimpleTemplateResponse instance.

If the callback returns a value that is not None, this will be used as the response instead of the original response object (and will be passed to the next post rendering callback etc.)

SimpleTemplateResponse.render()[source]

Sets response.content to the result obtained by SimpleTemplateResponse.rendered_content, runs all post-rendering callbacks, and returns the resulting response object.

render() will only have an effect the first time it is called. On subsequent calls, it will return the result obtained from the first call.

TemplateResponse objects

class TemplateResponse[source]

TemplateResponse is a subclass of SimpleTemplateResponse that knows about the current HttpRequest.

Methods

TemplateResponse.__init__(request, template, context=None, content_type=None, status=None, current_app=None, charset=None, using=None)[source]

Instantiates a TemplateResponse object with the given request, template, context, content type, HTTP status, and charset.

request

An HttpRequest instance.

template

A backend-dependent template object (such as those returned by get_template()), the name of a template, or a list of template names.

Deprecated since version 1.8: template used to accept a Template.

context

A dict of values to add to the template context. By default, this is an empty dictionary.

Deprecated since version 1.8: context used to accept a Context.

content_type

The value included in the HTTP Content-Type header, including the MIME type specification and the character set encoding. If content_type is specified, then its value is used. Otherwise, DEFAULT_CONTENT_TYPE is used.

status

The HTTP status code for the response.

current_app

A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

Deprecated since version 1.8: The current_app argument is deprecated. Instead you should set request.current_app.

charset

The charset in which the response will be encoded. If not given it will be extracted from content_type, and if that is unsuccessful, the DEFAULT_CHARSET setting will be used.

using

The NAME of a template engine to use for loading the template.

Changed in Django 1.8:
The charset and using parameters were added.

The rendering process

Before a TemplateResponse instance can be returned to the client, it must be rendered. The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client.

There are three circumstances under which a TemplateResponse will be rendered:

- When the TemplateResponse instance is explicitly rendered, using the SimpleTemplateResponse.render() method.

- When the content of the response is explicitly set by assigning response.content.

- After passing through template response middleware, but before passing through response middleware.

A TemplateResponse can only be rendered once. The first call to SimpleTemplateResponse.render() sets the content of the response; subsequent rendering calls do not change the response content.

However, when response.content is explicitly assigned, the change is always applied. If you want to force the content to be re-rendered, you can re-evaluate the rendered content, and assign the content of the response manually:

# Set up a rendered TemplateResponse
>>> from django.template.response import TemplateResponse
>>> t = TemplateResponse(request, 'original.html', {})
>>> t.render()
>>> print(t.content)
Original content

# Re-rendering doesn't change content
>>> t.template_name = 'new.html'
>>> t.render()
>>> print(t.content)
Original content

# Assigning content does change, no render() call required
>>> t.content = t.rendered_content
>>> print(t.content)
New content

Post-render callbacks

Some operations – such as caching – cannot be performed on an unrendered template. They must be performed on a fully complete and rendered response.

If you’re using middleware, the solution is easy. Middleware provides multiple opportunities to process a response on exit from a view. If you put behavior in the response middleware, it’s guaranteed to execute after template rendering has taken place.

However, if you’re using a decorator, the same opportunities do not exist. Any behavior defined in a decorator is handled immediately.

To compensate for this (and any other analogous use cases), TemplateResponse allows you to register callbacks that will be invoked when rendering has completed. Using this callback, you can defer critical processing until a point where you can guarantee that rendered content will be available.

To define a post-render callback, just define a function that takes a single argument – response – and register that function with the template response:

from django.template.response import TemplateResponse

def my_render_callback(response):
# Do content-sensitive processing
do_post_processing()

def my_view(request):
# Create a response
response = TemplateResponse(request, 'mytemplate.html', {})
# Register the callback
response.add_post_render_callback(my_render_callback)
# Return the response
return response

my_render_callback() will be invoked after the mytemplate.html has been rendered, and will be provided the fully rendered TemplateResponse instance as an argument.

If the template has already been rendered, the callback will be invoked immediately.

Using TemplateResponse and SimpleTemplateResponse

A TemplateResponse object can be used anywhere that a normal django.http.HttpResponse can be used. It can also be used as an alternative to calling render().

For example, the following simple view returns a TemplateResponse with a simple template and a context containing a queryset:

from django.template.response import TemplateResponse

def blog_index(request):
return TemplateResponse(request, 'entry_list.html', {'entries': Entry.objects.all()})

Unicode data

Django natively supports Unicode data everywhere. Providing your database can somehow store the data, you can safely pass around Unicode strings to templates, models and the database.

This document tells you what you need to know if you’re writing applications that use data or templates that are encoded in something other than ASCII.

Creating the database

Make sure your database is configured to be able to store arbitrary string data. Normally, this means giving it an encoding of UTF-8 or UTF-16. If you use a more restrictive encoding – for example, latin1 (iso8859-1) – you won’t be able to store certain characters in the database, and information will be lost.

- MySQL users, refer to the MySQL manual for details on how to set or alter the database character set encoding.

- PostgreSQL users, refer to the PostgreSQL manual (section 22.3.2 in PostgreSQL 9) for details on creating databases with the correct encoding.

- Oracle users, refer to the Oracle manual for details on how to set (section 2) or alter (section 11) the database character set encoding.

- SQLite users, there is nothing you need to do. SQLite always uses UTF-8 for internal encoding.

All of Django’s database backends automatically convert Unicode strings into the appropriate encoding for talking to the database. They also automatically convert strings retrieved from the database into Python Unicode strings. You don’t even need to tell Django what encoding your database uses: that is handled transparently.

For more, see the section “The database API” below.

General string handling

Whenever you use strings with Django – e.g., in database lookups, template rendering or anywhere else – you have two choices for encoding those strings. You can use Unicode strings, or you can use normal strings (sometimes called “bytestrings”) that are encoded using UTF-8.

In Python 3, the logic is reversed, that is normal strings are Unicode, and when you want to specifically create a bytestring, you have to prefix the string with a ‘b’. As we are doing in Django code from version 1.5, we recommend that you import unicode_literals from the __future__ library in your code. Then, when you specifically want to create a bytestring literal, prefix the string with ‘b’.

Python 2 legacy:

my_string = "This is a bytestring"
my_unicode = u"This is an Unicode string"

Python 2 with unicode literals or Python 3:

from __future__ import unicode_literals

my_string = b"This is a bytestring"
my_unicode = "This is an Unicode string"

See also Python 3 compatibility.

Warning

A bytestring does not carry any information with it about its encoding. For that reason, we have to make an assumption, and Django assumes that all bytestrings are in UTF-8.

If you pass a string to Django that has been encoded in some other format, things will go wrong in interesting ways. Usually, Django will raise a UnicodeDecodeError at some point.

If your code only uses ASCII data, it’s safe to use your normal strings, passing them around at will, because ASCII is a subset of UTF-8.

Don’t be fooled into thinking that if your DEFAULT_CHARSET setting is set to something other than 'utf-8' you can use that other encoding in your bytestrings! DEFAULT_CHARSET only applies to the strings generated as the result of template rendering (and email). Django will always assume UTF-8 encoding for internal bytestrings. The reason for this is that the DEFAULT_CHARSET setting is not actually under your control (if you are the application developer). It’s under the control of the person installing and using your application – and if that person chooses a different setting, your code must still continue to work. Ergo, it cannot rely on that setting.

In most cases when Django is dealing with strings, it will convert them to Unicode strings before doing anything else. So, as a general rule, if you pass in a bytestring, be prepared to receive a Unicode string back in the result.

Translated strings

Aside from Unicode strings and bytestrings, there’s a third type of string-like object you may encounter when using Django. The framework’s internationalization features introduce the concept of a “lazy translation” – a string that has been marked as translated but whose actual translation result isn’t determined until the object is used in a string. This feature is useful in cases where the translation locale is unknown until the string is used, even though the string might have originally been created when the code was first imported.

Normally, you won’t have to worry about lazy translations. Just be aware that if you examine an object and it claims to be a django.utils.functional.__proxy__ object, it is a lazy translation. Calling unicode() with the lazy translation as the argument will generate a Unicode string in the current locale.

For more details about lazy translation objects, refer to the internationalization documentation.

Useful utility functions

Because some string operations come up again and again, Django ships with a few useful functions that should make working with Unicode and bytestring objects a bit easier.

Conversion functions

The django.utils.encoding module contains a few functions that are handy for converting back and forth between Unicode and bytestrings.

- smart_text(s, encoding='utf-8', strings_only=False, errors='strict') converts its input to a Unicode string. The encoding parameter specifies the input encoding. (For example, Django uses this internally when processing form input data, which might not be UTF-8 encoded.) The strings_only parameter, if set to True, will result in Python numbers, booleans and None not being converted to a string (they keep their original types). The errors parameter takes any of the values that are accepted by Python’s unicode() function for its error handling.

If you pass smart_text() an object that has a __unicode__ method, it will use that method to do the conversion.

- force_text(s, encoding='utf-8', strings_only=False, errors='strict') is identical to smart_text() in almost all cases. The difference is when the first argument is a lazy translation instance. While smart_text() preserves lazy translations, force_text() forces those objects to a Unicode string (causing the translation to occur). Normally, you’ll want to use smart_text(). However, force_text() is useful in template tags and filters that absolutely must have a string to work with, not just something that can be converted to a string.

- smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict') is essentially the opposite of smart_text(). It forces the first argument to a bytestring. The strings_only parameter has the same behavior as for smart_text() and force_text(). This is slightly different semantics from Python’s builtin str() function, but the difference is needed in a few places within Django’s internals.

Normally, you’ll only need to use smart_text(). Call it as early as possible on any input data that might be either Unicode or a bytestring, and from then on, you can treat the result as always being Unicode.

URI and IRI handling

Web frameworks have to deal with URLs (which are a type of IRI). One requirement of URLs is that they are encoded using only ASCII characters. However, in an international environment, you might need to construct a URL from an IRI – very loosely speaking, a URI that can contain Unicode characters. Quoting and converting an IRI to URI can be a little tricky, so Django provides some assistance.

- The function django.utils.encoding.iri_to_uri() implements the conversion from IRI to URI as required by the specification (RFC 3987#section-3.1).

- The functions django.utils.http.urlquote() and django.utils.http.urlquote_plus() are versions of Python’s standard urllib.quote() and urllib.quote_plus() that work with non-ASCII characters. (The data is converted to UTF-8 prior to encoding.)

These two groups of functions have slightly different purposes, and it’s important to keep them straight. Normally, you would use urlquote() on the individual portions of the IRI or URI path so that any reserved characters such as ‘&’ or ‘%’ are correctly encoded. Then, you apply iri_to_uri() to the full IRI and it converts any non-ASCII characters to the correct encoded values.

Note

Technically, it isn’t correct to say that iri_to_uri() implements the full algorithm in the IRI specification. It doesn’t (yet) perform the international domain name encoding portion of the algorithm.

The iri_to_uri() function will not change ASCII characters that are otherwise permitted in a URL. So, for example, the character ‘%’ is not further encoded when passed to iri_to_uri(). This means you can pass a full URL to this function and it will not mess up the query string or anything like that.

An example might clarify things here:

>>> urlquote('Paris & Orléans')
'Paris%20%26%20Orl%C3%A9ans'
>>> iri_to_uri('/favorites/François/%s' % urlquote('Paris & Orléans'))
'/favorites/Fran%C3%A7ois/Paris%20%26%20Orl%C3%A9ans'

If you look carefully, you can see that the portion that was generated by urlquote() in the second example was not double-quoted when passed to iri_to_uri(). This is a very important and useful feature. It means that you can construct your IRI without worrying about whether it contains non-ASCII characters and then, right at the end, call iri_to_uri() on the result.

Similarly, Django provides django.utils.encoding.uri_to_iri() which implements the conversion from URI to IRI as per RFC 3987#section-3.2. It decodes all percent-encodings except those that don’t represent a valid UTF-8 sequence.

An example to demonstrate:

>>> uri_to_iri('/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93')
'/♥♥/?utf8=✓'
>>> uri_to_iri('%A9helloworld')
'%A9helloworld'

In the first example, the UTF-8 characters and reserved characters are unquoted. In the second, the percent-encoding remains unchanged because it lies outside the valid UTF-8 range.

Both iri_to_uri() and uri_to_iri() functions are idempotent, which means the following is always true:

iri_to_uri(iri_to_uri(some_string)) == iri_to_uri(some_string)
uri_to_iri(uri_to_iri(some_string)) == uri_to_iri(some_string)

So you can safely call it multiple times on the same URI/IRI without risking double-quoting problems.

Models

Because all strings are returned from the database as Unicode strings, model fields that are character based (CharField, TextField, URLField, etc.) will contain Unicode values when Django retrieves data from the database. This is always the case, even if the data could fit into an ASCII bytestring.

You can pass in bytestrings when creating a model or populating a field, and Django will convert it to Unicode when it needs to.

Choosing between __str__() and __unicode__()

Note

If you are on Python 3, you can skip this section because you’ll always create __str__() rather than __unicode__(). If you’d like compatibility with Python 2, you can decorate your model class with python_2_unicode_compatible().

One consequence of using Unicode by default is that you have to take some care when printing data from the model.

In particular, rather than giving your model a __str__() method, we recommended you implement a __unicode__() method. In the __unicode__() method, you can quite safely return the values of all your fields without having to worry about whether they fit into a bytestring or not. (The way Python works, the result of __str__() is always a bytestring, even if you accidentally try to return a Unicode object).

You can still create a __str__() method on your models if you want, of course, but you shouldn’t need to do this unless you have a good reason. Django’s Model base class automatically provides a __str__() implementation that calls __unicode__() and encodes the result into UTF-8. This means you’ll normally only need to implement a __unicode__() method and let Django handle the coercion to a bytestring when required.

Taking care in get_absolute_url()

URLs can only contain ASCII characters. If you’re constructing a URL from pieces of data that might be non-ASCII, be careful to encode the results in a way that is suitable for a URL. The reverse() function handles this for you automatically.

If you’re constructing a URL manually (i.e., not using the reverse() function), you’ll need to take care of the encoding yourself. In this case, use the iri_to_uri() and urlquote() functions that were documented above. For example:

from django.utils.encoding import iri_to_uri
from django.utils.http import urlquote

def get_absolute_url(self):
url = '/person/%s/?x=0&y=0' % urlquote(self.location)
return iri_to_uri(url)

This function returns a correctly encoded URL even if self.location is something like “Jack visited Paris & Orléans”. (In fact, the iri_to_uri() call isn’t strictly necessary in the above example, because all the non-ASCII characters would have been removed in quoting in the first line.)

The database API

You can pass either Unicode strings or UTF-8 bytestrings as arguments to filter() methods and the like in the database API. The following two querysets are identical:

from __future__ import unicode_literals

qs = People.objects.filter(name__contains='Å')
qs = People.objects.filter(name__contains=b'\xc3\x85') # UTF-8 encoding of Å

Templates

You can use either Unicode or bytestrings when creating templates manually:

from __future__ import unicode_literals
from django.template import Template
t1 = Template(b'This is a bytestring template.')
t2 = Template('This is a Unicode template.')

But the common case is to read templates from the filesystem, and this creates a slight complication: not all filesystems store their data encoded as UTF-8. If your template files are not stored with a UTF-8 encoding, set the FILE_CHARSET setting to the encoding of the files on disk. When Django reads in a template file, it will convert the data from this encoding to Unicode. (FILE_CHARSET is set to 'utf-8' by default.)

The DEFAULT_CHARSET setting controls the encoding of rendered templates. This is set to UTF-8 by default.

Template tags and filters

A couple of tips to remember when writing your own template tags and filters:

- Always return Unicode strings from a template tag’s render() method and from template filters.

- Use force_text() in preference to smart_text() in these places. Tag rendering and filter calls occur as the template is being rendered, so there is no advantage to postponing the conversion of lazy translation objects into strings. It’s easier to work solely with Unicode strings at that point.

Files

If you intend to allow users to upload files, you must ensure that the environment used to run Django is configured to work with non-ASCII file names. If your environment isn’t configured correctly, you’ll encounter UnicodeEncodeError exceptions when saving files with file names that contain non-ASCII characters.

Filesystem support for UTF-8 file names varies and might depend on the environment. Check your current configuration in an interactive Python shell by running:

import sys
sys.getfilesystemencoding()

This should output “UTF-8”.

The LANG environment variable is responsible for setting the expected encoding on Unix platforms. Consult the documentation for your operating system and application server for the appropriate syntax and location to set this variable.

In your development environment, you might need to add a setting to your ~.bashrc analogous to::

export LANG="en_US.UTF-8"

Email

Django’s email framework (in django.core.mail) supports Unicode transparently. You can use Unicode data in the message bodies and any headers. However, you’re still obligated to respect the requirements of the email specifications, so, for example, email addresses should use only ASCII characters.

The following code example demonstrates that everything except email addresses can be non-ASCII:

from __future__ import unicode_literals
from django.core.mail import EmailMessage

subject = 'My visit to Sør-Trøndelag'
sender = 'Arnbjörg Ráðormsdóttir <arnbjorg@example.com>'
recipients = ['Fred <fred@example.com']
body = '...'
msg = EmailMessage(subject, body, sender, recipients)
msg.attach("Une pièce jointe.pdf", "%PDF-1.4.%...", mimetype="application/pdf")
msg.send()

Form submission

HTML form submission is a tricky area. There’s no guarantee that the submission will include encoding information, which means the framework might have to guess at the encoding of submitted data.

Django adopts a “lazy” approach to decoding form data. The data in an HttpRequest object is only decoded when you access it. In fact, most of the data is not decoded at all. Only the HttpRequest.GET and HttpRequest.POST data structures have any decoding applied to them. Those two fields will return their members as Unicode data. All other attributes and methods of HttpRequest return data exactly as it was submitted by the client.

By default, the DEFAULT_CHARSET setting is used as the assumed encoding for form data. If you need to change this for a particular form, you can set the encoding attribute on an HttpRequest instance. For example:

def some_view(request):
# We know that the data must be encoded as KOI8-R (for some reason).
request.encoding = 'koi8-r'
...

You can even change the encoding after having accessed request.GET or request.POST, and all subsequent accesses will use the new encoding.

Most developers won’t need to worry about changing form encoding, but this is a useful feature for applications that talk to legacy systems whose encoding you cannot control.

Django does not decode the data of file uploads, because that data is normally treated as collections of bytes, rather than strings. Any automatic decoding there would alter the meaning of the stream of bytes.

django.core.urlresolvers utility functions

reverse()

If you need to use something similar to the url template tag in your code, Django provides the following function:

reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)[source]

viewname can be a string containing the Python path to the view object, a URL pattern name, or the callable view object. For example, given the following url:

from news import views

url(r'^archive/$', views.archive, name='news-archive')

you can use any of the following to reverse the URL:

# using the named URL
reverse('news-archive')

# passing a callable object
# (This is discouraged because you can't reverse namespaced views this way.)
from news import views
reverse(views.archive)

If the URL accepts arguments, you may pass them in args. For example:

from django.core.urlresolvers import reverse

def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))

You can also pass kwargs instead of args. For example:

>>> reverse('admin:app_list', kwargs={'app_label': 'auth'})
'/admin/auth/'

args and kwargs cannot be passed to reverse() at the same time.

If no match can be made, reverse() raises a NoReverseMatch exception.

The reverse() function can reverse a large variety of regular expression patterns for URLs, but not every possible one. The main restriction at the moment is that the pattern cannot contain alternative choices using the vertical bar ("|") character. You can quite happily use such patterns for matching against incoming URLs and sending them off to views, but you cannot reverse such patterns.

The current_app argument allows you to provide a hint to the resolver indicating the application to which the currently executing view belongs. This current_app argument is used as a hint to resolve application namespaces into URLs on specific application instances, according to the namespaced URL resolution strategy.

The urlconf argument is the URLconf module containing the URL patterns to use for reversing. By default, the root URLconf for the current thread is used.

Deprecated since version 1.8: The ability to reverse using the Python path, e.g. reverse('news.views.archive'), has been deprecated.

Make sure your views are all correct.

As part of working out which URL names map to which patterns, the reverse() function has to import all of your URLconf files and examine the name of each view. This involves importing each view function. If there are any errors while importing any of your view functions, it will cause reverse() to raise an error, even if that view function is not the one you are trying to reverse.

Make sure that any views you reference in your URLconf files exist and can be imported correctly. Do not include lines that reference views you haven’t written yet, because those views will not be importable.

Note

The string returned by reverse() is already urlquoted. For example:

>>> reverse('cities', args=['Orléans'])
'.../Orl%C3%A9ans/'

Applying further encoding (such as urlquote() or urllib.quote) to the output of reverse() may produce undesirable results.

reverse_lazy()

A lazily evaluated version of reverse().

reverse_lazy(viewname, urlconf=None, args=None, kwargs=None, current_app=None)

It is useful for when you need to use a URL reversal before your project’s URLConf is loaded. Some common cases where this function is necessary are:

- providing a reversed URL as the url attribute of a generic class-based view.

- providing a reversed URL to a decorator (such as the login_url argument for the django.contrib.auth.decorators.permission_required() decorator).

- providing a reversed URL as a default value for a parameter in a function’s signature.

resolve()

The resolve() function can be used for resolving URL paths to the corresponding view functions. It has the following signature:

resolve(path, urlconf=None)[source]

path is the URL path you want to resolve. As with reverse(), you don’t need to worry about the urlconf parameter. The function returns a ResolverMatch object that allows you to access various meta-data about the resolved URL.

If the URL does not resolve, the function raises a Resolver404 exception (a subclass of Http404) .

class ResolverMatch[source]

func

The view function that would be used to serve the URL

args

The arguments that would be passed to the view function, as parsed from the URL.

kwargs

The keyword arguments that would be passed to the view function, as parsed from the URL.

url_name

The name of the URL pattern that matches the URL.

app_name

The application namespace for the URL pattern that matches the URL.

app_names

New in Django 1.9.

The list of individual namespace components in the full application namespace for the URL pattern that matches the URL. For example, if the app_name is 'foo:bar', then app_names will be ['foo', 'bar'].

namespace

The instance namespace for the URL pattern that matches the URL.

namespaces

The list of individual namespace components in the full instance namespace for the URL pattern that matches the URL. i.e., if the namespace is foo:bar, then namespaces will be ['foo', 'bar'].

view_name

The name of the view that matches the URL, including the namespace if there is one.

A ResolverMatch object can then be interrogated to provide information about the URL pattern that matches a URL:

# Resolve a URL
match = resolve('/some/path/')
# Print the URL pattern that matches the URL
print(match.url_name)

A ResolverMatch object can also be assigned to a triple:

func, args, kwargs = resolve('/some/path/')

One possible use of resolve() would be to test whether a view would raise a Http404 error before redirecting to it:

from django.core.urlresolvers import resolve
from django.http import HttpResponseRedirect, Http404
from django.utils.six.moves.urllib.parse import urlparse

def myview(request):
next = request.META.get('HTTP_REFERER', None) or '/'
response = HttpResponseRedirect(next)

# modify the request and response as required, e.g. change locale
# and set corresponding locale cookie

view, args, kwargs = resolve(urlparse(next)[2])
kwargs['request'] = request
try:
view(*args, **kwargs)
except Http404:
return HttpResponseRedirect('/')
return response

get_script_prefix()

get_script_prefix()[source]

Normally, you should always use reverse() to define URLs within your application. However, if your application constructs part of the URL hierarchy itself, you may occasionally need to generate URLs. In that case, you need to be able to find the base URL of the Django project within its Web server (normally, reverse() takes care of this for you). In that case, you can call get_script_prefix(), which will return the script prefix portion of the URL for your Django project. If your Django project is at the root of its web server, this is always "/".

django.conf.urls utility functions

patterns()

patterns(prefix, pattern_description, ...)[source]

Deprecated since version 1.8: urlpatterns should be a plain list of django.conf.urls.url() instances instead.

A function that takes a prefix, and an arbitrary number of URL patterns, and returns a list of URL patterns in the format Django needs.

The first argument to patterns() is a string prefix. Here’s the example URLconf from the Django overview:

from django.conf.urls import patterns, url

urlpatterns = patterns('',
url(r'^articles/([0-9]{4})/$', 'news.views.year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'news.views.month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'news.views.article_detail'),
)

In this example, each view has a common prefix – 'news.views'. Instead of typing that out for each entry in urlpatterns, you can use the first argument to the patterns() function to specify a prefix to apply to each view function.

With this in mind, the above example can be written more concisely as:

from django.conf.urls import patterns, url

urlpatterns = patterns('news.views',
url(r'^articles/([0-9]{4})/$', 'year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'article_detail'),
)

Note that you don’t put a trailing dot (".") in the prefix. Django puts that in automatically.

The remaining arguments should be tuples in this format:

(regular expression, Python callback function [, optional_dictionary [, optional_name]])

The optional_dictionary and optional_name parameters are described in Passing extra options to view functions.

Note

Because patterns() is a function call, it accepts a maximum of 255 arguments (URL patterns, in this case). This is a limit for all Python function calls. This is rarely a problem in practice, because you’ll typically structure your URL patterns modularly by using include() sections. However, on the off-chance you do hit the 255-argument limit, realize that patterns() returns a Python list, so you can split up the construction of the list.

urlpatterns = patterns('',
...
)
urlpatterns += patterns('',
...
)

Python lists have unlimited size, so there’s no limit to how many URL patterns you can construct. The only limit is that you can only create 254 at a time (the 255th argument is the initial prefix argument).

static()

static.static(prefix, view=django.views.static.serve, **kwargs)

Helper function to return a URL pattern for serving files in debug mode:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Changed in Django 1.8:
The view argument changed from a string ('django.views.static.serve') to the function.

url()

url(regex, view, kwargs=None, name=None, prefix='')[source]

urlpatterns should be a list of url() instances. For example:

urlpatterns = [
url(r'^index/$', index_view, name="main-view"),
...
]

This function takes five arguments, most of which are optional:

url(regex, view, kwargs=None, name=None, prefix='')

The kwargs parameter allows you to pass additional arguments to the view function or method. See Passing extra options to view functions for an example.

See Naming URL patterns for why the name parameter is useful.

Deprecated since version 1.8: Support for string view arguments is deprecated and will be removed in Django 1.10. Pass the callable instead.

The prefix parameter has the same meaning as the first argument to patterns() and is only relevant when you’re passing a string as the view parameter.

include()

include(module, namespace=None, app_name=None)[source]

include(pattern_list)

include((pattern_list, app_namespace), namespace=None)

include((pattern_list, app_namespace, instance_namespace))

A function that takes a full Python import path to another URLconf module that should be “included” in this place. Optionally, the application namespace and instance namespace where the entries will be included into can also be specified.

Usually, the application namespace should be specified by the included module. If an application namespace is set, the namespace argument can be used to set a different instance namespace.

include() also accepts as an argument either an iterable that returns URL patterns, a 2-tuple containing such iterable plus the names of the application namespaces, or a 3-tuple containing the iterable and the names of both the application and instance namespace.

Parameters:

- module – URLconf module (or module name)

- namespace (string) – Instance namespace for the URL entries being included

- app_name (string) – Application namespace for the URL entries being included

- pattern_list – Iterable of django.conf.urls.url() instances

- app_namespace (string) – Application namespace for the URL entries being included

- instance_namespace (string) – Instance namespace for the URL entries being included

See Including other URLconfs and URL namespaces and included URLconfs.

Deprecated since version 1.9: Support for the app_name argument is deprecated and will be removed in Django 2.0. Specify the app_name as explained in URL namespaces and included URLconfs instead.

Support for passing a 3-tuple is also deprecated and will be removed in Django 2.0. Pass a 2-tuple containing the pattern list and application namespace, and use the namespace argument instead.

Lastly, support for an instance namespace without an application namespace has been deprecated and will be removed in Django 2.0. Specify the application namespace or remove the instance namespace.

handler400

handler400

A callable, or a string representing the full Python import path to the view that should be called if the HTTP client has sent a request that caused an error condition and a response with a status code of 400.

By default, this is 'django.views.defaults.bad_request'. If you implement a custom view, be sure it returns an HttpResponseBadRequest.

See the documentation about the 400 (bad request) view for more information.

handler403

handler403

A callable, or a string representing the full Python import path to the view that should be called if the user doesn’t have the permissions required to access a resource.

By default, this is 'django.views.defaults.permission_denied'. If you implement a custom view, be sure it returns an HttpResponseForbidden.

See the documentation about the 403 (HTTP Forbidden) view for more information.

handler404

handler404

A callable, or a string representing the full Python import path to the view that should be called if none of the URL patterns match.

By default, this is 'django.views.defaults.page_not_found'. If you implement a custom view, be sure it returns an HttpResponseNotFound.

See the documentation about the 404 (HTTP Not Found) view for more information.

handler500

handler500

A callable, or a string representing the full Python import path to the view that should be called in case of server errors. Server errors happen when you have runtime errors in view code.

By default, this is 'django.views.defaults.server_error'. If you implement a custom view, be sure it returns an HttpResponseServerError.

See the documentation about the 500 (HTTP Internal Server Error) view for more information.

Django Utils

This document covers all stable modules in django.utils. Most of the modules in django.utils are designed for internal use and only the following parts can be considered stable and thus backwards compatible as per the internal release deprecation policy.

django.utils.cache

This module contains helper functions for controlling caching. It does so by managing the Vary header of responses. It includes functions to patch the header of response objects directly and decorators that change functions to do that header-patching themselves.

For information on the Vary header, see RFC 7231#section-7.1.4.

Essentially, the Vary HTTP header defines which headers a cache should take into account when building its cache key. Requests with the same path but different header content for headers named in Vary need to get different cache keys to prevent delivery of wrong content.

For example, internationalization middleware would need to distinguish caches by the Accept-language header.

patch_cache_control(response, **kwargs)[source]

This function patches the Cache-Control header by adding all keyword arguments to it. The transformation is as follows:

- All keyword parameter names are turned to lowercase, and underscores are converted to hyphens.

- If the value of a parameter is True (exactly True, not just a true value), only the parameter name is added to the header.

- All other parameters are added with their value, after applying str() to it.

get_max_age(response)[source]

Returns the max-age from the response Cache-Control header as an integer (or None if it wasn’t found or wasn’t an integer).

patch_response_headers(response, cache_timeout=None)[source]

Adds some useful headers to the given HttpResponse object:

- ETag

- Last-Modified

- Expires

- Cache-Control

Each header is only added if it isn’t already set.

cache_timeout is in seconds. The CACHE_MIDDLEWARE_SECONDS setting is used by default.

add_never_cache_headers(response)[source]

Adds a Cache-Control: max-age=0, no-cache, no-store, must-revalidate header to a response to indicate that a page should never be cached.

Changed in Django 1.8.8:
In older versions, Cache-Control: max-age=0 was sent. This didn’t reliably prevent caching in all browsers.

patch_vary_headers(response, newheaders)[source]

Adds (or updates) the Vary header in the given HttpResponse object. newheaders is a list of header names that should be in Vary. Existing headers in Vary aren’t removed.

get_cache_key(request, key_prefix=None)[source]

Returns a cache key based on the request path. It can be used in the request phase because it pulls the list of headers to take into account from the global path registry and uses those to build a cache key to check against.

If there is no headerlist stored, the page needs to be rebuilt, so this function returns None.

learn_cache_key(request, response, cache_timeout=None, key_prefix=None)[source]

Learns what headers to take into account for some request path from the response object. It stores those headers in a global path registry so that later access to that path will know what headers to take into account without building the response object itself. The headers are named in the Vary header of the response, but we want to prevent response generation.

The list of headers to use for cache key generation is stored in the same cache as the pages themselves. If the cache ages some data out of the cache, this just means that we have to build the response once to get at the Vary header and so at the list of headers to use for the cache key.

django.utils.dateparse

The functions defined in this module share the following properties:

- They raise ValueError if their input is well formatted but isn’t a valid date or time.

- They return None if it isn’t well formatted at all.

- They accept up to picosecond resolution in input, but they truncate it to microseconds, since that’s what Python supports.

parse_date(value)[source]

Parses a string and returns a datetime.date.

parse_time(value)[source]

Parses a string and returns a datetime.time.

UTC offsets aren’t supported; if value describes one, the result is None.

parse_datetime(value)[source]

Parses a string and returns a datetime.datetime.

UTC offsets are supported; if value describes one, the result’s tzinfo attribute is a FixedOffset instance.

parse_duration(value)[source]

New in Django 1.8.

Parses a string and returns a datetime.timedelta.

Expects data in the format "DD HH:MM:SS.uuuuuu" or as specified by ISO 8601 (e.g. P4DT1H15M20S which is equivalent to 4 1:15:20).

django.utils.decorators

method_decorator(decorator, name='')[source]

Converts a function decorator into a method decorator. It can be used to decorate methods or classes; in the latter case, name is the name of the method to be decorated and is required.

decorator may also be a list or tuple of functions. They are wrapped in reverse order so that the call order is the order in which the functions appear in the list/tuple.

See decorating class based views for example usage.

Changed in Django 1.9:
The ability to decorate classes, the name parameter, and the ability for decorator to accept a list/tuple of decorator functions were added.

decorator_from_middleware(middleware_class)[source]

Given a middleware class, returns a view decorator. This lets you use middleware functionality on a per-view basis. The middleware is created with no params passed.

decorator_from_middleware_with_args(middleware_class)[source]

Like decorator_from_middleware, but returns a function that accepts the arguments to be passed to the middleware_class. For example, the cache_page() decorator is created from the CacheMiddleware like this:

cache_page = decorator_from_middleware_with_args(CacheMiddleware)

@cache_page(3600)
def my_view(request):
pass

django.utils.encoding

python_2_unicode_compatible()[source]

A decorator that defines __unicode__ and __str__ methods under Python 2. Under Python 3 it does nothing.

To support Python 2 and 3 with a single code base, define a __str__ method returning text and apply this decorator to the class.

smart_text(s, encoding='utf-8', strings_only=False, errors='strict')[source]

Returns a text object representing s – unicode on Python 2 and str on Python 3. Treats bytestrings using the encoding codec.

If strings_only is True, don’t convert (some) non-string-like objects.

smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')

Historical name of smart_text(). Only available under Python 2.

is_protected_type(obj)[source]

Determine if the object instance is of a protected type.

Objects of protected types are preserved as-is when passed to force_text(strings_only=True).

force_text(s, encoding='utf-8', strings_only=False, errors='strict')[source]

Similar to smart_text, except that lazy instances are resolved to strings, rather than kept as lazy objects.

If strings_only is True, don’t convert (some) non-string-like objects.

force_unicode(s, encoding='utf-8', strings_only=False, errors='strict')

Historical name of force_text(). Only available under Python 2.

smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict')[source]

Returns a bytestring version of s, encoded as specified in encoding.

If strings_only is True, don’t convert (some) non-string-like objects.

force_bytes(s, encoding='utf-8', strings_only=False, errors='strict')[source]

Similar to smart_bytes, except that lazy instances are resolved to bytestrings, rather than kept as lazy objects.

If strings_only is True, don’t convert (some) non-string-like objects.

smart_str(s, encoding='utf-8', strings_only=False, errors='strict')

Alias of smart_bytes() on Python 2 and smart_text() on Python 3. This function returns a str or a lazy string.

For instance, this is suitable for writing to sys.stdout on Python 2 and 3.

force_str(s, encoding='utf-8', strings_only=False, errors='strict')

Alias of force_bytes() on Python 2 and force_text() on Python 3. This function always returns a str.

iri_to_uri(iri)[source]

Convert an Internationalized Resource Identifier (IRI) portion to a URI portion that is suitable for inclusion in a URL.

This is the algorithm from section 3.1 of RFC 3987#section-3.1. However, since we are assuming input is either UTF-8 or unicode already, we can simplify things a little from the full method.

Takes an IRI in UTF-8 bytes and returns ASCII bytes containing the encoded result.

uri_to_iri(uri)[source]

New in Django 1.8.

Converts a Uniform Resource Identifier into an Internationalized Resource Identifier.

This is an algorithm from section 3.2 of RFC 3987#section-3.2.

Takes a URI in ASCII bytes and returns a unicode string containing the encoded result.

filepath_to_uri(path)[source]

Convert a file system path to a URI portion that is suitable for inclusion in a URL. The path is assumed to be either UTF-8 or unicode.

This method will encode certain characters that would normally be recognized as special characters for URIs. Note that this method does not encode the ‘ character, as it is a valid character within URIs. See encodeURIComponent() JavaScript function for more details.

Returns an ASCII string containing the encoded result.

escape_uri_path(path)[source]

New in Django 1.8.

Escapes the unsafe characters from the path portion of a Uniform Resource Identifier (URI).

django.utils.feedgenerator

Sample usage:

>>> from django.utils import feedgenerator
>>> feed = feedgenerator.Rss201rev2Feed(
...     title="Poynter E-Media Tidbits",
...     link="http://www.poynter.org/column.asp?id=31",
...     description="A group Weblog by the sharpest minds in online media/journalism/publishing.",
...     language="en",
... )
>>> feed.add_item(
...     title="Hello",
...     link="http://www.holovaty.com/test/",
...     description="Testing.",
... )
>>> with open('test.rss', 'w') as fp:
...     feed.write(fp, 'utf-8')

For simplifying the selection of a generator use feedgenerator.DefaultFeed which is currently Rss201rev2Feed

For definitions of the different versions of RSS, see: https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/02/04/incompatible-rss

get_tag_uri(url, date)[source]

Creates a TagURI.

See https://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id

SyndicationFeed

class SyndicationFeed[source]

Base class for all syndication feeds. Subclasses should provide write().

__init__(title, link, description, language=None, author_email=None, author_name=None, author_link=None, subtitle=None, categories=None, feed_url=None, feed_copyright=None, feed_guid=None, ttl=None, **kwargs)[source]

Initialize the feed with the given dictionary of metadata, which applies to the entire feed.

Any extra keyword arguments you pass to __init__ will be stored in self.feed.

All parameters should be Unicode objects, except categories, which should be a sequence of Unicode objects.

add_item(title, link, description, author_email=None, author_name=None, author_link=None, pubdate=None, comments=None, unique_id=None, enclosure=None, categories=(), item_copyright=None, ttl=None, updateddate=None, enclosures=None, **kwargs)[source]

Adds an item to the feed. All args are expected to be Python unicode objects except pubdate and updateddate, which are datetime.datetime objects, enclosure, which is an Enclosure instance, and enclosures, which is a list of Enclosure instances.

Deprecated since version 1.9: The enclosure keyword argument is deprecated in favor of the new enclosures keyword argument which accepts a list of Enclosure objects.

num_items()[source]

root_attributes()[source]

Return extra attributes to place on the root (i.e. feed/channel) element. Called from write().

add_root_elements(handler)[source]

Add elements in the root (i.e. feed/channel) element. Called from write().

item_attributes(item)[source]

Return extra attributes to place on each item (i.e. item/entry) element.

add_item_elements(handler, item)[source]

Add elements on each item (i.e. item/entry) element.

write(outfile, encoding)[source]

Outputs the feed in the given encoding to outfile, which is a file-like object. Subclasses should override this.

writeString(encoding)[source]

Returns the feed in the given encoding as a string.

latest_post_date()[source]

Returns the latest pubdate or updateddate for all items in the feed. If no items have either of these attributes this returns the current date/time.

Enclosure

class Enclosure[source]

Represents an RSS enclosure

RssFeed

class RssFeed(SyndicationFeed)[source]

Rss201rev2Feed

class Rss201rev2Feed(RssFeed)[source]

Spec: https://cyber.law.harvard.edu/rss/rss.html

RssUserland091Feed

class RssUserland091Feed(RssFeed)[source]

Spec: http://backend.userland.com/rss091

Atom1Feed

class Atom1Feed(SyndicationFeed)[source]

Spec: https://tools.ietf.org/html/rfc4287

django.utils.functional

class cached_property(object, name)[source]

The @cached_property decorator caches the result of a method with a single self argument as a property. The cached result will persist as long as the instance does, so if the instance is passed around and the function subsequently invoked, the cached result will be returned.

Consider a typical case, where a view might need to call a model’s method to perform some computation, before placing the model instance into the context, where the template might invoke the method once more:

# the model
class Person(models.Model):

def friends(self):
# expensive computation
...
return friends

# in the view:
if person.friends():
...

And in the template you would have:

{% for friend in person.friends %}

Here, friends() will be called twice. Since the instance person in the view and the template are the same, @cached_property can avoid that:

from django.utils.functional import cached_property

@cached_property
def friends(self):
# expensive computation
...
return friends

Note that as the method is now a property, in Python code it will need to be invoked appropriately:

# in the view:
if person.friends:
...

The cached value can be treated like an ordinary attribute of the instance:

# clear it, requiring re-computation next time it's called
del person.friends # or delattr(person, "friends")

# set a value manually, that will persist on the instance until cleared
person.friends = ["Huckleberry Finn", "Tom Sawyer"]

As well as offering potential performance advantages, @cached_property can ensure that an attribute’s value does not change unexpectedly over the life of an instance. This could occur with a method whose computation is based on datetime.now(), or simply if a change were saved to the database by some other process in the brief interval between subsequent invocations of a method on the same instance.

New in Django 1.8.

You can use the name argument to make cached properties of other methods. For example, if you had an expensive get_friends() method and wanted to allow calling it without retrieving the cached value, you could write:

friends = cached_property(get_friends, name='friends')

While person.get_friends() will recompute the friends on each call, the value of the cached property will persist until you delete it as described above:

x = person.friends         # calls first time
y = person.get_friends()   # calls again
z = person.friends         # does not call
x is z                     # is True

allow_lazy(func, *resultclasses)[source]

Django offers many utility functions (particularly in django.utils) that take a string as their first argument and do something to that string. These functions are used by template filters as well as directly in other code.

If you write your own similar functions and deal with translations, you’ll face the problem of what to do when the first argument is a lazy translation object. You don’t want to convert it to a string immediately, because you might be using this function outside of a view (and hence the current thread’s locale setting will not be correct).

For cases like this, use the django.utils.functional.allow_lazy() decorator. It modifies the function so that if it’s called with a lazy translation as one of its arguments, the function evaluation is delayed until it needs to be converted to a string.

For example:

from django.utils.functional import allow_lazy

def fancy_utility_function(s, ...):
# Do some conversion on string 's'
...
# Replace unicode by str on Python 3
fancy_utility_function = allow_lazy(fancy_utility_function, unicode)

The allow_lazy() decorator takes, in addition to the function to decorate, a number of extra arguments (*args) specifying the type(s) that the original function can return. Usually, it’s enough to include unicode (or str on Python 3) here and ensure that your function returns only Unicode strings.

Using this decorator means you can write your function and assume that the input is a proper string, then add support for lazy translation objects at the end.

django.utils.html

Usually you should build up HTML using Django’s templates to make use of its autoescape mechanism, using the utilities in django.utils.safestring where appropriate. This module provides some additional low level utilities for escaping HTML.

escape(text)[source]

Returns the given text with ampersands, quotes and angle brackets encoded for use in HTML. The input is first passed through force_text() and the output has mark_safe() applied.

conditional_escape(text)[source]

Similar to escape(), except that it doesn’t operate on pre-escaped strings, so it will not double escape.

format_html(format_string, *args, **kwargs)[source]

This is similar to str.format(), except that it is appropriate for building up HTML fragments. All args and kwargs are passed through conditional_escape() before being passed to str.format().

For the case of building up small HTML fragments, this function is to be preferred over string interpolation using % or str.format() directly, because it applies escaping to all arguments - just like the template system applies escaping by default.

So, instead of writing:

mark_safe("%s <b>%s</b> %s" % (
some_html,
escape(some_text),
escape(some_other_text),
))

You should instead use:

format_html("{} <b>{}</b> {}",
mark_safe(some_html),
some_text,
some_other_text,
)

This has the advantage that you don’t need to apply escape() to each argument and risk a bug and an XSS vulnerability if you forget one.

Note that although this function uses str.format() to do the interpolation, some of the formatting options provided by str.format() (e.g. number formatting) will not work, since all arguments are passed through conditional_escape() which (ultimately) calls force_text() on the values.

format_html_join(sep, format_string, args_generator)[source]

A wrapper of format_html(), for the common case of a group of arguments that need to be formatted using the same format string, and then joined using sep. sep is also passed through conditional_escape().

args_generator should be an iterator that returns the sequence of args that will be passed to format_html(). For example:

format_html_join(
'\n', "<li>{} {}</li>",
((u.first_name, u.last_name) for u in users)
)

strip_tags(value)[source]

Tries to remove anything that looks like an HTML tag from the string, that is anything contained within <>.

Absolutely NO guarantee is provided about the resulting string being HTML safe. So NEVER mark safe the result of a strip_tag call without escaping it first, for example with escape().

For example:

strip_tags(value)

If value is "<b>Joel</b> <button>is</button> a <span>slug</span>" the return value will be "Joel is a slug".

If you are looking for a more robust solution, take a look at the bleach Python library.

remove_tags(value, tags)[source]

Deprecated since version 1.8: remove_tags() cannot guarantee HTML safe output and has been deprecated due to security concerns. Consider using bleach instead.

Removes a space-separated list of [X]HTML tag names from the output.

Absolutely NO guarantee is provided about the resulting string being HTML safe. In particular, it doesn’t work recursively, so the output of remove_tags("<sc<script>ript>alert('XSS')</sc</script>ript>", "script") won’t remove the “nested” script tags. So if the value is untrusted, NEVER mark safe the result of a remove_tags() call without escaping it first, for example with escape().

For example:

remove_tags(value, "b span")

If value is "<b>Joel</b> <button>is</button> a <span>slug</span>" the return value will be "Joel <button>is</button> a slug".

Note that this filter is case-sensitive.

If value is "<B>Joel</B> <button>is</button> a <span>slug</span>" the return value will be "<B>Joel</B> <button>is</button> a slug".

html_safe()[source]

New in Django 1.8.

The __html__() method on a class helps non-Django templates detect classes whose output doesn’t require HTML escaping.

This decorator defines the __html__() method on the decorated class by wrapping the __unicode__() (Python 2) or __str__() (Python 3) in mark_safe(). Ensure the __unicode__() or __str__() method does indeed return text that doesn’t require HTML escaping.

django.utils.http

urlquote(url, safe='/')[source]

A version of Python’s urllib.quote() function that can operate on unicode strings. The url is first UTF-8 encoded before quoting. The returned string can safely be used as part of an argument to a subsequent iri_to_uri() call without double-quoting occurring. Employs lazy execution.

urlquote_plus(url, safe='')[source]

A version of Python’s urllib.quote_plus() function that can operate on unicode strings. The url is first UTF-8 encoded before quoting. The returned string can safely be used as part of an argument to a subsequent iri_to_uri() call without double-quoting occurring. Employs lazy execution.

urlencode(query, doseq=0)[source]

A version of Python’s urllib.urlencode() function that can operate on unicode strings. The parameters are first cast to UTF-8 encoded strings and then encoded as per normal.

cookie_date(epoch_seconds=None)[source]

Formats the time to ensure compatibility with Netscape’s cookie standard.

Accepts a floating point number expressed in seconds since the epoch in UTC–such as that outputted by time.time(). If set to None, defaults to the current time.

Outputs a string in the format Wdy, DD-Mon-YYYY HH:MM:SS GMT.

http_date(epoch_seconds=None)[source]

Formats the time to match the RFC 1123 date format as specified by HTTP RFC 7231#section-7.1.1.1.

Accepts a floating point number expressed in seconds since the epoch in UTC–such as that outputted by time.time(). If set to None, defaults to the current time.

Outputs a string in the format Wdy, DD Mon YYYY HH:MM:SS GMT.

base36_to_int(s)[source]

Converts a base 36 string to an integer. On Python 2 the output is guaranteed to be an int and not a long.

int_to_base36(i)[source]

Converts a positive integer to a base 36 string. On Python 2 i must be smaller than sys.maxint.

urlsafe_base64_encode(s)[source]

Encodes a bytestring in base64 for use in URLs, stripping any trailing equal signs.

urlsafe_base64_decode(s)[source]

Decodes a base64 encoded string, adding back any trailing equal signs that might have been stripped.

django.utils.module_loading

Functions for working with Python modules.

import_string(dotted_path)[source]

Imports a dotted module path and returns the attribute/class designated by the last name in the path. Raises ImportError if the import failed. For example:

from django.utils.module_loading import import_string
ValidationError = import_string('django.core.exceptions.ValidationError')

is equivalent to:

from django.core.exceptions import ValidationError

django.utils.safestring

Functions and classes for working with “safe strings”: strings that can be displayed safely without further escaping in HTML. Marking something as a “safe string” means that the producer of the string has already turned characters that should not be interpreted by the HTML engine (e.g. ‘<’) into the appropriate entities.

class SafeBytes[source]

A bytes subclass that has been specifically marked as “safe” (requires no further escaping) for HTML output purposes.

class SafeString

A str subclass that has been specifically marked as “safe” (requires no further escaping) for HTML output purposes. This is SafeBytes on Python 2 and SafeText on Python 3.

class SafeText[source]

A str (in Python 3) or unicode (in Python 2) subclass that has been specifically marked as “safe” for HTML output purposes.

class SafeUnicode

Historical name of SafeText. Only available under Python 2.

mark_safe(s)[source]

Explicitly mark a string as safe for (HTML) output purposes. The returned object can be used everywhere a string or unicode object is appropriate.

Can be called multiple times on a single string.

For building up fragments of HTML, you should normally be using django.utils.html.format_html() instead.

String marked safe will become unsafe again if modified. For example:

>>> mystr = '<b>Hello World</b>   '
>>> mystr = mark_safe(mystr)
>>> type(mystr)
<class 'django.utils.safestring.SafeBytes'>

>>> mystr = mystr.strip()  # removing whitespace
>>> type(mystr)
<type 'str'>

mark_for_escaping(s)[source]

Explicitly mark a string as requiring HTML escaping upon output. Has no effect on SafeData subclasses.

Can be called multiple times on a single string (the resulting escaping is only applied once).

django.utils.text

slugify(allow_unicode=False)[source]

Converts to ASCII if allow_unicode is False (default). Converts spaces to hyphens. Removes characters that aren’t alphanumerics, underscores, or hyphens. Converts to lowercase. Also strips leading and trailing whitespace.

For example:

slugify(value)

If value is "Joel is a slug", the output will be "joel-is-a-slug".

You can set the allow_unicode parameter to True, if you want to allow Unicode characters:

slugify(value, allow_unicode=True)

If value is "你好 World", the output will be "你好-world".

Changed in Django 1.9:
The allow_unicode parameter was added.

django.utils.timezone

utc

tzinfo instance that represents UTC.

class FixedOffset(offset=None, name=None)[source]

A tzinfo subclass modeling a fixed offset from UTC. offset is an integer number of minutes east of UTC.

get_fixed_timezone(offset)[source]

Returns a tzinfo instance that represents a time zone with a fixed offset from UTC.

offset is a datetime.timedelta or an integer number of minutes. Use positive values for time zones east of UTC and negative values for west of UTC.

get_default_timezone()[source]

Returns a tzinfo instance that represents the default time zone.

get_default_timezone_name()[source]

Returns the name of the default time zone.

get_current_timezone()[source]

Returns a tzinfo instance that represents the current time zone.

get_current_timezone_name()[source]

Returns the name of the current time zone.

activate(timezone)[source]

Sets the current time zone. The timezone argument must be an instance of a tzinfo subclass or, if pytz is available, a time zone name.

deactivate()[source]

Unsets the current time zone.

override(timezone)[source]

This is a Python context manager that sets the current time zone on entry with activate(), and restores the previously active time zone on exit. If the timezone argument is None, the current time zone is unset on entry with deactivate() instead.

Changed in Django 1.8:
override is now usable as a function decorator.

localtime(value, timezone=None)[source]

Converts an aware datetime to a different time zone, by default the current time zone.

This function doesn’t work on naive datetimes; use make_aware() instead.

now()[source]

Returns a datetime that represents the current point in time. Exactly what’s returned depends on the value of USE_TZ:

- If USE_TZ is False, this will be a naive datetime (i.e. a datetime without an associated timezone) that represents the current time in the system’s local timezone.

- If USE_TZ is True, this will be an aware datetime representing the current time in UTC. Note that now() will always return times in UTC regardless of the value of TIME_ZONE; you can use localtime() to convert to a time in the current time zone.

is_aware(value)[source]

Returns True if value is aware, False if it is naive. This function assumes that value is a datetime.

is_naive(value)[source]

Returns True if value is naive, False if it is aware. This function assumes that value is a datetime.

make_aware(value, timezone=None, is_dst=None)[source]

Returns an aware datetime that represents the same point in time as value in timezone, value being a naive datetime. If timezone is set to None, it defaults to the current time zone.

When pytz is installed, the exception pytz.AmbiguousTimeError will be raised if you try to make value aware during a DST transition where the same time occurs twice (when reverting from DST). Setting is_dst to True or False will avoid the exception by choosing if the time is pre-transition or post-transition respectively.

When pytz is installed, the exception pytz.NonExistentTimeError will be raised if you try to make value aware during a DST transition such that the time never occurred (when entering into DST). Setting is_dst to True or False will avoid the exception by moving the hour backwards or forwards by 1 respectively. For example, is_dst=True would change a non-existent time of 2:30 to 1:30 and is_dst=False would change the time to 3:30.

is_dst has no effect when pytz is not installed.

Changed in Django 1.8:
In older versions of Django, timezone was a required argument.

Changed in Django 1.9:
The is_dst argument was added.

make_naive(value, timezone=None)[source]

Returns an naive datetime that represents in timezone the same point in time as value, value being an aware datetime. If timezone is set to None, it defaults to the current time zone.

Changed in Django 1.8:
In older versions of Django, timezone was a required argument.

django.utils.translation

For a complete discussion on the usage of the following see the translation documentation.

gettext(message)[source]

Translates message and returns it in a UTF-8 bytestring

ugettext(message)[source]

Translates message and returns it in a unicode string

pgettext(context, message)[source]

Translates message given the context and returns it in a unicode string.

For more information, see Contextual markers.

gettext_lazy(message)

ugettext_lazy(message)

pgettext_lazy(context, message)

Same as the non-lazy versions above, but using lazy execution.

See lazy translations documentation.

gettext_noop(message)[source]

ugettext_noop(message)

Marks strings for translation but doesn’t translate them now. This can be used to store strings in global variables that should stay in the base language (because they might be used externally) and will be translated later.

ngettext(singular, plural, number)[source]

Translates singular and plural and returns the appropriate string based on number in a UTF-8 bytestring.

ungettext(singular, plural, number)[source]

Translates singular and plural and returns the appropriate string based on number in a unicode string.

npgettext(context, singular, plural, number)[source]

Translates singular and plural and returns the appropriate string based on number and the context in a unicode string.

ngettext_lazy(singular, plural, number)[source]

ungettext_lazy(singular, plural, number)[source]

npgettext_lazy(context, singular, plural, number)[source]

Same as the non-lazy versions above, but using lazy execution.

See lazy translations documentation.

string_concat(*strings)

Lazy variant of string concatenation, needed for translations that are constructed from multiple parts.

activate(language)[source]

Fetches the translation object for a given language and activates it as the current translation object for the current thread.

deactivate()[source]

Deactivates the currently active translation object so that further _ calls will resolve against the default translation object, again.

deactivate_all()[source]

Makes the active translation object a NullTranslations() instance. This is useful when we want delayed translations to appear as the original string for some reason.

override(language, deactivate=False)[source]

A Python context manager that uses django.utils.translation.activate() to fetch the translation object for a given language, activates it as the translation object for the current thread and reactivates the previous active language on exit. Optionally, it can simply deactivate the temporary translation on exit with django.utils.translation.deactivate() if the deactivate argument is True. If you pass None as the language argument, a NullTranslations() instance is activated within the context.

Changed in Django 1.8:
override is now usable as a function decorator.

check_for_language(lang_code)[source]

Checks whether there is a global language file for the given language code (e.g. ‘fr’, ‘pt_BR’). This is used to decide whether a user-provided language is available.

get_language()[source]

Returns the currently selected language code. Returns None if translations are temporarily deactivated (by deactivate_all() or when None is passed to override()).

Changed in Django 1.8:
Before Django 1.8, get_language() always returned LANGUAGE_CODE when translations were deactivated.

get_language_bidi()[source]

Returns selected language’s BiDi layout:

- False = left-to-right layout

- True = right-to-left layout

get_language_from_request(request, check_path=False)[source]

Analyzes the request to find what language the user wants the system to show. Only languages listed in settings.LANGUAGES are taken into account. If the user requests a sublanguage where we have a main language, we send out the main language.

If check_path is True, the function first checks the requested URL for whether its path begins with a language code listed in the LANGUAGES setting.

to_locale(language)[source]

Turns a language name (en-us) into a locale name (en_US).

templatize(src)[source]

Turns a Django template into something that is understood by xgettext. It does so by translating the Django translation tags into standard gettext function invocations.

LANGUAGE_SESSION_KEY

Session key under which the active language for the current session is stored.

Validators

Writing validators

A validator is a callable that takes a value and raises a ValidationError if it doesn’t meet some criteria. Validators can be useful for re-using validation logic between different types of fields.

For example, here’s a validator that only allows even numbers:

from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _

def validate_even(value):
if value % 2 != 0:
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)

You can add this to a model field via the field’s validators argument:

from django.db import models

class MyModel(models.Model):
even_field = models.IntegerField(validators=[validate_even])

Because values are converted to Python before validators are run, you can even use the same validator with forms:

from django import forms

class MyForm(forms.Form):
even_field = forms.IntegerField(validators=[validate_even])

You can also use a class with a __call__() method for more complex or configurable validators. RegexValidator, for example, uses this technique. If a class-based validator is used in the validators model field option, you should make sure it is serializable by the migration framework by adding deconstruct() and __eq__() methods.

How validators are run

See the form validation for more information on how validators are run in forms, and Validating objects for how they’re run in models. Note that validators will not be run automatically when you save a model, but if you are using a ModelForm, it will run your validators on any fields that are included in your form. See the ModelForm documentation for information on how model validation interacts with forms.

Built-in validators

The django.core.validators module contains a collection of callable validators for use with model and form fields. They’re used internally but are available for use with your own fields, too. They can be used in addition to, or in lieu of custom field.clean() methods.

RegexValidator

class RegexValidator(regex=None, message=None, code=None, inverse_match=None, flags=0)[source]

Parameters:

- regex – If not None, overrides regex. Can be a regular expression string or a pre-compiled regular expression.

- message – If not None, overrides message.

- code – If not None, overrides code.

- inverse_match – If not None, overrides inverse_match.

- flags – If not None, overrides flags. In that case, regex must be a regular expression string, or TypeError is raised.

regex

The regular expression pattern to search for the provided value, or a pre-compiled regular expression. By default, raises a ValidationError with message and code if a match is not found. That standard behavior can be reversed by setting inverse_match to True, in which case the ValidationError is raised when a match is found. By default, matches any string (including an empty string).

message

The error message used by ValidationError if validation fails. Defaults to "Enter a valid value".

code

The error code used by ValidationError if validation fails. Defaults to "invalid".

inverse_match

The match mode for regex. Defaults to False.

flags

The flags used when compiling the regular expression string regex. If regex is a pre-compiled regular expression, and flags is overridden, TypeError is raised. Defaults to 0.

EmailValidator

class EmailValidator(message=None, code=None, whitelist=None)[source]

Parameters:

- message – If not None, overrides message.

- code – If not None, overrides code.

- whitelist – If not None, overrides whitelist.

message

The error message used by ValidationError if validation fails. Defaults to "Enter a valid email address".

code

The error code used by ValidationError if validation fails. Defaults to "invalid".

whitelist

Whitelist of email domains to allow. By default, a regular expression (the domain_regex attribute) is used to validate whatever appears after the @ sign. However, if that string appears in the whitelist, this validation is bypassed. If not provided, the default whitelist is ['localhost']. Other domains that don’t contain a dot won’t pass validation, so you’d need to whitelist them as necessary.

URLValidator

class URLValidator(schemes=None, regex=None, message=None, code=None)[source]

A RegexValidator that ensures a value looks like a URL, and raises an error code of 'invalid' if it doesn’t.

Loopback addresses and reserved IP spaces are considered valid. Literal IPv6 addresses (RFC 2732) and unicode domains are both supported.

In addition to the optional arguments of its parent RegexValidator class, URLValidator accepts an extra optional attribute:

schemes

URL/URI scheme list to validate against. If not provided, the default list is ['http', 'https', 'ftp', 'ftps']. As a reference, the IANA website provides a full list of valid URI schemes.

Changed in Django 1.8:
Support for IPv6 addresses, unicode domains, and URLs containing authentication data was added.

validate_email

validate_email

An EmailValidator instance without any customizations.

validate_slug

validate_slug

A RegexValidator instance that ensures a value consists of only letters, numbers, underscores or hyphens.

validate_unicode_slug

validate_unicode_slug

New in Django 1.9.

A RegexValidator instance that ensures a value consists of only Unicode letters, numbers, underscores, or hyphens.

validate_ipv4_address

validate_ipv4_address

A RegexValidator instance that ensures a value looks like an IPv4 address.

validate_ipv6_address

validate_ipv6_address[source]

Uses django.utils.ipv6 to check the validity of an IPv6 address.

validate_ipv46_address

validate_ipv46_address[source]

Uses both validate_ipv4_address and validate_ipv6_address to ensure a value is either a valid IPv4 or IPv6 address.

validate_comma_separated_integer_list

validate_comma_separated_integer_list

A RegexValidator instance that ensures a value is a comma-separated list of integers.

int_list_validator

int_list_validator(sep=', ', message=None, code='invalid')[source]

New in Django 1.9.

Returns a RegexValidator instance that ensures a string consists of integers separated by sep.

MaxValueValidator

class MaxValueValidator(max_value, message=None)[source]

Raises a ValidationError with a code of 'max_value' if value is greater than max_value.

Changed in Django 1.8:
The message parameter was added.

MinValueValidator

class MinValueValidator(min_value, message=None)[source]

Raises a ValidationError with a code of 'min_value' if value is less than min_value.

Changed in Django 1.8:
The message parameter was added.

MaxLengthValidator

class MaxLengthValidator(max_length, message=None)[source]

Raises a ValidationError with a code of 'max_length' if the length of value is greater than max_length.

Changed in Django 1.8:
The message parameter was added.

MinLengthValidator

class MinLengthValidator(min_length, message=None)[source]

Raises a ValidationError with a code of 'min_length' if the length of value is less than min_length.

Changed in Django 1.8:
The message parameter was added.

DecimalValidator

class DecimalValidator(max_digits, decimal_places)[source]

New in Django 1.9.

Raises ValidationError with the following codes:

- 'max_digits' if the number of digits is larger than max_digits.

- 'max_decimal_places' if the number of decimals is larger than decimal_places.

- 'max_whole_digits' if the number of whole digits is larger than the difference between max_digits and decimal_places.

Built-in Views

Several of Django’s built-in views are documented in Writing views as well as elsewhere in the documentation.

Serving files in development

static.serve(request, path, document_root, show_indexes=False)

There may be files other than your project’s static assets that, for convenience, you’d like to have Django serve for you in local development. The serve() view can be used to serve any directory you give it. (This view is not hardened for production use and should be used only as a development aid; you should serve these files in production using a real front-end web server).

The most likely example is user-uploaded content in MEDIA_ROOT. django.contrib.staticfiles is intended for static assets and has no built-in handling for user-uploaded files, but you can have Django serve your MEDIA_ROOT by appending something like this to your URLconf:

from django.conf import settings
from django.views.static import serve

# ... the rest of your URLconf goes here ...

if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT,
}),
]

Note, the snippet assumes your MEDIA_URL has a value of '/media/'. This will call the serve() view, passing in the path from the URLconf and the (required) document_root parameter.

Since it can become a bit cumbersome to define this URL pattern, Django ships with a small URL helper function static() that takes as parameters the prefix such as MEDIA_URL and a dotted path to a view, such as 'django.views.static.serve'. Any other function parameter will be transparently passed to the view.

Error views

Django comes with a few views by default for handling HTTP errors. To override these with your own custom views, see Customizing error views.

The 404 (page not found) view

defaults.page_not_found(request, exception, template_name='404.html')

When you raise Http404 from within a view, Django loads a special view devoted to handling 404 errors. By default, it’s the view django.views.defaults.page_not_found(), which either produces a very simple “Not Found” message or loads and renders the template 404.html if you created it in your root template directory.

The default 404 view will pass two variables to the template: request_path, which is the URL that resulted in the error, and exception, which is a useful representation of the exception that triggered the view (e.g. containing any message passed to a specific Http404 instance).

Three things to note about 404 views:

- The 404 view is also called if Django doesn’t find a match after checking every regular expression in the URLconf.

- The 404 view is passed a RequestContext and will have access to variables supplied by your template context processors (e.g. MEDIA_URL).

- If DEBUG is set to True (in your settings module), then your 404 view will never be used, and your URLconf will be displayed instead, with some debug information.

Changed in Django 1.9:
The signature of page_not_found() changed. The function now accepts a second parameter, the exception that triggered the error. A useful representation of the exception is also passed in the template context.

The 500 (server error) view

defaults.server_error(request, template_name='500.html')

Similarly, Django executes special-case behavior in the case of runtime errors in view code. If a view results in an exception, Django will, by default, call the view django.views.defaults.server_error, which either produces a very simple “Server Error” message or loads and renders the template 500.html if you created it in your root template directory.

The default 500 view passes no variables to the 500.html template and is rendered with an empty Context to lessen the chance of additional errors.

If DEBUG is set to True (in your settings module), then your 500 view will never be used, and the traceback will be displayed instead, with some debug information.

The 403 (HTTP Forbidden) view

defaults.permission_denied(request, exception, template_name='403.html')

In the same vein as the 404 and 500 views, Django has a view to handle 403 Forbidden errors. If a view results in a 403 exception then Django will, by default, call the view django.views.defaults.permission_denied.

This view loads and renders the template 403.html in your root template directory, or if this file does not exist, instead serves the text “403 Forbidden”, as per RFC 7231#section-6.5.3 (the HTTP 1.1 Specification). The template context contains exception, which is the unicode representation of the exception that triggered the view.

django.views.defaults.permission_denied is triggered by a PermissionDenied exception. To deny access in a view you can use code like this:

from django.core.exceptions import PermissionDenied

def edit(request, pk):
if not request.user.is_staff:
raise PermissionDenied
# ...

Changed in Django 1.9:
The signature of permission_denied() changed in Django 1.9. The function now accepts a second parameter, the exception that triggered the error. The unicode representation of the exception is also passed in the template context.

The 400 (bad request) view

defaults.bad_request(request, exception, template_name='400.html')

When a SuspiciousOperation is raised in Django, it may be handled by a component of Django (for example resetting the session data). If not specifically handled, Django will consider the current request a ‘bad request’ instead of a server error.

django.views.defaults.bad_request, is otherwise very similar to the server_error view, but returns with the status code 400 indicating that the error condition was the result of a client operation. By default, nothing related to the exception that triggered the view is passed to the template context, as the exception message might contain sensitive information like filesystem paths.

bad_request views are also only used when DEBUG is False.

Changed in Django 1.9:
The signature of bad_request() changed in Django 1.9. The function now accepts a second parameter, the exception that triggered the error.

Meta-documentation and miscellany

Documentation that we can’t find a more organized place for. Like that drawer in your kitchen with the scissors, batteries, duct tape, and other junk.

- API stability

- What “stable” means

- Stable APIs

- Exceptions

- Design philosophies

- Overall

- Models

- Database API

- URL design

- Template system

- Views

- Cache Framework

- Third-party distributions of Django

- For distributors

API stability

Django promises API stability and forwards-compatibility since version 1.0. In a nutshell, this means that code you develop against a version of Django will continue to work with future releases. You may need to make minor changes when upgrading the version of Django your project uses: see the “Backwards incompatible changes” section of the release note for the version or versions to which you are upgrading.

What “stable” means

In this context, stable means:

- All the public APIs (everything in this documentation) will not be moved or renamed without providing backwards-compatible aliases.

- If new features are added to these APIs – which is quite possible – they will not break or change the meaning of existing methods. In other words, “stable” does not (necessarily) mean “complete.”

- If, for some reason, an API declared stable must be removed or replaced, it will be declared deprecated but will remain in the API for at least two feature releases. Warnings will be issued when the deprecated method is called.

See Official releases for more details on how Django’s version numbering scheme works, and how features will be deprecated.

- We’ll only break backwards compatibility of these APIs if a bug or security hole makes it completely unavoidable.

Stable APIs

In general, everything covered in the documentation – with the exception of anything in the internals area is considered stable.

Exceptions

There are a few exceptions to this stability and backwards-compatibility promise.

Security fixes

If we become aware of a security problem – hopefully by someone following our security reporting policy – we’ll do everything necessary to fix it. This might mean breaking backwards compatibility; security trumps the compatibility guarantee.

APIs marked as internal

Certain APIs are explicitly marked as “internal” in a couple of ways:

- Some documentation refers to internals and mentions them as such. If the documentation says that something is internal, we reserve the right to change it.

- Functions, methods, and other objects prefixed by a leading underscore (_). This is the standard Python way of indicating that something is private; if any method starts with a single _, it’s an internal API.

Design philosophies

This document explains some of the fundamental philosophies Django’s developers have used in creating the framework. Its goal is to explain the past and guide the future.

Overall

Loose coupling

A fundamental goal of Django’s stack is loose coupling and tight cohesion. The various layers of the framework shouldn’t “know” about each other unless absolutely necessary.

For example, the template system knows nothing about Web requests, the database layer knows nothing about data display and the view system doesn’t care which template system a programmer uses.

Although Django comes with a full stack for convenience, the pieces of the stack are independent of another wherever possible.

Less code

Django apps should use as little code as possible; they should lack boilerplate. Django should take full advantage of Python’s dynamic capabilities, such as introspection.

Quick development

The point of a Web framework in the 21st century is to make the tedious aspects of Web development fast. Django should allow for incredibly quick Web development.

Don’t repeat yourself (DRY)

Every distinct concept and/or piece of data should live in one, and only one, place. Redundancy is bad. Normalization is good.

The framework, within reason, should deduce as much as possible from as little as possible.

See also

The discussion of DRY on the Portland Pattern Repository

Explicit is better than implicit

This is a core Python principle listed in PEP 20, and it means Django shouldn’t do too much “magic.” Magic shouldn’t happen unless there’s a really good reason for it. Magic is worth using only if it creates a huge convenience unattainable in other ways, and it isn’t implemented in a way that confuses developers who are trying to learn how to use the feature.

Consistency

The framework should be consistent at all levels. Consistency applies to everything from low-level (the Python coding style used) to high-level (the “experience” of using Django).

Models

Explicit is better than implicit

Fields shouldn’t assume certain behaviors based solely on the name of the field. This requires too much knowledge of the system and is prone to errors. Instead, behaviors should be based on keyword arguments and, in some cases, on the type of the field.

Include all relevant domain logic

Models should encapsulate every aspect of an “object,” following Martin Fowler’s Active Record design pattern.

This is why both the data represented by a model and information about it (its human-readable name, options like default ordering, etc.) are defined in the model class; all the information needed to understand a given model should be stored in the model.

Database API

The core goals of the database API are:

SQL efficiency

It should execute SQL statements as few times as possible, and it should optimize statements internally.

This is why developers need to call save() explicitly, rather than the framework saving things behind the scenes silently.

This is also why the select_related() QuerySet method exists. It’s an optional performance booster for the common case of selecting “every related object.”

Terse, powerful syntax

The database API should allow rich, expressive statements in as little syntax as possible. It should not rely on importing other modules or helper objects.

Joins should be performed automatically, behind the scenes, when necessary.

Every object should be able to access every related object, systemwide. This access should work both ways.

Option to drop into raw SQL easily, when needed

The database API should realize it’s a shortcut but not necessarily an end-all-be-all. The framework should make it easy to write custom SQL – entire statements, or just custom WHERE clauses as custom parameters to API calls.

URL design

Loose coupling

URLs in a Django app should not be coupled to the underlying Python code. Tying URLs to Python function names is a Bad And Ugly Thing.

Along these lines, the Django URL system should allow URLs for the same app to be different in different contexts. For example, one site may put stories at /stories/, while another may use /news/.

Infinite flexibility

URLs should be as flexible as possible. Any conceivable URL design should be allowed.

Encourage best practices

The framework should make it just as easy (or even easier) for a developer to design pretty URLs than ugly ones.

File extensions in Web-page URLs should be avoided.

Vignette-style commas in URLs deserve severe punishment.

Definitive URLs

Technically, foo.com/bar and foo.com/bar/ are two different URLs, and search-engine robots (and some Web traffic-analyzing tools) would treat them as separate pages. Django should make an effort to “normalize” URLs so that search-engine robots don’t get confused.

This is the reasoning behind the APPEND_SLASH setting.

Template system

Separate logic from presentation

We see a template system as a tool that controls presentation and presentation-related logic – and that’s it. The template system shouldn’t support functionality that goes beyond this basic goal.

Discourage redundancy

The majority of dynamic websites use some sort of common sitewide design – a common header, footer, navigation bar, etc. The Django template system should make it easy to store those elements in a single place, eliminating duplicate code.

This is the philosophy behind template inheritance.

Be decoupled from HTML

The template system shouldn’t be designed so that it only outputs HTML. It should be equally good at generating other text-based formats, or just plain text.

XML should not be used for template languages

Using an XML engine to parse templates introduces a whole new world of human error in editing templates – and incurs an unacceptable level of overhead in template processing.

Assume designer competence

The template system shouldn’t be designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of a limitation and wouldn’t allow the syntax to be as nice as it is. Django expects template authors are comfortable editing HTML directly.

Treat whitespace obviously

The template system shouldn’t do magic things with whitespace. If a template includes whitespace, the system should treat the whitespace as it treats text – just display it. Any whitespace that’s not in a template tag should be displayed.

Don’t invent a programming language

The goal is not to invent a programming language. The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions. The Django Template Language (DTL) aims to avoid advanced logic.

The Django template system recognizes that templates are most often written by designers, not programmers, and therefore should not assume Python knowledge.

Safety and security

The template system, out of the box, should forbid the inclusion of malicious code – such as commands that delete database records.

This is another reason the template system doesn’t allow arbitrary Python code.

Extensibility

The template system should recognize that advanced template authors may want to extend its technology.

This is the philosophy behind custom template tags and filters.

Views

Simplicity

Writing a view should be as simple as writing a Python function. Developers shouldn’t have to instantiate a class when a function will do.

Use request objects

Views should have access to a request object – an object that stores metadata about the current request. The object should be passed directly to a view function, rather than the view function having to access the request data from a global variable. This makes it light, clean and easy to test views by passing in “fake” request objects.

Loose coupling

A view shouldn’t care about which template system the developer uses – or even whether a template system is used at all.

Differentiate between GET and POST

GET and POST are distinct; developers should explicitly use one or the other. The framework should make it easy to distinguish between GET and POST data.

Cache Framework

The core goals of Django’s cache framework are:

Less code

A cache should be as fast as possible. Hence, all framework code surrounding the cache backend should be kept to the absolute minimum, especially for get() operations.

Consistency

The cache API should provide a consistent interface across the different cache backends.

Extensibility

The cache API should be extensible at the application level based on the developer’s needs (for example, see Cache key transformation).

Third-party distributions of Django

Many third-party distributors are now providing versions of Django integrated with their package-management systems. These can make installation and upgrading much easier for users of Django since the integration includes the ability to automatically install dependencies (like database adapters) that Django requires.

Typically, these packages are based on the latest stable release of Django, so if you want to use the development version of Django you’ll need to follow the instructions for installing the development version from our Git repository.

If you’re using Linux or a Unix installation, such as OpenSolaris, check with your distributor to see if they already package Django. If you’re using a Linux distro and don’t know how to find out if a package is available, then now is a good time to learn. The Django Wiki contains a list of Third Party Distributions to help you out.

For distributors

If you’d like to package Django for distribution, we’d be happy to help out! Please join the django-developers mailing list and introduce yourself.

We also encourage all distributors to subscribe to the django-announce mailing list, which is a (very) low-traffic list for announcing new releases of Django and important bugfixes.

Glossary

concrete model

A non-abstract (abstract=False) model.

field

An attribute on a model; a given field usually maps directly to a single database column.

See Models.

generic view

A higher-order view function that provides an abstract/generic implementation of a common idiom or pattern found in view development.

See Class-based views.

model

Models store your application’s data.

See Models.

MTV

“Model-template-view”; a software pattern, similar in style to MVC, but a better description of the way Django does things.

See the FAQ entry.

MVC

Model-view-controller; a software pattern. Django follows MVC to some extent.

project

A Python package – i.e. a directory of code – that contains all the settings for an instance of Django. This would include database configuration, Django-specific options and application-specific settings.

property

Also known as “managed attributes”, and a feature of Python since version 2.2. This is a neat way to implement attributes whose usage resembles attribute access, but whose implementation uses method calls.

See property.

queryset

An object representing some set of rows to be fetched from the database.

See Making queries.

slug

A short label for something, containing only letters, numbers, underscores or hyphens. They’re generally used in URLs. For example, in a typical blog entry URL:

https://www.djangoproject.com/weblog/2008/apr/12/spring/

the last bit (spring) is the slug.

template

A chunk of text that acts as formatting for representing data. A template helps to abstract the presentation of data from the data itself.

See Templates.

view

A function responsible for rendering a page.

Release notes

Release notes for the official Django releases. Each release note will tell you what’s new in each version, and will also describe any backwards-incompatible changes made in that version.

For those upgrading to a new version of Django, you will need to check all the backwards-incompatible changes and deprecated features for each ‘final’ release from the one after your current Django version, up to and including the new version.

Final releases

Below are release notes through Django 1.9 and its patch releases. Newer versions of the documentation contain the release notes for any later releases.

1.9 release

- Django 1.9.9 release notes

- Django 1.9.8 release notes

- Django 1.9.7 release notes

- Django 1.9.6 release notes

- Django 1.9.5 release notes

- Django 1.9.4 release notes

- Django 1.9.3 release notes

- Django 1.9.2 release notes

- Django 1.9.1 release notes

- Django 1.9 release notes

1.8 release

- Django 1.8.14 release notes

- Django 1.8.13 release notes

- Django 1.8.12 release notes

- Django 1.8.11 release notes

- Django 1.8.10 release notes

- Django 1.8.9 release notes

- Django 1.8.8 release notes

- Django 1.8.7 release notes

- Django 1.8.6 release notes

- Django 1.8.5 release notes

- Django 1.8.4 release notes

- Django 1.8.3 release notes

- Django 1.8.2 release notes

- Django 1.8.1 release notes

- Django 1.8 release notes

1.7 release

- Django 1.7.11 release notes

- Django 1.7.10 release notes

- Django 1.7.9 release notes

- Django 1.7.8 release notes

- Django 1.7.7 release notes

- Django 1.7.6 release notes

- Django 1.7.5 release notes

- Django 1.7.4 release notes

- Django 1.7.3 release notes

- Django 1.7.2 release notes

- Django 1.7.1 release notes

- Django 1.7 release notes

1.6 release

- Django 1.6.11 release notes

- Django 1.6.10 release notes

- Django 1.6.9 release notes

- Django 1.6.8 release notes

- Django 1.6.7 release notes

- Django 1.6.6 release notes

- Django 1.6.5 release notes

- Django 1.6.4 release notes

- Django 1.6.3 release notes

- Django 1.6.2 release notes

- Django 1.6.1 release notes

- Django 1.6 release notes

1.5 release

- Django 1.5.12 release notes

- Django 1.5.11 release notes

- Django 1.5.10 release notes

- Django 1.5.9 release notes

- Django 1.5.8 release notes

- Django 1.5.7 release notes

- Django 1.5.6 release notes

- Django 1.5.5 release notes

- Django 1.5.4 release notes

- Django 1.5.3 release notes

- Django 1.5.2 release notes

- Django 1.5.1 release notes

- Django 1.5 release notes

1.4 release

- Django 1.4.22 release notes

- Django 1.4.21 release notes

- Django 1.4.20 release notes

- Django 1.4.19 release notes

- Django 1.4.18 release notes

- Django 1.4.17 release notes

- Django 1.4.16 release notes

- Django 1.4.15 release notes

- Django 1.4.14 release notes

- Django 1.4.13 release notes

- Django 1.4.12 release notes

- Django 1.4.11 release notes

- Django 1.4.10 release notes

- Django 1.4.9 release notes

- Django 1.4.8 release notes

- Django 1.4.7 release notes

- Django 1.4.6 release notes

- Django 1.4.5 release notes

- Django 1.4.4 release notes

- Django 1.4.3 release notes

- Django 1.4.2 release notes

- Django 1.4.1 release notes

- Django 1.4 release notes

1.3 release

- Django 1.3.7 release notes

- Django 1.3.6 release notes

- Django 1.3.5 release notes

- Django 1.3.4 release notes

- Django 1.3.3 release notes

- Django 1.3.2 release notes

- Django 1.3.1 release notes

- Django 1.3 release notes

1.2 release

- Django 1.2.7 release notes

- Django 1.2.6 release notes

- Django 1.2.5 release notes

- Django 1.2.4 release notes

- Django 1.2.3 release notes

- Django 1.2.2 release notes

- Django 1.2.1 release notes

- Django 1.2 release notes

1.1 release

- Django 1.1.4 release notes

- Django 1.1.3 release notes

- Django 1.1.2 release notes

- Django 1.1 release notes

1.0 release

- Django 1.0.2 release notes

- Django 1.0.1 release notes

- Django 1.0 release notes

Pre-1.0 releases

- Django version 0.96 release notes

- Django version 0.95 release notes

Security releases

Whenever a security issue is disclosed via Django’s security policies, appropriate release notes are now added to all affected release series.

Additionally, an archive of disclosed security issues is maintained.

Django 1.9.9 release notes

Under development

Django 1.9.9 fixes several bugs in 1.9.8.

Bugfixes

- Fixed invalid HTML in template postmortem on the debug page (#26938).

- Fixed some GIS database function crashes on MySQL 5.7 (#26657).

Django 1.9.8 release notes

July 18, 2016

Django 1.9.8 fixes a security issue and several bugs in 1.9.7.

XSS in admin’s add/change related popup

Unsafe usage of JavaScript’s Element.innerHTML could result in XSS in the admin’s add/change related popup. Element.textContent is now used to prevent execution of the data.

The debug view also used innerHTML. Although a security issue wasn’t identified there, out of an abundance of caution it’s also updated to use textContent.

Bugfixes

- Fixed missing varchar/text_pattern_ops index on CharField and TextField respectively when using AddField on PostgreSQL (#26889).

- Fixed makemessages crash on Python 2 with non-ASCII file names (#26897).

Django 1.9.7 release notes

June 4, 2016

Django 1.9.7 fixes several bugs in 1.9.6.

Bugfixes

- Removed the need for the request context processor on the admin login page to fix a regression in 1.9 (#26558).

- Fixed translation of password validators’ help_text in forms (#26544).

- Fixed a regression causing the cached template loader to crash when using lazy template names (#26603).

- Fixed on_commit callbacks execution order when callbacks make transactions (#26627).

- Fixed HStoreField to raise a ValidationError instead of crashing on non-dictionary JSON input (#26672).

- Fixed dbshell crash on PostgreSQL with an empty database name (#26698).

- Fixed a regression in queries on a OneToOneField that has to_field and primary_key=True (#26667).

Django 1.9.6 release notes

May 2, 2016

Django 1.9.6 fixes several bugs in 1.9.5.

Bugfixes

- Added support for relative path redirects to the test client and to SimpleTestCase.assertRedirects() because Django 1.9 no longer converts redirects to absolute URIs (#26428).

- Fixed TimeField microseconds round-tripping on MySQL and SQLite (#26498).

- Prevented makemigrations from generating infinite migrations for a model field that references a functools.partial (#26475).

- Fixed a regression where SessionBase.pop() returned None rather than raising a KeyError for nonexistent values (#26520).

- Fixed a regression causing the cached template loader to crash when using template names starting with a dash (#26536).

- Restored conversion of an empty string to null when saving values of GenericIPAddressField on SQLite and MySQL (#26557).

- Fixed a makemessages regression where temporary .py extensions were leaked in source file paths (#26341).

Django 1.9.5 release notes

April 1, 2016

Django 1.9.5 fixes several bugs in 1.9.4.

Bugfixes

- Made MultiPartParser ignore filenames that normalize to an empty string to fix crash in MemoryFileUploadHandler on specially crafted user input (#26325).

- Fixed a race condition in BaseCache.get_or_set() (#26332). It now returns the default value instead of False if there’s an error when trying to add the value to the cache.

- Fixed data loss on SQLite where DurationField values with fractional seconds could be saved as None (#26324).

- The forms in contrib.auth no longer strip trailing and leading whitespace from the password fields (#26334). The change requires users who set their password to something with such whitespace after a site updated to Django 1.9 to reset their password. It provides backwards-compatibility for earlier versions of Django.

- Fixed a memory leak in the cached template loader (#26306).

- Fixed a regression that caused collectstatic --clear to fail if the storage doesn’t implement path() (#26297).

- Fixed a crash when using a reverse lookup with a subquery when a ForeignKey has a to_field set to something other than the primary key (#26373).

- Fixed a regression in CommonMiddleware that caused spurious warnings in logs on requests missing a trailing slash (#26293).

- Restored the functionality of the admin’s raw_id_fields in list_editable (#26387).

- Fixed a regression with abstract model inheritance and explicit parent links (#26413).

- Fixed a migrations crash on SQLite when renaming the primary key of a model containing a ForeignKey to 'self' (#26384).

- Fixed JSONField inadvertently escaping its contents when displaying values after failed form validation (#25532).

Django 1.9.4 release notes

March 5, 2016

Django 1.9.4 fixes a regression on Python 2 in the 1.9.3 security release where utils.http.is_safe_url() crashes on bytestring URLs (#26308).

Django 1.9.3 release notes

March 1, 2016

Django 1.9.3 fixes two security issues and several bugs in 1.9.2.

CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security check for these redirects (namely django.utils.http.is_safe_url()) considered some URLs with basic authentication credentials “safe” when they shouldn’t be.

For example, a URL like http://mysite.example.com\@attacker.com would be considered safe if the request’s host is http://mysite.example.com, but redirecting to this URL sends the user to attacker.com.

Also, if a developer relies on is_safe_url() to provide safe redirect targets and puts such a URL into a link, they could suffer from an XSS attack.

CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade

In each major version of Django since 1.6, the default number of iterations for the PBKDF2PasswordHasher and its subclasses has increased. This improves the security of the password as the speed of hardware increases, however, it also creates a timing difference between a login request for a user with a password encoded in an older number of iterations and login request for a nonexistent user (which runs the default hasher’s default number of iterations since Django 1.6).

This only affects users who haven’t logged in since the iterations were increased. The first time a user logs in after an iterations increase, their password is updated with the new iterations and there is no longer a timing difference.

The new BasePasswordHasher.harden_runtime() method allows hashers to bridge the runtime gap between the work factor (e.g. iterations) supplied in existing encoded passwords and the default work factor of the hasher. This method is implemented for PBKDF2PasswordHasher and BCryptPasswordHasher. The number of rounds for the latter hasher hasn’t changed since Django 1.4, but some projects may subclass it and increase the work factor as needed.

A warning will be emitted for any third-party password hashers that don’t implement a harden_runtime() method.

If you have different password hashes in your database (such as SHA1 hashes from users who haven’t logged in since the default hasher switched to PBKDF2 in Django 1.4), the timing difference on a login request for these users may be even greater and this fix doesn’t remedy that difference (or any difference when changing hashers). You may be able to upgrade those hashes to prevent a timing attack for that case.

Bugfixes

- Skipped URL checks (new in 1.9) if the ROOT_URLCONF setting isn’t defined (#26155).

- Fixed a crash on PostgreSQL that prevented using TIME_ZONE=None and USE_TZ=False (#26177).

- Added system checks for query name clashes of hidden relationships (#26162).

- Fixed a regression for cases where ForeignObject.get_extra_descriptor_filter() returned a Q object (#26153).

- Fixed regression with an __in=qs lookup for a ForeignKey with to_field set (#26196).

- Made forms.FileField and utils.translation.lazy_number() picklable (#26212).

- Fixed RangeField and ArrayField serialization with None values (#26215).

- Fixed a crash when filtering by a Decimal in RawQuery (#26219).

- Reallowed dashes in top-level domain names of URLs checked by URLValidator to fix a regression in Django 1.8 (#26204).

- Fixed some crashing deprecation shims in SimpleTemplateResponse that regressed in Django 1.9 (#26253).

- Fixed BoundField to reallow slices of subwidgets (#26267).

- Changed the admin’s “permission denied” message in the login template to use get_username instead of username to support custom user models (#26231).

- Fixed a crash when passing a nonexistent template name to the cached template loader’s load_template() method (#26280).

- Prevented ContentTypeManager instances from sharing their cache (#26286).

- Reverted a change in Django 1.9.2 (#25858) that prevented relative lazy relationships defined on abstract models to be resolved according to their concrete model’s app_label (#26186).

Django 1.9.2 release notes

February 1, 2016

Django 1.9.2 fixes a security regression in 1.9 and several bugs in 1.9.1. It also makes a small backwards incompatible change that hopefully doesn’t affect any users.

Security issue: User with “change” but not “add” permission can create objects for ModelAdmin’s with save_as=True

If a ModelAdmin uses save_as=True (not the default), the admin provides an option when editing objects to “Save as new”. A regression in Django 1.9 prevented that form submission from raising a “Permission Denied” error for users without the “add” permission.

Backwards incompatible change: .py-tpl files rewritten in project/app templates

The addition of some Django template language syntax to the default app template in Django 1.9 means those files now have some invalid Python syntax. This causes difficulties for packaging systems that unconditionally byte-compile *.py files.

To remedy this, a .py-tpl suffix is now used for the project and app template files included in Django. The .py-tpl suffix is replaced with .py by the startproject and startapp commands. For example, a template with the filename manage.py-tpl will be created as manage.py.

Please file a ticket if you have a custom project template containing .py-tpl files and find this behavior problematic.

Bugfixes

- Fixed a regression in ConditionalGetMiddleware causing If-None-Match checks to always return HTTP 200 (#26024).

- Fixed a regression that caused the “user-tools” items to display on the admin’s logout page (#26035).

- Fixed a crash in the translations system when the current language has no translations (#26046).

- Fixed a regression that caused the incorrect day to be selected when opening the admin calendar widget for timezones from GMT+0100 to GMT+1200 (#24980).

- Fixed a regression in the admin’s edit related model popup that caused an escaped value to be displayed in the select dropdown of the parent window (#25997).

- Fixed a regression in 1.8.8 causing incorrect index handling in migrations on PostgreSQL when adding db_index=True or unique=True to a CharField or TextField that already had the other specified, or when removing one of them from a field that had both, or when adding unique=True to a field already listed in unique_together (#26034).

- Fixed a regression where defining a relation on an abstract model’s field using a string model name without an app_label no longer resolved that reference to the abstract model’s app if using that model in another application (#25858).

- Fixed a crash when destroying an existing test database on MySQL or PostgreSQL (#26096).

- Fixed CSRF cookie check on POST requests when USE_X_FORWARDED_PORT=True (#26094).

- Fixed a QuerySet.order_by() crash when ordering by a relational field of a ManyToManyField through model (#26092).

- Fixed a regression that caused an exception when making database queries on SQLite with more than 2000 parameters when DEBUG is True on distributions that increase the SQLITE_MAX_VARIABLE_NUMBER compile-time limit to over 2000, such as Debian (#26063).

- Fixed a crash when using a reverse OneToOneField in ModelAdmin.readonly_fields (#26060).

- Fixed a crash when calling the migrate command in a test case with the available_apps attribute pointing to an application with migrations disabled using the MIGRATION_MODULES setting (#26135).

- Restored the ability for testing and debugging tools to determine the template from which a node came from, even during template inheritance or inclusion. Prior to Django 1.9, debugging tools could access the template origin from the node via Node.token.source[0]. This was an undocumented, private API. The origin is now available directly on each node using the Node.origin attribute (#25848).

- Fixed a regression in Django 1.8.5 that broke copying a SimpleLazyObject with copy.copy() (#26122).

- Always included geometry_field in the GeoJSON serializer output regardless of the fields parameter (#26138).

- Fixed the contrib.gis map widgets when using USE_THOUSAND_SEPARATOR=True (#20415).

- Made invalid forms display the initial of values of their disabled fields (#26129).

Django 1.9.1 release notes

January 2, 2016

Django 1.9.1 fixes several bugs in 1.9.

Bugfixes

- Fixed BaseCache.get_or_set() with the DummyCache backend (#25840).

- Fixed a regression in FormMixin causing forms to be validated twice (#25548, #26018).

- Fixed a system check crash with nested ArrayFields (#25867).

- Fixed a state bug when migrating a SeparateDatabaseAndState operation backwards (#25896).

- Fixed a regression in CommonMiddleware causing If-None-Match checks to always return HTTP 200 (#25900).

- Fixed missing varchar/text_pattern_ops index on CharField and TextField respectively when using AlterField on PostgreSQL (#25412).

- Fixed admin’s delete confirmation page’s summary counts of related objects (#25883).

- Added from __future__ import unicode_literals to the default apps.py created by startapp on Python 2 (#25909). Add this line to your own apps.py files created using Django 1.9 if you want your migrations to work on both Python 2 and Python 3.

- Prevented QuerySet.delete() from crashing on MySQL when querying across relations (#25882).

- Fixed evaluation of zero-length slices of QuerySet.values() (#25894).

- Fixed a state bug when using an AlterModelManagers operation (#25852).

- Fixed TypedChoiceField change detection with nullable fields (#25942).

- Fixed incorrect timezone warnings in custom admin templates that don’t have a data-admin-utc-offset attribute in the body tag. (#25845).

- Fixed a regression which prevented using a language not in Django’s default language list (LANGUAGES) (#25915).

- Avoided hiding some exceptions, like an invalid INSTALLED_APPS setting, behind AppRegistryNotReady when starting runserver (#25510). This regression appeared in 1.8.5 as a side effect of fixing #24704 and by mistake the fix wasn’t applied to the stable/1.9.x branch.

- Fixed migrate --fake-initial detection of many-to-many tables (#25922).

- Restored the functionality of the admin’s list_editable add and change buttons (#25903).

- Fixed isnull query lookup for ForeignObject (#25972).

- Fixed a regression in the admin which ignored line breaks in read-only fields instead of converting them to <br> (#25465).

- Fixed incorrect object reference in SingleObjectMixin.get_context_object_name() (#26006).

- Made loaddata skip disabling and enabling database constraints when it doesn’t load any fixtures (#23372).

- Restored contrib.auth hashers compatibility with py-bcrypt (#26016).

- Fixed a crash in QuerySet.values()/values_list() after an annotate() and order_by() when values()/values_list() includes a field not in the order_by() (#25316).

Django 1.9 release notes

December 1, 2015

Welcome to Django 1.9!

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.8 or older versions. We’ve dropped some features that have reached the end of their deprecation cycle, and we’ve begun the deprecation process for some features.

See the Upgrading Django to a newer version guide if you’re updating an existing project.

Python compatibility

Django 1.9 requires Python 2.7, 3.4, or 3.5. We highly recommend and only officially support the latest release of each series.

The Django 1.8 series is the last to support Python 3.2 and 3.3.

What’s new in Django 1.9

Performing actions after a transaction commit

The new on_commit() hook allows performing actions after a database transaction is successfully committed. This is useful for tasks such as sending notification emails, creating queued tasks, or invalidating caches.

This functionality from the django-transaction-hooks package has been integrated into Django.

Password validation

Django now offers password validation to help prevent the usage of weak passwords by users. The validation is integrated in the included password change and reset forms and is simple to integrate in any other code. Validation is performed by one or more validators, configured in the new AUTH_PASSWORD_VALIDATORS setting.

Four validators are included in Django, which can enforce a minimum length, compare the password to the user’s attributes like their name, ensure passwords aren’t entirely numeric, or check against an included list of common passwords. You can combine multiple validators, and some validators have custom configuration options. For example, you can choose to provide a custom list of common passwords. Each validator provides a help text to explain its requirements to the user.

By default, no validation is performed and all passwords are accepted, so if you don’t set AUTH_PASSWORD_VALIDATORS, you will not see any change. In new projects created with the default startproject template, a simple set of validators is enabled. To enable basic validation in the included auth forms for your project, you could set, for example:

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]

See Password validation for more details.

Permission mixins for class-based views

Django now ships with the mixins AccessMixin, LoginRequiredMixin, PermissionRequiredMixin, and UserPassesTestMixin to provide the functionality of the django.contrib.auth.decorators for class-based views. These mixins have been taken from, or are at least inspired by, the django-braces project.

There are a few differences between Django’s and django-braces’ implementation, though:

- The raise_exception attribute can only be True or False. Custom exceptions or callables are not supported.

- The handle_no_permission() method does not take a request argument. The current request is available in self.request.

- The custom test_func() of UserPassesTestMixin does not take a user argument. The current user is available in self.request.user.

- The permission_required attribute supports a string (defining one permission) or a list/tuple of strings (defining multiple permissions) that need to be fulfilled to grant access.

- The new permission_denied_message attribute allows passing a message to the PermissionDenied exception.

New styling for contrib.admin

The admin sports a modern, flat design with new SVG icons which look perfect on HiDPI screens. It still provides a fully-functional experience to YUI’s A-grade browsers. Older browser may experience varying levels of graceful degradation.

Running tests in parallel

The test command now supports a --parallel option to run a project’s tests in multiple processes in parallel.

Each process gets its own database. You must ensure that different test cases don’t access the same resources. For instance, test cases that touch the filesystem should create a temporary directory for their own use.

This option is enabled by default for Django’s own test suite provided:

- the OS supports it (all but Windows)

- the database backend supports it (all the built-in backends but Oracle)

Minor features

django.contrib.admin

- Admin views now have model_admin or admin_site attributes.

- The URL of the admin change view has been changed (was at /admin/<app>/<model>/<pk>/ by default and is now at /admin/<app>/<model>/<pk>/change/). This should not affect your application unless you have hardcoded admin URLs. In that case, replace those links by reversing admin URLs instead. Note that the old URL still redirects to the new one for backwards compatibility, but it may be removed in a future version.

- ModelAdmin.get_list_select_related() was added to allow changing the select_related() values used in the admin’s changelist query based on the request.

- The available_apps context variable, which lists the available applications for the current user, has been added to the AdminSite.each_context() method.

- AdminSite.empty_value_display and ModelAdmin.empty_value_display were added to override the display of empty values in admin change list. You can also customize the value for each field.

- Added jQuery events when an inline form is added or removed on the change form page.

- The time picker widget includes a ‘6 p.m’ option for consistency of having predefined options every 6 hours.

- JavaScript slug generation now supports Romanian characters.

django.contrib.admindocs

- The model section of the admindocs now also describes methods that take arguments, rather than ignoring them.

django.contrib.auth

- The default iteration count for the PBKDF2 password hasher has been increased by 20%. This backwards compatible change will not affect users who have subclassed django.contrib.auth.hashers.PBKDF2PasswordHasher to change the default value.

- The BCryptSHA256PasswordHasher will now update passwords if its rounds attribute is changed.

- AbstractBaseUser and BaseUserManager were moved to a new django.contrib.auth.base_user module so that they can be imported without including django.contrib.auth in INSTALLED_APPS (doing so raised a deprecation warning in older versions and is no longer supported in Django 1.9).

- The permission argument of permission_required() accepts all kinds of iterables, not only list and tuples.

- The new PersistentRemoteUserMiddleware makes it possible to use REMOTE_USER for setups where the header is only populated on login pages instead of every request in the session.

- The password_reset() view accepts an extra_email_context parameter.

django.contrib.contenttypes

- It’s now possible to use order_with_respect_to with a GenericForeignKey.

django.contrib.gis

- All GeoQuerySet methods have been deprecated and replaced by equivalent database functions. As soon as the legacy methods have been replaced in your code, you should even be able to remove the special GeoManager from your GIS-enabled classes.

- The GDAL interface now supports instantiating file-based and in-memory GDALRaster objects from raw data. Setters for raster properties such as projection or pixel values have been added.

- For PostGIS users, the new RasterField allows storing GDALRaster objects. It supports automatic spatial index creation and reprojection when saving a model. It does not yet support spatial querying.

- The new GDALRaster.warp() method allows warping a raster by specifying target raster properties such as origin, width, height, or pixel size (amongst others).

- The new GDALRaster.transform() method allows transforming a raster into a different spatial reference system by specifying a target srid.

- The new GeoIP2 class allows using MaxMind’s GeoLite2 databases which includes support for IPv6 addresses.

django.contrib.postgres

- Added support for the rangefield.contained_by lookup for some built in fields which correspond to the range fields.

- Added JSONField.

- Added PostgreSQL specific aggregation functions.

- Added the TransactionNow database function.

django.contrib.sessions

- The session model and SessionStore classes for the db and cached_db backends are refactored to allow a custom database session backend to build upon them. See Extending database-backed session engines for more details.

django.contrib.sites

- get_current_site() now handles the case where request.get_host() returns domain:port, e.g. example.com:80. If the lookup fails because the host does not match a record in the database and the host has a port, the port is stripped and the lookup is retried with the domain part only.

django.contrib.syndication

- Support for multiple enclosures per feed item has been added. If multiple enclosures are defined on a RSS feed, an exception is raised as RSS feeds, unlike Atom feeds, do not support multiple enclosures per feed item.

Cache

- django.core.cache.backends.base.BaseCache now has a get_or_set() method.

- django.views.decorators.cache.never_cache() now sends more persuasive headers (added no-cache, no-store, must-revalidate to Cache-Control) to better prevent caching. This was also added in Django 1.8.8.

CSRF

- The request header’s name used for CSRF authentication can be customized with CSRF_HEADER_NAME.

- The CSRF referer header is now validated against the CSRF_COOKIE_DOMAIN setting if set. See How it works for details.

- The new CSRF_TRUSTED_ORIGINS setting provides a way to allow cross-origin unsafe requests (e.g. POST) over HTTPS.

Database backends

- The PostgreSQL backend (django.db.backends.postgresql_psycopg2) is also available as django.db.backends.postgresql. The old name will continue to be available for backwards compatibility.

File Storage

- Storage.get_valid_name() is now called when the upload_to is a callable.

- File now has the seekable() method when using Python 3.

Forms

- ModelForm accepts the new Meta option field_classes to customize the type of the fields. See Overriding the default fields for details.

- You can now specify the order in which form fields are rendered with the field_order attribute, the field_order constructor argument , or the order_fields() method.

- A form prefix can be specified inside a form class, not only when instantiating a form. See Prefixes for forms for details.

- You can now specify keyword arguments that you want to pass to the constructor of forms in a formset.

- SlugField now accepts an allow_unicode argument to allow Unicode characters in slugs.

- CharField now accepts a strip argument to strip input data of leading and trailing whitespace. As this defaults to True this is different behavior from previous releases.

- Form fields now support the disabled argument, allowing the field widget to be displayed disabled by browsers.

- It’s now possible to customize bound fields by overriding a field’s get_bound_field() method.

Generic Views

- Class-based views generated using as_view() now have view_class and view_initkwargs attributes.

- method_decorator() can now be used with a list or tuple of decorators. It can also be used to decorate classes instead of methods.

Internationalization

- The django.views.i18n.set_language() view now properly redirects to translated URLs, when available.

- The django.views.i18n.javascript_catalog() view now works correctly if used multiple times with different configurations on the same page.

- The django.utils.timezone.make_aware() function gained an is_dst argument to help resolve ambiguous times during DST transitions.

- You can now use locale variants supported by gettext. These are usually used for languages which can be written in different scripts, for example Latin and Cyrillic (e.g. be@latin).

- Added the django.views.i18n.json_catalog() view to help build a custom client-side i18n library upon Django translations. It returns a JSON object containing a translations catalog, formatting settings, and a plural rule.

- Added the name_translated attribute to the object returned by the get_language_info template tag. Also added a corresponding template filter: language_name_translated.

- You can now run compilemessages from the root directory of your project and it will find all the app message files that were created by makemessages.

- makemessages now calls xgettext once per locale directory rather than once per translatable file. This speeds up localization builds.

- blocktrans supports assigning its output to a variable using asvar.

- Two new languages are available: Colombian Spanish and Scottish Gaelic.

Management Commands

- The new sendtestemail command lets you send a test email to easily confirm that email sending through Django is working.

- To increase the readability of the SQL code generated by sqlmigrate, the SQL code generated for each migration operation is preceded by the operation’s description.

- The dumpdata command output is now deterministically ordered. Moreover, when the --output option is specified, it also shows a progress bar in the terminal.

- The createcachetable command now has a --dry-run flag to print out the SQL rather than execute it.

- The startapp command creates an apps.py file. Since it doesn’t use default_app_config (a discouraged API), you must specify the app config’s path, e.g. 'polls.apps.PollsConfig', in INSTALLED_APPS for it to be used (instead of just 'polls').

- When using the PostgreSQL backend, the dbshell command can connect to the database using the password from your settings file (instead of requiring it to be manually entered).

- The django package may be run as a script, i.e. python -m django, which will behave the same as django-admin.

- Management commands that have the --noinput option now also take --no-input as an alias for that option.

Migrations

- Initial migrations are now marked with an initial = True class attribute which allows migrate --fake-initial to more easily detect initial migrations.

- Added support for serialization of functools.partial and LazyObject instances.

- When supplying None as a value in MIGRATION_MODULES, Django will consider the app an app without migrations.

- When applying migrations, the “Rendering model states” step that’s displayed when running migrate with verbosity 2 or higher now computes only the states for the migrations that have already been applied. The model states for migrations being applied are generated on demand, drastically reducing the amount of required memory.

However, this improvement is not available when unapplying migrations and therefore still requires the precomputation and storage of the intermediate migration states.

This improvement also requires that Django no longer supports mixed migration plans. Mixed plans consist of a list of migrations where some are being applied and others are being unapplied. This was never officially supported and never had a public API that supports this behavior.

- The squashmigrations command now supports specifying the starting migration from which migrations will be squashed.

Models

- QuerySet.bulk_create() now works on proxy models.

- Database configuration gained a TIME_ZONE option for interacting with databases that store datetimes in local time and don’t support time zones when USE_TZ is True.

- Added the RelatedManager.set() method to the related managers created by ForeignKey, GenericForeignKey, and ManyToManyField.

- The add() method on a reverse foreign key now has a bulk parameter to allow executing one query regardless of the number of objects being added rather than one query per object.

- Added the keep_parents parameter to Model.delete() to allow deleting only a child’s data in a model that uses multi-table inheritance.

- Model.delete() and QuerySet.delete() return the number of objects deleted.

- Added a system check to prevent defining both Meta.ordering and order_with_respect_to on the same model.

- Date and time lookups can be chained with other lookups (such as exact, gt, lt, etc.). For example: Entry.objects.filter(pub_date__month__gt=6).

- Time lookups (hour, minute, second) are now supported by TimeField for all database backends. Support for backends other than SQLite was added but undocumented in Django 1.7.

- You can specify the output_field parameter of the Avg aggregate in order to aggregate over non-numeric columns, such as DurationField.

- Added the date lookup to DateTimeField to allow querying the field by only the date portion.

- Added the Greatest and Least database functions.

- Added the Now database function, which returns the current date and time.

- Transform is now a subclass of Func() which allows Transforms to be used on the right hand side of an expression, just like regular Funcs. This allows registering some database functions like Length, Lower, and Upper as transforms.

- SlugField now accepts an allow_unicode argument to allow Unicode characters in slugs.

- Added support for referencing annotations in QuerySet.distinct().

- connection.queries shows queries with substituted parameters on SQLite.

- Query expressions can now be used when creating new model instances using save(), create(), and bulk_create().

Requests and Responses

- Unless HttpResponse.reason_phrase is explicitly set, it now is determined by the current value of HttpResponse.status_code. Modifying the value of status_code outside of the constructor will also modify the value of reason_phrase.

- The debug view now shows details of chained exceptions on Python 3.

- The default 40x error views now accept a second positional parameter, the exception that triggered the view.

- View error handlers now support TemplateResponse, commonly used with class-based views.

- Exceptions raised by the render() method are now passed to the process_exception() method of each middleware.

- Request middleware can now set HttpRequest.urlconf to None to revert any changes made by previous middleware and return to using the ROOT_URLCONF.

- The DISALLOWED_USER_AGENTS check in CommonMiddleware now raises a PermissionDenied exception as opposed to returning an HttpResponseForbidden so that handler403 is invoked.

- Added HttpRequest.get_port() to fetch the originating port of the request.

- Added the json_dumps_params parameter to JsonResponse to allow passing keyword arguments to the json.dumps() call used to generate the response.

- The BrokenLinkEmailsMiddleware now ignores 404s when the referer is equal to the requested URL. To circumvent the empty referer check already implemented, some Web bots set the referer to the requested URL.

Templates

- Template tags created with the simple_tag() helper can now store results in a template variable by using the as argument.

- Added a Context.setdefault() method.

- The django.template logger was added and includes the following messages:

- A DEBUG level message for missing context variables.

- A WARNING level message for uncaught exceptions raised during the rendering of an {% include %} when debug mode is off (helpful since {% include %} silences the exception and returns an empty string).

- The firstof template tag supports storing the output in a variable using ‘as’.

- Context.update() can now be used as a context manager.

- Django template loaders can now extend templates recursively.

- The debug page template postmortem now include output from each engine that is installed.

- Debug page integration for custom template engines was added.

- The DjangoTemplates backend gained the ability to register libraries and builtins explicitly through the template OPTIONS.

- The timesince and timeuntil filters were improved to deal with leap years when given large time spans.

- The include tag now caches parsed templates objects during template rendering, speeding up reuse in places such as for loops.

Tests

- Added the json() method to test client responses to give access to the response body as JSON.

- Added the force_login() method to the test client. Use this method to simulate the effect of a user logging into the site while skipping the authentication and verification steps of login().

URLs

- Regular expression lookaround assertions are now allowed in URL patterns.

- The application namespace can now be set using an app_name attribute on the included module or object. It can also be set by passing a 2-tuple of (<list of patterns>, <application namespace>) as the first argument to include().

- System checks have been added for common URL pattern mistakes.

Validators

- Added django.core.validators.int_list_validator() to generate validators of strings containing integers separated with a custom character.

- EmailValidator now limits the length of domain name labels to 63 characters per RFC 1034.

- Added validate_unicode_slug() to validate slugs that may contain Unicode characters.

Backwards incompatible changes in 1.9

Warning

In addition to the changes outlined in this section, be sure to review the Features removed in 1.9 for the features that have reached the end of their deprecation cycle and therefore been removed. If you haven’t updated your code within the deprecation timeline for a given feature, its removal may appear as a backwards incompatible change.

Database backend API

- A couple of new tests rely on the ability of the backend to introspect column defaults (returning the result as Field.default). You can set the can_introspect_default database feature to False if your backend doesn’t implement this. You may want to review the implementation on the backends that Django includes for reference (#24245).

- Registering a global adapter or converter at the level of the DB-API module to handle time zone information of datetime values passed as query parameters or returned as query results on databases that don’t support time zones is discouraged. It can conflict with other libraries.

The recommended way to add a time zone to datetime values fetched from the database is to register a converter for DateTimeField in DatabaseOperations.get_db_converters().

The needs_datetime_string_cast database feature was removed. Database backends that set it must register a converter instead, as explained above.

- The DatabaseOperations.value_to_db_<type>() methods were renamed to adapt_<type>field_value() to mirror the convert_<type>field_value() methods.

- To use the new date lookup, third-party database backends may need to implement the DatabaseOperations.datetime_cast_date_sql() method.

- The DatabaseOperations.time_extract_sql() method was added. It calls the existing date_extract_sql() method. This method is overridden by the SQLite backend to add time lookups (hour, minute, second) to TimeField, and may be needed by third-party database backends.

- The DatabaseOperations.datetime_cast_sql() method (not to be confused with DatabaseOperations.datetime_cast_date_sql() mentioned above) has been removed. This method served to format dates on Oracle long before 1.0, but hasn’t been overridden by any core backend in years and hasn’t been called anywhere in Django’s code or tests.

- In order to support test parallelization, you must implement the DatabaseCreation._clone_test_db() method and set DatabaseFeatures.can_clone_databases = True. You may have to adjust DatabaseCreation.get_test_db_clone_settings().

Default settings that were tuples are now lists

The default settings in django.conf.global_settings were a combination of lists and tuples. All settings that were formerly tuples are now lists.

is_usable attribute on template loaders is removed

Django template loaders previously required an is_usable attribute to be defined. If a loader was configured in the template settings and this attribute was False, the loader would be silently ignored. In practice, this was only used by the egg loader to detect if setuptools was installed. The is_usable attribute is now removed and the egg loader instead fails at runtime if setuptools is not installed.

Related set direct assignment

Direct assignment of related objects in the ORM used to perform a clear() followed by a call to add(). This caused needlessly large data changes and prevented using the m2m_changed signal to track individual changes in many-to-many relations.

Direct assignment now relies on the the new set() method on related managers which by default only processes changes between the existing related set and the one that’s newly assigned. The previous behavior can be restored by replacing direct assignment by a call to set() with the keyword argument clear=True.

ModelForm, and therefore ModelAdmin, internally rely on direct assignment for many-to-many relations and as a consequence now use the new behavior.

Filesystem-based template loaders catch more specific exceptions

When using the filesystem.Loader or app_directories.Loader template loaders, earlier versions of Django raised a TemplateDoesNotExist error if a template source existed but was unreadable. This could happen under many circumstances, such as if Django didn’t have permissions to open the file, or if the template source was a directory. Now, Django only silences the exception if the template source does not exist. All other situations result in the original IOError being raised.

HTTP redirects no longer forced to absolute URIs

Relative redirects are no longer converted to absolute URIs. RFC 2616 required the Location header in redirect responses to be an absolute URI, but it has been superseded by RFC 7231 which allows relative URIs in Location, recognizing the actual practice of user agents, almost all of which support them.

Consequently, the expected URLs passed to assertRedirects should generally no longer include the scheme and domain part of the URLs. For example, self.assertRedirects(response, 'http://testserver/some-url/') should be replaced by self.assertRedirects(response, '/some-url/') (unless the redirection specifically contained an absolute URL, of course).

Dropped support for PostgreSQL 9.0

Upstream support for PostgreSQL 9.0 ended in September 2015. As a consequence, Django 1.9 sets 9.1 as the minimum PostgreSQL version it officially supports.

Dropped support for Oracle 11.1

Upstream support for Oracle 11.1 ended in August 2015. As a consequence, Django 1.9 sets 11.2 as the minimum Oracle version it officially supports.

Bulk behavior of add() method of related managers

To improve performance, the add() methods of the related managers created by ForeignKey and GenericForeignKey changed from a series of Model.save() calls to a single QuerySet.update() call. The change means that pre_save and post_save signals aren’t sent anymore. You can use the bulk=False keyword argument to revert to the previous behavior.

Template LoaderOrigin and StringOrigin are removed

In previous versions of Django, when a template engine was initialized with debug as True, an instance of django.template.loader.LoaderOrigin or django.template.base.StringOrigin was set as the origin attribute on the template object. These classes have been combined into Origin and is now always set regardless of the engine debug setting. For a minimal level of backwards compatibility, the old class names will be kept as aliases to the new Origin class until Django 2.0.

Changes to the default logging configuration

To make it easier to write custom logging configurations, Django’s default logging configuration no longer defines ‘django.request’ and ‘django.security’ loggers. Instead, it defines a single ‘django’ logger, filtered at the INFO level, with two handlers:

- ‘console’: filtered at the INFO level and only active if DEBUG=True.

- ‘mail_admins’: filtered at the ERROR level and only active if DEBUG=False.

If you aren’t overriding Django’s default logging, you should see minimal changes in behavior, but you might see some new logging to the runserver console, for example.

If you are overriding Django’s default logging, you should check to see how your configuration merges with the new defaults.

HttpRequest details in error reporting

It was redundant to display the full details of the HttpRequest each time it appeared as a stack frame variable in the HTML version of the debug page and error email. Thus, the HTTP request will now display the same standard representation as other variables (repr(request)). As a result, the ExceptionReporterFilter.get_request_repr() method and the undocumented django.http.build_request_repr() function were removed.

The contents of the text version of the email were modified to provide a traceback of the same structure as in the case of AJAX requests. The traceback details are rendered by the ExceptionReporter.get_traceback_text() method.

Removal of time zone aware global adapters and converters for datetimes

Django no longer registers global adapters and converters for managing time zone information on datetime values sent to the database as query parameters or read from the database in query results. This change affects projects that meet all the following conditions:

- The USE_TZ setting is True.

- The database is SQLite, MySQL, Oracle, or a third-party database that doesn’t support time zones. In doubt, you can check the value of connection.features.supports_timezones.

- The code queries the database outside of the ORM, typically with cursor.execute(sql, params).

If you’re passing aware datetime parameters to such queries, you should turn them into naive datetimes in UTC:

from django.utils import timezone
param = timezone.make_naive(param, timezone.utc)

If you fail to do so, the conversion will be performed as in earlier versions (with a deprecation warning) up until Django 1.11. Django 2.0 won’t perform any conversion, which may result in data corruption.

If you’re reading datetime values from the results, they will be naive instead of aware. You can compensate as follows:

from django.utils import timezone
value = timezone.make_aware(value, timezone.utc)

You don’t need any of this if you’re querying the database through the ORM, even if you’re using raw() queries. The ORM takes care of managing time zone information.

Template tag modules are imported when templates are configured

The DjangoTemplates backend now performs discovery on installed template tag modules when instantiated. This update enables libraries to be provided explicitly via the 'libraries' key of OPTIONS when defining a DjangoTemplates backend. Import or syntax errors in template tag modules now fail early at instantiation time rather than when a template with a {% load %} tag is first compiled.

django.template.base.add_to_builtins() is removed

Although it was a private API, projects commonly used add_to_builtins() to make template tags and filters available without using the {% load %} tag. This API has been formalized. Projects should now define built-in libraries via the 'builtins' key of OPTIONS when defining a DjangoTemplates backend.

simple_tag now wraps tag output in conditional_escape

In general, template tags do not autoescape their contents, and this behavior is documented. For tags like inclusion_tag, this is not a problem because the included template will perform autoescaping. For assignment_tag, the output will be escaped when it is used as a variable in the template.

For the intended use cases of simple_tag, however, it is very easy to end up with incorrect HTML and possibly an XSS exploit. For example:

@register.simple_tag(takes_context=True)
def greeting(context):
return "Hello {0}!".format(context['request'].user.first_name)

In older versions of Django, this will be an XSS issue because user.first_name is not escaped.

In Django 1.9, this is fixed: if the template context has autoescape=True set (the default), then simple_tag will wrap the output of the tag function with conditional_escape().

To fix your simple_tags, it is best to apply the following practices:

- Any code that generates HTML should use either the template system or format_html().

- If the output of a simple_tag needs escaping, use escape() or conditional_escape().

- If you are absolutely certain that you are outputting HTML from a trusted source (e.g. a CMS field that stores HTML entered by admins), you can mark it as such using mark_safe().

Tags that follow these rules will be correct and safe whether they are run on Django 1.9+ or earlier.

Paginator.page_range

Paginator.page_range is now an iterator instead of a list.

In versions of Django previous to 1.8, Paginator.page_range returned a list in Python 2 and a range in Python 3. Django 1.8 consistently returned a list, but an iterator is more efficient.

Existing code that depends on list specific features, such as indexing, can be ported by converting the iterator into a list using list().

Implicit QuerySet __in lookup removed

In earlier versions, queries such as:

Model.objects.filter(related_id=RelatedModel.objects.all())

would implicitly convert to:

Model.objects.filter(related_id__in=RelatedModel.objects.all())

resulting in SQL like "related_id IN (SELECT id FROM ...)".

This implicit __in no longer happens so the “IN” SQL is now “=”, and if the subquery returns multiple results, at least some databases will throw an error.

contrib.admin browser support

The admin no longer supports Internet Explorer 8 and below, as these browsers have reached end-of-life.

CSS and images to support Internet Explorer 6 and 7 have been removed. PNG and GIF icons have been replaced with SVG icons, which are not supported by Internet Explorer 8 and earlier.

The jQuery library embedded in the admin has been upgraded from version 1.11.2 to 2.1.4. jQuery 2.x has the same API as jQuery 1.x, but does not support Internet Explorer 6, 7, or 8, allowing for better performance and a smaller file size. If you need to support IE8 and must also use the latest version of Django, you can override the admin’s copy of jQuery with your own by creating a Django application with this structure:

app/static/admin/js/vendor/
jquery.js
jquery.min.js

SyntaxError when installing Django setuptools 5.5.x

When installing Django 1.9 or 1.9.1 with setuptools 5.5.x, you’ll see:

Compiling django/conf/app_template/apps.py ...
File "django/conf/app_template/apps.py", line 4
class {{ camel_case_app_name }}Config(AppConfig):
^
SyntaxError: invalid syntax

Compiling django/conf/app_template/models.py ...
File "django/conf/app_template/models.py", line 1
{{ unicode_literals }}from django.db import models
^
SyntaxError: invalid syntax

It’s safe to ignore these errors (Django will still install just fine), but you can avoid them by upgrading setuptools to a more recent version. If you’re using pip, you can upgrade pip using pip install -U pip which will also upgrade setuptools. This is resolved in later versions of Django as described in the Django 1.9.2 release notes.

Miscellaneous

- The jQuery static files in contrib.admin have been moved into a vendor/jquery subdirectory.

- The text displayed for null columns in the admin changelist list_display cells has changed from (None) (or its translated equivalent) to - (a dash).

- django.http.responses.REASON_PHRASES and django.core.handlers.wsgi.STATUS_CODE_TEXT have been removed. Use Python’s stdlib instead: http.client.responses for Python 3 and httplib.responses for Python 2.

- ValuesQuerySet and ValuesListQuerySet have been removed.

- The admin/base.html template no longer sets window.__admin_media_prefix__ or window.__admin_utc_offset__. Image references in JavaScript that used that value to construct absolute URLs have been moved to CSS for easier customization. The UTC offset is stored on a data attribute of the <body> tag.

- CommaSeparatedIntegerField validation has been refined to forbid values like ',', ',1', and '1,,2'.

- Form initialization was moved from the ProcessFormView.get() method to the new FormMixin.get_context_data() method. This may be backwards incompatible if you have overridden the get_context_data() method without calling super().

- Support for PostGIS 1.5 has been dropped.

- The django.contrib.sites.models.Site.domain field was changed to be unique.

- In order to enforce test isolation, database queries are not allowed by default in SimpleTestCase tests anymore. You can disable this behavior by setting the allow_database_queries class attribute to True on your test class.

- ResolverMatch.app_name was changed to contain the full namespace path in the case of nested namespaces. For consistency with ResolverMatch.namespace, the empty value is now an empty string instead of None.

- For security hardening, session keys must be at least 8 characters.

- Private function django.utils.functional.total_ordering() has been removed. It contained a workaround for a functools.total_ordering() bug in Python versions older than 2.7.3.

- XML serialization (either through dumpdata or the syndication framework) used to output any characters it received. Now if the content to be serialized contains any control characters not allowed in the XML 1.0 standard, the serialization will fail with a ValueError.

- CharField now strips input of leading and trailing whitespace by default. This can be disabled by setting the new strip argument to False.

- Template text that is translated and uses two or more consecutive percent signs, e.g. "%%", may have a new msgid after makemessages is run (most likely the translation will be marked fuzzy). The new msgid will be marked "#, python-format".

- If neither request.current_app nor Context.current_app are set, the url template tag will now use the namespace of the current request. Set request.current_app to None if you don’t want to use a namespace hint.

- The SILENCED_SYSTEM_CHECKS setting now silences messages of all levels. Previously, messages of ERROR level or higher were printed to the console.

- The FlatPage.enable_comments field is removed from the FlatPageAdmin as it’s unused by the application. If your project or a third-party app makes use of it, create a custom ModelAdmin to add it back.

- The return value of setup_databases() and the first argument of teardown_databases() changed. They used to be (old_names, mirrors) tuples. Now they’re just the first item, old_names.

- By default LiveServerTestCase attempts to find an available port in the 8081-8179 range instead of just trying port 8081.

- The system checks for ModelAdmin now check instances rather than classes.

- The private API to apply mixed migration plans has been dropped for performance reasons. Mixed plans consist of a list of migrations where some are being applied and others are being unapplied.

- The related model object descriptor classes in django.db.models.fields.related (private API) are moved from the related module to related_descriptors and renamed as follows:

- ReverseSingleRelatedObjectDescriptor is ForwardManyToOneDescriptor

- SingleRelatedObjectDescriptor is ReverseOneToOneDescriptor

- ForeignRelatedObjectsDescriptor is ReverseManyToOneDescriptor

- ManyRelatedObjectsDescriptor is ManyToManyDescriptor

- If you implement a custom handler404 view, it must return a response with an HTTP 404 status code. Use HttpResponseNotFound or pass status=404 to the HttpResponse. Otherwise, APPEND_SLASH won’t work correctly with DEBUG=False.

Features deprecated in 1.9

assignment_tag()

Django 1.4 added the assignment_tag helper to ease the creation of template tags that store results in a template variable. The simple_tag() helper has gained this same ability, making the assignment_tag obsolete. Tags that use assignment_tag should be updated to use simple_tag.

{% cycle %} syntax with comma-separated arguments

The cycle tag supports an inferior old syntax from previous Django versions:

{% cycle row1,row2,row3 %}

Its parsing caused bugs with the current syntax, so support for the old syntax will be removed in Django 1.10 following an accelerated deprecation.

ForeignKey and OneToOneField on_delete argument

In order to increase awareness about cascading model deletion, the on_delete argument of ForeignKey and OneToOneField will be required in Django 2.0.

Update models and existing migrations to explicitly set the argument. Since the default is models.CASCADE, add on_delete=models.CASCADE to all ForeignKey and OneToOneFields that don’t use a different option. You can also pass it as the second positional argument if you don’t care about compatibility with older versions of Django.

Field.rel changes

Field.rel and its methods and attributes have changed to match the related fields API. The Field.rel attribute is renamed to remote_field and many of its methods and attributes are either changed or renamed.

The aim of these changes is to provide a documented API for relation fields.

GeoManager and GeoQuerySet custom methods

All custom GeoQuerySet methods (area(), distance(), gml(), ...) have been replaced by equivalent geographic expressions in annotations (see in new features). Hence the need to set a custom GeoManager to GIS-enabled models is now obsolete. As soon as your code doesn’t call any of the deprecated methods, you can simply remove the objects = GeoManager() lines from your models.

Template loader APIs have changed

Django template loaders have been updated to allow recursive template extending. This change necessitated a new template loader API. The old load_template() and load_template_sources() methods are now deprecated. Details about the new API can be found in the template loader documentation.

Passing a 3-tuple or an app_name to include()

The instance namespace part of passing a tuple as an argument to include() has been replaced by passing the namespace argument to include(). For example:

polls_patterns = [
url(...),
]

urlpatterns = [
url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),
]

becomes:

polls_patterns = ([
url(...),
], 'polls')  # 'polls' is the app_name

urlpatterns = [
url(r'^polls/', include(polls_patterns, namespace='author-polls')),
]

The app_name argument to include() has been replaced by passing a 2-tuple (as above), or passing an object or module with an app_name attribute (as below). If the app_name is set in this new way, the namespace argument is no longer required. It will default to the value of app_name. For example, the URL patterns in the tutorial are changed from:

mysite/urls.py

urlpatterns = [
url(r'^polls/', include('polls.urls', namespace="polls")),
...
]

to:

mysite/urls.py

urlpatterns = [
url(r'^polls/', include('polls.urls')),  # 'namespace="polls"' removed
...
]

polls/urls.py

app_name = 'polls'  # added
urlpatterns = [...]

This change also means that the old way of including an AdminSite instance is deprecated. Instead, pass admin.site.urls directly to url():

urls.py

from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
url(r'^admin/', admin.site.urls),
]

URL application namespace required if setting an instance namespace

In the past, an instance namespace without an application namespace would serve the same purpose as the application namespace, but it was impossible to reverse the patterns if there was an application namespace with the same name. Includes that specify an instance namespace require that the included URLconf sets an application namespace.

current_app parameter to contrib.auth views

All views in django.contrib.auth.views have the following structure:

def view(request, ..., current_app=None, ...):

...

if current_app is not None:
request.current_app = current_app

return TemplateResponse(request, template_name, context)

As of Django 1.8, current_app is set on the request object. For consistency, these views will require the caller to set current_app on the request instead of passing it in a separate argument.

django.contrib.gis.geoip

The django.contrib.gis.geoip2 module supersedes django.contrib.gis.geoip. The new module provides a similar API except that it doesn’t provide the legacy GeoIP-Python API compatibility methods.

Miscellaneous

- The weak argument to django.dispatch.signals.Signal.disconnect() has been deprecated as it has no effect.

- The check_aggregate_support() method of django.db.backends.base.BaseDatabaseOperations has been deprecated and will be removed in Django 2.0. The more general check_expression_support() should be used instead.

- django.forms.extras is deprecated. You can find SelectDateWidget in django.forms.widgets (or simply django.forms) instead.

- Private API django.db.models.fields.add_lazy_relation() is deprecated.

- The django.contrib.auth.tests.utils.skipIfCustomUser() decorator is deprecated. With the test discovery changes in Django 1.6, the tests for django.contrib apps are no longer run as part of the user’s project. Therefore, the @skipIfCustomUser decorator is no longer needed to decorate tests in django.contrib.auth.

- If you customized some error handlers, the view signatures with only one request parameter are deprecated. The views should now also accept a second exception positional parameter.

- The django.utils.feedgenerator.Atom1Feed.mime_type and django.utils.feedgenerator.RssFeed.mime_type attributes are deprecated in favor of content_type.

- Signer now issues a warning if an invalid separator is used. This will become an exception in Django 1.10.

- django.db.models.Field._get_val_from_obj() is deprecated in favor of Field.value_from_object().

- django.template.loaders.eggs.Loader is deprecated as distributing applications as eggs is not recommended.

- The callable_obj keyword argument to SimpleTestCase.assertRaisesMessage() is deprecated. Pass the callable as a positional argument instead.

- The allow_tags attribute on methods of ModelAdmin has been deprecated. Use format_html(), format_html_join(), or mark_safe() when constructing the method’s return value instead.

- The enclosure keyword argument to SyndicationFeed.add_item() is deprecated. Use the new enclosures argument which accepts a list of Enclosure objects instead of a single one.

- The django.template.loader.LoaderOrigin and django.template.base.StringOrigin aliases for django.template.base.Origin are deprecated.

Features removed in 1.9

These features have reached the end of their deprecation cycle and are removed in Django 1.9. See Features deprecated in 1.7 for details, including how to remove usage of these features.

- django.utils.dictconfig is removed.

- django.utils.importlib is removed.

- django.utils.tzinfo is removed.

- django.utils.unittest is removed.

- The syncdb command is removed.

- django.db.models.signals.pre_syncdb and django.db.models.signals.post_syncdb is removed.

- Support for allow_syncdb on database routers is removed.

- Automatic syncing of apps without migrations is removed. Migrations are compulsory for all apps unless you pass the migrate --run-syncdb option.

- The SQL management commands for apps without migrations, sql, sqlall, sqlclear, sqldropindexes, and sqlindexes, are removed.

- Support for automatic loading of initial_data fixtures and initial SQL data is removed.

- All models need to be defined inside an installed application or declare an explicit app_label. Furthermore, it isn’t possible to import them before their application is loaded. In particular, it isn’t possible to import models inside the root package of an application.

- The model and form IPAddressField is removed. A stub field remains for compatibility with historical migrations.

- AppCommand.handle_app() is no longer supported.

- RequestSite and get_current_site() are no longer importable from django.contrib.sites.models.

- FastCGI support via the runfcgi management command is removed.

- django.utils.datastructures.SortedDict is removed.

- ModelAdmin.declared_fieldsets is removed.

- The util modules that provided backwards compatibility are removed:

- django.contrib.admin.util

- django.contrib.gis.db.backends.util

- django.db.backends.util

- django.forms.util

- ModelAdmin.get_formsets is removed.

- The backward compatible shims introduced to rename the BaseMemcachedCache._get_memcache_timeout() method to get_backend_timeout() is removed.

- The --natural and -n options for dumpdata are removed.

- The use_natural_keys argument for serializers.serialize() is removed.

- Private API django.forms.forms.get_declared_fields() is removed.

- The ability to use a SplitDateTimeWidget with DateTimeField is removed.

- The WSGIRequest.REQUEST property is removed.

- The class django.utils.datastructures.MergeDict is removed.

- The zh-cn and zh-tw language codes are removed.

- The internal django.utils.functional.memoize() is removed.

- django.core.cache.get_cache is removed.

- django.db.models.loading is removed.

- Passing callable arguments to querysets is no longer possible.

- BaseCommand.requires_model_validation is removed in favor of requires_system_checks. Admin validators is replaced by admin checks.

- The ModelAdmin.validator_class and default_validator_class attributes are removed.

- ModelAdmin.validate() is removed.

- django.db.backends.DatabaseValidation.validate_field is removed in favor of the check_field method.

- The validate management command is removed.

- django.utils.module_loading.import_by_path is removed in favor of django.utils.module_loading.import_string.

- ssi and url template tags are removed from the future template tag library.

- django.utils.text.javascript_quote() is removed.

- Database test settings as independent entries in the database settings, prefixed by TEST_, are no longer supported.

- The cache_choices option to ModelChoiceField and ModelMultipleChoiceField is removed.

- The default value of the RedirectView.permanent attribute has changed from True to False.

- django.contrib.sitemaps.FlatPageSitemap is removed in favor of django.contrib.flatpages.sitemaps.FlatPageSitemap.

- Private API django.test.utils.TestTemplateLoader is removed.

- The django.contrib.contenttypes.generic module is removed.

Django 1.8.14 release notes

July 18, 2016

Django 1.8.14 fixes a security issue and a bug in 1.8.13.

XSS in admin’s add/change related popup

Unsafe usage of JavaScript’s Element.innerHTML could result in XSS in the admin’s add/change related popup. Element.textContent is now used to prevent execution of the data.

The debug view also used innerHTML. Although a security issue wasn’t identified there, out of an abundance of caution it’s also updated to use textContent.

Bugfixes

- Fixed missing varchar/text_pattern_ops index on CharField and TextField respectively when using AddField on PostgreSQL (#26889).

Django 1.8.13 release notes

May 2, 2016

Django 1.8.13 fixes several bugs in 1.8.12.

Bugfixes

- Fixed TimeField microseconds round-tripping on MySQL and SQLite (#26498).

- Restored conversion of an empty string to null when saving values of GenericIPAddressField on SQLite and MySQL (#26557).

Django 1.8.12 release notes

April 1, 2016

Django 1.8.12 fixes several bugs in 1.8.11.

Bugfixes

- Made MultiPartParser ignore filenames that normalize to an empty string to fix crash in MemoryFileUploadHandler on specially crafted user input (#26325).

- Fixed data loss on SQLite where DurationField values with fractional seconds could be saved as None (#26324).

- Restored the functionality of the admin’s raw_id_fields in list_editable (#26387).

Django 1.8.11 release notes

March 5, 2016

Django 1.8.11 fixes a regression on Python 2 in the 1.8.10 security release where utils.http.is_safe_url() crashes on bytestring URLs (#26308).

Django 1.8.10 release notes

March 1, 2016

Django 1.8.10 fixes two security issues and several bugs in 1.8.9.

CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security check for these redirects (namely django.utils.http.is_safe_url()) considered some URLs with basic authentication credentials “safe” when they shouldn’t be.

For example, a URL like http://mysite.example.com\@attacker.com would be considered safe if the request’s host is http://mysite.example.com, but redirecting to this URL sends the user to attacker.com.

Also, if a developer relies on is_safe_url() to provide safe redirect targets and puts such a URL into a link, they could suffer from an XSS attack.

CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade

In each major version of Django since 1.6, the default number of iterations for the PBKDF2PasswordHasher and its subclasses has increased. This improves the security of the password as the speed of hardware increases, however, it also creates a timing difference between a login request for a user with a password encoded in an older number of iterations and login request for a nonexistent user (which runs the default hasher’s default number of iterations since Django 1.6).

This only affects users who haven’t logged in since the iterations were increased. The first time a user logs in after an iterations increase, their password is updated with the new iterations and there is no longer a timing difference.

The new BasePasswordHasher.harden_runtime() method allows hashers to bridge the runtime gap between the work factor (e.g. iterations) supplied in existing encoded passwords and the default work factor of the hasher. This method is implemented for PBKDF2PasswordHasher and BCryptPasswordHasher. The number of rounds for the latter hasher hasn’t changed since Django 1.4, but some projects may subclass it and increase the work factor as needed.

A warning will be emitted for any third-party password hashers that don’t implement a harden_runtime() method.

If you have different password hashes in your database (such as SHA1 hashes from users who haven’t logged in since the default hasher switched to PBKDF2 in Django 1.4), the timing difference on a login request for these users may be even greater and this fix doesn’t remedy that difference (or any difference when changing hashers). You may be able to upgrade those hashes to prevent a timing attack for that case.

Bugfixes

- Fixed a crash on PostgreSQL that prevented using TIME_ZONE=None and USE_TZ=False (#26177).

- Added system checks for query name clashes of hidden relationships (#26162).

- Made forms.FileField and utils.translation.lazy_number() picklable (#26212).

- Fixed RangeField and ArrayField serialization with None values (#26215).

- Reallowed dashes in top-level domain names of URLs checked by URLValidator to fix a regression in Django 1.8 (#26204).

- Fixed BoundField to reallow slices of subwidgets (#26267).

- Prevented ContentTypeManager instances from sharing their cache (#26286).

Django 1.8.9 release notes

February 1, 2016

Django 1.8.9 fixes several bugs in 1.8.8.

Bugfixes

- Fixed a regression that caused the “user-tools” items to display on the admin’s logout page (#26035).

- Fixed a crash in the translations system when the current language has no translations (#26046).

- Fixed a regression that caused the incorrect day to be selected when opening the admin calendar widget for timezones from GMT+0100 to GMT+1200 (#24980).

- Fixed a regression in 1.8.8 causing incorrect index handling in migrations on PostgreSQL when adding db_index=True or unique=True to a CharField or TextField that already had the other specified, or when removing one of them from a field that had both, or when adding unique=True to a field already listed in unique_together (#26034).

- Fixed a crash when using an __in lookup inside a Case expression (#26071).

- Fixed a crash when using a reverse OneToOneField in ModelAdmin.readonly_fields (#26060).

- Fixed a regression in Django 1.8.5 that broke copying a SimpleLazyObject with copy.copy() (#26122).

- Fixed the contrib.gis map widgets when using USE_THOUSAND_SEPARATOR=True (#20415).

Django 1.8.8 release notes

January 2, 2016

Django 1.8.8 fixes several bugs in 1.8.7.

Python 3.2 users, please be advised that we’ve decided to drop support for Python 3.2 in Django 1.8.x at the end of 2016. We won’t break things intentionally after that, but we won’t test subsequent releases against Python 3.2 either. Upstream support for Python 3.2 ends February 2016 so we don’t find much value in providing security updates for a version of Python that could be insecure. To read more about the decision and to let us know if this will be problematic for you, please read the django-developers thread.

Bugfixes

- Fixed incorrect unique_together field name generation by inspectdb (#25274).

- Corrected __len query lookup on ArrayField for empty arrays (#25772).

- Restored the ability to use custom formats from formats.py with django.utils.formats.get_format() and the date template filter (#25812).

- Fixed a state bug when migrating a SeparateDatabaseAndState operation backwards (#25896).

- Fixed missing varchar/text_pattern_ops index on CharField and TextField respectively when using AlterField on PostgreSQL (#25412).

- Fixed a state bug when using an AlterModelManagers operation (#25852).

- Fixed a regression which prevented using a language not in Django’s default language list (LANGUAGES) (#25915).

- django.views.decorators.cache.never_cache() now sends more persuasive headers (added no-cache, no-store, must-revalidate to Cache-Control) to better prevent caching (#13008). This fixes a problem where a page refresh in Firefox cleared the selected entries in the admin’s filter_horizontal and filter_vertical widgets, which could result in inadvertent data loss if a user didn’t notice that and then submitted the form (#22955).

- Fixed a regression in the admin which ignored line breaks in read-only fields instead of converting them to <br> (#25465).

- Made loaddata skip disabling and enabling database constraints when it doesn’t load any fixtures (#23372).

- Fixed a crash in QuerySet.values()/values_list() after an annotate() and order_by() when values()/values_list() includes a field not in the order_by() (#25316).

Django 1.8.7 release notes

November 24, 2015

Django 1.8.7 fixes a security issue and several bugs in 1.8.6.

Additionally, Django’s vendored version of six, django.utils.six, has been upgraded to the latest release (1.10.0).

Fixed settings leak possibility in date template filter

If an application allows users to specify an unvalidated format for dates and passes this format to the date filter, e.g. {{ last_updated|date:user_date_format }}, then a malicious user could obtain any secret in the application’s settings by specifying a settings key instead of a date format. e.g. "SECRET_KEY" instead of "j/m/Y".

To remedy this, the underlying function used by the date template filter, django.utils.formats.get_format(), now only allows accessing the date/time formatting settings.

Bugfixes

- Fixed a crash of the debug view during the autumn DST change when USE_TZ is False and pytz is installed.

- Fixed a regression in 1.8.6 that caused database routers without an allow_migrate() method to crash (#25686).

- Fixed a regression in 1.8.6 by restoring the ability to use Manager objects for the queryset argument of ModelChoiceField (#25683).

- Fixed a regression in 1.8.6 that caused an application with South migrations in the migrations directory to fail (#25618).

- Fixed a data loss possibility with Prefetch if to_attr is set to a ManyToManyField (#25693).

- Fixed a regression in 1.8 by making gettext() once again return UTF-8 bytestrings on Python 2 if the input is a bytestring (#25720).

- Fixed serialization of DateRangeField and DateTimeRangeField (#24937).

- Fixed the exact lookup of ArrayField (#25666).

- Fixed Model.refresh_from_db() updating of ForeignKey fields with on_delete=models.SET_NULL (#25715).

- Fixed a duplicate query regression in 1.8 on proxied model deletion (#25685).

- Fixed set_FOO_order() crash when the ForeignKey of a model with order_with_respect_to references a model with a OneToOneField primary key (#25786).

- Fixed incorrect validation for PositiveIntegerField and PositiveSmallIntegerField on MySQL resulting in values greater than 4294967295 or 65535, respectively, passing validation and being silently truncated by the database (#25767).

Django 1.8.6 release notes

November 4, 2015

Django 1.8.6 adds official support for Python 3.5 and fixes several bugs in 1.8.5.

Bugfixes

- Fixed a regression causing ModelChoiceField to ignore prefetch_related() on its queryset (#25496).

- Allowed “mode=memory” in SQLite test database name if supported (#12118).

- Fixed system check crash on ForeignKey to abstract model (#25503).

- Fixed incorrect queries when you have multiple ManyToManyFields on different models that have the same field name, point to the same model, and have their reverse relations disabled (#25545).

- Allowed filtering over a RawSQL annotation (#25506).

- Made the Concat database function idempotent on SQLite (#25517).

- Avoided a confusing stack trace when starting runserver with an invalid INSTALLED_APPS setting (#25510). This regression appeared in 1.8.5 as a side effect of fixing #24704.

- Made deferred models use their proxied model’s _meta.apps for caching and retrieval (#25563). This prevents any models generated in data migrations using QuerySet.defer() from leaking to test and application code.

- Fixed a typo in the name of the strictly_above PostGIS lookup (#25592).

- Fixed crash with contrib.postgres.forms.SplitArrayField and IntegerField on invalid value (#25597).

- Added a helpful error message when Django and South migrations exist in the same directory (#25618).

- Fixed a regression in URLValidator that allowed URLs with consecutive dots in the domain section (like http://example..com/) to pass (#25620).

- Fixed a crash with GenericRelation and BaseModelAdmin.to_field_allowed (#25622).

Django 1.8.5 release notes

October 3, 2015

Django 1.8.5 fixes several bugs in 1.8.4.

Bugfixes

- Made the development server’s autoreload more robust (#24704).

- Fixed AssertionError in some delete queries with a model containing a field that is both a foreign and primary key (#24951).

- Fixed AssertionError in some complex queries (#24525).

- Fixed a migrations crash with GenericForeignKey (#25040).

- Made translation.override() clear the overridden language when a translation isn’t initially active (#25295).

- Fixed crash when using a value in ModelAdmin.list_display that clashed with a reverse field on the model (#25299).

- Fixed autocompletion for options of non-argparse management commands (#25372).

- Alphabetized ordering of imports in from django.db import migrations, models statement in newly created migrations (#25384).

- Fixed migrations crash on MySQL when adding a text or a blob field with an unhashable default (#25393).

- Changed Count queries to execute COUNT(*) instead of COUNT('*') as versions of Django before 1.8 did (#25377). This may fix a performance regression on some databases.

- Fixed custom queryset chaining with values() and values_list() (#20625).

- Moved the unsaved model instance assignment data loss check on reverse relations to Model.save() (#25160).

- Readded inline foreign keys to form instances when validating model formsets (#25431).

- Allowed using ORM write methods after disabling autocommit with set_autocommit(False) (#24921).

- Fixed the manage.py test --keepdb option on Oracle (#25421).

- Fixed incorrect queries with multiple many-to-many fields on a model with the same ‘to’ model and with related_name set to ‘+’ (#24505, #25486).

- Fixed pickling a SimpleLazyObject wrapping a model (#25389).

Django 1.8.4 release notes

August 18, 2015

Django 1.8.4 fixes a security issue and several bugs in 1.8.3.

Denial-of-service possibility in logout() view by filling session store

Previously, a session could be created when anonymously accessing the django.contrib.auth.views.logout() view (provided it wasn’t decorated with login_required() as done in the admin). This could allow an attacker to easily create many new session records by sending repeated requests, potentially filling up the session store or causing other users’ session records to be evicted.

The SessionMiddleware has been modified to no longer create empty session records, including when SESSION_SAVE_EVERY_REQUEST is active.

Bugfixes

- Added the ability to serialize values from the newly added UUIDField (#25019).

- Added a system check warning if the old TEMPLATE_* settings are defined in addition to the new TEMPLATES setting.

- Fixed QuerySet.raw() so InvalidQuery is not raised when using the db_column name of a ForeignKey field with primary_key=True (#12768).

- Prevented an exception in TestCase.setUpTestData() from leaking the transaction (#25176).

- Fixed has_changed() method in contrib.postgres.forms.HStoreField (#25215, #25233).

- Fixed the recording of squashed migrations when running the migrate command (#25231).

- Moved the unsaved model instance assignment data loss check to Model.save() to allow easier usage of in-memory models (#25160).

- Prevented varchar_patterns_ops and text_patterns_ops indexes for ArrayField (#25180).

Django 1.8.3 release notes

July 8, 2015

Django 1.8.3 fixes several security issues and bugs in 1.8.2.

Also, django.utils.deprecation.RemovedInDjango20Warning was renamed to RemovedInDjango110Warning as the version roadmap was revised to 1.9, 1.10, 1.11 (LTS), 2.0 (drops Python 2 support). For backwards compatibility, RemovedInDjango20Warning remains as an importable alias.

Denial-of-service possibility by filling session store

In previous versions of Django, the session backends created a new empty record in the session storage anytime request.session was accessed and there was a session key provided in the request cookies that didn’t already have a session record. This could allow an attacker to easily create many new session records simply by sending repeated requests with unknown session keys, potentially filling up the session store or causing other users’ session records to be evicted.

The built-in session backends now create a session record only if the session is actually modified; empty session records are not created. Thus this potential DoS is now only possible if the site chooses to expose a session-modifying view to anonymous users.

As each built-in session backend was fixed separately (rather than a fix in the core sessions framework), maintainers of third-party session backends should check whether the same vulnerability is present in their backend and correct it if so.

Header injection possibility since validators accept newlines in input

Some of Django’s built-in validators (EmailValidator, most seriously) didn’t prohibit newline characters (due to the usage of $ instead of \Z in the regular expressions). If you use values with newlines in HTTP response or email headers, you can suffer from header injection attacks. Django itself isn’t vulnerable because HttpResponse and the mail sending utilities in django.core.mail prohibit newlines in HTTP and SMTP headers, respectively. While the validators have been fixed in Django, if you’re creating HTTP responses or email messages in other ways, it’s a good idea to ensure that those methods prohibit newlines as well. You might also want to validate that any existing data in your application doesn’t contain unexpected newlines.

validate_ipv4_address(), validate_slug(), and URLValidator are also affected, however, as of Django 1.6 the GenericIPAddresseField, IPAddressField, SlugField, and URLField form fields which use these validators all strip the input, so the possibility of newlines entering your data only exists if you are using these validators outside of the form fields.

The undocumented, internally unused validate_integer() function is now stricter as it validates using a regular expression instead of simply casting the value using int() and checking if an exception was raised.

Denial-of-service possibility in URL validation

URLValidator included a regular expression that was extremely slow to evaluate against certain invalid inputs. This regular expression has been simplified and optimized.

Bugfixes

- Fixed BaseRangeField.prepare_value() to use each base_field’s prepare_value() method (#24841).

- Fixed crash during makemigrations if a migrations module either is missing __init__.py or is a file (#24848).

- Fixed QuerySet.exists() returning incorrect results after annotation with Count() (#24835).

- Corrected HStoreField.has_changed() (#24844).

- Reverted an optimization to the CSRF template context processor which caused a regression (#24836).

- Fixed a regression which caused template context processors to overwrite variables set on a RequestContext after it’s created (#24847).

- Prevented the loss of null/not null column properties during field renaming of MySQL databases (#24817).

- Fixed a crash when using a reverse one-to-one relation in ModelAdmin.list_display (#24851).

- Fixed quoting of SQL when renaming a field to AutoField in PostgreSQL (#24892).

- Fixed lack of unique constraint when changing a field from primary_key=True to unique=True (#24893).

- Fixed queryset pickling when using prefetch_related() after deleting objects (#24831).

- Allowed using choices longer than 1 day with DurationField (#24897).

- Fixed a crash when loading squashed migrations from two apps with a dependency between them, where the dependent app’s replaced migrations are partially applied (#24895).

- Fixed recording of applied status for squashed (replacement) migrations (#24628).

- Fixed queryset annotations when using Case expressions with exclude() (#24833).

- Corrected join promotion for multiple Case expressions. Annotating a query with multiple Case expressions could unexpectedly filter out results (#24924).

- Fixed usage of transforms in subqueries (#24744).

- Fixed SimpleTestCase.assertRaisesMessage() on Python 2.7.10 (#24903).

- Provided better backwards compatibility for the verbosity argument in optparse management commands by casting it to an integer (#24769).

- Fixed prefetch_related() on databases other than PostgreSQL for models using UUID primary keys (#24912).

- Fixed removing unique_together constraints on MySQL (#24972).

- Fixed crash when uploading images with MIME types that Pillow doesn’t detect, such as bitmap, in forms.ImageField (#24948).

- Fixed a regression when deleting a model through the admin that has a GenericRelation with a related_query_name (#24940).

- Reallowed non-ASCII values for ForeignKey.related_name on Python 3 by fixing the false positive system check (#25016).

- Fixed inline forms that use a parent object that has a UUIDField primary key and a child object that has an AutoField primary key (#24958).

- Fixed a regression in the unordered_list template filter on certain inputs (#25031).

- Fixed a regression in URLValidator that invalidated Punycode TLDs (#25059).

- Improved pyinotify runserver polling (#23882).

Django 1.8.2 release notes

May 20, 2015

Django 1.8.2 fixes a security issue and several bugs in 1.8.1.

Fixed session flushing in the cached_db backend

A change to session.flush() in the cached_db session backend in Django 1.8 mistakenly sets the session key to an empty string rather than None. An empty string is treated as a valid session key and the session cookie is set accordingly. Any users with an empty string in their session cookie will use the same session store. session.flush() is called by django.contrib.auth.logout() and, more seriously, by django.contrib.auth.login() when a user switches accounts. If a user is logged in and logs in again to a different account (without logging out) the session is flushed to avoid reuse. After the session is flushed (and its session key becomes '') the account details are set on the session and the session is saved. Any users with an empty string in their session cookie will now be logged into that account.

Bugfixes

- Fixed check for template engine alias uniqueness (#24685).

- Fixed crash when reusing the same Case instance in a query (#24752).

- Corrected join promotion for Case expressions. For example, annotating a query with a Case expression could unexpectedly filter out results (#24766).

- Fixed negated Q objects in expressions. Cases like Case(When(~Q(friends__age__lte=30))) tried to generate a subquery which resulted in a crash (#24705).

- Fixed incorrect GROUP BY clause generation on MySQL when the query’s model has a self-referential foreign key (#24748).

- Implemented ForeignKey.get_db_prep_value() so that ForeignKeys pointing to UUIDField and inheritance on models with UUIDField primary keys work correctly (#24698, #24712).

- Fixed isnull lookup for HStoreField (#24751).

- Fixed a MySQL crash when a migration removes a combined index (unique_together or index_together) containing a foreign key (#24757).

- Fixed session cookie deletion when using SESSION_COOKIE_DOMAIN (#24799).

- On PostgreSQL, when no access is granted for the postgres database, Django now falls back to the default database when it normally requires a “no database” connection (#24791).

- Fixed display of contrib.admin’s ForeignKey widget when it’s used in a row with other fields (#24784).

Django 1.8.1 release notes

May 1, 2015

Django 1.8.1 fixes several bugs in 1.8 and includes some optimizations in the migrations framework.

Bugfixes

- Added support for serializing timedelta objects in migrations (#24566).

- Restored proper parsing of the testserver command’s positional arguments (fixture names) (#24571).

- Prevented TypeError in translation functions check_for_language() and get_language_bidi() when translations are deactivated (#24569).

- Fixed squashmigrations command when using SeparateDatabaseAndState (#24278).

- Stripped microseconds from datetime values when using an older version of the MySQLdb DB API driver as it does not support fractional seconds (#24584).

- Fixed a migration crash when altering ManyToManyFields (#24513).

- Fixed a crash with QuerySet.update() on foreign keys to one-to-one fields (#24578).

- Fixed a regression in the model detail view of admindocs when a model has a reverse foreign key relation (#24624).

- Prevented arbitrary file inclusions in admindocs (#24625).

- Fixed a crash with QuerySet.update() on foreign keys to instances with uuid primary keys (#24611).

- Fixed database introspection with SQLite 3.8.9 (released April 8, 2015) (#24637).

- Updated urlpatterns examples generated by startproject to remove usage of referencing views by dotted path in url() which is deprecated in Django 1.8 (#24635).

- Fixed queries where an expression was referenced in order_by(), but wasn’t part of the select clause. An example query is qs.annotate(foo=F('field')).values('pk').order_by('foo')) (#24615).

- Fixed a database table name quoting regression (#24605).

- Prevented the loss of null/not null column properties during field alteration of MySQL databases (#24595).

- Fixed JavaScript path of contrib.admin’s related field widget when using alternate static file storages (#24655).

- Fixed a migration crash when adding new relations to models (#24573).

- Fixed a migration crash when applying migrations with model managers on Python 3 that were generated on Python 2 (#24701).

- Restored the ability to use iterators as queryset filter arguments (#24719).

- Fixed a migration crash when renaming the target model of a many-to-many relation (#24725).

- Removed flushing of the test database with test --keepdb, which prevented apps with data migrations from using the option (#24729).

- Fixed makemessages crash in some locales (#23271).

- Fixed help text positioning of contrib.admin fields that use the ModelAdmin.filter_horizontal and filter_vertical options (#24676).

- Fixed AttributeError: function ‘GDALAllRegister’ not found error when initializing contrib.gis on Windows.

Optimizations

- Changed ModelState to deepcopy fields instead of deconstructing and reconstructing (#24591). This speeds up the rendering of model states and reduces memory usage when running manage.py migrate (although other changes in this release may negate any performance benefits).

Django 1.8 release notes

April 1, 2015

Welcome to Django 1.8!

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.7 or older versions. We’ve also begun the deprecation process for some features, and some features have reached the end of their deprecation process and have been removed.

See the Upgrading Django to a newer version guide if you’re updating an existing project.

Django 1.8 has been designated as Django’s second long-term support release. It will receive security updates for at least three years after its release. Support for the previous LTS, Django 1.4, will end 6 months from the release date of Django 1.8.

Python compatibility

Django 1.8 requires Python 2.7, 3.2, 3.3, 3.4, or 3.5. We highly recommend and only officially support the latest release of each series.

Django 1.8 is the first release to support Python 3.5.

Due to the end of upstream support for Python 3.2 in February 2016, we won’t test Django 1.8.x on Python 3.2 after the end of 2016.

What’s new in Django 1.8

Model._meta API

Django now has a formalized API for Model._meta, providing an officially supported way to retrieve fields and filter fields based on their attributes.

The Model._meta object has been part of Django since the days of pre-0.96 “Magic Removal” – it just wasn’t an official, stable API. In recognition of this, we’ve endeavored to maintain backwards-compatibility with the old API endpoint where possible. However, API endpoints that aren’t part of the new official API have been deprecated and will eventually be removed. A guide to migrating from the old API to the new API has been provided.

Multiple template engines

Django 1.8 defines a stable API for integrating template backends. It includes built-in support for the Django template language and for Jinja2. It supports rendering templates with multiple engines within the same project. Learn more about the new features in the topic guide and check the upgrade instructions for details.

Security enhancements

Several features of the django-secure third-party library have been integrated into Django. django.middleware.security.SecurityMiddleware provides several security enhancements to the request/response cycle. The new check --deploy option allows you to check your production settings file for ways to increase the security of your site.

New PostgreSQL specific functionality

Django now has a module with extensions for PostgreSQL specific features, such as ArrayField, HStoreField, Range Fields, and unaccent lookup. A full breakdown of the features is available in the documentation.

New data types

- Django now has a UUIDField for storing universally unique identifiers. It is stored as the native uuid data type on PostgreSQL and as a fixed length character field on other backends. There is a corresponding form field.

- Django now has a DurationField for storing periods of time - modeled in Python by timedelta. It is stored in the native interval data type on PostgreSQL, as a INTERVAL DAY(9) TO SECOND(6) on Oracle, and as a bigint of microseconds on other backends. Date and time related arithmetic has also been improved on all backends. There is a corresponding form field.

Query Expressions, Conditional Expressions, and Database Functions

Query Expressions allow you to create, customize, and compose complex SQL expressions. This has enabled annotate to accept expressions other than aggregates. Aggregates are now able to reference multiple fields, as well as perform arithmetic, similar to F() objects. order_by() has also gained the ability to accept expressions.

Conditional Expressions allow you to use if ... elif ... else logic within queries.

A collection of database functions is also included with functionality such as Coalesce, Concat, and Substr.

TestCase data setup

TestCase has been refactored to allow for data initialization at the class level using transactions and savepoints. Database backends which do not support transactions, like MySQL with the MyISAM storage engine, will still be able to run these tests but won’t benefit from the improvements. Tests are now run within two nested atomic() blocks: one for the whole class and one for each test.

- The class method TestCase.setUpTestData() adds the ability to setup test data at the class level. Using this technique can speed up the tests as compared to using setUp().

- Fixture loading within TestCase is now performed once for the whole TestCase.

Minor features

django.contrib.admin

- ModelAdmin now has a has_module_permission() method to allow limiting access to the module on the admin index page.

- InlineModelAdmin now has an attribute show_change_link that supports showing a link to an inline object’s change form.

- Use the new django.contrib.admin.RelatedOnlyFieldListFilter in ModelAdmin.list_filter to limit the list_filter choices to foreign objects which are attached to those from the ModelAdmin.

- The ModelAdmin.delete_view() displays a summary of objects to be deleted on the deletion confirmation page.

- The jQuery library embedded in the admin has been upgraded to version 1.11.2.

- You can now specify AdminSite.site_url in order to display a link to the front-end site.

- You can now specify ModelAdmin.show_full_result_count to control whether or not the full count of objects should be displayed on a filtered admin page.

- The AdminSite.password_change() method now has an extra_context parameter.

- You can now control who may login to the admin site by overriding only AdminSite.has_permission() and AdminSite.login_form. The base.html template has a new block usertools which contains the user-specific header. A new context variable has_permission, which gets its value from has_permission(), indicates whether the user may access the site.

- Foreign key dropdowns now have buttons for changing or deleting related objects using a popup.

django.contrib.admindocs

- reStructuredText is now parsed in model docstrings.

django.contrib.auth

- Authorization backends can now raise PermissionDenied in has_perm() and has_module_perms() to short-circuit permission checking.

- PasswordResetForm now has a method send_email() that can be overridden to customize the mail to be sent.

- The max_length of Permission.name has been increased from 50 to 255 characters. Please run the database migration.

- USERNAME_FIELD and REQUIRED_FIELDS now supports ForeignKeys.

- The default iteration count for the PBKDF2 password hasher has been increased by 33%. This backwards compatible change will not affect users who have subclassed django.contrib.auth.hashers.PBKDF2PasswordHasher to change the default value.

django.contrib.gis

- A new GeoJSON serializer is now available.

- It is now allowed to include a subquery as a geographic lookup argument, for example City.objects.filter(point__within=Country.objects.filter(continent='Africa').values('mpoly')).

- The Spatialite backend now supports Collect and Extent aggregates when the database version is 3.0 or later.

- The PostGIS 2 CREATE EXTENSION postgis and the Spatialite SELECT InitSpatialMetaData initialization commands are now automatically run by migrate.

- The GDAL interface now supports retrieving properties of raster (image) data file.

- Compatibility shims for SpatialRefSys and GeometryColumns changed in Django 1.2 have been removed.

- All GDAL-related exceptions are now raised with GDALException. The former OGRException has been kept for backwards compatibility but should not be used any longer.

django.contrib.sessions

- Session cookie is now deleted after flush() is called.

django.contrib.sitemaps

- The new Sitemap.i18n attribute allows you to generate a sitemap based on the LANGUAGES setting.

django.contrib.sites

- get_current_site() will now lookup the current site based on request.get_host() if the SITE_ID setting is not defined.

- The default Site created when running migrate now respects the SITE_ID setting (instead of always using pk=1).

Cache

- The incr() method of the django.core.cache.backends.locmem.LocMemCache backend is now thread-safe.

Cryptography

- The max_age parameter of the django.core.signing.TimestampSigner.unsign() method now also accepts a datetime.timedelta object.

Database backends

- The MySQL backend no longer strips microseconds from datetime values as MySQL 5.6.4 and up supports fractional seconds depending on the declaration of the datetime field (when DATETIME includes fractional precision greater than 0). New datetime database columns created with Django 1.8 and MySQL 5.6.4 and up will support microseconds. See the MySQL database notes for more details.

- The MySQL backend no longer creates explicit indexes for foreign keys when using the InnoDB storage engine, as MySQL already creates them automatically.

- The Oracle backend no longer defines the connection_persists_old_columns feature as True. Instead, Oracle will now include a cache busting clause when getting the description of a table.

Email

- Email backends now support the context manager protocol for opening and closing connections.

- The SMTP email backend now supports keyfile and certfile authentication with the EMAIL_SSL_CERTFILE and EMAIL_SSL_KEYFILE settings.

- The SMTP EmailBackend now supports setting the timeout parameter with the EMAIL_TIMEOUT setting.

- EmailMessage and EmailMultiAlternatives now support the reply_to parameter.

File Storage

- Storage.get_available_name() and Storage.save() now take a max_length argument to implement storage-level maximum filename length constraints. Filenames exceeding this argument will get truncated. This prevents a database error when appending a unique suffix to a long filename that already exists on the storage. See the deprecation note about adding this argument to your custom storage classes.

Forms

- Form widgets now render attributes with a value of True or False as HTML5 boolean attributes.

- The new has_error() method allows checking if a specific error has happened.

- If required_css_class is defined on a form, then the <label> tags for required fields will have this class present in its attributes.

- The rendering of non-field errors in unordered lists (<ul>) now includes nonfield in its list of classes to distinguish them from field-specific errors.

- Field now accepts a label_suffix argument, which will override the form’s label_suffix. This enables customizing the suffix on a per-field basis — previously it wasn’t possible to override a form’s label_suffix while using shortcuts such as {{ form.as_p }} in templates.

- SelectDateWidget now accepts an empty_label argument, which will override the top list choice label when DateField is not required.

- After an ImageField has been cleaned and validated, the UploadedFile object will have an additional image attribute containing the Pillow Image instance used to check if the file was a valid image. It will also update UploadedFile.content_type with the image’s content type as determined by Pillow.

- You can now pass a callable that returns an iterable of choices when instantiating a ChoiceField.

Generic Views

- Generic views that use MultipleObjectMixin may now specify the ordering applied to the queryset by setting ordering or overriding get_ordering().

- The new SingleObjectMixin.query_pk_and_slug attribute allows changing the behavior of get_object() so that it’ll perform its lookup using both the primary key and the slug.

- The get_form() method doesn’t require a form_class to be provided anymore. If not provided form_class defaults to get_form_class().

- Placeholders in ModelFormMixin.success_url now support the Python str.format() syntax. The legacy %(<foo>)s syntax is still supported but will be removed in Django 1.10.

Internationalization

- FORMAT_MODULE_PATH can now be a list of strings representing module paths. This allows importing several format modules from different reusable apps. It also allows overriding those custom formats in your main Django project.

Logging

- The django.utils.log.AdminEmailHandler class now has a send_mail() method to make it more subclass friendly.

Management Commands

- Database connections are now always closed after a management command called from the command line has finished doing its job.

- Commands from alternate package formats like eggs are now also discovered.

- The new dumpdata --output option allows specifying a file to which the serialized data is written.

- The new makemessages --exclude and compilemessages --exclude options allow excluding specific locales from processing.

- compilemessages now has a --use-fuzzy or -f option which includes fuzzy translations into compiled files.

- The loaddata --ignorenonexistent option now ignores data for models that no longer exist.

- runserver now uses daemon threads for faster reloading.

- inspectdb now outputs Meta.unique_together. It is also able to introspect AutoField for MySQL and PostgreSQL databases.

- When calling management commands with options using call_command(), the option name can match the command line option name (without the initial dashes) or the final option destination variable name, but in either case, the resulting option received by the command is now always the dest name specified in the command option definition (as long as the command uses the argparse module).

- The dbshell command now supports MySQL’s optional SSL certificate authority setting (--ssl-ca).

- The new makemigrations --name allows giving the migration(s) a custom name instead of a generated one.

- The loaddata command now prevents repeated fixture loading. If FIXTURE_DIRS contains duplicates or a default fixture directory path (app_name/fixtures), an exception is raised.

- The new makemigrations --exit option allows exiting with an error code if no migrations are created.

- The new showmigrations command allows listing all migrations and their dependencies in a project.

Middleware

- The CommonMiddleware.response_redirect_class attribute allows you to customize the redirects issued by the middleware.

- A debug message will be logged to the django.request logger when a middleware raises a MiddlewareNotUsed exception in DEBUG mode.

Migrations

- The RunSQL operation can now handle parameters passed to the SQL statements.

- It is now possible to have migrations (most probably data migrations) for applications without models.

- Migrations can now serialize model managers as part of the model state.

- A generic mechanism to handle the deprecation of model fields was added.

- The RunPython.noop() and RunSQL.noop class method/attribute were added to ease in making RunPython and RunSQL operations reversible.

- The migration operations RunPython and RunSQL now call the allow_migrate() method of database routers. The router can use the newly introduced app_label and hints arguments to make a routing decision. To take advantage of this feature you need to update the router to the new allow_migrate signature, see the deprecation section for more details.

Models

- Django now logs at most 9000 queries in connections.queries, in order to prevent excessive memory usage in long-running processes in debug mode.

- There is now a model Meta option to define a default related name for all relational fields of a model.

- Pickling models and querysets across different versions of Django isn’t officially supported (it may work, but there’s no guarantee). An extra variable that specifies the current Django version is now added to the pickled state of models and querysets, and Django raises a RuntimeWarning when these objects are unpickled in a different version than the one in which they were pickled.

- Added Model.from_db() which Django uses whenever objects are loaded using the ORM. The method allows customizing model loading behavior.

- extra(select={...}) now allows you to escape a literal %s sequence using %%s.

- Custom Lookups can now be registered using a decorator pattern.

- The new Transform.bilateral attribute allows creating bilateral transformations. These transformations are applied to both lhs and rhs when used in a lookup expression, providing opportunities for more sophisticated lookups.

- SQL special characters (, %, _) are now escaped properly when a pattern lookup (e.g. contains, startswith, etc.) is used with an F() expression as the right-hand side. In those cases, the escaping is performed by the database, which can lead to somewhat complex queries involving nested REPLACE function calls.

- You can now refresh model instances by using Model.refresh_from_db().

- You can now get the set of deferred fields for a model using Model.get_deferred_fields().

- Model field default’s are now used when primary key field’s are set to None.

Signals

- Exceptions from the (receiver, exception) tuples returned by Signal.send_robust() now have their traceback attached as a __traceback__ attribute.

- The environ argument, which contains the WSGI environment structure from the request, was added to the request_started signal.

- You can now import the setting_changed() signal from django.core.signals to avoid loading django.test in non-test situations. Django no longer does so itself.

System Check Framework

- register can now be used as a function.

Templates

- urlize now supports domain-only links that include characters after the top-level domain (e.g. djangoproject.com/ and djangoproject.com/download/).

- urlize doesn’t treat exclamation marks at the end of a domain or its query string as part of the URL (the URL in e.g. 'djangoproject.com! is djangoproject.com)

- Added a locmem.Loader class that loads Django templates from a Python dictionary.

- The now tag can now store its output in a context variable with the usual syntax: {% now 'j n Y' as varname %}.

Requests and Responses

- WSGIRequest now respects paths starting with //.

- The HttpRequest.build_absolute_uri() method now handles paths starting with // correctly.

- If DEBUG is True and a request raises a SuspiciousOperation, the response will be rendered with a detailed error page.

- The query_string argument of QueryDict is now optional, defaulting to None, so a blank QueryDict can now be instantiated with QueryDict() instead of QueryDict(None) or QueryDict('').

- The GET and POST attributes of an HttpRequest object are now QueryDicts rather than dictionaries, and the FILES attribute is now a MultiValueDict. This brings this class into line with the documentation and with WSGIRequest.

- The HttpResponse.charset attribute was added.

- WSGIRequestHandler now follows RFC in converting URI to IRI, using uri_to_iri().

- The HttpRequest.get_full_path() method now escapes unsafe characters from the path portion of a Uniform Resource Identifier (URI) properly.

- HttpResponse now implements a few additional methods like getvalue() so that instances can be used as stream objects.

- The new HttpResponse.setdefault() method allows setting a header unless it has already been set.

- You can use the new FileResponse to stream files.

- The condition() decorator for conditional view processing now supports the If-unmodified-since header.

Tests

- The RequestFactory.trace() and Client.trace() methods were implemented, allowing you to create TRACE requests in your tests.

- The count argument was added to assertTemplateUsed(). This allows you to assert that a template was rendered a specific number of times.

- The new assertJSONNotEqual() assertion allows you to test that two JSON fragments are not equal.

- Added options to the test command to preserve the test database (--keepdb), to run the test cases in reverse order (--reverse), and to enable SQL logging for failing tests (--debug-sql).

- Added the resolver_match attribute to test client responses.

- Added several settings that allow customization of test tablespace parameters for Oracle: DATAFILE, DATAFILE_TMP, DATAFILE_MAXSIZE and DATAFILE_TMP_MAXSIZE.

- The override_settings() decorator can now affect the master router in DATABASE_ROUTERS.

- Added test client support for file uploads with file-like objects.

- A shared cache is now used when testing with an SQLite in-memory database when using Python 3.4+ and SQLite 3.7.13+. This allows sharing the database between threads.

Validators

- URLValidator now supports IPv6 addresses, unicode domains, and URLs containing authentication data.

Backwards incompatible changes in 1.8

Warning

In addition to the changes outlined in this section, be sure to review the deprecation plan for any features that have been removed. If you haven’t updated your code within the deprecation timeline for a given feature, its removal may appear as a backwards incompatible change.

Related object operations are run in a transaction

Some operations on related objects such as add() or direct assignment ran multiple data modifying queries without wrapping them in transactions. To reduce the risk of data corruption, all data modifying methods that affect multiple related objects (i.e. add(), remove(), clear(), and direct assignment) now perform their data modifying queries from within a transaction, provided your database supports transactions.

This has one backwards incompatible side effect, signal handlers triggered from these methods are now executed within the method’s transaction and any exception in a signal handler will prevent the whole operation.

Assigning unsaved objects to relations raises an error

Note

To more easily allow in-memory usage of models, this change was reverted in Django 1.8.4 and replaced with a check during model.save(). For example:

>>> book = Book.objects.create(name="Django")
>>> book.author = Author(name="John")
>>> book.save()
Traceback (most recent call last):
...
ValueError: save() prohibited to prevent data loss due to unsaved related object 'author'.

A similar check on assignment to reverse one-to-one relations was removed in Django 1.8.5.

Assigning unsaved objects to a ForeignKey, GenericForeignKey, and OneToOneField now raises a ValueError.

Previously, the assignment of an unsaved object would be silently ignored. For example:

>>> book = Book.objects.create(name="Django")
>>> book.author = Author(name="John")
>>> book.author.save()
>>> book.save()

>>> Book.objects.get(name="Django")
>>> book.author
>>>

Now, an error will be raised to prevent data loss:

>>> book.author = Author(name="john")
Traceback (most recent call last):
...
ValueError: Cannot assign "<Author: John>": "Author" instance isn't saved in the database.

If you require allowing the assignment of unsaved instances (the old behavior) and aren’t concerned about the data loss possibility (e.g. you never save the objects to the database), you can disable this check by using the ForeignKey.allow_unsaved_instance_assignment attribute. (This attribute was removed in 1.8.4 as it’s no longer relevant.)

Management commands that only accept positional arguments

If you have written a custom management command that only accepts positional arguments and you didn’t specify the args command variable, you might get an error like Error: unrecognized arguments: ..., as variable parsing is now based on argparse which doesn’t implicitly accept positional arguments. You can make your command backwards compatible by simply setting the args class variable. However, if you don’t have to keep compatibility with older Django versions, it’s better to implement the new add_arguments() method as described in Writing custom django-admin commands.

Custom test management command arguments through test runner

The method to add custom arguments to the test management command through the test runner has changed. Previously, you could provide an option_list class variable on the test runner to add more arguments (à la optparse). Now to implement the same behavior, you have to create an add_arguments(cls, parser) class method on the test runner and call parser.add_argument to add any custom arguments, as parser is now an argparse.ArgumentParser instance.

Model check ensures auto-generated column names are within limits specified by database

A field name that’s longer than the column name length supported by a database can create problems. For example, with MySQL you’ll get an exception trying to create the column, and with PostgreSQL the column name is truncated by the database (you may see a warning in the PostgreSQL logs).

A model check has been introduced to better alert users to this scenario before the actual creation of database tables.

If you have an existing model where this check seems to be a false positive, for example on PostgreSQL where the name was already being truncated, simply use db_column to specify the name that’s being used.

The check also applies to the columns generated in an implicit ManyToManyField.through model. If you run into an issue there, use through to create an explicit model and then specify db_column on its column(s) as needed.

Query relation lookups now check object types

Querying for model lookups now checks if the object passed is of correct type and raises a ValueError if not. Previously, Django didn’t care if the object was of correct type; it just used the object’s related field attribute (e.g. id) for the lookup. Now, an error is raised to prevent incorrect lookups:

>>> book = Book.objects.create(name="Django")
>>> book = Book.objects.filter(author=book)
Traceback (most recent call last):
...
ValueError: Cannot query "<Book: Django>": Must be "Author" instance.

select_related() now checks given fields

select_related() now validates that the given fields actually exist. Previously, nonexistent fields were silently ignored. Now, an error is raised:

>>> book = Book.objects.select_related('nonexistent_field')
Traceback (most recent call last):
...
FieldError: Invalid field name(s) given in select_related: 'nonexistent_field'

The validation also makes sure that the given field is relational:

>>> book = Book.objects.select_related('name')
Traceback (most recent call last):
...
FieldError: Non-relational field given in select_related: 'name'

Default EmailField.max_length increased to 254

The old default 75 character max_length was not capable of storing all possible RFC3696/5321-compliant email addresses. In order to store all possible valid email addresses, the max_length has been increased to 254 characters. You will need to generate and apply database migrations for your affected models (or add max_length=75 if you wish to keep the length on your current fields). A migration for django.contrib.auth.models.User.email is included.

Support for PostgreSQL versions older than 9.0

The end of upstream support periods was reached in July 2014 for PostgreSQL 8.4. As a consequence, Django 1.8 sets 9.0 as the minimum PostgreSQL version it officially supports.

This also includes dropping support for PostGIS 1.3 and 1.4 as these versions are not supported on versions of PostgreSQL later than 8.4.

Django also now requires the use of Psycopg2 version 2.4.5 or higher (or 2.5+ if you want to use django.contrib.postgres).

Support for MySQL versions older than 5.5

The end of upstream support periods was reached in January 2012 for MySQL 5.0 and December 2013 for MySQL 5.1. As a consequence, Django 1.8 sets 5.5 as the minimum MySQL version it officially supports.

Support for Oracle versions older than 11.1

The end of upstream support periods was reached in July 2010 for Oracle 9.2, January 2012 for Oracle 10.1, and July 2013 for Oracle 10.2. As a consequence, Django 1.8 sets 11.1 as the minimum Oracle version it officially supports.

Specific privileges used instead of roles for tests on Oracle

Earlier versions of Django granted the CONNECT and RESOURCE roles to the test user on Oracle. These roles have been deprecated, so Django 1.8 uses the specific underlying privileges instead. This changes the privileges required of the main user for running tests (unless the project is configured to avoid creating a test user). The exact privileges required now are detailed in Oracle notes.

AbstractUser.last_login allows null values

The AbstractUser.last_login field now allows null values. Previously, it defaulted to the time when the user was created which was misleading if the user never logged in. If you are using the default user (django.contrib.auth.models.User), run the database migration included in contrib.auth.

If you are using a custom user model that inherits from AbstractUser, you’ll need to run makemigrations and generate a migration for your app that contains that model. Also, if wish to set last_login to NULL for users who haven’t logged in, you can run this query:

from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractBaseUser

UserModel = get_user_model()
if issubclass(UserModel, AbstractBaseUser):
UserModel._default_manager.filter(
last_login=models.F('date_joined')
).update(last_login=None)

django.contrib.gis

- Support for GEOS 3.1 and GDAL 1.6 has been dropped.

- Support for SpatiaLite < 2.4 has been dropped.

- GIS-specific lookups have been refactored to use the django.db.models.Lookup API.

- The default str representation of GEOSGeometry objects has been changed from WKT to EWKT format (including the SRID). As this representation is used in the serialization framework, that means that dumpdata output will now contain the SRID value of geometry objects.

Priority of context processors for TemplateResponse brought in line with render

The TemplateResponse constructor is designed to be a drop-in replacement for the render() function. However, it had a slight incompatibility, in that for TemplateResponse, context data from the passed in context dictionary could be shadowed by context data returned from context processors, whereas for render it was the other way around. This was a bug, and the behavior of render is more appropriate, since it allows the globally defined context processors to be overridden locally in the view. If you were relying on the fact context data in a TemplateResponse could be overridden using a context processor, you will need to change your code.

Overriding setUpClass / tearDownClass in test cases

The decorators override_settings() and modify_settings() now act at the class level when used as class decorators. As a consequence, when overriding setUpClass() or tearDownClass(), the super implementation should always be called.

Removal of django.contrib.formtools

The formtools contrib app has been moved to a separate package and the relevant documentation pages have been updated or removed.

The new package is available on GitHub and on PyPI.

Database connection reloading between tests

Django previously closed database connections between each test within a TestCase. This is no longer the case as Django now wraps the whole TestCase within a transaction. If some of your tests relied on the old behavior, you should have them inherit from TransactionTestCase instead.

Cleanup of the django.template namespace

If you’ve been relying on private APIs exposed in the django.template module, you may have to import them from django.template.base instead.

Also private APIs django.template.base.compile_string(), django.template.loader.find_template(), and django.template.loader.get_template_from_string() were removed.

model attribute on private model relations

In earlier versions of Django, on a model with a reverse foreign key relationship (for example), model._meta.get_all_related_objects() returned the relationship as a django.db.models.related.RelatedObject with the model attribute set to the source of the relationship. Now, this method returns the relationship as django.db.models.fields.related.ManyToOneRel (private API RelatedObject has been removed), and the model attribute is set to the target of the relationship instead of the source. The source model is accessible on the related_model attribute instead.

Consider this example from the tutorial in Django 1.8:

>>> p = Poll.objects.get(pk=1)
>>> p._meta.get_all_related_objects()
[<ManyToOneRel: polls.choice>]
>>> p._meta.get_all_related_objects()[0].model
<class 'polls.models.Poll'>
>>> p._meta.get_all_related_objects()[0].related_model
<class 'polls.models.Choice'>

and compare it to the behavior on older versions:

>>> p._meta.get_all_related_objects()
[<RelatedObject: polls:choice related to poll>]
>>> p._meta.get_all_related_objects()[0].model
<class 'polls.models.Choice'>

To access the source model, you can use a pattern like this to write code that will work with both Django 1.8 and older versions:

for relation in opts.get_all_related_objects():
to_model = getattr(relation, 'related_model', relation.model)

Also note that get_all_related_objects() is deprecated in 1.8. See the upgrade guide for the new API.

Database backend API

The following changes to the database backend API are documented to assist those writing third-party backends in updating their code:

- BaseDatabaseXXX classes have been moved to django.db.backends.base. Please import them from the new locations:

from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.backends.base.client import BaseDatabaseClient
from django.db.backends.base.creation import BaseDatabaseCreation
from django.db.backends.base.features import BaseDatabaseFeatures
from django.db.backends.base.introspection import BaseDatabaseIntrospection
from django.db.backends.base.introspection import FieldInfo, TableInfo
from django.db.backends.base.operations import BaseDatabaseOperations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.backends.base.validation import BaseDatabaseValidation

- The data_types, data_types_suffix, and data_type_check_constraints attributes have moved from the DatabaseCreation class to DatabaseWrapper.

- The SQLCompiler.as_sql() method now takes a subquery parameter (#24164).

- The BaseDatabaseOperations.date_interval_sql() method now only takes a timedelta parameter.

django.contrib.admin

- AdminSite no longer takes an app_name argument and its app_name attribute has been removed. The application name is always admin (as opposed to the instance name which you can still customize using AdminSite(name="...").

- The ModelAdmin.get_object() method (private API) now takes a third argument named from_field in order to specify which field should match the provided object_id.

- The ModelAdmin.response_delete() method now takes a second argument named obj_id which is the serialized identifier used to retrieve the object before deletion.

Default autoescaping of functions in django.template.defaultfilters

In order to make built-in template filters that output HTML “safe by default” when calling them in Python code, the following functions in django.template.defaultfilters have been changed to automatically escape their input value:

- join

- linebreaksbr

- linebreaks_filter

- linenumbers

- unordered_list

- urlize

- urlizetrunc

You can revert to the old behavior by specifying autoescape=False if you are passing trusted content. This change doesn’t have any effect when using the corresponding filters in templates.

Miscellaneous

- connections.queries is now a read-only attribute.

- Database connections are considered equal only if they’re the same object. They aren’t hashable any more.

- GZipMiddleware used to disable compression for some content types when the request is from Internet Explorer, in order to work around a bug in IE6 and earlier. This behavior could affect performance on IE7 and later. It was removed.

- URLField.to_python no longer adds a trailing slash to pathless URLs.

- The length template filter now returns 0 for an undefined variable, rather than an empty string.

- ForeignKey.default_error_message['invalid'] has been changed from '%(model)s instance with pk %(pk)r does not exist.' to '%(model)s instance with %(field)s %(value)r does not exist.' If you are using this message in your own code, please update the list of interpolated parameters. Internally, Django will continue to provide the pk parameter in params for backwards compatibility.

- UserCreationForm.error_messages['duplicate_username'] is no longer used. If you wish to customize that error message, override it on the form using the 'unique' key in Meta.error_messages['username'] or, if you have a custom form field for 'username', using the the 'unique' key in its error_messages argument.

- The block usertools in the base.html template of django.contrib.admin now requires the has_permission context variable to be set. If you have any custom admin views that use this template, update them to pass AdminSite.has_permission() as this new variable’s value or simply include AdminSite.each_context(request) in the context.

- Internal changes were made to the ClearableFileInput widget to allow more customization. The undocumented url_markup_template attribute was removed in favor of template_with_initial.

- For consistency with other major vendors, the en_GB locale now has Monday as the first day of the week.

- Seconds have been removed from any locales that had them in TIME_FORMAT, DATETIME_FORMAT, or SHORT_DATETIME_FORMAT.

- The default max size of the Oracle test tablespace has increased from 300M (or 200M, before 1.7.2) to 500M.

- reverse() and reverse_lazy() now return Unicode strings instead of byte strings.

- The CacheClass shim has been removed from all cache backends. These aliases were provided for backwards compatibility with Django 1.3. If you are still using them, please update your project to use the real class name found in the BACKEND key of the CACHES setting.

- By default, call_command() now always skips the check framework (unless you pass it skip_checks=False).

- When iterating over lines, File now uses universal newlines. The following are recognized as ending a line: the Unix end-of-line convention '\n', the Windows convention '\r\n', and the old Macintosh convention '\r'.

- The Memcached cache backends MemcachedCache and PyLibMCCache will delete a key if set() fails. This is necessary to ensure the cache_db session store always fetches the most current session data.

- Private APIs override_template_loaders and override_with_test_loader in django.test.utils were removed. Override TEMPLATES with override_settings instead.

- Warnings from the MySQL database backend are no longer converted to exceptions when DEBUG is True.

- HttpRequest now has a simplified repr (e.g. <WSGIRequest: GET '/somepath/'>). This won’t change the behavior of the SafeExceptionReporterFilter class.

- Class-based views that use ModelFormMixin will raise an ImproperlyConfigured exception when both the fields and form_class attributes are specified. Previously, fields was silently ignored.

- When following redirects, the test client now raises RedirectCycleError if it detects a loop or hits a maximum redirect limit (rather than passing silently).

- Translatable strings set as the default parameter of the field are cast to concrete strings later, so the return type of Field.get_default() is different in some cases. There is no change to default values which are the result of a callable.

- GenericIPAddressField.empty_strings_allowed is now False. Database backends that interpret empty strings as null (only Oracle among the backends that Django includes) will no longer convert null values back to an empty string. This is consistent with other backends.

- When the leave_locale_alone attribute is False, translations are now deactivated instead of forcing the “en-us” locale. In the case your models contained non-English strings and you counted on English translations to be activated in management commands, this will not happen any longer. It might be that new database migrations are generated (once) after migrating to 1.8.

- django.utils.translation.get_language() now returns None instead of LANGUAGE_CODE when translations are temporarily deactivated.

- When a translation doesn’t exist for a specific literal, the fallback is now taken from the LANGUAGE_CODE language (instead of from the untranslated msgid message).

- The name field of django.contrib.contenttypes.models.ContentType has been removed by a migration and replaced by a property. That means it’s not possible to query or filter a ContentType by this field any longer.

Be careful if you upgrade to Django 1.8 and skip Django 1.7. If you run manage.py migrate --fake, this migration will be skipped and you’ll see a RuntimeError: Error creating new content types. exception because the name column won’t be dropped from the database. Use migrate.py migrate --fake-initial to fake only the initial migration instead.

- The new migrate --fake-initial option allows faking initial migrations. In 1.7, initial migrations were always automatically faked if all tables created in an initial migration already existed.

- An app without migrations with a ForeignKey to an app with migrations may now result in a foreign key constraint error when migrating the database or running tests. In Django 1.7, this could fail silently and result in a missing constraint. To resolve the error, add migrations to the app without them.

Features deprecated in 1.8

Selected methods in django.db.models.options.Options

As part of the formalization of the Model._meta API (from the django.db.models.options.Options class), a number of methods have been deprecated and will be removed in Django 1.10:

- get_all_field_names()

- get_all_related_objects()

- get_all_related_objects_with_model()

- get_all_related_many_to_many_objects()

- get_all_related_m2m_objects_with_model()

- get_concrete_fields_with_model()

- get_field_by_name()

- get_fields_with_model()

- get_m2m_with_model()

A migration guide has been provided to assist in converting your code from the old API to the new, official API.

Loading cycle and firstof template tags from future library

Django 1.6 introduced {% load cycle from future %} and {% load firstof from future %} syntax for forward compatibility of the cycle and firstof template tags. This syntax is now deprecated and will be removed in Django 1.10. You can simply remove the {% load ... from future %} tags.

django.conf.urls.patterns()

In the olden days of Django, it was encouraged to reference views as strings in urlpatterns:

urlpatterns = patterns('',
url('^$', 'myapp.views.myview'),
)

and Django would magically import myapp.views.myview internally and turn the string into a real function reference. In order to reduce repetition when referencing many views from the same module, the patterns() function takes a required initial prefix argument which is prepended to all views-as-strings in that set of urlpatterns:

urlpatterns = patterns('myapp.views',
url('^$', 'myview'),
url('^other/$', 'otherview'),
)

In the modern era, we have updated the tutorial to instead recommend importing your views module and referencing your view functions (or classes) directly. This has a number of advantages, all deriving from the fact that we are using normal Python in place of “Django String Magic”: the errors when you mistype a view name are less obscure, IDEs can help with autocompletion of view names, etc.

So these days, the above use of the prefix arg is much more likely to be written (and is better written) as:

from myapp import views

urlpatterns = patterns('',
url('^$', views.myview),
url('^other/$', views.otherview),
)

Thus patterns() serves little purpose and is a burden when teaching new users (answering the newbie’s question “why do I need this empty string as the first argument to patterns()?”). For these reasons, we are deprecating it. Updating your code is as simple as ensuring that urlpatterns is a list of django.conf.urls.url() instances. For example:

from django.conf.urls import url
from myapp import views

urlpatterns = [
url('^$', views.myview),
url('^other/$', views.otherview),
]

Passing a string as view to url()

Related to the previous item, referencing views as strings in the url() function is deprecated. Pass the callable view as described in the previous section instead.

Template-related settings

As a consequence of the multiple template engines refactor, several settings are deprecated in favor of TEMPLATES:

- ALLOWED_INCLUDE_ROOTS

- TEMPLATE_CONTEXT_PROCESSORS

- TEMPLATE_DEBUG

- TEMPLATE_DIRS

- TEMPLATE_LOADERS

- TEMPLATE_STRING_IF_INVALID

django.core.context_processors

Built-in template context processors have been moved to django.template.context_processors.

django.test.SimpleTestCase.urls

The attribute SimpleTestCase.urls for specifying URLconf configuration in tests has been deprecated and will be removed in Django 1.10. Use @override_settings(ROOT_URLCONF=...) instead.

prefix argument to i18n_patterns()

Related to the previous item, the prefix argument to django.conf.urls.i18n.i18n_patterns() has been deprecated. Simply pass a list of django.conf.urls.url() instances instead.

Using an incorrect count of unpacked values in the for template tag

Using an incorrect count of unpacked values in for tag will raise an exception rather than fail silently in Django 1.10.

Passing a dotted path to reverse() and url

Passing a dotted path to reverse() and url

Reversing URLs by Python path is an expensive operation as it causes the path being reversed to be imported. This behavior has also resulted in a security issue. Use named URL patterns for reversing instead.

If you are using django.contrib.sitemaps, add the name argument to the url that references django.contrib.sitemaps.views.sitemap():

from django.contrib.sitemaps.views import sitemap

url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap')

to ensure compatibility when reversing by Python path is removed in Django 1.10.

Similarly for GIS sitemaps, add name='django.contrib.gis.sitemaps.views.kml' or name='django.contrib.gis.sitemaps.views.kmz'.

If you are using a Python path for the LOGIN_URL or LOGIN_REDIRECT_URL setting, use the name of the url() instead.

Aggregate methods and modules

The django.db.models.sql.aggregates and django.contrib.gis.db.models.sql.aggregates modules (both private API), have been deprecated as django.db.models.aggregates and django.contrib.gis.db.models.aggregates are now also responsible for SQL generation. The old modules will be removed in Django 1.10.

If you were using the old modules, see Query Expressions for instructions on rewriting custom aggregates using the new stable API.

The following methods and properties of django.db.models.sql.query.Query have also been deprecated and the backwards compatibility shims will be removed in Django 1.10:

- Query.aggregates, replaced by annotations.

- Query.aggregate_select, replaced by annotation_select.

- Query.add_aggregate(), replaced by add_annotation().

- Query.set_aggregate_mask(), replaced by set_annotation_mask().

- Query.append_aggregate_mask(), replaced by append_annotation_mask().

Extending management command arguments through Command.option_list

Management commands now use argparse instead of optparse to parse command-line arguments passed to commands. This also means that the way to add custom arguments to commands has changed: instead of extending the option_list class list, you should now override the add_arguments() method and add arguments through argparse.add_argument(). See this example for more details.

django.core.management.NoArgsCommand

The class NoArgsCommand is now deprecated and will be removed in Django 1.10. Use BaseCommand instead, which takes no arguments by default.

Listing all migrations in a project

The --list option of the migrate management command is deprecated and will be removed in Django 1.10. Use showmigrations instead.

cache_choices option of ModelChoiceField and ModelMultipleChoiceField

ModelChoiceField and ModelMultipleChoiceField took an undocumented, untested option cache_choices. This cached querysets between multiple renderings of the same Form object. This option is subject to an accelerated deprecation and will be removed in Django 1.9.

django.template.resolve_variable()

The function has been informally marked as “Deprecated” for some time. Replace resolve_variable(path, context) with django.template.Variable(path).resolve(context).

django.contrib.webdesign

It provided the lorem template tag which is now included in the built-in tags. Simply remove 'django.contrib.webdesign' from INSTALLED_APPS and {% load webdesign %} from your templates.

error_message argument to django.forms.RegexField

It provided backwards compatibility for pre-1.0 code, but its functionality is redundant. Use Field.error_messages['invalid'] instead.

Old unordered_list syntax

An older (pre-1.0), more restrictive and verbose input format for the unordered_list template filter has been deprecated:

``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``

Using the new syntax, this becomes:

``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``

django.forms.Field._has_changed()

Rename this method to has_changed() by removing the leading underscore. The old name will still work until Django 1.10.

django.utils.html.remove_tags() and removetags template filter

django.utils.html.remove_tags() as well as the template filter removetags have been deprecated as they cannot guarantee safe output. Their existence is likely to lead to their use in security-sensitive contexts where they are not actually safe.

The unused and undocumented django.utils.html.strip_entities() function has also been deprecated.

is_admin_site argument to django.contrib.auth.views.password_reset()

It’s a legacy option that should no longer be necessary.

SubfieldBase

django.db.models.fields.subclassing.SubfieldBase has been deprecated and will be removed in Django 1.10. Historically, it was used to handle fields where type conversion was needed when loading from the database, but it was not used in .values() calls or in aggregates. It has been replaced with from_db_value(). Note that the new approach does not call the to_python() method on assignment as was the case with SubfieldBase.

django.utils.checksums

The django.utils.checksums module has been deprecated and will be removed in Django 1.10. The functionality it provided (validating checksum using the Luhn algorithm) was undocumented and not used in Django. The module has been moved to the django-localflavor package (version 1.1+).

InlineAdminForm.original_content_type_id

The original_content_type_id attribute on InlineAdminForm has been deprecated and will be removed in Django 1.10. Historically, it was used to construct the “view on site” URL. This URL is now accessible using the absolute_url attribute of the form.

django.views.generic.edit.FormMixin.get_form()’s form_class argument

FormMixin subclasses that override the get_form() method should make sure to provide a default value for the form_class argument since it’s now optional.

Rendering templates loaded by get_template() with a Context

The return type of get_template() has changed in Django 1.8: instead of a django.template.Template, it returns a Template instance whose exact type depends on which backend loaded it.

Both classes provide a render() method, however, the former takes a django.template.Context as an argument while the latter expects a dict. This change is enforced through a deprecation path for Django templates.

Since it’s easier to understand with examples, the upgrade guide shows how to adapt affected code.

All this also applies to select_template().

Template and Context classes in template responses

Some methods of SimpleTemplateResponse and TemplateResponse accepted django.template.Context and django.template.Template objects as arguments. They should now receive dict and backend-dependent template objects respectively.

This also applies to the return types if you have subclassed either template response class.

Check the template response API documentation for details.

current_app argument of template-related APIs

The following functions and classes will no longer accept a current_app parameter to set an URL namespace in Django 1.10:

- django.shortcuts.render()

- django.template.Context()

- django.template.RequestContext()

- django.template.response.TemplateResponse()

Set request.current_app instead, where request is the first argument to these functions or classes. If you’re using a plain Context, use a RequestContext instead.

dictionary and context_instance arguments of rendering functions

The following functions will no longer accept the dictionary and context_instance parameters in Django 1.10:

- django.shortcuts.render()

- django.shortcuts.render_to_response()

- django.template.loader.render_to_string()

Use the context parameter instead. When dictionary is passed as a positional argument, which is the most common idiom, no changes are needed.

If you’re passing a Context in context_instance, pass a dict in the context parameter instead. If you’re passing a RequestContext, pass the request separately in the request parameter.

If you’re using context_instance=RequestContext(request)) with render_to_response(), use django.shortcuts.render(), which always makes RequestContext available, instead. For example:

from django.shortcuts import render_to_response
from django.template import RequestContext
render_to_response('template.html', {...}, context_instance=RequestContext(request))

becomes:

from django.shortcuts import render
render(request, 'template.html', {...})

dirs argument of template-finding functions

The following functions will no longer accept a dirs parameter to override TEMPLATE_DIRS in Django 1.10:

- django.template.loader.get_template()

- django.template.loader.select_template()

- django.shortcuts.render()

- django.shortcuts.render_to_response()

The parameter didn’t work consistently across different template loaders and didn’t work for included templates.

django.template.loader.BaseLoader

django.template.loader.BaseLoader was renamed to django.template.loaders.base.Loader. If you’ve written a custom template loader that inherits BaseLoader, you must inherit Loader instead.

django.test.utils.TestTemplateLoader

Private API django.test.utils.TestTemplateLoader is deprecated in favor of django.template.loaders.locmem.Loader and will be removed in Django 1.9.

Support for the max_length argument on custom Storage classes

Storage subclasses should add max_length=None as a parameter to get_available_name() and/or save() if they override either method. Support for storages that do not accept this argument will be removed in Django 1.10.

qn replaced by compiler

In previous Django versions, various internal ORM methods (mostly as_sql methods) accepted a qn (for “quote name”) argument, which was a reference to a function that quoted identifiers for sending to the database. In Django 1.8, that argument has been renamed to compiler and is now a full SQLCompiler instance. For backwards-compatibility, calling a SQLCompiler instance performs the same name-quoting that the qn function used to. However, this backwards-compatibility shim is immediately deprecated: you should rename your qn arguments to compiler, and call compiler.quote_name_unless_alias(...) where you previously called qn(...).

Default value of RedirectView.permanent

The default value of the RedirectView.permanent attribute will change from True to False in Django 1.9.

Using AuthenticationMiddleware without SessionAuthenticationMiddleware

django.contrib.auth.middleware.SessionAuthenticationMiddleware was added in Django 1.7. In Django 1.7.2, its functionality was moved to auth.get_user() and, for backwards compatibility, enabled only if 'django.contrib.auth.middleware.SessionAuthenticationMiddleware' appears in MIDDLEWARE_CLASSES.

In Django 1.10, session verification will be enabled regardless of whether or not SessionAuthenticationMiddleware is enabled (at which point SessionAuthenticationMiddleware will have no significance). You can add it to your MIDDLEWARE_CLASSES sometime before then to opt-in. Please read the upgrade considerations first.

django.contrib.sitemaps.FlatPageSitemap

django.contrib.sitemaps.FlatPageSitemap has moved to django.contrib.flatpages.sitemaps.FlatPageSitemap. The old import location is deprecated and will be removed in Django 1.9.

Model Field.related

Private attribute django.db.models.Field.related is deprecated in favor of Field.rel. The latter is an instance of django.db.models.fields.related.ForeignObjectRel which replaces django.db.models.related.RelatedObject. The django.db.models.related module has been removed and the Field.related attribute will be removed in Django 1.10.

ssi template tag

The ssi template tag allows files to be included in a template by absolute path. This is of limited use in most deployment situations, and the include tag often makes more sense. This tag is now deprecated and will be removed in Django 1.10.

= as comparison operator in if template tag

Using a single equals sign with the {% if %} template tag for equality testing was undocumented and untested. It’s now deprecated in favor of ==.

%(<foo>)s syntax in ModelFormMixin.success_url

The legacy %(<foo>)s syntax in ModelFormMixin.success_url is deprecated and will be removed in Django 1.10.

GeoQuerySet aggregate methods

The collect(), extent(), extent3d(), make_line(), and unionagg() aggregate methods are deprecated and should be replaced by their function-based aggregate equivalents (Collect, Extent, Extent3D, MakeLine, and Union).

Signature of the allow_migrate router method

The signature of the allow_migrate() method of database routers has changed from allow_migrate(db, model) to allow_migrate(db, app_label, model_name=None, **hints).

When model_name is set, the value that was previously given through the model positional argument may now be found inside the hints dictionary under the key 'model'.

After switching to the new signature the router will also be called by the RunPython and RunSQL operations.

Features removed in 1.8

These features have reached the end of their deprecation cycle and are removed in Django 1.8. See Features deprecated in 1.6 for details, including how to remove usage of these features.

- django.contrib.comments is removed.

- The following transaction management APIs are removed:

- TransactionMiddleware

- the decorators and context managers autocommit, commit_on_success, and commit_manually, defined in django.db.transaction

- the functions commit_unless_managed and rollback_unless_managed, also defined in django.db.transaction

- the TRANSACTIONS_MANAGED setting

- The cycle and firstof template tags auto-escape their arguments.

- The SEND_BROKEN_LINK_EMAILS setting is removed.

- django.middleware.doc.XViewMiddleware is removed.

- The Model._meta.module_name alias is removed.

- The backward compatible shims introduced to rename get_query_set and similar queryset methods are removed. This affects the following classes: BaseModelAdmin, ChangeList, BaseCommentNode, GenericForeignKey, Manager, SingleRelatedObjectDescriptor and ReverseSingleRelatedObjectDescriptor.

- The backward compatible shims introduced to rename the attributes ChangeList.root_query_set and ChangeList.query_set are removed.

- django.views.defaults.shortcut and django.conf.urls.shortcut are removed.

- Support for the Python Imaging Library (PIL) module is removed.

- The following private APIs are removed:

- django.db.backend

- django.db.close_connection()

- django.db.backends.creation.BaseDatabaseCreation.set_autocommit()

- django.db.transaction.is_managed()

- django.db.transaction.managed()

- django.forms.widgets.RadioInput is removed.

- The module django.test.simple and the class django.test.simple.DjangoTestSuiteRunner are removed.

- The module django.test._doctest is removed.

- The CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting is removed. This change affects both django.middleware.cache.CacheMiddleware and django.middleware.cache.UpdateCacheMiddleware despite the lack of a deprecation warning in the latter class.

- Usage of the hard-coded Hold down “Control”, or “Command” on a Mac, to select more than one. string to override or append to user-provided help_text in forms for ManyToMany model fields is not performed by Django anymore either at the model or forms layer.

- The Model._meta.get_(add|change|delete)_permission methods are removed.

- The session key django_language is no longer read for backwards compatibility.

- Geographic Sitemaps are removed (django.contrib.gis.sitemaps.views.index and django.contrib.gis.sitemaps.views.sitemap).

- django.utils.html.fix_ampersands, the fix_ampersands template filter, and django.utils.html.clean_html are removed.

Django 1.7.11 release notes

November 24, 2015

Django 1.7.11 fixes a security issue and a data loss bug in 1.7.10.

Fixed settings leak possibility in date template filter

If an application allows users to specify an unvalidated format for dates and passes this format to the date filter, e.g. {{ last_updated|date:user_date_format }}, then a malicious user could obtain any secret in the application’s settings by specifying a settings key instead of a date format. e.g. "SECRET_KEY" instead of "j/m/Y".

To remedy this, the underlying function used by the date template filter, django.utils.formats.get_format(), now only allows accessing the date/time formatting settings.

Bugfixes

- Fixed a data loss possibility with Prefetch if to_attr is set to a ManyToManyField (#25693).

Django 1.7.10 release notes

August 18, 2015

Django 1.7.10 fixes a security issue in 1.7.9.

Denial-of-service possibility in logout() view by filling session store

Previously, a session could be created when anonymously accessing the django.contrib.auth.views.logout() view (provided it wasn’t decorated with login_required() as done in the admin). This could allow an attacker to easily create many new session records by sending repeated requests, potentially filling up the session store or causing other users’ session records to be evicted.

The SessionMiddleware has been modified to no longer create empty session records, including when SESSION_SAVE_EVERY_REQUEST is active.

Additionally, the contrib.sessions.backends.base.SessionBase.flush() and cache_db.SessionStore.flush() methods have been modified to avoid creating a new empty session. Maintainers of third-party session backends should check if the same vulnerability is present in their backend and correct it if so.

Django 1.7.9 release notes

July 8, 2015

Django 1.7.9 fixes several security issues and bugs in 1.7.8.

Denial-of-service possibility by filling session store

In previous versions of Django, the session backends created a new empty record in the session storage anytime request.session was accessed and there was a session key provided in the request cookies that didn’t already have a session record. This could allow an attacker to easily create many new session records simply by sending repeated requests with unknown session keys, potentially filling up the session store or causing other users’ session records to be evicted.

The built-in session backends now create a session record only if the session is actually modified; empty session records are not created. Thus this potential DoS is now only possible if the site chooses to expose a session-modifying view to anonymous users.

As each built-in session backend was fixed separately (rather than a fix in the core sessions framework), maintainers of third-party session backends should check whether the same vulnerability is present in their backend and correct it if so.

Header injection possibility since validators accept newlines in input

Some of Django’s built-in validators (EmailValidator, most seriously) didn’t prohibit newline characters (due to the usage of $ instead of \Z in the regular expressions). If you use values with newlines in HTTP response or email headers, you can suffer from header injection attacks. Django itself isn’t vulnerable because HttpResponse and the mail sending utilities in django.core.mail prohibit newlines in HTTP and SMTP headers, respectively. While the validators have been fixed in Django, if you’re creating HTTP responses or email messages in other ways, it’s a good idea to ensure that those methods prohibit newlines as well. You might also want to validate that any existing data in your application doesn’t contain unexpected newlines.

validate_ipv4_address(), validate_slug(), and URLValidator are also affected, however, as of Django 1.6 the GenericIPAddresseField, IPAddressField, SlugField, and URLField form fields which use these validators all strip the input, so the possibility of newlines entering your data only exists if you are using these validators outside of the form fields.

The undocumented, internally unused validate_integer() function is now stricter as it validates using a regular expression instead of simply casting the value using int() and checking if an exception was raised.

Bugfixes

- Prevented the loss of null/not null column properties during field renaming of MySQL databases (#24817).

- Fixed SimpleTestCase.assertRaisesMessage() on Python 2.7.10 (#24903).

Django 1.7.8 release notes

May 1, 2015

Django 1.7.8 fixes:

- Database introspection with SQLite 3.8.9 (released April 8, 2015) (#24637).

- A database table name quoting regression in 1.7.2 (#24605).

- The loss of null/not null column properties during field alteration of MySQL databases (#24595).

Django 1.7.7 release notes

March 18, 2015

Django 1.7.7 fixes several bugs and security issues in 1.7.6.

Denial-of-service possibility with strip_tags()

Last year strip_tags() was changed to work iteratively. The problem is that the size of the input it’s processing can increase on each iteration which results in an infinite loop in strip_tags(). This issue only affects versions of Python that haven’t received a bugfix in HTMLParser; namely Python < 2.7.7 and 3.3.5. Some operating system vendors have also backported the fix for the Python bug into their packages of earlier versions.

To remedy this issue, strip_tags() will now return the original input if it detects the length of the string it’s processing increases. Remember that absolutely NO guarantee is provided about the results of strip_tags() being HTML safe. So NEVER mark safe the result of a strip_tags() call without escaping it first, for example with escape().

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) accepted URLs with leading control characters and so considered URLs like \x08javascript:... safe. This issue doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there. Browsers we tested also treat URLs prefixed with control characters such as %08//example.com as relative paths so redirection to an unsafe target isn’t a problem either.

However, if a developer relies on is_safe_url() to provide safe redirect targets and puts such a URL into a link, they could suffer from an XSS attack as some browsers such as Google Chrome ignore control characters at the start of a URL in an anchor href.

Bugfixes

- Fixed renaming of classes in migrations where renaming a subclass would cause incorrect state to be recorded for objects that referenced the superclass (#24354).

- Stopped writing migration files in dry run mode when merging migration conflicts. When makemigrations --merge is called with verbosity=3 the migration file is written to stdout (#24427).

Django 1.7.6 release notes

March 9, 2015

Django 1.7.6 fixes a security issue and several bugs in 1.7.5.

Mitigated an XSS attack via properties in ModelAdmin.readonly_fields

The ModelAdmin.readonly_fields attribute in the Django admin allows displaying model fields and model attributes. While the former were correctly escaped, the latter were not. Thus untrusted content could be injected into the admin, presenting an exploitation vector for XSS attacks.

In this vulnerability, every model attribute used in readonly_fields that is not an actual model field (e.g. a property) will fail to be escaped even if that attribute is not marked as safe. In this release, autoescaping is now correctly applied.

Bugfixes

- Fixed crash when coercing ManyRelatedManager to a string (#24352).

- Fixed a bug that prevented migrations from adding a foreign key constraint when converting an existing field to a foreign key (#24447).

Django 1.7.5 release notes

February 25, 2015

Django 1.7.5 fixes several bugs in 1.7.4.

Bugfixes

- Reverted a fix that prevented a migration crash when unapplying contrib.contenttypes’s or contrib.auth’s first migration (#24075) due to severe impact on the test performance (#24251) and problems in multi-database setups (#24298).

- Fixed a regression that prevented custom fields inheriting from ManyToManyField from being recognized in migrations (#24236).

- Fixed crash in contrib.sites migrations when a default database isn’t used (#24332).

- Added the ability to set the isolation level on PostgreSQL with psycopg2 ≥ 2.4.2 (#24318). It was advertised as a new feature in Django 1.6 but it didn’t work in practice.

- Formats for the Azerbaijani locale (az) have been added.

Django 1.7.4 release notes

January 27, 2015

Django 1.7.4 fixes several bugs in 1.7.3.

Bugfixes

- Fixed a migration crash when unapplying contrib.contenttypes’s or contrib.auth’s first migration (#24075).

- Made the migration’s RenameModel operation rename ManyToManyField tables (#24135).

- Fixed a migration crash on MySQL when migrating from a OneToOneField to a ForeignKey (#24163).

- Prevented the static.serve view from producing ResourceWarnings in certain circumstances (security fix regression, #24193).

- Fixed schema check for ManyToManyField to look for internal type instead of checking class instance, so you can write custom m2m-like fields with the same behavior. (#24104).

Django 1.7.3 release notes

January 13, 2015

Django 1.7.3 fixes several security issues and bugs in 1.7.2.

WSGI header spoofing via underscore/dash conflation

When HTTP headers are placed into the WSGI environ, they are normalized by converting to uppercase, converting all dashes to underscores, and prepending HTTP_. For instance, a header X-Auth-User would become HTTP_X_AUTH_USER in the WSGI environ (and thus also in Django’s request.META dictionary).

Unfortunately, this means that the WSGI environ cannot distinguish between headers containing dashes and headers containing underscores: X-Auth-User and X-Auth_User both become HTTP_X_AUTH_USER. This means that if a header is used in a security-sensitive way (for instance, passing authentication information along from a front-end proxy), even if the proxy carefully strips any incoming value for X-Auth-User, an attacker may be able to provide an X-Auth_User header (with underscore) and bypass this protection.

In order to prevent such attacks, both Nginx and Apache 2.4+ strip all headers containing underscores from incoming requests by default. Django’s built-in development server now does the same. Django’s development server is not recommended for production use, but matching the behavior of common production servers reduces the surface area for behavior changes during deployment.

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) didn’t strip leading whitespace on the tested URL and as such considered URLs like \njavascript:... safe. If a developer relied on is_safe_url() to provide safe redirect targets and put such a URL into a link, they could suffer from a XSS attack. This bug doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there.

Denial-of-service attack against django.views.static.serve

In older versions of Django, the django.views.static.serve() view read the files it served one line at a time. Therefore, a big file with no newlines would result in memory usage equal to the size of that file. An attacker could exploit this and launch a denial-of-service attack by simultaneously requesting many large files. This view now reads the file in chunks to prevent large memory usage.

Note, however, that this view has always carried a warning that it is not hardened for production use and should be used only as a development aid. Now may be a good time to audit your project and serve your files in production using a real front-end web server if you are not doing so.

Database denial-of-service with ModelMultipleChoiceField

Given a form that uses ModelMultipleChoiceField and show_hidden_initial=True (not a documented API), it was possible for a user to cause an unreasonable number of SQL queries by submitting duplicate values for the field’s data. The validation logic in ModelMultipleChoiceField now deduplicates submitted values to address this issue.

Bugfixes

- The default iteration count for the PBKDF2 password hasher has been increased by 25%. This part of the normal major release process was inadvertently omitted in 1.7. This backwards compatible change will not affect users who have subclassed django.contrib.auth.hashers.PBKDF2PasswordHasher to change the default value.

- Fixed a crash in the CSRF middleware when handling non-ASCII referer header (#23815).

- Fixed a crash in the django.contrib.auth.redirect_to_login view when passing a reverse_lazy() result on Python 3 (#24097).

- Added correct formats for Greek (el) (#23967).

- Fixed a migration crash when unapplying a migration where multiple operations interact with the same model (#24110).

Django 1.7.2 release notes

January 2, 2015

Django 1.7.2 fixes several bugs in 1.7.1.

Additionally, Django’s vendored version of six, django.utils.six, has been upgraded to the latest release (1.9.0).

Bugfixes

- Fixed migration’s renaming of auto-created many-to-many tables when changing Meta.db_table (#23630).

- Fixed a migration crash when adding an explicit id field to a model on SQLite (#23702).

- Added a warning for duplicate models when a module is reloaded. Previously a RuntimeError was raised every time two models clashed in the app registry. (#23621).

- Prevented flush from loading initial data for migrated apps (#23699).

- Fixed a makemessages regression in 1.7.1 when STATIC_ROOT has the default None value (#23717).

- Added GeoDjango compatibility with mysqlclient database driver.

- Fixed MySQL 5.6+ crash with GeometryFields in migrations (#23719).

- Fixed a migration crash when removing a field that is referenced in AlterIndexTogether or AlterUniqueTogether (#23614).

- Updated the first day of the week in the Ukrainian locale to Monday.

- Added support for transactional spatial metadata initialization on SpatiaLite 4.1+ (#23152).

- Fixed a migration crash that prevented changing a nullable field with a default to non-nullable with the same default (#23738).

- Fixed a migration crash when adding GeometryFields with blank=True on PostGIS (#23731).

- Allowed usage of DateTimeField() as Transform.output_field (#23420).

- Fixed a migration serializing bug involving float("nan") and float("inf") (#23770).

- Fixed a regression where custom form fields having a queryset attribute but no limit_choices_to could not be used in a ModelForm (#23795).

- Fixed a custom field type validation error with MySQL backend when db_type returned None (#23761).

- Fixed a migration crash when a field is renamed that is part of an index_together (#23859).

- Fixed squashmigrations to respect the --no-optimize parameter (#23799).

- Made RenameModel reversible (#22248)

- Avoided unnecessary rollbacks of migrations from other apps when migrating backwards (#23410).

- Fixed a rare query error when using deeply nested subqueries (#23605).

- Fixed a crash in migrations when deleting a field that is part of a index/unique_together constraint (#23794).

- Fixed django.core.files.File.__repr__() when the file’s name contains Unicode characters (#23888).

- Added missing context to the admin’s delete_selected view that prevented custom site header, etc. from appearing (#23898).

- Fixed a regression with dynamically generated inlines and allowed field references in the admin (#23754).

- Fixed an infinite loop bug for certain cyclic migration dependencies, and made the error message for cyclic dependencies much more helpful.

- Added missing index_together handling for SQLite (#23880).

- Fixed a crash when RunSQL SQL content was collected by the schema editor, typically when using sqlmigrate (#23909).

- Fixed a regression in contrib.admin add/change views which caused some ModelAdmin methods to receive the incorrect obj value (#23934).

- Fixed runserver crash when socket error message contained Unicode characters (#23946).

- Fixed serialization of type when adding a deconstruct() method (#23950).

- Prevented the SessionAuthenticationMiddleware from setting a "Vary: Cookie" header on all responses (#23939).

- Fixed a crash when adding blank=True to TextField() on MySQL (#23920).

- Fixed index creation by the migration infrastructure, particularly when dealing with PostgreSQL specific {text|varchar}_pattern_ops indexes (#23954).

- Fixed bug in makemigrations that created broken migration files when dealing with multiple table inheritance and inheriting from more than one model (#23956).

- Fixed a crash when a MultiValueField has invalid data (#23674).

- Fixed a crash in the admin when using “Save as new” and also deleting a related inline (#23857).

- Always converted related_name to text (unicode), since that is required on Python 3 for interpolation. Removed conversion of related_name to text in migration deconstruction (#23455 and #23982).

- Enlarged the sizes of tablespaces which are created by default for testing on Oracle (the main tablespace was increased from 200M to 300M and the temporary tablespace from 100M to 150M). This was required to accommodate growth in Django’s own test suite (#23969).

- Fixed timesince filter translations in Korean (#23989).

- Fixed the SQLite SchemaEditor to properly add defaults in the absence of a user specified default. For example, a CharField with blank=True didn’t set existing rows to an empty string which resulted in a crash when adding the NOT NULL constraint (#23987).

- makemigrations no longer prompts for a default value when adding TextField() or CharField() without a default (#23405).

- Fixed a migration crash when adding order_with_respect_to to a table with existing rows (#23983).

- Restored the pre_migrate signal if all apps have migrations (#23975).

- Made admin system checks run for custom AdminSites (#23497).

- Ensured the app registry is fully populated when unpickling models. When an external script (like a queueing infrastructure) reloads pickled models, it could crash with an AppRegistryNotReady exception (#24007).

- Added quoting to field indexes in the SQL generated by migrations to prevent a crash when the index name requires it (##24015).

- Added datetime.time support to migrations questioner (#23998).

- Fixed admindocs crash on apps installed as eggs (#23525).

- Changed migrations autodetector to generate an AlterModelOptions operation instead of DeleteModel and CreateModel operations when changing Meta.managed. This prevents data loss when changing managed from False to True and vice versa (#24037).

- Enabled the sqlsequencereset command on apps with migrations (#24054).

- Added tablespace SQL to apps with migrations (#24051).

- Corrected contrib.sites default site creation in a multiple database setup (#24000).

- Restored support for objects that aren’t str or bytes in mark_for_escaping() on Python 3.

- Supported strings escaped by third-party libraries with the __html__ convention in the template engine (#23831).

- Prevented extraneous DROP DEFAULT SQL in migrations (#23581).

- Restored the ability to use more than five levels of subqueries (#23758).

- Fixed crash when ValidationError is initialized with a ValidationError that is initialized with a dictionary (#24008).

- Prevented a crash on apps without migrations when running migrate --list (#23366).

Django 1.7.1 release notes

October 22, 2014

Django 1.7.1 fixes several bugs in 1.7.

Bugfixes

- Allowed related many-to-many fields to be referenced in the admin (#23604).

- Added a more helpful error message if you try to migrate an app without first creating the contenttypes table (#22411).

- Modified migrations dependency algorithm to avoid possible infinite recursion.

- Fixed a UnicodeDecodeError when the flush error message contained Unicode characters (#22882).

- Reinstated missing CHECK SQL clauses which were omitted on some backends when not using migrations (#23416).

- Fixed serialization of type objects in migrations (#22951).

- Allowed inline and hidden references to admin fields (#23431).

- The @deconstructible decorator now fails with a ValueError if the decorated object cannot automatically be imported (#23418).

- Fixed a typo in an inlineformset_factory() error message that caused a crash (#23451).

- Restored the ability to use ABSOLUTE_URL_OVERRIDES with the 'auth.User' model (#11775). As a side effect, the setting now adds a get_absolute_url() method to any model that appears in ABSOLUTE_URL_OVERRIDES but doesn’t define get_absolute_url().

- Avoided masking some ImportError exceptions during application loading (#22920).

- Empty index_together or unique_together model options no longer results in infinite migrations (#23452).

- Fixed crash in contrib.sitemaps if lastmod returned a date rather than a datetime (#23403).

- Allowed migrations to work with app_labels that have the same last part (e.g. django.contrib.auth and vendor.auth) (#23483).

- Restored the ability to deepcopy F objects (#23492).

- Formats for Welsh (cy) and several Chinese locales (zh_CN, zh_Hans, zh_Hant and zh_TW) have been added. Formats for Macedonian have been fixed (trailing dot removed, #23532).

- Added quoting of constraint names in the SQL generated by migrations to prevent crash with uppercase characters in the name (#23065).

- Fixed renaming of models with a self-referential many-to-many field (ManyToManyField('self')) (#23503).

- Added the get_extra(), get_max_num(), and get_min_num() hooks to GenericInlineModelAdmin (#23539).

- Made migrations.RunSQL no longer require percent sign escaping. This is now consistent with cursor.execute() (#23426).

- Made the SERIALIZE entry in the TEST dictionary usable (#23421).

- Fixed bug in migrations that prevented foreign key constraints to unmanaged models with a custom primary key (#23415).

- Added SchemaEditor for MySQL GIS backend so that spatial indexes will be created for apps with migrations (#23538).

- Added SchemaEditor for Oracle GIS backend so that spatial metadata and indexes will be created for apps with migrations (#23537).

- Coerced the related_name model field option to unicode during migration generation to generate migrations that work with both Python 2 and 3 (#23455).

- Fixed MigrationWriter to handle builtin types without imports (#23560).

- Fixed deepcopy on ErrorList (#23594).

- Made the admindocs view to browse view details check if the view specified in the URL exists in the URLconf. Previously it was possible to import arbitrary packages from the Python path. This was not considered a security issue because admindocs is only accessible to staff users (#23601).

- Fixed UnicodeDecodeError crash in AdminEmailHandler with non-ASCII characters in the request (#23593).

- Fixed missing get_or_create and update_or_create on related managers causing IntegrityError (#23611).

- Made urlsafe_base64_decode() return the proper type (byte string) on Python 3 (#23333).

- makemigrations can now serialize timezone-aware values (#23365).

- Added a prompt to the migrations questioner when removing the null constraint from a field to prevent an IntegrityError on existing NULL rows (#23609).

- Fixed generic relations in ModelAdmin.list_filter (#23616).

- Restored RFC compliance for the SMTP backend on Python 3 (#23063).

- Fixed a crash while parsing cookies containing invalid content (#23638).

- The system check framework now raises error models.E020 when the class method Model.check() is unreachable (#23615).

- Made the Oracle test database creation drop the test user in the event of an unclean exit of a previous test run (#23649).

- Fixed makemigrations to detect changes to Meta.db_table (#23629).

- Fixed a regression when feeding the Django test client with an empty data string (#21740).

- Fixed a regression in makemessages where static files were unexpectedly ignored (#23583).

Django 1.7 release notes

September 2, 2014

Welcome to Django 1.7!

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.6 or older versions. We’ve begun the deprecation process for some features, and some features have reached the end of their deprecation process and have been removed.

Python compatibility

Django 1.7 requires Python 2.7, 3.2, 3.3, or 3.4. We highly recommend and only officially support the latest release of each series.

The Django 1.6 series is the last to support Python 2.6. Django 1.7 is the first release to support Python 3.4.

This change should affect only a small number of Django users, as most operating-system vendors today are shipping Python 2.7 or newer as their default version. If you’re still using Python 2.6, however, you’ll need to stick to Django 1.6 until you can upgrade your Python version. Per our support policy, Django 1.6 will continue to receive security support until the release of Django 1.8.

What’s new in Django 1.7

Schema migrations

Django now has built-in support for schema migrations. It allows models to be updated, changed, and deleted by creating migration files that represent the model changes and which can be run on any development, staging or production database.

Migrations are covered in their own documentation, but a few of the key features are:

- syncdb has been deprecated and replaced by migrate. Don’t worry - calls to syncdb will still work as before.

- A new makemigrations command provides an easy way to autodetect changes to your models and make migrations for them.

django.db.models.signals.pre_syncdb and django.db.models.signals.post_syncdb have been deprecated, to be replaced by pre_migrate and post_migrate respectively. These new signals have slightly different arguments. Check the documentation for details.

- The allow_syncdb method on database routers is now called allow_migrate, but still performs the same function. Routers with allow_syncdb methods will still work, but that method name is deprecated and you should change it as soon as possible (nothing more than renaming is required).

- initial_data fixtures are no longer loaded for apps with migrations; if you want to load initial data for an app, we suggest you create a migration for your application and define a RunPython or RunSQL operation in the operations section of the migration.

- Test rollback behavior is different for apps with migrations; in particular, Django will no longer emulate rollbacks on non-transactional databases or inside TransactionTestCase unless specifically requested.

- It is not advised to have apps without migrations depend on (have a ForeignKey or ManyToManyField to) apps with migrations.

- If you are upgrading from South, see our Upgrading from South documentation, and third-party app authors should read the South 1.0 release notes for details on how to support South and Django migrations simultaneously.

App-loading refactor

Historically, Django applications were tightly linked to models. A singleton known as the “app cache” dealt with both installed applications and models. The models module was used as an identifier for applications in many APIs.

As the concept of Django applications matured, this code showed some shortcomings. It has been refactored into an “app registry” where models modules no longer have a central role and where it’s possible to attach configuration data to applications.

Improvements thus far include:

- Applications can run code at startup, before Django does anything else, with the ready() method of their configuration.

- Application labels are assigned correctly to models even when they’re defined outside of models.py. You don’t have to set app_label explicitly any more.

- It is possible to omit models.py entirely if an application doesn’t have any models.

- Applications can be relabeled with the label attribute of application configurations, to work around label conflicts.

- The name of applications can be customized in the admin with the verbose_name of application configurations.

- The admin automatically calls autodiscover() when Django starts. You can consequently remove this line from your URLconf.

- Django imports all application configurations and models as soon as it starts, through a deterministic and straightforward process. This should make it easier to diagnose import issues such as import loops.

New method on Field subclasses

To help power both schema migrations and to enable easier addition of composite keys in future releases of Django, the Field API now has a new required method: deconstruct().

This method takes no arguments, and returns a tuple of four items:

- name: The field’s attribute name on its parent model, or None if it is not part of a model

- path: A dotted, Python path to the class of this field, including the class name.

- args: Positional arguments, as a list

- kwargs: Keyword arguments, as a dict

These four values allow any field to be serialized into a file, as well as allowing the field to be copied safely, both essential parts of these new features.

This change should not affect you unless you write custom Field subclasses; if you do, you may need to reimplement the deconstruct() method if your subclass changes the method signature of __init__ in any way. If your field just inherits from a built-in Django field and doesn’t override __init__, no changes are necessary.

If you do need to override deconstruct(), a good place to start is the built-in Django fields (django/db/models/fields/__init__.py) as several fields, including DecimalField and DateField, override it and show how to call the method on the superclass and simply add or remove extra arguments.

This also means that all arguments to fields must themselves be serializable; to see what we consider serializable, and to find out how to make your own classes serializable, read the migration serialization documentation.

Calling custom QuerySet methods from the Manager

Historically, the recommended way to make reusable model queries was to create methods on a custom Manager class. The problem with this approach was that after the first method call, you’d get back a QuerySet instance and couldn’t call additional custom manager methods.

Though not documented, it was common to work around this issue by creating a custom QuerySet so that custom methods could be chained; but the solution had a number of drawbacks:

- The custom QuerySet and its custom methods were lost after the first call to values() or values_list().

- Writing a custom Manager was still necessary to return the custom QuerySet class and all methods that were desired on the Manager had to be proxied to the QuerySet. The whole process went against the DRY principle.

The QuerySet.as_manager() class method can now directly create Manager with QuerySet methods:

class FoodQuerySet(models.QuerySet):
def pizzas(self):
return self.filter(kind='pizza')

def vegetarian(self):
return self.filter(vegetarian=True)

class Food(models.Model):
kind = models.CharField(max_length=50)
vegetarian = models.BooleanField(default=False)
objects = FoodQuerySet.as_manager()

Food.objects.pizzas().vegetarian()

Using a custom manager when traversing reverse relations

It is now possible to specify a custom manager when traversing a reverse relationship:

class Blog(models.Model):
pass

class Entry(models.Model):
blog = models.ForeignKey(Blog)

objects = models.Manager()  # Default Manager
entries = EntryManager()    # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()

New system check framework

We’ve added a new System check framework for detecting common problems (like invalid models) and providing hints for resolving those problems. The framework is extensible so you can add your own checks for your own apps and libraries.

To perform system checks, you use the check management command. This command replaces the older validate management command.

New Prefetch object for advanced prefetch_related operations.

The new Prefetch object allows customizing prefetch operations.

You can specify the QuerySet used to traverse a given relation or customize the storage location of prefetch results.

This enables things like filtering prefetched relations, calling select_related() from a prefetched relation, or prefetching the same relation multiple times with different querysets. See prefetch_related() for more details.

Admin shortcuts support time zones

The “today” and “now” shortcuts next to date and time input widgets in the admin are now operating in the current time zone. Previously, they used the browser time zone, which could result in saving the wrong value when it didn’t match the current time zone on the server.

In addition, the widgets now display a help message when the browser and server time zone are different, to clarify how the value inserted in the field will be interpreted.

Using database cursors as context managers

Prior to Python 2.7, database cursors could be used as a context manager. The specific backend’s cursor defined the behavior of the context manager. The behavior of magic method lookups was changed with Python 2.7 and cursors were no longer usable as context managers.

Django 1.7 allows a cursor to be used as a context manager. That is, the following can be used:

with connection.cursor() as c:
c.execute(...)

instead of:

c = connection.cursor()
try:
c.execute(...)
finally:
c.close()

Custom lookups

It is now possible to write custom lookups and transforms for the ORM. Custom lookups work just like Django’s built-in lookups (e.g. lte, icontains) while transforms are a new concept.

The django.db.models.Lookup class provides a way to add lookup operators for model fields. As an example it is possible to add day_lte operator for DateFields.

The django.db.models.Transform class allows transformations of database values prior to the final lookup. For example it is possible to write a year transform that extracts year from the field’s value. Transforms allow for chaining. After the year transform has been added to DateField it is possible to filter on the transformed value, for example qs.filter(author__birthdate__year__lte=1981).

For more information about both custom lookups and transforms refer to the custom lookups documentation.

Improvements to Form error handling

Form.add_error()

Previously there were two main patterns for handling errors in forms:

- Raising a ValidationError from within certain functions (e.g. Field.clean(), Form.clean_<fieldname>(), or Form.clean() for non-field errors.)

- Fiddling with Form._errors when targeting a specific field in Form.clean() or adding errors from outside of a “clean” method (e.g. directly from a view).

Using the former pattern was straightforward since the form can guess from the context (i.e. which method raised the exception) where the errors belong and automatically process them. This remains the canonical way of adding errors when possible. However the latter was fiddly and error-prone, since the burden of handling edge cases fell on the user.

The new add_error() method allows adding errors to specific form fields from anywhere without having to worry about the details such as creating instances of django.forms.utils.ErrorList or dealing with Form.cleaned_data. This new API replaces manipulating Form._errors which now becomes a private API.

See Cleaning and validating fields that depend on each other for an example using Form.add_error().

Error metadata

The ValidationError constructor accepts metadata such as error code or params which are then available for interpolating into the error message (see Raising ValidationError for more details); however, before Django 1.7 those metadata were discarded as soon as the errors were added to Form.errors.

Form.errors and django.forms.utils.ErrorList now store the ValidationError instances so these metadata can be retrieved at any time through the new Form.errors.as_data method.

The retrieved ValidationError instances can then be identified thanks to their error code which enables things like rewriting the error’s message or writing custom logic in a view when a given error is present. It can also be used to serialize the errors in a custom format such as XML.

The new Form.errors.as_json() method is a convenience method which returns error messages along with error codes serialized as JSON. as_json() uses as_data() and gives an idea of how the new system could be extended.

Error containers and backward compatibility

Heavy changes to the various error containers were necessary in order to support the features above, specifically Form.errors, django.forms.utils.ErrorList, and the internal storages of ValidationError. These containers which used to store error strings now store ValidationError instances and public APIs have been adapted to make this as transparent as possible, but if you’ve been using private APIs, some of the changes are backwards incompatible; see ValidationError constructor and internal storage for more details.

Minor features

django.contrib.admin

- You can now implement site_header, site_title, and index_title attributes on a custom AdminSite in order to easily change the admin site’s page title and header text. No more needing to override templates!

- Buttons in django.contrib.admin now use the border-radius CSS property for rounded corners rather than GIF background images.

- Some admin templates now have app-<app_name> and model-<model_name> classes in their <body> tag to allow customizing the CSS per app or per model.

- The admin changelist cells now have a field-<field_name> class in the HTML to enable style customizations.

- The admin’s search fields can now be customized per-request thanks to the new django.contrib.admin.ModelAdmin.get_search_fields() method.

- The ModelAdmin.get_fields() method may be overridden to customize the value of ModelAdmin.fields.

- In addition to the existing admin.site.register syntax, you can use the new register() decorator to register a ModelAdmin.

- You may specify ModelAdmin.list_display_links = None to disable links on the change list page grid.

- You may now specify ModelAdmin.view_on_site to control whether or not to display the “View on site” link.

- You can specify a descending ordering for a ModelAdmin.list_display value by prefixing the admin_order_field value with a hyphen.

- The ModelAdmin.get_changeform_initial_data() method may be overridden to define custom behavior for setting initial change form data.

django.contrib.auth

- Any **kwargs passed to email_user() are passed to the underlying send_mail() call.

- The permission_required() decorator can take a list of permissions as well as a single permission.

- You can override the new AuthenticationForm.confirm_login_allowed() method to more easily customize the login policy.

- django.contrib.auth.views.password_reset() takes an optional html_email_template_name parameter used to send a multipart HTML email for password resets.

- The AbstractBaseUser.get_session_auth_hash() method was added and if your AUTH_USER_MODEL inherits from AbstractBaseUser, changing a user’s password now invalidates old sessions if the SessionAuthenticationMiddleware is enabled. See Session invalidation on password change for more details including upgrade considerations when enabling this new middleware.

django.contrib.formtools

- Calls to WizardView.done() now include a form_dict to allow easier access to forms by their step name.

django.contrib.gis

- The default OpenLayers library version included in widgets has been updated from 2.11 to 2.13.

- Prepared geometries now also support the crosses, disjoint, overlaps, touches and within predicates, if GEOS 3.3 or later is installed.

django.contrib.messages

- The backends for django.contrib.messages that use cookies, will now follow the SESSION_COOKIE_SECURE and SESSION_COOKIE_HTTPONLY settings.

- The messages context processor now adds a dictionary of default levels under the name DEFAULT_MESSAGE_LEVELS.

- Message objects now have a level_tag attribute that contains the string representation of the message level.

django.contrib.redirects

- RedirectFallbackMiddleware has two new attributes (response_gone_class and response_redirect_class) that specify the types of HttpResponse instances the middleware returns.

django.contrib.sessions

- The "django.contrib.sessions.backends.cached_db" session backend now respects SESSION_CACHE_ALIAS. In previous versions, it always used the default cache.

django.contrib.sitemaps

- The sitemap framework now makes use of lastmod to set a Last-Modified header in the response. This makes it possible for the ConditionalGetMiddleware to handle conditional GET requests for sitemaps which set lastmod.

django.contrib.sites

- The new django.contrib.sites.middleware.CurrentSiteMiddleware allows setting the current site on each request.

django.contrib.staticfiles

- The static files storage classes may be subclassed to override the permissions that collected static files and directories receive by setting the file_permissions_mode and directory_permissions_mode parameters. See collectstatic for example usage.

- The CachedStaticFilesStorage backend gets a sibling class called ManifestStaticFilesStorage that doesn’t use the cache system at all but instead a JSON file called staticfiles.json for storing the mapping between the original file name (e.g. css/styles.css) and the hashed file name (e.g. css/styles.55e7cbb9ba48.css). The staticfiles.json file is created when running the collectstatic management command and should be a less expensive alternative for remote storages such as Amazon S3.

See the ManifestStaticFilesStorage docs for more information.

- findstatic now accepts verbosity flag level 2, meaning it will show the relative paths of the directories it searched. See findstatic for example output.

django.contrib.syndication

- The Atom1Feed syndication feed’s updated element now utilizes updateddate instead of pubdate, allowing the published element to be included in the feed (which relies on pubdate).

Cache

- Access to caches configured in CACHES is now available via django.core.cache.caches. This dict-like object provides a different instance per thread. It supersedes django.core.cache.get_cache() which is now deprecated.

- If you instantiate cache backends directly, be aware that they aren’t thread-safe any more, as django.core.cache.caches now yields different instances per thread.

- Defining the TIMEOUT argument of the CACHES setting as None will set the cache keys as “non-expiring” by default. Previously, it was only possible to pass timeout=None to the cache backend’s set() method.

Cross Site Request Forgery

- The CSRF_COOKIE_AGE setting facilitates the use of session-based CSRF cookies.

Email

- send_mail() now accepts an html_message parameter for sending a multipart text/plain and text/html email.

- The SMTP EmailBackend now accepts a timeout parameter.

File Storage

- File locking on Windows previously depended on the PyWin32 package; if it wasn’t installed, file locking failed silently. That dependency has been removed, and file locking is now implemented natively on both Windows and Unix.

File Uploads

- The new UploadedFile.content_type_extra attribute contains extra parameters passed to the content-type header on a file upload.

- The new FILE_UPLOAD_DIRECTORY_PERMISSIONS setting controls the file system permissions of directories created during file upload, like FILE_UPLOAD_PERMISSIONS does for the files themselves.

- The FileField.upload_to attribute is now optional. If it is omitted or given None or an empty string, a subdirectory won’t be used for storing the uploaded files.

- Uploaded files are now explicitly closed before the response is delivered to the client. Partially uploaded files are also closed as long as they are named file in the upload handler.

- Storage.get_available_name() now appends an underscore plus a random 7 character alphanumeric string (e.g. "_x3a1gho"), rather than iterating through an underscore followed by a number (e.g. "_1", "_2", etc.) to prevent a denial-of-service attack. This change was also made in the 1.6.6, 1.5.9, and 1.4.14 security releases.

Forms

- The <label> and <input> tags rendered by RadioSelect and CheckboxSelectMultiple when looping over the radio buttons or checkboxes now include for and id attributes, respectively. Each radio button or checkbox includes an id_for_label attribute to output the element’s ID.

- The <textarea> tags rendered by Textarea now include a maxlength attribute if the TextField model field has a max_length.

- Field.choices now allows you to customize the “empty choice” label by including a tuple with an empty string or None for the key and the custom label as the value. The default blank option "----------" will be omitted in this case.

- MultiValueField allows optional subfields by setting the require_all_fields argument to False. The required attribute for each individual field will be respected, and a new incomplete validation error will be raised when any required fields are empty.

- The clean() method on a form no longer needs to return self.cleaned_data. If it does return a changed dictionary then that will still be used.

- After a temporary regression in Django 1.6, it’s now possible again to make TypedChoiceField coerce method return an arbitrary value.

- SelectDateWidget.months can be used to customize the wording of the months displayed in the select widget.

- The min_num and validate_min parameters were added to formset_factory() to allow validating a minimum number of submitted forms.

- The metaclasses used by Form and ModelForm have been reworked to support more inheritance scenarios. The previous limitation that prevented inheriting from both Form and ModelForm simultaneously have been removed as long as ModelForm appears first in the MRO.

- It’s now possible to remove a field from a Form when subclassing by setting the name to None.

- It’s now possible to customize the error messages for ModelForm’s unique, unique_for_date, and unique_together constraints. In order to support unique_together or any other NON_FIELD_ERROR, ModelForm now looks for the NON_FIELD_ERROR key in the error_messages dictionary of the ModelForm’s inner Meta class. See considerations regarding model’s error_messages for more details.

Internationalization

- The django.middleware.locale.LocaleMiddleware.response_redirect_class attribute allows you to customize the redirects issued by the middleware.

- The LocaleMiddleware now stores the user’s selected language with the session key _language. This should only be accessed using the LANGUAGE_SESSION_KEY constant. Previously it was stored with the key django_language and the LANGUAGE_SESSION_KEY constant did not exist, but keys reserved for Django should start with an underscore. For backwards compatibility django_language is still read from in 1.7. Sessions will be migrated to the new key as they are written.

- The blocktrans tag now supports a trimmed option. This option will remove newline characters from the beginning and the end of the content of the {% blocktrans %} tag, replace any whitespace at the beginning and end of a line and merge all lines into one using a space character to separate them. This is quite useful for indenting the content of a {% blocktrans %} tag without having the indentation characters end up in the corresponding entry in the PO file, which makes the translation process easier.

- When you run makemessages from the root directory of your project, any extracted strings will now be automatically distributed to the proper app or project message file. See Localization: how to create language files for details.

- The makemessages command now always adds the --previous command line flag to the msgmerge command, keeping previously translated strings in po files for fuzzy strings.

- The following settings to adjust the language cookie options were introduced: LANGUAGE_COOKIE_AGE, LANGUAGE_COOKIE_DOMAIN and LANGUAGE_COOKIE_PATH.

- Added Format localization for Esperanto.

Management Commands

- The new --no-color option for django-admin disables the colorization of management command output.

- The new dumpdata --natural-foreign and dumpdata --natural-primary options, and the new use_natural_foreign_keys and use_natural_primary_keys arguments for serializers.serialize(), allow the use of natural primary keys when serializing.

- It is no longer necessary to provide the cache table name or the --database option for the createcachetable command. Django takes this information from your settings file. If you have configured multiple caches or multiple databases, all cache tables are created.

- The runserver command received several improvements:

- On Linux systems, if pyinotify is installed, the development server will reload immediately when a file is changed. Previously, it polled the filesystem for changes every second. That caused a small delay before reloads and reduced battery life on laptops.

- In addition, the development server automatically reloads when a translation file is updated, i.e. after running compilemessages.

- All HTTP requests are logged to the console, including requests for static files or favicon.ico that used to be filtered out.

- Management commands can now produce syntax colored output under Windows if the ANSICON third-party tool is installed and active.

- collectstatic command with symlink option is now supported on Windows NT 6 (Windows Vista and newer).

- Initial SQL data now works better if the sqlparse Python library is installed.

Note that it’s deprecated in favor of the RunSQL operation of migrations, which benefits from the improved behavior.

Models

- The QuerySet.update_or_create() method was added.

- The new default_permissions model Meta option allows you to customize (or disable) creation of the default add, change, and delete permissions.

- Explicit OneToOneField for Multi-table inheritance are now discovered in abstract classes.

- It is now possible to avoid creating a backward relation for OneToOneField by setting its related_name to '+' or ending it with '+'.

- F expressions support the power operator (**).

- The remove() and clear() methods of the related managers created by ForeignKey and GenericForeignKey now accept the bulk keyword argument to control whether or not to perform operations in bulk (i.e. using QuerySet.update()). Defaults to True.

- It is now possible to use None as a query value for the iexact lookup.

- It is now possible to pass a callable as value for the attribute limit_choices_to when defining a ForeignKey or ManyToManyField.

- Calling only() and defer() on the result of QuerySet.values() now raises an error (before that, it would either result in a database error or incorrect data).

- You can use a single list for index_together (rather than a list of lists) when specifying a single set of fields.

- Custom intermediate models having more than one foreign key to any of the models participating in a many-to-many relationship are now permitted, provided you explicitly specify which foreign keys should be used by setting the new ManyToManyField.through_fields argument.

- Assigning a model instance to a non-relation field will now throw an error. Previously this used to work if the field accepted integers as input as it took the primary key.

- Integer fields are now validated against database backend specific min and max values based on their internal_type. Previously model field validation didn’t prevent values out of their associated column data type range from being saved resulting in an integrity error.

- It is now possible to explicitly order_by() a relation _id field by using its attribute name.

Signals

- The enter argument was added to the setting_changed signal.

- The model signals can be now be connected to using a str of the 'app_label.ModelName' form – just like related fields – to lazily reference their senders.

Templates

- The Context.push() method now returns a context manager which automatically calls pop() upon exiting the with statement. Additionally, push() now accepts parameters that are passed to the dict constructor used to build the new context level.

- The new Context.flatten() method returns a Context‘s stack as one flat dictionary.

- Context objects can now be compared for equality (internally, this uses Context.flatten() so the internal structure of each Context‘s stack doesn’t matter as long as their flattened version is identical).

- The widthratio template tag now accepts an "as" parameter to capture the result in a variable.

- The include template tag will now also accept anything with a render() method (such as a Template) as an argument. String arguments will be looked up using get_template() as always.

- It is now possible to include templates recursively.

- Template objects now have an origin attribute set when TEMPLATE_DEBUG is True. This allows template origins to be inspected and logged outside of the django.template infrastructure.

- TypeError exceptions are no longer silenced when raised during the rendering of a template.

- The following functions now accept a dirs parameter which is a list or tuple to override TEMPLATE_DIRS:

- django.template.loader.get_template()

- django.template.loader.select_template()

- django.shortcuts.render()

- django.shortcuts.render_to_response()

- The time filter now accepts timezone-related format specifiers 'e', 'O' , 'T' and 'Z' and is able to digest time-zone-aware datetime instances performing the expected rendering.

- The cache tag will now try to use the cache called “template_fragments” if it exists and fall back to using the default cache otherwise. It also now accepts an optional using keyword argument to control which cache it uses.

- The new truncatechars_html filter truncates a string to be no longer than the specified number of characters, taking HTML into account.

Requests and Responses

- The new HttpRequest.scheme attribute specifies the scheme of the request (http or https normally).

- The shortcut redirect() now supports relative URLs.

- The new JsonResponse subclass of HttpResponse helps easily create JSON-encoded responses.

Tests

- DiscoverRunner has two new attributes, test_suite and test_runner, which facilitate overriding the way tests are collected and run.

- The fetch_redirect_response argument was added to assertRedirects(). Since the test client can’t fetch externals URLs, this allows you to use assertRedirects with redirects that aren’t part of your Django app.

- Correct handling of scheme when making comparisons in assertRedirects().

- The secure argument was added to all the request methods of Client. If True, the request will be made through HTTPS.

- assertNumQueries() now prints out the list of executed queries if the assertion fails.

- The WSGIRequest instance generated by the test handler is now attached to the django.test.Response.wsgi_request attribute.

- The database settings for testing have been collected into a dictionary named TEST.

Utilities

- Improved strip_tags() accuracy (but it still cannot guarantee an HTML-safe result, as stated in the documentation).

Validators

- RegexValidator now accepts the optional flags and Boolean inverse_match arguments. The inverse_match attribute determines if the ValidationError should be raised when the regular expression pattern matches (True) or does not match (False, by default) the provided value. The flags attribute sets the flags used when compiling a regular expression string.

- URLValidator now accepts an optional schemes argument which allows customization of the accepted URI schemes (instead of the defaults http(s) and ftp(s)).

- validate_email() now accepts addresses with IPv6 literals, like example@[2001:db8::1], as specified in RFC 5321.

Backwards incompatible changes in 1.7

Warning

In addition to the changes outlined in this section, be sure to review the deprecation plan for any features that have been removed. If you haven’t updated your code within the deprecation timeline for a given feature, its removal may appear as a backwards incompatible change.

allow_syncdb / allow_migrate

While Django will still look at allow_syncdb methods even though they should be renamed to allow_migrate, there is a subtle difference in which models get passed to these methods.

For apps with migrations, allow_migrate will now get passed historical models, which are special versioned models without custom attributes, methods or managers. Make sure your allow_migrate methods are only referring to fields or other items in model._meta.

initial_data

Apps with migrations will not load initial_data fixtures when they have finished migrating. Apps without migrations will continue to load these fixtures during the phase of migrate which emulates the old syncdb behavior, but any new apps will not have this support.

Instead, you are encouraged to load initial data in migrations if you need it (using the RunPython operation and your model classes); this has the added advantage that your initial data will not need updating every time you change the schema.

Additionally, like the rest of Django’s old syncdb code, initial_data has been started down the deprecation path and will be removed in Django 1.9.

deconstruct() and serializability

Django now requires all Field classes and all of their constructor arguments to be serializable. If you modify the constructor signature in your custom Field in any way, you’ll need to implement a deconstruct() method; we’ve expanded the custom field documentation with instructions on implementing this method.

The requirement for all field arguments to be serializable means that any custom class instances being passed into Field constructors - things like custom Storage subclasses, for instance - need to have a deconstruct method defined on them as well, though Django provides a handy class decorator that will work for most applications.

App-loading changes

Start-up sequence

Django 1.7 loads application configurations and models as soon as it starts. While this behavior is more straightforward and is believed to be more robust, regressions cannot be ruled out. See Troubleshooting for solutions to some problems you may encounter.

Standalone scripts

If you’re using Django in a plain Python script — rather than a management command — and you rely on the DJANGO_SETTINGS_MODULE environment variable, you must now explicitly initialize Django at the beginning of your script with:

>>> import django
>>> django.setup()

Otherwise, you will hit an AppRegistryNotReady exception.

WSGI scripts

Until Django 1.3, the recommended way to create a WSGI application was:

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

In Django 1.4, support for WSGI was improved and the API changed to:

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

If you’re still using the former style in your WSGI script, you need to upgrade to the latter, or you will hit an AppRegistryNotReady exception.

App registry consistency

It is no longer possible to have multiple installed applications with the same label. In previous versions of Django, this didn’t always work correctly, but didn’t crash outright either.

If you have two apps with the same label, you should create an AppConfig for one of them and override its label there. You should then adjust your code wherever it references this application or its models with the old label.

It isn’t possible to import the same model twice through different paths any more. As of Django 1.6, this may happen only if you’re manually putting a directory and a subdirectory on PYTHONPATH. Refer to the section on the new project layout in the 1.4 release notes for migration instructions.

You should make sure that:

- All models are defined in applications that are listed in INSTALLED_APPS or have an explicit app_label.

- Models aren’t imported as a side-effect of loading their application. Specifically, you shouldn’t import models in the root module of an application nor in the module that define its configuration class.

Django will enforce these requirements as of version 1.9, after a deprecation period.

Subclassing AppCommand

Subclasses of AppCommand must now implement a handle_app_config() method instead of handle_app(). This method receives an AppConfig instance instead of a models module.

Introspecting applications

Since INSTALLED_APPS now supports application configuration classes in addition to application modules, you should review code that accesses this setting directly and use the app registry (django.apps.apps) instead.

The app registry has preserved some features of the old app cache. Even though the app cache was a private API, obsolete methods and arguments will be removed through a standard deprecation path, with the exception of the following changes that take effect immediately:

- get_model raises LookupError instead of returning None when no model is found.

- The only_installed argument of get_model and get_models no longer exists, nor does the seed_cache argument of get_model.

Management commands and order of INSTALLED_APPS

When several applications provide management commands with the same name, Django loads the command from the application that comes first in INSTALLED_APPS. Previous versions loaded the command from the application that came last.

This brings discovery of management commands in line with other parts of Django that rely on the order of INSTALLED_APPS, such as static files, templates, and translations.

ValidationError constructor and internal storage

The behavior of the ValidationError constructor has changed when it receives a container of errors as an argument (e.g. a list or an ErrorList):

- It converts any strings it finds to instances of ValidationError before adding them to its internal storage.

- It doesn’t store the given container but rather copies its content to its own internal storage; previously the container itself was added to the ValidationError instance and used as internal storage.

This means that if you access the ValidationError internal storages, such as error_list; error_dict; or the return value of update_error_dict() you may find instances of ValidationError where you would have previously found strings.

Also if you directly assigned the return value of update_error_dict() to Form._errors you may inadvertently add list instances where ErrorList instances are expected. This is a problem because unlike a simple list, an ErrorList knows how to handle instances of ValidationError.

Most use-cases that warranted using these private APIs are now covered by the newly introduced Form.add_error() method:

# Old pattern:
try:
# ...
except ValidationError as e:
self._errors = e.update_error_dict(self._errors)

# New pattern:
try:
# ...
except ValidationError as e:
self.add_error(None, e)

If you need both Django <= 1.6 and 1.7 compatibility you can’t use Form.add_error() since it wasn’t available before Django 1.7, but you can use the following workaround to convert any list into ErrorList:

try:
# ...
except ValidationError as e:
self._errors = e.update_error_dict(self._errors)

# Additional code to ensure ``ErrorDict`` is exclusively
# composed of ``ErrorList`` instances.
for field, error_list in self._errors.items():
if not isinstance(error_list, self.error_class):
self._errors[field] = self.error_class(error_list)

Behavior of LocMemCache regarding pickle errors

An inconsistency existed in previous versions of Django regarding how pickle errors are handled by different cache backends. django.core.cache.backends.locmem.LocMemCache used to fail silently when such an error occurs, which is inconsistent with other backends and leads to cache-specific errors. This has been fixed in Django 1.7, see #21200 for more details.

Cache keys are now generated from the request’s absolute URL

Previous versions of Django generated cache keys using a request’s path and query string but not the scheme or host. If a Django application was serving multiple subdomains or domains, cache keys could collide. In Django 1.7, cache keys vary by the absolute URL of the request including scheme, host, path, and query string. For example, the URL portion of a cache key is now generated from https://www.example.com/path/to/?key=val rather than /path/to/?key=val. The cache keys generated by Django 1.7 will be different from the keys generated by older versions of Django. After upgrading to Django 1.7, the first request to any previously cached URL will be a cache miss.

Passing None to Manager.db_manager()

In previous versions of Django, it was possible to use db_manager(using=None) on a model manager instance to obtain a manager instance using default routing behavior, overriding any manually specified database routing. In Django 1.7, a value of None passed to db_manager will produce a router that retains any manually assigned database routing – the manager will not be reset. This was necessary to resolve an inconsistency in the way routing information cascaded over joins. See #13724 for more details.

pytz may be required

If your project handles datetimes before 1970 or after 2037 and Django raises a ValueError when encountering them, you will have to install pytz. You may be affected by this problem if you use Django’s time zone-related date formats or django.contrib.syndication.

remove() and clear() methods of related managers

The remove() and clear() methods of the related managers created by ForeignKey, GenericForeignKey, and ManyToManyField suffered from a number of issues. Some operations ran multiple data modifying queries without wrapping them in a transaction, and some operations didn’t respect default filtering when it was present (i.e. when the default manager on the related model implemented a custom get_queryset()).

Fixing the issues introduced some backward incompatible changes:

- The default implementation of remove() for ForeignKey related managers changed from a series of Model.save() calls to a single QuerySet.update() call. The change means that pre_save and post_save signals aren’t sent anymore. You can use the bulk=False keyword argument to revert to the previous behavior.

- The remove() and clear() methods for GenericForeignKey related managers now perform bulk delete. The Model.delete() method isn’t called on each instance anymore. You can use the bulk=False keyword argument to revert to the previous behavior.

- The remove() and clear() methods for ManyToManyField related managers perform nested queries when filtering is involved, which may or may not be an issue depending on your database and your data itself. See this note for more details.

Admin login redirection strategy

Historically, the Django admin site passed the request from an unauthorized or unauthenticated user directly to the login view, without HTTP redirection. In Django 1.7, this behavior changed to conform to a more traditional workflow where any unauthorized request to an admin page will be redirected (by HTTP status code 302) to the login page, with the next parameter set to the referring path. The user will be redirected there after a successful login.

Note also that the admin login form has been updated to not contain the this_is_the_login_form field (now unused) and the ValidationError code has been set to the more regular invalid_login key.

select_for_update() requires a transaction

Historically, queries that use select_for_update() could be executed in autocommit mode, outside of a transaction. Before Django 1.6, Django’s automatic transactions mode allowed this to be used to lock records until the next write operation. Django 1.6 introduced database-level autocommit; since then, execution in such a context voids the effect of select_for_update(). It is, therefore, assumed now to be an error and raises an exception.

This change was made because such errors can be caused by including an app which expects global transactions (e.g. ATOMIC_REQUESTS set to True), or Django’s old autocommit behavior, in a project which runs without them; and further, such errors may manifest as data-corruption bugs. It was also made in Django 1.6.3.

This change may cause test failures if you use select_for_update() in a test class which is a subclass of TransactionTestCase rather than TestCase.

Contrib middleware removed from default MIDDLEWARE_CLASSES

The app-loading refactor deprecated using models from apps which are not part of the INSTALLED_APPS setting. This exposed an incompatibility between the default INSTALLED_APPS and MIDDLEWARE_CLASSES in the global defaults (django.conf.global_settings). To bring these settings in sync and prevent deprecation warnings when doing things like testing reusable apps with minimal settings, SessionMiddleware, AuthenticationMiddleware, and MessageMiddleware were removed from the defaults. These classes will still be included in the default settings generated by startproject. Most projects will not be affected by this change but if you were not previously declaring the MIDDLEWARE_CLASSES in your project settings and relying on the global default you should ensure that the new defaults are in line with your project’s needs. You should also check for any code that accesses django.conf.global_settings.MIDDLEWARE_CLASSES directly.

Miscellaneous

- The django.core.files.uploadhandler.FileUploadHandler.new_file() method is now passed an additional content_type_extra parameter. If you have a custom FileUploadHandler that implements new_file(), be sure it accepts this new parameter.

- ModelFormSets no longer delete instances when save(commit=False) is called. See can_delete for instructions on how to manually delete objects from deleted forms.

- Loading empty fixtures emits a RuntimeWarning rather than raising CommandError.

- django.contrib.staticfiles.views.serve() will now raise an Http404 exception instead of ImproperlyConfigured when DEBUG is False. This change removes the need to conditionally add the view to your root URLconf, which in turn makes it safe to reverse by name. It also removes the ability for visitors to generate spurious HTTP 500 errors by requesting static files that don’t exist or haven’t been collected yet.

- The django.db.models.Model.__eq__() method is now defined in a way where instances of a proxy model and its base model are considered equal when primary keys match. Previously only instances of exact same class were considered equal on primary key match.

- The django.db.models.Model.__eq__() method has changed such that two Model instances without primary key values won’t be considered equal (unless they are the same instance).

- The django.db.models.Model.__hash__() method will now raise TypeError when called on an instance without a primary key value. This is done to avoid mutable __hash__ values in containers.

- AutoField columns in SQLite databases will now be created using the AUTOINCREMENT option, which guarantees monotonic increments. This will cause primary key numbering behavior to change on SQLite, becoming consistent with most other SQL databases. This will only apply to newly created tables. If you have a database created with an older version of Django, you will need to migrate it to take advantage of this feature. For example, you could do the following:

1. Use dumpdata to save your data.

2. Rename the existing database file (keep it as a backup).

3. Run migrate to create the updated schema.

4. Use loaddata to import the fixtures you exported in (1).

- django.contrib.auth.models.AbstractUser no longer defines a get_absolute_url() method. The old definition returned "/users/%s/" % urlquote(self.username) which was arbitrary since applications may or may not define such a url in urlpatterns. Define a get_absolute_url() method on your own custom user object or use ABSOLUTE_URL_OVERRIDES if you want a URL for your user.

- The static asset-serving functionality of the django.test.LiveServerTestCase class has been simplified: Now it’s only able to serve content already present in STATIC_ROOT when tests are run. The ability to transparently serve all the static assets (similarly to what one gets with DEBUG = True at development-time) has been moved to a new class that lives in the staticfiles application (the one actually in charge of such feature): django.contrib.staticfiles.testing.StaticLiveServerTestCase. In other words, LiveServerTestCase itself is less powerful but at the same time has less magic.

Rationale behind this is removal of dependency of non-contrib code on contrib applications.

- The old cache URI syntax (e.g. "locmem://") is no longer supported. It still worked, even though it was not documented or officially supported. If you’re still using it, please update to the current CACHES syntax.

- The default ordering of Form fields in case of inheritance has changed to follow normal Python MRO. Fields are now discovered by iterating through the MRO in reverse with the topmost class coming last. This only affects you if you relied on the default field ordering while having fields defined on both the current class and on a parent Form.

- The required argument of SelectDateWidget has been removed. This widget now respects the form field’s is_required attribute like other widgets.

- Widget.is_hidden is now a read-only property, getting its value by introspecting the presence of input_type == 'hidden'.

- select_related() now chains in the same way as other similar calls like prefetch_related. That is, select_related('foo', 'bar') is equivalent to select_related('foo').select_related('bar'). Previously the latter would have been equivalent to select_related('bar').

- GeoDjango dropped support for GEOS < 3.1.

- The init_connection_state method of database backends now executes in autocommit mode (unless you set AUTOCOMMIT to False). If you maintain a custom database backend, you should check that method.

- The django.db.backends.BaseDatabaseFeatures.allows_primary_key_0 attribute has been renamed to allows_auto_pk_0 to better describe it. It’s True for all database backends included with Django except MySQL which does allow primary keys with value 0. It only forbids autoincrement primary keys with value 0.

- Shadowing model fields defined in a parent model has been forbidden as this creates ambiguity in the expected model behavior. In addition, clashing fields in the model inheritance hierarchy result in a system check error. For example, if you use multi-inheritance, you need to define custom primary key fields on parent models, otherwise the default id fields will clash. See Multiple inheritance for details.

- django.utils.translation.parse_accept_lang_header() now returns lowercase locales, instead of the case as it was provided. As locales should be treated case-insensitive this allows us to speed up locale detection.

- django.utils.translation.get_language_from_path() and django.utils.translation.trans_real.get_supported_language_variant() now no longer have a supported argument.

- The shortcut view in django.contrib.contenttypes.views now supports protocol-relative URLs (e.g. //example.com).

- GenericRelation now supports an optional related_query_name argument. Setting related_query_name adds a relation from the related object back to the content type for filtering, ordering and other query operations.

- When running tests on PostgreSQL, the USER will need read access to the built-in postgres database. This is in lieu of the previous behavior of connecting to the actual non-test database.

- As part of the System check framework, fields, models, and model managers all implement a check() method that is registered with the check framework. If you have an existing method called check() on one of these objects, you will need to rename it.

- As noted above in the “Cache” section of “Minor Features”, defining the TIMEOUT argument of the CACHES setting as None will set the cache keys as “non-expiring”. Previously, with the memcache backend, a TIMEOUT of 0 would set non-expiring keys, but this was inconsistent with the set-and-expire (i.e. no caching) behavior of set("key", "value", timeout=0). If you want non-expiring keys, please update your settings to use None instead of 0 as the latter now designates set-and-expire in the settings as well.

- The sql* management commands now respect the allow_migrate() method of DATABASE_ROUTERS. If you have models synced to non-default databases, use the --database flag to get SQL for those models (previously they would always be included in the output).

- Decoding the query string from URLs now falls back to the ISO-8859-1 encoding when the input is not valid UTF-8.

- With the addition of the SessionAuthenticationMiddleware to the default project template (pre-1.7.2 only), a database must be created before accessing a page using runserver.

- The addition of the schemes argument to URLValidator will appear as a backwards-incompatible change if you were previously using a custom regular expression to validate schemes. Any scheme not listed in schemes will fail validation, even if the regular expression matches the given URL.

Features deprecated in 1.7

django.core.cache.get_cache

django.core.cache.get_cache has been supplanted by django.core.cache.caches.

django.utils.dictconfig/django.utils.importlib

django.utils.dictconfig and django.utils.importlib were copies of respectively logging.config and importlib provided for Python versions prior to 2.7. They have been deprecated.

django.utils.module_loading.import_by_path

The current django.utils.module_loading.import_by_path function catches AttributeError, ImportError, and ValueError exceptions, and re-raises ImproperlyConfigured. Such exception masking makes it needlessly hard to diagnose circular import problems, because it makes it look like the problem comes from inside Django. It has been deprecated in favor of import_string().

django.utils.tzinfo

django.utils.tzinfo provided two tzinfo subclasses, LocalTimezone and FixedOffset. They’ve been deprecated in favor of more correct alternatives provided by django.utils.timezone, django.utils.timezone.get_default_timezone() and django.utils.timezone.get_fixed_timezone().

django.utils.unittest

django.utils.unittest provided uniform access to the unittest2 library on all Python versions. Since unittest2 became the standard library’s unittest module in Python 2.7, and Django 1.7 drops support for older Python versions, this module isn’t useful anymore. It has been deprecated. Use unittest instead.

django.utils.datastructures.SortedDict

As OrderedDict was added to the standard library in Python 2.7, SortedDict is no longer needed and has been deprecated.

The two additional, deprecated methods provided by SortedDict (insert() and value_for_index()) have been removed. If you relied on these methods to alter structures like form fields, you should now treat these OrderedDicts as immutable objects and override them to change their content.

For example, you might want to override MyFormClass.base_fields (although this attribute isn’t considered a public API) to change the ordering of fields for all MyFormClass instances; or similarly, you could override self.fields from inside MyFormClass.__init__(), to change the fields for a particular form instance. For example (from Django itself):

PasswordChangeForm.base_fields = OrderedDict(
(k, PasswordChangeForm.base_fields[k])
for k in ['old_password', 'new_password1', 'new_password2']
)

Custom SQL location for models package

Previously, if models were organized in a package (myapp/models/) rather than simply myapp/models.py, Django would look for initial SQL data in myapp/models/sql/. This bug has been fixed so that Django will search myapp/sql/ as documented. After this issue was fixed, migrations were added which deprecates initial SQL data. Thus, while this change still exists, the deprecation is irrelevant as the entire feature will be removed in Django 1.9.

Reorganization of django.contrib.sites

django.contrib.sites provides reduced functionality when it isn’t in INSTALLED_APPS. The app-loading refactor adds some constraints in that situation. As a consequence, two objects were moved, and the old locations are deprecated:

- RequestSite now lives in django.contrib.sites.requests.

- get_current_site() now lives in django.contrib.sites.shortcuts.

declared_fieldsets attribute on ModelAdmin

ModelAdmin.declared_fieldsets has been deprecated. Despite being a private API, it will go through a regular deprecation path. This attribute was mostly used by methods that bypassed ModelAdmin.get_fieldsets() but this was considered a bug and has been addressed.

Reorganization of django.contrib.contenttypes

Since django.contrib.contenttypes.generic defined both admin and model related objects, an import of this module could trigger unexpected side effects. As a consequence, its contents were split into contenttypes submodules and the django.contrib.contenttypes.generic module is deprecated:

- GenericForeignKey and GenericRelation now live in fields.

- BaseGenericInlineFormSet and generic_inlineformset_factory() now live in forms.

- GenericInlineModelAdmin, GenericStackedInline and GenericTabularInline now live in admin.

syncdb

The syncdb command has been deprecated in favor of the new migrate command. migrate takes the same arguments as syncdb used to plus a few more, so it’s safe to just change the name you’re calling and nothing else.

util modules renamed to utils

The following instances of util.py in the Django codebase have been renamed to utils.py in an effort to unify all util and utils references:

- django.contrib.admin.util

- django.contrib.gis.db.backends.util

- django.db.backends.util

- django.forms.util

get_formsets method on ModelAdmin

ModelAdmin.get_formsets has been deprecated in favor of the new get_formsets_with_inlines(), in order to better handle the case of selectively showing inlines on a ModelAdmin.

IPAddressField

The django.db.models.IPAddressField and django.forms.IPAddressField fields have been deprecated in favor of django.db.models.GenericIPAddressField and django.forms.GenericIPAddressField.

BaseMemcachedCache._get_memcache_timeout method

The BaseMemcachedCache._get_memcache_timeout() method has been renamed to get_backend_timeout(). Despite being a private API, it will go through the normal deprecation.

Natural key serialization options

The --natural and -n options for dumpdata have been deprecated. Use dumpdata --natural-foreign instead.

Similarly, the use_natural_keys argument for serializers.serialize() has been deprecated. Use use_natural_foreign_keys instead.

Merging of POST and GET arguments into WSGIRequest.REQUEST

It was already strongly suggested that you use GET and POST instead of REQUEST, because the former are more explicit. The property REQUEST is deprecated and will be removed in Django 1.9.

django.utils.datastructures.MergeDict class

MergeDict exists primarily to support merging POST and GET arguments into a REQUEST property on WSGIRequest. To merge dictionaries, use dict.update() instead. The class MergeDict is deprecated and will be removed in Django 1.9.

Language codes zh-cn, zh-tw and fy-nl

The currently used language codes for Simplified Chinese zh-cn, Traditional Chinese zh-tw and (Western) Frysian fy-nl are deprecated and should be replaced by the language codes zh-hans, zh-hant and fy respectively. If you use these language codes, you should rename the locale directories and update your settings to reflect these changes. The deprecated language codes will be removed in Django 1.9.

django.utils.functional.memoize function

The function memoize is deprecated and should be replaced by the functools.lru_cache decorator (available from Python 3.2 onwards).

Django ships a backport of this decorator for older Python versions and it’s available at django.utils.lru_cache.lru_cache. The deprecated function will be removed in Django 1.9.

Geo Sitemaps

Google has retired support for the Geo Sitemaps format. Hence Django support for Geo Sitemaps is deprecated and will be removed in Django 1.8.

Passing callable arguments to queryset methods

Callable arguments for querysets were an undocumented feature that was unreliable. It’s been deprecated and will be removed in Django 1.9.

Callable arguments were evaluated when a queryset was constructed rather than when it was evaluated, thus this feature didn’t offer any benefit compared to evaluating arguments before passing them to queryset and created confusion that the arguments may have been evaluated at query time.

ADMIN_FOR setting

The ADMIN_FOR feature, part of the admindocs, has been removed. You can remove the setting from your configuration at your convenience.

SplitDateTimeWidget with DateTimeField

SplitDateTimeWidget support in DateTimeField is deprecated, use SplitDateTimeWidget with SplitDateTimeField instead.

validate

The validate management command is deprecated in favor of the check command.

django.core.management.BaseCommand

requires_model_validation is deprecated in favor of a new requires_system_checks flag. If the latter flag is missing, then the value of the former flag is used. Defining both requires_system_checks and requires_model_validation results in an error.

The check() method has replaced the old validate() method.

ModelAdmin validators

The ModelAdmin.validator_class and default_validator_class attributes are deprecated in favor of the new checks_class attribute.

The ModelAdmin.validate() method is deprecated in favor of ModelAdmin.check().

The django.contrib.admin.validation module is deprecated.

django.db.backends.DatabaseValidation.validate_field

This method is deprecated in favor of a new check_field method. The functionality required by check_field() is the same as that provided by validate_field(), but the output format is different. Third-party database backends needing this functionality should provide an implementation of check_field().

Loading ssi and url template tags from future library

Django 1.3 introduced {% load ssi from future %} and {% load url from future %} syntax for forward compatibility of the ssi and url template tags. This syntax is now deprecated and will be removed in Django 1.9. You can simply remove the {% load ... from future %} tags.

django.utils.text.javascript_quote

javascript_quote() was an undocumented function present in django.utils.text. It was used internally in the javascript_catalog view whose implementation was changed to make use of json.dumps() instead. If you were relying on this function to provide safe output from untrusted strings, you should use django.utils.html.escapejs or the escapejs template filter. If all you need is to generate valid JavaScript strings, you can simply use json.dumps().

fix_ampersands utils method and template filter

The django.utils.html.fix_ampersands method and the fix_ampersands template filter are deprecated, as the escaping of ampersands is already taken care of by Django’s standard HTML escaping features. Combining this with fix_ampersands would either result in double escaping, or, if the output is assumed to be safe, a risk of introducing XSS vulnerabilities. Along with fix_ampersands, django.utils.html.clean_html is deprecated, an undocumented function that calls fix_ampersands. As this is an accelerated deprecation, fix_ampersands and clean_html will be removed in Django 1.8.

Reorganization of database test settings

All database settings with a TEST_ prefix have been deprecated in favor of entries in a TEST dictionary in the database settings. The old settings will be supported until Django 1.9. For backwards compatibility with older versions of Django, you can define both versions of the settings as long as they match.

FastCGI support

FastCGI support via the runfcgi management command will be removed in Django 1.9. Please deploy your project using WSGI.

Moved objects in contrib.sites

Following the app-loading refactor, two objects in django.contrib.sites.models needed to be moved because they must be available without importing django.contrib.sites.models when django.contrib.sites isn’t installed. Import RequestSite from django.contrib.sites.requests and get_current_site() from django.contrib.sites.shortcuts. The old import locations will work until Django 1.9.

django.forms.forms.get_declared_fields()

Django no longer uses this functional internally. Even though it’s a private API, it’ll go through the normal deprecation cycle.

Private Query Lookup APIs

Private APIs django.db.models.sql.where.WhereNode.make_atom() and django.db.models.sql.where.Constraint are deprecated in favor of the new custom lookups API.

Features removed in 1.7

These features have reached the end of their deprecation cycle and are removed in Django 1.7. See Features deprecated in 1.5 for details, including how to remove usage of these features.

- django.utils.simplejson is removed.

- django.utils.itercompat.product is removed.

- INSTALLED_APPS and TEMPLATE_DIRS are no longer corrected from a plain string into a tuple.

- HttpResponse, SimpleTemplateResponse, TemplateResponse, render_to_response(), index(), and sitemap() no longer take a mimetype argument

- HttpResponse immediately consumes its content if it’s an iterator.

- The AUTH_PROFILE_MODULE setting, and the get_profile() method on the User model are removed.

- The cleanup management command is removed.

- The daily_cleanup.py script is removed.

- select_related() no longer has a depth keyword argument.

- The get_warnings_state()/restore_warnings_state() functions from django.test.utils and the save_warnings_state()/ restore_warnings_state() django.test.*TestCase are removed.

- The check_for_test_cookie method in AuthenticationForm is removed.

- The version of django.contrib.auth.views.password_reset_confirm() that supports base36 encoded user IDs (django.contrib.auth.views.password_reset_confirm_uidb36) is removed.

- The django.utils.encoding.StrAndUnicode mix-in is removed.

Django 1.6.11 release notes

March 18, 2015

Django 1.6.11 fixes two security issues in 1.6.10.

Denial-of-service possibility with strip_tags()

Last year strip_tags() was changed to work iteratively. The problem is that the size of the input it’s processing can increase on each iteration which results in an infinite loop in strip_tags(). This issue only affects versions of Python that haven’t received a bugfix in HTMLParser; namely Python < 2.7.7 and 3.3.5. Some operating system vendors have also backported the fix for the Python bug into their packages of earlier versions.

To remedy this issue, strip_tags() will now return the original input if it detects the length of the string it’s processing increases. Remember that absolutely NO guarantee is provided about the results of strip_tags() being HTML safe. So NEVER mark safe the result of a strip_tags() call without escaping it first, for example with escape().

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) accepted URLs with leading control characters and so considered URLs like \x08javascript:... safe. This issue doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there. Browsers we tested also treat URLs prefixed with control characters such as %08//example.com as relative paths so redirection to an unsafe target isn’t a problem either.

However, if a developer relies on is_safe_url() to provide safe redirect targets and puts such a URL into a link, they could suffer from an XSS attack as some browsers such as Google Chrome ignore control characters at the start of a URL in an anchor href.

Django 1.6.10 release notes

January 13, 2015

Django 1.6.10 fixes several security issues in 1.6.9.

WSGI header spoofing via underscore/dash conflation

When HTTP headers are placed into the WSGI environ, they are normalized by converting to uppercase, converting all dashes to underscores, and prepending HTTP_. For instance, a header X-Auth-User would become HTTP_X_AUTH_USER in the WSGI environ (and thus also in Django’s request.META dictionary).

Unfortunately, this means that the WSGI environ cannot distinguish between headers containing dashes and headers containing underscores: X-Auth-User and X-Auth_User both become HTTP_X_AUTH_USER. This means that if a header is used in a security-sensitive way (for instance, passing authentication information along from a front-end proxy), even if the proxy carefully strips any incoming value for X-Auth-User, an attacker may be able to provide an X-Auth_User header (with underscore) and bypass this protection.

In order to prevent such attacks, both Nginx and Apache 2.4+ strip all headers containing underscores from incoming requests by default. Django’s built-in development server now does the same. Django’s development server is not recommended for production use, but matching the behavior of common production servers reduces the surface area for behavior changes during deployment.

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) didn’t strip leading whitespace on the tested URL and as such considered URLs like \njavascript:... safe. If a developer relied on is_safe_url() to provide safe redirect targets and put such a URL into a link, they could suffer from a XSS attack. This bug doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there.

Denial-of-service attack against django.views.static.serve

In older versions of Django, the django.views.static.serve() view read the files it served one line at a time. Therefore, a big file with no newlines would result in memory usage equal to the size of that file. An attacker could exploit this and launch a denial-of-service attack by simultaneously requesting many large files. This view now reads the file in chunks to prevent large memory usage.

Note, however, that this view has always carried a warning that it is not hardened for production use and should be used only as a development aid. Now may be a good time to audit your project and serve your files in production using a real front-end web server if you are not doing so.

Database denial-of-service with ModelMultipleChoiceField

Given a form that uses ModelMultipleChoiceField and show_hidden_initial=True (not a documented API), it was possible for a user to cause an unreasonable number of SQL queries by submitting duplicate values for the field’s data. The validation logic in ModelMultipleChoiceField now deduplicates submitted values to address this issue.

Django 1.6.9 release notes

January 2, 2015

Django 1.6.9 fixes a regression in the 1.6.6 security release.

Additionally, Django’s vendored version of six, django.utils.six, has been upgraded to the latest release (1.9.0).

Bugfixes

- Fixed a regression with dynamically generated inlines and allowed field references in the admin (#23754).

Django 1.6.8 release notes

October 22, 2014

Django 1.6.8 fixes a couple regressions in the 1.6.6 security release.

Bugfixes

- Allowed related many-to-many fields to be referenced in the admin (#23604).

- Allowed inline and hidden references to admin fields (#23431).

Django 1.6.7 release notes

September 2, 2014

Django 1.6.7 fixes several bugs in 1.6.6, including a regression related to a security fix in that release.

Bugfixes

- Allowed inherited and m2m fields to be referenced in the admin (#23329).

- Fixed a crash when using QuerySet.defer() with select_related() (#23370).

Django 1.6.6 release notes

August 20, 2014

Django 1.6.6 fixes several security issues and bugs in 1.6.5.

reverse() could generate URLs pointing to other hosts

In certain situations, URL reversing could generate scheme-relative URLs (URLs starting with two slashes), which could unexpectedly redirect a user to a different host. An attacker could exploit this, for example, by redirecting users to a phishing site designed to ask for user’s passwords.

To remedy this, URL reversing now ensures that no URL starts with two slashes (//), replacing the second slash with its URL encoded counterpart (%2F). This approach ensures that semantics stay the same, while making the URL relative to the domain and not to the scheme.

File upload denial-of-service

Before this release, Django’s file upload handing in its default configuration may degrade to producing a huge number of os.stat() system calls when a duplicate filename is uploaded. Since stat() may invoke IO, this may produce a huge data-dependent slowdown that slowly worsens over time. The net result is that given enough time, a user with the ability to upload files can cause poor performance in the upload handler, eventually causing it to become very slow simply by uploading 0-byte files. At this point, even a slow network connection and few HTTP requests would be all that is necessary to make a site unavailable.

We’ve remedied the issue by changing the algorithm for generating file names if a file with the uploaded name already exists. Storage.get_available_name() now appends an underscore plus a random 7 character alphanumeric string (e.g. "_x3a1gho"), rather than iterating through an underscore followed by a number (e.g. "_1", "_2", etc.).

RemoteUserMiddleware session hijacking

When using the RemoteUserMiddleware and the RemoteUserBackend, a change to the REMOTE_USER header between requests without an intervening logout could result in the prior user’s session being co-opted by the subsequent user. The middleware now logs the user out on a failed login attempt.

Data leakage via query string manipulation in contrib.admin

In older versions of Django it was possible to reveal any field’s data by modifying the “popup” and “to_field” parameters of the query string on an admin change form page. For example, requesting a URL like /admin/auth/user/?_popup=1&t=password and viewing the page’s HTML allowed viewing the password hash of each user. While the admin requires users to have permissions to view the change form pages in the first place, this could leak data if you rely on users having access to view only certain fields on a model.

To address the issue, an exception will now be raised if a to_field value that isn’t a related field to a model that has been registered with the admin is specified.

Bugfixes

- Corrected email and URL validation to reject a trailing dash (#22579).

- Prevented indexes on PostgreSQL virtual fields (#22514).

- Prevented edge case where values of FK fields could be initialized with a wrong value when an inline model formset is created for a relationship defined to point to a field other than the PK (#13794).

- Restored pre_delete signals for GenericRelation cascade deletion (#22998).

- Fixed transaction handling when specifying non-default database in createcachetable and flush (#23089).

- Fixed the “ORA-01843: not a valid month” errors when using Unicode with older versions of Oracle server (#20292).

- Restored bug fix for sending unicode email with Python 2.6.5 and below (#19107).

- Prevented UnicodeDecodeError in runserver with non-UTF-8 and non-English locale (#23265).

- Fixed JavaScript errors while editing multi-geometry objects in the OpenLayers widget (#23137, #23293).

- Prevented a crash on Python 3 with query strings containing unencoded non-ASCII characters (#22996).

Django 1.6.5 release notes

May 14, 2014

Django 1.6.5 fixes two security issues and several bugs in 1.6.4.

Issue: Caches may incorrectly be allowed to store and serve private data

In certain situations, Django may allow caches to store private data related to a particular session and then serve that data to requests with a different session, or no session at all. This can lead to information disclosure and can be a vector for cache poisoning.

When using Django sessions, Django will set a Vary: Cookie header to ensure caches do not serve cached data to requests from other sessions. However, older versions of Internet Explorer (most likely only Internet Explorer 6, and Internet Explorer 7 if run on Windows XP or Windows Server 2003) are unable to handle the Vary header in combination with many content types. Therefore, Django would remove the header if the request was made by Internet Explorer.

To remedy this, the special behavior for these older Internet Explorer versions has been removed, and the Vary header is no longer stripped from the response. In addition, modifications to the Cache-Control header for all Internet Explorer requests with a Content-Disposition header have also been removed as they were found to have similar issues.

Issue: Malformed redirect URLs from user input not correctly validated

The validation for redirects did not correctly validate some malformed URLs, which are accepted by some browsers. This allows a user to be redirected to an unsafe URL unexpectedly.

Django relies on user input in some cases (e.g. django.contrib.auth.views.login(), django.contrib.comments, and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) did not correctly validate some malformed URLs, such as http:\\\djangoproject.com, which are accepted by some browsers with more liberal URL parsing.

To remedy this, the validation in is_safe_url() has been tightened to be able to handle and correctly validate these malformed URLs.

Bugfixes

- Made the year_lookup_bounds_for_datetime_field Oracle backend method Python 3 compatible (#22551).

- Fixed pgettext_lazy crash when receiving bytestring content on Python 2 (#22565).

- Fixed the SQL generated when filtering by a negated Q object that contains a F object. (#22429).

- Avoided overwriting data fetched by select_related() in certain cases which could cause minor performance regressions (#22508).

Django 1.6.4 release notes

April 28, 2014

Django 1.6.4 fixes several bugs in 1.6.3.

Bugfixes

- Added backwards compatibility support for the django.contrib.messages cookie format of Django 1.4 and earlier to facilitate upgrading to 1.6 from 1.4 (#22426).

- Restored the ability to reverse() views created using functools.partial() (#22486).

- Fixed the object_id of the LogEntry that’s created after a user password change in the admin (#22515).

Django 1.6.3 release notes

April 21, 2014

Django 1.6.3 fixes several bugs in 1.6.2, including three security issues, and makes one backwards-incompatible change:

Unexpected code execution using reverse()

Django’s URL handling is based on a mapping of regex patterns (representing the URLs) to callable views, and Django’s own processing consists of matching a requested URL against those patterns to determine the appropriate view to invoke.

Django also provides a convenience function – reverse() – which performs this process in the opposite direction. The reverse() function takes information about a view and returns a URL which would invoke that view. Use of reverse() is encouraged for application developers, as the output of reverse() is always based on the current URL patterns, meaning developers do not need to change other code when making changes to URLs.

One argument signature for reverse() is to pass a dotted Python path to the desired view. In this situation, Django will import the module indicated by that dotted path as part of generating the resulting URL. If such a module has import-time side effects, those side effects will occur.

Thus it is possible for an attacker to cause unexpected code execution, given the following conditions:

1. One or more views are present which construct a URL based on user input (commonly, a “next” parameter in a querystring indicating where to redirect upon successful completion of an action).

2. One or more modules are known to an attacker to exist on the server’s Python import path, which perform code execution with side effects on importing.

To remedy this, reverse() will now only accept and import dotted paths based on the view-containing modules listed in the project’s URL pattern configuration, so as to ensure that only modules the developer intended to be imported in this fashion can or will be imported.

Caching of anonymous pages could reveal CSRF token

Django includes both a caching framework and a system for preventing cross-site request forgery (CSRF) attacks. The CSRF-protection system is based on a random nonce sent to the client in a cookie which must be sent by the client on future requests and, in forms, a hidden value which must be submitted back with the form.

The caching framework includes an option to cache responses to anonymous (i.e., unauthenticated) clients.

When the first anonymous request to a given page is by a client which did not have a CSRF cookie, the cache framework will also cache the CSRF cookie and serve the same nonce to other anonymous clients who do not have a CSRF cookie. This can allow an attacker to obtain a valid CSRF cookie value and perform attacks which bypass the check for the cookie.

To remedy this, the caching framework will no longer cache such responses. The heuristic for this will be:

1. If the incoming request did not submit any cookies, and

2. If the response did send one or more cookies, and

3. If the Vary: Cookie header is set on the response, then the response will not be cached.

MySQL typecasting

The MySQL database is known to “typecast” on certain queries; for example, when querying a table which contains string values, but using a query which filters based on an integer value, MySQL will first silently coerce the strings to integers and return a result based on that.

If a query is performed without first converting values to the appropriate type, this can produce unexpected results, similar to what would occur if the query itself had been manipulated.

Django’s model field classes are aware of their own types and most such classes perform explicit conversion of query arguments to the correct database-level type before querying. However, three model field classes did not correctly convert their arguments:

- FilePathField

- GenericIPAddressField

- IPAddressField

These three fields have been updated to convert their arguments to the correct types before querying.

Additionally, developers of custom model fields are now warned via documentation to ensure their custom field classes will perform appropriate type conversions, and users of the raw() and extra() query methods – which allow the developer to supply raw SQL or SQL fragments – will be advised to ensure they perform appropriate manual type conversions prior to executing queries.

select_for_update() requires a transaction

Historically, queries that use select_for_update() could be executed in autocommit mode, outside of a transaction. Before Django 1.6, Django’s automatic transactions mode allowed this to be used to lock records until the next write operation. Django 1.6 introduced database-level autocommit; since then, execution in such a context voids the effect of select_for_update(). It is, therefore, assumed now to be an error and raises an exception.

This change was made because such errors can be caused by including an app which expects global transactions (e.g. ATOMIC_REQUESTS set to True), or Django’s old autocommit behavior, in a project which runs without them; and further, such errors may manifest as data-corruption bugs.

This change may cause test failures if you use select_for_update() in a test class which is a subclass of TransactionTestCase rather than TestCase.

Other bugfixes and changes

- Content retrieved from the GeoIP library is now properly decoded from its default iso-8859-1 encoding (#21996).

- Fixed AttributeError when using bulk_create() with ForeignObject (#21566).

- Fixed crash of QuerySets that use F() + timedelta() when their query was compiled more once (#21643).

- Prevented custom widget class attribute of IntegerField subclasses from being overwritten by the code in their __init__ method (#22245).

- Improved strip_tags() accuracy (but it still cannot guarantee an HTML-safe result, as stated in the documentation).

- Fixed a regression in the django.contrib.gis SQL compiler for non-concrete fields (#22250).

- Fixed ModelAdmin.preserve_filters when running a site with a URL prefix (#21795).

- Fixed a crash in the find_command management utility when the PATH environment variable wasn’t set (#22256).

- Fixed changepassword on Windows (#22364).

- Avoided shadowing deadlock exceptions on MySQL (#22291).

- Wrapped database exceptions in _set_autocommit (#22321).

- Fixed atomicity when closing a database connection or when the database server disconnects (#21239 and #21202)

- Fixed regression in prefetch_related that caused the related objects query to include an unnecessary join (#21760).

Additionally, Django’s vendored version of six, django.utils.six has been upgraded to the latest release (1.6.1).

Django 1.6.2 release notes

February 6, 2014

This is Django 1.6.2, a bugfix release for Django 1.6. Django 1.6.2 fixes several bugs in 1.6.1:

- Prevented the base geometry object of a prepared geometry to be garbage collected, which could lead to crash Django (#21662).

- Fixed a crash when executing the changepassword command when the user object representation contained non-ASCII characters (#21627).

- The collectstatic command will raise an error rather than default to using the current working directory if STATIC_ROOT is not set. Combined with the --clear option, the previous behavior could wipe anything below the current working directory (#21581).

- Fixed mail encoding on Python 3.3.3+ (#21093).

- Fixed an issue where when settings.DATABASES['default']['AUTOCOMMIT'] = False, the connection wasn’t in autocommit mode but Django pretended it was.

- Fixed a regression in multiple-table inheritance exclude() queries (#21787).

- Added missing items to django.utils.timezone.__all__ (#21880).

- Fixed a field misalignment issue with select_related() and model inheritance (#21413).

- Fixed join promotion for negated AND conditions (#21748).

- Oracle database introspection now works with boolean and float fields (#19884).

- Fixed an issue where lazy objects weren’t actually marked as safe when passed through mark_safe() and could end up being double-escaped (#21882).

Additionally, Django’s vendored version of six, django.utils.six has been upgraded to the latest release (1.5.2).

Django 1.6.1 release notes

December 12, 2013

This is Django 1.6.1, a bugfix release for Django 1.6. In addition to the bug fixes listed below, translations submitted since the 1.6 release are also included.

Bug fixes

- Fixed BCryptSHA256PasswordHasher with py-bcrypt and Python 3 (#21398).

- Fixed a regression that prevented a ForeignKey with a hidden reverse manager (related_name ending with ‘+’) from being used as a lookup for prefetch_related (#21410).

- Fixed Queryset.datetimes raising AttributeError in some situations (#21432).

- Fixed ModelBackend raising UnboundLocalError if get_user_model() raised an error (#21439).

- Fixed a regression that prevented editable GenericRelation subclasses from working in ModelForms (#21428).

- Added missing to_python method for ModelMultipleChoiceField which is required in Django 1.6 to properly detect changes from initial values (#21568).

- Fixed django.contrib.humanize translations where the unicode sequence for the non-breaking space was returned verbatim (#21415).

- Fixed loaddata error when fixture file name contained any dots not related to file extensions (#21457) or when fixture path was relative but located in a subdirectory (#21551).

- Fixed display of inline instances in formsets when parent has 0 for primary key (#21472).

- Fixed a regression where custom querysets for foreign keys were overwritten if ModelAdmin had ordering set (#21405).

- Removed mention of a feature in the --locale/-l option of the makemessages and compilemessages commands that never worked as promised: Support of multiple locale names separated by commas. It’s still possible to specify multiple locales in one run by using the option multiple times (#21488, #17181).

- Fixed a regression that unnecessarily triggered settings configuration when importing get_wsgi_application (#21486).

- Fixed test client logout() method when using the cookie-based session backend (#21448).

- Fixed a crash when a GeometryField uses a non-geometric widget (#21496).

- Fixed password hash upgrade when changing the iteration count (#21535).

- Fixed a bug in the debug view when the URLconf only contains one element (#21530).

- Re-added missing search result count and reset link in changelist admin view (#21510).

- The current language is no longer saved to the session by LocaleMiddleware on every response, but rather only after a logout (#21473).

- Fixed a crash when executing runserver on non-English systems and when the formatted date in its output contained non-ASCII characters (#21358).

- Fixed a crash in the debug view after an exception occurred on Python ≥ 3.3 (#21443).

- Fixed a crash in ImageField on some platforms (Homebrew and RHEL6 reported) (#21355).

- Fixed a regression when using generic relations in ModelAdmin.list_filter (#21431).

Django 1.6 release notes

Note

Dedicated to Malcolm Tredinnick

On March 17, 2013, the Django project and the free software community lost a very dear friend and developer.

Malcolm was a long-time contributor to Django, a model community member, a brilliant mind, and a friend. His contributions to Django — and to many other open source projects — are nearly impossible to enumerate. Many on the core Django team had their first patches reviewed by him; his mentorship enriched us. His consideration, patience, and dedication will always be an inspiration to us.

This release of Django is for Malcolm.

– The Django Developers

November 6, 2013

Welcome to Django 1.6!

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.5 or older versions. We’ve also dropped some features, which are detailed in our deprecation plan, and we’ve begun the deprecation process for some features.

Python compatibility

Django 1.6, like Django 1.5, requires Python 2.6.5 or above. Python 3 is also officially supported. We highly recommend the latest minor release for each supported Python series (2.6.X, 2.7.X, 3.2.X, and 3.3.X).

Django 1.6 will be the final release series to support Python 2.6; beginning with Django 1.7, the minimum supported Python version will be 2.7.

Python 3.4 is not supported, but support will be added in Django 1.7.

What’s new in Django 1.6

Simplified default project and app templates

The default templates used by startproject and startapp have been simplified and modernized. The admin is now enabled by default in new projects; the sites framework no longer is. clickjacking prevention is now on and the database defaults to SQLite.

If the default templates don’t suit your tastes, you can use custom project and app templates.

Improved transaction management

Django’s transaction management was overhauled. Database-level autocommit is now turned on by default. This makes transaction handling more explicit and should improve performance. The existing APIs were deprecated, and new APIs were introduced, as described in the transaction management docs.

Persistent database connections

Django now supports reusing the same database connection for several requests. This avoids the overhead of re-establishing a connection at the beginning of each request. For backwards compatibility, this feature is disabled by default. See Persistent connections for details.

Discovery of tests in any test module

Django 1.6 ships with a new test runner that allows more flexibility in the location of tests. The previous runner (django.test.simple.DjangoTestSuiteRunner) found tests only in the models.py and tests.py modules of a Python package in INSTALLED_APPS.

The new runner (django.test.runner.DiscoverRunner) uses the test discovery features built into unittest2 (the version of unittest in the Python 2.7+ standard library, and bundled with Django). With test discovery, tests can be located in any module whose name matches the pattern test*.py.

In addition, the test labels provided to ./manage.py test to nominate specific tests to run must now be full Python dotted paths (or directory paths), rather than applabel.TestCase.test_method_name pseudo-paths. This allows running tests located anywhere in your codebase, rather than only in INSTALLED_APPS. For more details, see Testing in Django.

This change is backwards-incompatible; see the backwards-incompatibility notes.

Time zone aware aggregation

The support for time zones introduced in Django 1.4 didn’t work well with QuerySet.dates(): aggregation was always performed in UTC. This limitation was lifted in Django 1.6. Use QuerySet.datetimes() to perform time zone aware aggregation on a DateTimeField.

Support for savepoints in SQLite

Django 1.6 adds support for savepoints in SQLite, with some limitations.

BinaryField model field

A new django.db.models.BinaryField model field allows storage of raw binary data in the database.

GeoDjango form widgets

GeoDjango now provides form fields and widgets for its geo-specialized fields. They are OpenLayers-based by default, but they can be customized to use any other JS framework.

check management command added for verifying compatibility

A check management command was added, enabling you to verify if your current configuration (currently oriented at settings) is compatible with the current version of Django.

Model.save() algorithm changed

The Model.save() method now tries to directly UPDATE the database if the instance has a primary key value. Previously SELECT was performed to determine if UPDATE or INSERT were needed. The new algorithm needs only one query for updating an existing row while the old algorithm needed two. See Model.save() for more details.

In some rare cases the database doesn’t report that a matching row was found when doing an UPDATE. An example is the PostgreSQL ON UPDATE trigger which returns NULL. In such cases it is possible to set django.db.models.Options.select_on_save flag to force saving to use the old algorithm.

Minor features

- Authentication backends can raise PermissionDenied to immediately fail the authentication chain.

- The HttpOnly flag can be set on the CSRF cookie with CSRF_COOKIE_HTTPONLY.

- The assertQuerysetEqual() now checks for undefined order and raises ValueError if undefined order is spotted. The order is seen as undefined if the given QuerySet isn’t ordered and there are more than one ordered values to compare against.

- Added earliest() for symmetry with latest().

- In addition to year, month and day, the ORM now supports hour, minute and second lookups.

- Django now wraps all PEP-249 exceptions.

- The default widgets for EmailField, URLField, IntegerField, FloatField and DecimalField use the new type attributes available in HTML5 (type='email', type='url', type='number'). Note that due to erratic support of the number input type with localized numbers in current browsers, Django only uses it when numeric fields are not localized.

- The number argument for lazy plural translations can be provided at translation time rather than at definition time.

- For custom management commands: Verification of the presence of valid settings in commands that ask for it by using the can_import_settings internal option is now performed independently from handling of the locale that should be active during the execution of the command. The latter can now be influenced by the new leave_locale_alone internal option. See Management commands and locales for more details.

- The success_url of DeletionMixin is now interpolated with its object’s __dict__.

- HttpResponseRedirect and HttpResponsePermanentRedirect now provide an url attribute (equivalent to the URL the response will redirect to).

- The MemcachedCache cache backend now uses the latest pickle protocol available.

- Added SuccessMessageMixin which provides a success_message attribute for FormView based classes.

- Added the django.db.models.ForeignKey.db_constraint and django.db.models.ManyToManyField.db_constraint options.

- The jQuery library embedded in the admin has been upgraded to version 1.9.1.

- Syndication feeds (django.contrib.syndication) can now pass extra context through to feed templates using a new Feed.get_context_data() callback.

- The admin list columns have a column-<field_name> class in the HTML so the columns header can be styled with CSS, e.g. to set a column width.

- The isolation level can be customized under PostgreSQL.

- The blocktrans template tag now respects TEMPLATE_STRING_IF_INVALID for variables not present in the context, just like other template constructs.

- SimpleLazyObjects will now present more helpful representations in shell debugging situations.

- Generic GeometryField is now editable with the OpenLayers widget in the admin.

- The documentation contains a deployment checklist.

- The diffsettings command gained a --all option.

- django.forms.fields.Field.__init__ now calls super(), allowing field mixins to implement __init__() methods that will reliably be called.

- The validate_max parameter was added to BaseFormSet and formset_factory(), and ModelForm and inline versions of the same. The behavior of validation for formsets with max_num was clarified. The previously undocumented behavior that hardened formsets against memory exhaustion attacks was documented, and the undocumented limit of the higher of 1000 or max_num forms was changed so it is always 1000 more than max_num.

- Added BCryptSHA256PasswordHasher to resolve the password truncation issue with bcrypt.

- Pillow is now the preferred image manipulation library to use with Django. PIL is pending deprecation (support to be removed in Django 1.8). To upgrade, you should first uninstall PIL, then install Pillow.

- ModelForm accepts several new Meta options.

- Fields included in the localized_fields list will be localized (by setting localize on the form field).

- The labels, help_texts and error_messages options may be used to customize the default fields, see Overriding the default fields for details.

- The choices argument to model fields now accepts an iterable of iterables instead of requiring an iterable of lists or tuples.

- The reason phrase can be customized in HTTP responses using reason_phrase.

- When giving the URL of the next page for logout(), password_reset(), password_reset_confirm(), and password_change(), you can now pass URL names and they will be resolved.

- The new dumpdata --pks option specifies the primary keys of objects to dump. This option can only be used with one model.

- Added QuerySet methods first() and last() which are convenience methods returning the first or last object matching the filters. Returns None if there are no objects matching.

- View and RedirectView now support HTTP PATCH method.

- GenericForeignKey now takes an optional for_concrete_model argument, which when set to False allows the field to reference proxy models. The default is True to retain the old behavior.

- The LocaleMiddleware now stores the active language in session if it is not present there. This prevents loss of language settings after session flush, e.g. logout.

- SuspiciousOperation has been differentiated into a number of subclasses, and each will log to a matching named logger under the django.security logging hierarchy. Along with this change, a handler400 mechanism and default view are used whenever a SuspiciousOperation reaches the WSGI handler to return an HttpResponseBadRequest.

- The DoesNotExist exception now includes a message indicating the name of the attribute used for the lookup.

- The get_or_create() method no longer requires at least one keyword argument.

- The SimpleTestCase class includes a new assertion helper for testing formset errors: assertFormsetError().

- The list of related fields added to a QuerySet by select_related() can be cleared using select_related(None).

- The get_extra() and get_max_num() methods on InlineModelAdmin may be overridden to customize the extra and maximum number of inline forms.

- Formsets now have a total_error_count() method.

- ModelForm fields can now override error messages defined in model fields by using the error_messages argument of a Field’s constructor. To take advantage of this new feature with your custom fields, see the updated recommendation for raising a ValidationError.

- ModelAdmin now preserves filters on the list view after creating, editing or deleting an object. It’s possible to restore the previous behavior of clearing filters by setting the preserve_filters attribute to False.

- Added FormMixin.get_prefix (which returns FormMixin.prefix by default) to allow customizing the prefix of the form.

- Raw queries (Manager.raw() or cursor.execute()) can now use the “pyformat” parameter style, where placeholders in the query are given as '%(name)s' and the parameters are passed as a dictionary rather than a list (except on SQLite). This has long been possible (but not officially supported) on MySQL and PostgreSQL, and is now also available on Oracle.

- The default iteration count for the PBKDF2 password hasher has been increased by 20%. This backwards compatible change will not affect existing passwords or users who have subclassed django.contrib.auth.hashers.PBKDF2PasswordHasher to change the default value. Passwords will be upgraded to use the new iteration count as necessary.

Backwards incompatible changes in 1.6

Warning

In addition to the changes outlined in this section, be sure to review the deprecation plan for any features that have been removed. If you haven’t updated your code within the deprecation timeline for a given feature, its removal may appear as a backwards incompatible change.

New transaction management model

Behavior changes

Database-level autocommit is enabled by default in Django 1.6. While this doesn’t change the general spirit of Django’s transaction management, there are a few backwards-incompatibilities.

Savepoints and assertNumQueries

The changes in transaction management may result in additional statements to create, release or rollback savepoints. This is more likely to happen with SQLite, since it didn’t support savepoints until this release.

If tests using assertNumQueries() fail because of a higher number of queries than expected, check that the extra queries are related to savepoints, and adjust the expected number of queries accordingly.

Autocommit option for PostgreSQL

In previous versions, database-level autocommit was only an option for PostgreSQL, and it was disabled by default. This option is now ignored and can be removed.

New test runner

In order to maintain greater consistency with Python’s unittest module, the new test runner (django.test.runner.DiscoverRunner) does not automatically support some types of tests that were supported by the previous runner:

- Tests in models.py and tests/__init__.py files will no longer be found and run. Move them to a file whose name begins with test.

- Doctests will no longer be automatically discovered. To integrate doctests in your test suite, follow the recommendations in the Python documentation.

Django bundles a modified version of the doctest module from the Python standard library (in django.test._doctest) and includes some additional doctest utilities. These utilities are deprecated and will be removed in Django 1.8; doctest suites should be updated to work with the standard library’s doctest module (or converted to unittest-compatible tests).

If you wish to delay updates to your test suite, you can set your TEST_RUNNER setting to django.test.simple.DjangoTestSuiteRunner to fully restore the old test behavior. DjangoTestSuiteRunner is deprecated but will not be removed from Django until version 1.8.

Removal of django.contrib.gis.tests.GeoDjangoTestSuiteRunner GeoDjango custom test runner

This is for developers working on the GeoDjango application itself and related to the item above about changes in the test runners:

The django.contrib.gis.tests.GeoDjangoTestSuiteRunner test runner has been removed and the standalone GeoDjango tests execution setup it implemented isn’t supported anymore. To run the GeoDjango tests simply use the new DiscoverRunner and specify the django.contrib.gis app.

Custom User models in tests

The introduction of the new test runner has also slightly changed the way that test models are imported. As a result, any test that overrides AUTH_USER_MODEL to test behavior with one of Django’s test user models ( django.contrib.auth.tests.custom_user.CustomUser and django.contrib.auth.tests.custom_user.ExtensionUser) must now explicitly import the User model in your test module:

from django.contrib.auth.tests.custom_user import CustomUser

@override_settings(AUTH_USER_MODEL='auth.CustomUser')
class CustomUserFeatureTests(TestCase):
def test_something(self):
# Test code here ...

This import forces the custom user model to be registered. Without this import, the test will be unable to swap in the custom user model, and you will get an error reporting:

ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed

Time zone-aware day, month, and week_day lookups

Django 1.6 introduces time zone support for day, month, and week_day lookups when USE_TZ is True. These lookups were previously performed in UTC regardless of the current time zone.

This requires time zone definitions in the database. If you’re using SQLite, you must install pytz. If you’re using MySQL, you must install pytz and load the time zone tables with mysql_tzinfo_to_sql.

Addition of QuerySet.datetimes()

When the time zone support added in Django 1.4 was active, QuerySet.dates() lookups returned unexpected results, because the aggregation was performed in UTC. To fix this, Django 1.6 introduces a new API, QuerySet.datetimes(). This requires a few changes in your code.

QuerySet.dates() returns date objects

QuerySet.dates() now returns a list of date. It used to return a list of datetime.

QuerySet.datetimes() returns a list of datetime.

QuerySet.dates() no longer usable on DateTimeField

QuerySet.dates() raises an error if it’s used on DateTimeField when time zone support is active. Use QuerySet.datetimes() instead.

date_hierarchy requires time zone definitions

The date_hierarchy feature of the admin now relies on QuerySet.datetimes() when it’s used on a DateTimeField.

This requires time zone definitions in the database when USE_TZ is True. Learn more.

date_list in generic views requires time zone definitions

For the same reason, accessing date_list in the context of a date-based generic view requires time zone definitions in the database when the view is based on a DateTimeField and USE_TZ is True. Learn more.

New lookups may clash with model fields

Django 1.6 introduces hour, minute, and second lookups on DateTimeField. If you had model fields called hour, minute, or second, the new lookups will clash with you field names. Append an explicit exact lookup if this is an issue.

BooleanField no longer defaults to False

When a BooleanField doesn’t have an explicit default, the implicit default value is None. In previous version of Django, it was False, but that didn’t represent accurately the lack of a value.

Code that relies on the default value being False may raise an exception when saving new model instances to the database, because None isn’t an acceptable value for a BooleanField. You should either specify default=False in the field definition, or ensure the field is set to True or False before saving the object.

Translations and comments in templates

Extraction of translations after comments

Extraction of translatable literals from templates with the makemessages command now correctly detects i18n constructs when they are located after a {# / #}-type comment on the same line. E.g.:

{# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}

Location of translator comments

Comments for translators in templates specified using {# / #} need to be at the end of a line. If they are not, the comments are ignored and makemessages will generate a warning. For example:

{# Translators: This is ignored #}{% trans "Translate me" %}
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>

Quoting in reverse()

Quoting in reverse()

When reversing URLs, Django didn’t apply urlquote() to arguments before interpolating them in URL patterns. This bug is fixed in Django 1.6. If you worked around this bug by applying URL quoting before passing arguments to reverse(), this may result in double-quoting. If this happens, simply remove the URL quoting from your code. You will also have to replace special characters in URLs used in assertRedirects() with their encoded versions.

Storage of IP addresses in the comments app

The comments app now uses a GenericIPAddressField for storing commenters’ IP addresses, to support comments submitted from IPv6 addresses. Until now, it stored them in an IPAddressField, which is only meant to support IPv4. When saving a comment made from an IPv6 address, the address would be silently truncated on MySQL databases, and raise an exception on Oracle. You will need to change the column type in your database to benefit from this change.

For MySQL, execute this query on your project’s database:

ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);

For Oracle, execute this query:

ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));

If you do not apply this change, the behavior is unchanged: on MySQL, IPv6 addresses are silently truncated; on Oracle, an exception is generated. No database change is needed for SQLite or PostgreSQL databases.

Percent literals in cursor.execute queries

When you are running raw SQL queries through the cursor.execute method, the rule about doubling percent literals (%) inside the query has been unified. Past behavior depended on the database backend. Now, across all backends, you only need to double literal percent characters if you are also providing replacement parameters. For example:

# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")

# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])

SQLite users need to check and update such queries.

Help text of model form fields for ManyToManyField fields

HTML rendering of model form fields corresponding to ManyToManyField model fields used to get the hard-coded sentence:

Hold down “Control”, or “Command” on a Mac, to select more than one.

(or its translation to the active locale) imposed as the help legend shown along them if neither model nor form help_text attributes were specified by the user (or this string was appended to any help_text that was provided).

Since this happened at the model layer, there was no way to prevent the text from appearing in cases where it wasn’t applicable such as form fields that implement user interactions that don’t involve a keyboard and/or a mouse.

Starting with Django 1.6, as an ad-hoc temporary backward-compatibility provision, the logic to add the “Hold down...” sentence has been moved to the model form field layer and modified to add the text only when the associated widget is SelectMultiple or selected subclasses.

The change can affect you in a backward incompatible way if you employ custom model form fields and/or widgets for ManyToManyField model fields whose UIs do rely on the automatic provision of the mentioned hard-coded sentence. These form field implementations need to adapt to the new scenario by providing their own handling of the help_text attribute.

Applications that use Django model form facilities together with Django built-in form fields and widgets aren’t affected but need to be aware of what’s described in Munging of help text of model form fields for ManyToManyField fields below.

QuerySet iteration

The QuerySet iteration was changed to immediately convert all fetched rows to Model objects. In Django 1.5 and earlier the fetched rows were converted to Model objects in chunks of 100.

Existing code will work, but the amount of rows converted to objects might change in certain use cases. Such usages include partially looping over a queryset or any usage which ends up doing __bool__ or __contains__.

Notably most database backends did fetch all the rows in one go already in 1.5.

It is still possible to convert the fetched rows to Model objects lazily by using the iterator() method.

BoundField.label_tag now includes the form’s label_suffix

This is consistent with how methods like Form.as_p and Form.as_ul render labels.

If you manually render label_tag in your templates:

{{ form.my_field.label_tag }}: {{ form.my_field }}

you’ll want to remove the colon (or whatever other separator you may be using) to avoid duplicating it when upgrading to Django 1.6. The following template in Django 1.6 will render identically to the above template in Django 1.5, except that the colon will appear inside the <label> element.

{{ form.my_field.label_tag }} {{ form.my_field }}

will render something like:

<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />

If you want to keep the current behavior of rendering label_tag without the label_suffix, instantiate the form label_suffix=''. You can also customize the label_suffix on a per-field basis using the new label_suffix parameter on label_tag().

Admin views _changelist_filters GET parameter

To achieve preserving and restoring list view filters, admin views now pass around the _changelist_filters GET parameter. It’s important that you account for that change if you have custom admin templates or if your tests rely on the previous URLs. If you want to revert to the original behavior you can set the preserve_filters attribute to False.

django.contrib.auth password reset uses base 64 encoding of User PK

Past versions of Django used base 36 encoding of the User primary key in the password reset views and URLs (django.contrib.auth.views.password_reset_confirm()). Base 36 encoding is sufficient if the user primary key is an integer, however, with the introduction of custom user models in Django 1.5, that assumption may no longer be true.

django.contrib.auth.views.password_reset_confirm() has been modified to take a uidb64 parameter instead of uidb36. If you are reversing this view, for example in a custom password_reset_email.html template, be sure to update your code.

A temporary shim for django.contrib.auth.views.password_reset_confirm() that will allow password reset links generated prior to Django 1.6 to continue to work has been added to provide backwards compatibility; this will be removed in Django 1.7. Thus, as long as your site has been running Django 1.6 for more than PASSWORD_RESET_TIMEOUT_DAYS, this change will have no effect. If not (for example, if you upgrade directly from Django 1.5 to Django 1.7), then any password reset links generated before you upgrade to Django 1.7 or later won’t work after the upgrade.

In addition, if you have any custom password reset URLs, you will need to update them by replacing uidb36 with uidb64 and the dash that follows that pattern with a slash. Also add _\- to the list of characters that may match the uidb64 pattern.

For example:

url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),

becomes:

url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),

You may also want to add the shim to support the old style reset links. Using the example above, you would modify the existing url by replacing django.contrib.auth.views.password_reset_confirm with django.contrib.auth.views.password_reset_confirm_uidb36 and also remove the name argument so it doesn’t conflict with the new url:

url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm_uidb36'),

You can remove this URL pattern after your app has been deployed with Django 1.6 for PASSWORD_RESET_TIMEOUT_DAYS.

Default session serialization switched to JSON

Historically, django.contrib.sessions used pickle to serialize session data before storing it in the backend. If you’re using the signed cookie session backend and SECRET_KEY is known by an attacker (there isn’t an inherent vulnerability in Django that would cause it to leak), the attacker could insert a string into his session which, when unpickled, executes arbitrary code on the server. The technique for doing so is simple and easily available on the internet. Although the cookie session storage signs the cookie-stored data to prevent tampering, a SECRET_KEY leak immediately escalates to a remote code execution vulnerability.

This attack can be mitigated by serializing session data using JSON rather than pickle. To facilitate this, Django 1.5.3 introduced a new setting, SESSION_SERIALIZER, to customize the session serialization format. For backwards compatibility, this setting defaulted to using pickle in Django 1.5.3, but we’ve changed the default to JSON in 1.6. If you upgrade and switch from pickle to JSON, sessions created before the upgrade will be lost. While JSON serialization does not support all Python objects like pickle does, we highly recommend using JSON-serialized sessions. Be aware of the following when checking your code to determine if JSON serialization will work for your application:

- JSON requires string keys, so you will likely run into problems if you are using non-string keys in request.session.

- Setting session expiration by passing datetime values to set_expiry() will not work as datetime values are not serializable in JSON. You can use integer values instead.

See the Session serialization documentation for more details.

Object Relational Mapper changes

Django 1.6 contains many changes to the ORM. These changes fall mostly in three categories:

1. Bug fixes (e.g. proper join clauses for generic relations, query combining, join promotion, and join trimming fixes)

2. Preparation for new features. For example the ORM is now internally ready for multicolumn foreign keys.

3. General cleanup.

These changes can result in some compatibility problems. For example, some queries will now generate different table aliases. This can affect QuerySet.extra(). In addition some queries will now produce different results. An example is exclude(condition) where the condition is a complex one (referencing multijoins inside Q objects). In many cases the affected queries didn’t produce correct results in Django 1.5 but do now. Unfortunately there are also cases that produce different results, but neither Django 1.5 nor 1.6 produce correct results.

Finally, there have been many changes to the ORM internal APIs.

Miscellaneous

- The django.db.models.query.EmptyQuerySet can’t be instantiated any more - it is only usable as a marker class for checking if none() has been called: isinstance(qs.none(), EmptyQuerySet)

- If your CSS/JavaScript code used to access HTML input widgets by type, you should review it as type='text' widgets might be now output as type='email', type='url' or type='number' depending on their corresponding field type.

- Form field’s error_messages that contain a placeholder should now always use a named placeholder ("Value '%(value)s' is too big" instead of "Value '%s' is too big"). See the corresponding field documentation for details about the names of the placeholders. The changes in 1.6 particularly affect DecimalField and ModelMultipleChoiceField.

- Some error_messages for IntegerField, EmailField, IPAddressField, GenericIPAddressField, and SlugField have been suppressed because they duplicated error messages already provided by validators tied to the fields.

- Due to a change in the form validation workflow, TypedChoiceField coerce method should always return a value present in the choices field attribute. That limitation should be lift again in Django 1.7.

- There have been changes in the way timeouts are handled in cache backends. Explicitly passing in timeout=None no longer results in using the default timeout. It will now set a non-expiring timeout. Passing 0 into the memcache backend no longer uses the default timeout, and now will set-and-expire-immediately the value.

- The django.contrib.flatpages app used to set custom HTTP headers for debugging purposes. This functionality was not documented and made caching ineffective so it has been removed, along with its generic implementation, previously available in django.core.xheaders.

- The XViewMiddleware has been moved from django.middleware.doc to django.contrib.admindocs.middleware because it is an implementation detail of admindocs, proven not to be reusable in general.

- GenericIPAddressField will now only allow blank values if null values are also allowed. Creating a GenericIPAddressField where blank is allowed but null is not will trigger a model validation error because blank values are always stored as null. Previously, storing a blank value in a field which did not allow null would cause a database exception at runtime.

- If a NoReverseMatch exception is raised from a method when rendering a template, it is not silenced. For example, {{ obj.view_href }} will cause template rendering to fail if view_href() raises NoReverseMatch. There is no change to the {% url %} tag, it causes template rendering to fail like always when NoReverseMatch is raised.

- django.test.Client.logout() now calls django.contrib.auth.logout() which will send the user_logged_out() signal.

- Authentication views are now reversed by name, not their locations in django.contrib.auth.views. If you are using the views without a name, you should update your urlpatterns to use url() with the name parameter. For example:

(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete')

becomes:

url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete')

- RedirectView now has a pattern_name attribute which allows it to choose the target by reversing the URL.

- In Django 1.4 and 1.5, a blank string was unintentionally not considered to be a valid password. This meant set_password() would save a blank password as an unusable password like set_unusable_password() does, and thus check_password() always returned False for blank passwords. This has been corrected in this release: blank passwords are now valid.

- The admin changelist_view previously accepted a pop GET parameter to signify it was to be displayed in a popup. This parameter has been renamed to _popup to be consistent with the rest of the admin views. You should update your custom templates if they use the previous parameter name.

- validate_email() now accepts email addresses with localhost as the domain.

- The new makemessages --keep-pot option prevents deleting the temporary .pot file generated before creating the .po file.

- The undocumented django.core.servers.basehttp.WSGIServerException has been removed. Use socket.error provided by the standard library instead. This change was also released in Django 1.5.5.

- The signature of django.views.generic.base.RedirectView.get_redirect_url() has changed and now accepts positional arguments as well (*args, **kwargs). Any unnamed captured group will now be passed to get_redirect_url() which may result in a TypeError if you don’t update the signature of your custom method.

Features deprecated in 1.6

Transaction management APIs

Transaction management was completely overhauled in Django 1.6, and the current APIs are deprecated:

- django.middleware.transaction.TransactionMiddleware

- django.db.transaction.autocommit

- django.db.transaction.commit_on_success

- django.db.transaction.commit_manually

- the TRANSACTIONS_MANAGED setting

django.contrib.comments

Django’s comment framework has been deprecated and is no longer supported. It will be available in Django 1.6 and 1.7, and removed in Django 1.8. Most users will be better served with a custom solution, or a hosted product like Disqus.

The code formerly known as django.contrib.comments is still available in an external repository.

Support for PostgreSQL versions older than 8.4

The end of upstream support periods was reached in December 2011 for PostgreSQL 8.2 and in February 2013 for 8.3. As a consequence, Django 1.6 sets 8.4 as the minimum PostgreSQL version it officially supports.

You’re strongly encouraged to use the most recent version of PostgreSQL available, because of performance improvements and to take advantage of the native streaming replication available in PostgreSQL 9.x.

Changes to cycle and firstof

The template system generally escapes all variables to avoid XSS attacks. However, due to an accident of history, the cycle and firstof tags render their arguments as-is.

Django 1.6 starts a process to correct this inconsistency. The future template library provides alternate implementations of cycle and firstof that autoescape their inputs. If you’re using these tags, you’re encouraged to include the following line at the top of your templates to enable the new behavior:

{% load cycle from future %}

or:

{% load firstof from future %}

The tags implementing the old behavior have been deprecated, and in Django 1.8, the old behavior will be replaced with the new behavior. To ensure compatibility with future versions of Django, existing templates should be modified to use the future versions.

If necessary, you can temporarily disable auto-escaping with mark_safe() or {% autoescape off %}.

CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting

CacheMiddleware and UpdateCacheMiddleware used to provide a way to cache requests only if they weren’t made by a logged-in user. This mechanism was largely ineffective because the middleware correctly takes into account the Vary: Cookie HTTP header, and this header is being set on a variety of occasions, such as:

- accessing the session, or

- using CSRF protection, which is turned on by default, or

- using a client-side library which sets cookies, like Google Analytics.

This makes the cache effectively work on a per-session basis regardless of the CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting.

SEND_BROKEN_LINK_EMAILS setting

CommonMiddleware used to provide basic reporting of broken links by email when SEND_BROKEN_LINK_EMAILS is set to True.

Because of intractable ordering problems between CommonMiddleware and LocaleMiddleware, this feature was split out into a new middleware: BrokenLinkEmailsMiddleware.

If you’re relying on this feature, you should add 'django.middleware.common.BrokenLinkEmailsMiddleware' to your MIDDLEWARE_CLASSES setting and remove SEND_BROKEN_LINK_EMAILS from your settings.

_has_changed method on widgets

If you defined your own form widgets and defined the _has_changed method on a widget, you should now define this method on the form field itself.

module_name model _meta attribute

Model._meta.module_name was renamed to model_name. Despite being a private API, it will go through a regular deprecation path.

get_(add|change|delete)_permission model _meta methods

Model._meta.get_(add|change|delete)_permission methods were deprecated. Even if they were not part of the public API they’ll also go through a regular deprecation path. You can replace them with django.contrib.auth.get_permission_codename('action', Model._meta) where 'action' is 'add', 'change', or 'delete'.

get_query_set and similar methods renamed to get_queryset

Methods that return a QuerySet such as Manager.get_query_set or ModelAdmin.queryset have been renamed to get_queryset.

If you are writing a library that implements, for example, a Manager.get_query_set method, and you need to support old Django versions, you should rename the method and conditionally add an alias with the old name:

class CustomManager(models.Manager):
def get_queryset(self):
pass # ...

if django.VERSION < (1, 6):
get_query_set = get_queryset

# For Django >= 1.6, models.Manager provides a get_query_set fallback
# that emits a warning when used.

If you are writing a library that needs to call the get_queryset method and must support old Django versions, you should write:

get_queryset = (some_manager.get_query_set
if hasattr(some_manager, 'get_query_set')
else some_manager.get_queryset)
return get_queryset() # etc

In the general case of a custom manager that both implements its own get_queryset method and calls that method, and needs to work with older Django versions, and libraries that have not been updated yet, it is useful to define a get_queryset_compat method as below and use it internally to your manager:

class YourCustomManager(models.Manager):
def get_queryset(self):
return YourCustomQuerySet() # for example

if django.VERSION < (1, 6):
get_query_set = get_queryset

def active(self): # for example
return self.get_queryset_compat().filter(active=True)

def get_queryset_compat(self):
get_queryset = (self.get_query_set
if hasattr(self, 'get_query_set')
else self.get_queryset)
return get_queryset()

This helps to minimize the changes that are needed, but also works correctly in the case of subclasses (such as RelatedManagers from Django 1.5) which might override either get_query_set or get_queryset.

shortcut view and URLconf

The shortcut view was moved from django.views.defaults to django.contrib.contenttypes.views shortly after the 1.0 release, but the old location was never deprecated. This oversight was corrected in Django 1.6 and you should now use the new location.

The URLconf django.conf.urls.shortcut was also deprecated. If you’re including it in an URLconf, simply replace:

(r'^prefix/', include('django.conf.urls.shortcut')),

with:

(r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contenttypes.views.shortcut'),

ModelForm without fields or exclude

Previously, if you wanted a ModelForm to use all fields on the model, you could simply omit the Meta.fields attribute, and all fields would be used.

This can lead to security problems where fields are added to the model and, unintentionally, automatically become editable by end users. In some cases, particular with boolean fields, it is possible for this problem to be completely invisible. This is a form of Mass assignment vulnerability.

For this reason, this behavior is deprecated, and using the Meta.exclude option is strongly discouraged. Instead, all fields that are intended for inclusion in the form should be listed explicitly in the fields attribute.

If this security concern really does not apply in your case, there is a shortcut to explicitly indicate that all fields should be used - use the special value "__all__" for the fields attribute:

class MyModelForm(ModelForm):
class Meta:
fields = "__all__"
model = MyModel

If you have custom ModelForms that only need to be used in the admin, there is another option. The admin has its own methods for defining fields (fieldsets etc.), and so adding a list of fields to the ModelForm is redundant. Instead, simply omit the Meta inner class of the ModelForm, or omit the Meta.model attribute. Since the ModelAdmin subclass knows which model it is for, it can add the necessary attributes to derive a functioning ModelForm. This behavior also works for earlier Django versions.

UpdateView and CreateView without explicit fields

The generic views CreateView and UpdateView, and anything else derived from ModelFormMixin, are vulnerable to the security problem described in the section above, because they can automatically create a ModelForm that uses all fields for a model.

For this reason, if you use these views for editing models, you must also supply the fields attribute (new in Django 1.6), which is a list of model fields and works in the same way as the ModelForm Meta.fields attribute. Alternatively, you can set the form_class attribute to a ModelForm that explicitly defines the fields to be used. Defining an UpdateView or CreateView subclass to be used with a model but without an explicit list of fields is deprecated.

Munging of help text of model form fields for ManyToManyField fields

All special handling of the help_text attribute of ManyToManyField model fields performed by standard model or model form fields as described in Help text of model form fields for ManyToManyField fields above is deprecated and will be removed in Django 1.8.

Help text of these fields will need to be handled either by applications, custom form fields or widgets, just like happens with the rest of the model field types.

Django 1.5.12 release notes

January 2, 2015

Django 1.5.12 fixes a regression in the 1.5.9 security release.

Bugfixes

- Fixed a regression with dynamically generated inlines and allowed field references in the admin (#23754).

Django 1.5.11 release notes

October 22, 2014

Django 1.5.11 fixes a couple regressions in the 1.5.9 security release.

Bugfixes

- Allowed related many-to-many fields to be referenced in the admin (#23604).

- Allowed inline and hidden references to admin fields (#23431).

Django 1.5.10 release notes

September 2, 2014

Django 1.5.10 fixes a regression in the 1.5.9 security release.

Bugfixes

- Allowed inherited and m2m fields to be referenced in the admin (#22486)

Django 1.5.9 release notes

August 20, 2014

Django 1.5.9 fixes several security issues in 1.5.8.

reverse() could generate URLs pointing to other hosts

In certain situations, URL reversing could generate scheme-relative URLs (URLs starting with two slashes), which could unexpectedly redirect a user to a different host. An attacker could exploit this, for example, by redirecting users to a phishing site designed to ask for user’s passwords.

To remedy this, URL reversing now ensures that no URL starts with two slashes (//), replacing the second slash with its URL encoded counterpart (%2F). This approach ensures that semantics stay the same, while making the URL relative to the domain and not to the scheme.

File upload denial-of-service

Before this release, Django’s file upload handing in its default configuration may degrade to producing a huge number of os.stat() system calls when a duplicate filename is uploaded. Since stat() may invoke IO, this may produce a huge data-dependent slowdown that slowly worsens over time. The net result is that given enough time, a user with the ability to upload files can cause poor performance in the upload handler, eventually causing it to become very slow simply by uploading 0-byte files. At this point, even a slow network connection and few HTTP requests would be all that is necessary to make a site unavailable.

We’ve remedied the issue by changing the algorithm for generating file names if a file with the uploaded name already exists. Storage.get_available_name() now appends an underscore plus a random 7 character alphanumeric string (e.g. "_x3a1gho"), rather than iterating through an underscore followed by a number (e.g. "_1", "_2", etc.).

RemoteUserMiddleware session hijacking

When using the RemoteUserMiddleware and the RemoteUserBackend, a change to the REMOTE_USER header between requests without an intervening logout could result in the prior user’s session being co-opted by the subsequent user. The middleware now logs the user out on a failed login attempt.

Data leakage via query string manipulation in contrib.admin

In older versions of Django it was possible to reveal any field’s data by modifying the “popup” and “to_field” parameters of the query string on an admin change form page. For example, requesting a URL like /admin/auth/user/?pop=1&t=password and viewing the page’s HTML allowed viewing the password hash of each user. While the admin requires users to have permissions to view the change form pages in the first place, this could leak data if you rely on users having access to view only certain fields on a model.

To address the issue, an exception will now be raised if a to_field value that isn’t a related field to a model that has been registered with the admin is specified.

Django 1.5.8 release notes

May 14, 2014

Django 1.5.8 fixes two security issues in 1.5.8.

Caches may incorrectly be allowed to store and serve private data

In certain situations, Django may allow caches to store private data related to a particular session and then serve that data to requests with a different session, or no session at all. This can lead to information disclosure and can be a vector for cache poisoning.

When using Django sessions, Django will set a Vary: Cookie header to ensure caches do not serve cached data to requests from other sessions. However, older versions of Internet Explorer (most likely only Internet Explorer 6, and Internet Explorer 7 if run on Windows XP or Windows Server 2003) are unable to handle the Vary header in combination with many content types. Therefore, Django would remove the header if the request was made by Internet Explorer.

To remedy this, the special behavior for these older Internet Explorer versions has been removed, and the Vary header is no longer stripped from the response. In addition, modifications to the Cache-Control header for all Internet Explorer requests with a Content-Disposition header have also been removed as they were found to have similar issues.

Malformed redirect URLs from user input not correctly validated

The validation for redirects did not correctly validate some malformed URLs, which are accepted by some browsers. This allows a user to be redirected to an unsafe URL unexpectedly.

Django relies on user input in some cases (e.g. django.contrib.auth.views.login(), django.contrib.comments, and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) did not correctly validate some malformed URLs, such as http:\\\djangoproject.com, which are accepted by some browsers with more liberal URL parsing.

To remedy this, the validation in is_safe_url() has been tightened to be able to handle and correctly validate these malformed URLs.

Django 1.5.7 release notes

April 28, 2014

Django 1.5.7 fixes a regression in the 1.5.6 security release.

Bugfixes

- Restored the ability to reverse() views created using functools.partial() (#22486).

Django 1.5.6 release notes

April 21, 2014

Django 1.5.6 fixes several bugs in 1.5.5, including three security issues.

Unexpected code execution using reverse()

Django’s URL handling is based on a mapping of regex patterns (representing the URLs) to callable views, and Django’s own processing consists of matching a requested URL against those patterns to determine the appropriate view to invoke.

Django also provides a convenience function – reverse() – which performs this process in the opposite direction. The reverse() function takes information about a view and returns a URL which would invoke that view. Use of reverse() is encouraged for application developers, as the output of reverse() is always based on the current URL patterns, meaning developers do not need to change other code when making changes to URLs.

One argument signature for reverse() is to pass a dotted Python path to the desired view. In this situation, Django will import the module indicated by that dotted path as part of generating the resulting URL. If such a module has import-time side effects, those side effects will occur.

Thus it is possible for an attacker to cause unexpected code execution, given the following conditions:

1. One or more views are present which construct a URL based on user input (commonly, a “next” parameter in a querystring indicating where to redirect upon successful completion of an action).

2. One or more modules are known to an attacker to exist on the server’s Python import path, which perform code execution with side effects on importing.

To remedy this, reverse() will now only accept and import dotted paths based on the view-containing modules listed in the project’s URL pattern configuration, so as to ensure that only modules the developer intended to be imported in this fashion can or will be imported.

Caching of anonymous pages could reveal CSRF token

Django includes both a caching framework and a system for preventing cross-site request forgery (CSRF) attacks. The CSRF-protection system is based on a random nonce sent to the client in a cookie which must be sent by the client on future requests and, in forms, a hidden value which must be submitted back with the form.

The caching framework includes an option to cache responses to anonymous (i.e., unauthenticated) clients.

When the first anonymous request to a given page is by a client which did not have a CSRF cookie, the cache framework will also cache the CSRF cookie and serve the same nonce to other anonymous clients who do not have a CSRF cookie. This can allow an attacker to obtain a valid CSRF cookie value and perform attacks which bypass the check for the cookie.

To remedy this, the caching framework will no longer cache such responses. The heuristic for this will be:

1. If the incoming request did not submit any cookies, and

2. If the response did send one or more cookies, and

3. If the Vary: Cookie header is set on the response, then the response will not be cached.

MySQL typecasting

The MySQL database is known to “typecast” on certain queries; for example, when querying a table which contains string values, but using a query which filters based on an integer value, MySQL will first silently coerce the strings to integers and return a result based on that.

If a query is performed without first converting values to the appropriate type, this can produce unexpected results, similar to what would occur if the query itself had been manipulated.

Django’s model field classes are aware of their own types and most such classes perform explicit conversion of query arguments to the correct database-level type before querying. However, three model field classes did not correctly convert their arguments:

- FilePathField

- GenericIPAddressField

- IPAddressField

These three fields have been updated to convert their arguments to the correct types before querying.

Additionally, developers of custom model fields are now warned via documentation to ensure their custom field classes will perform appropriate type conversions, and users of the raw() and extra() query methods – which allow the developer to supply raw SQL or SQL fragments – will be advised to ensure they perform appropriate manual type conversions prior to executing queries.

Bugfixes

- Fixed ModelBackend raising UnboundLocalError if get_user_model() raised an error (#21439).

Additionally, Django’s vendored version of six, django.utils.six, has been upgraded to the latest release (1.6.1).

Django 1.5.5 release notes

October 23, 2013

Django 1.5.5 fixes a couple security-related bugs and several other bugs in the 1.5 series.

Readdressed denial-of-service via password hashers

Django 1.5.4 imposes a 4096-byte limit on passwords in order to mitigate a denial-of-service attack through submission of bogus but extremely large passwords. In Django 1.5.5, we’ve reverted this change and instead improved the speed of our PBKDF2 algorithm by not rehashing the key on every iteration.

Properly rotate CSRF token on login

This behavior introduced as a security hardening measure in Django 1.5.2 did not work properly and is now fixed.

Bugfixes

- Fixed a data corruption bug with datetime_safe.datetime.combine (#21256).

- Fixed a Python 3 incompatibility in django.utils.text.unescape_entities() (#21185).

- Fixed a couple data corruption issues with QuerySet edge cases under Oracle and MySQL (#21203, #21126).

- Fixed crashes when using combinations of annotate(), select_related(), and only() (#16436).

Backwards incompatible changes

- The undocumented django.core.servers.basehttp.WSGIServerException has been removed. Use socket.error provided by the standard library instead.

Django 1.5.4 release notes

September 14, 2013

This is Django 1.5.4, the fourth release in the Django 1.5 series. It addresses two security issues and one bug.

Denial-of-service via password hashers

In previous versions of Django, no limit was imposed on the plaintext length of a password. This allowed a denial-of-service attack through submission of bogus but extremely large passwords, tying up server resources performing the (expensive, and increasingly expensive with the length of the password) calculation of the corresponding hash.

As of 1.5.4, Django’s authentication framework imposes a 4096-byte limit on passwords, and will fail authentication with any submitted password of greater length.

Corrected usage of sensitive_post_parameters() in django.contrib.auth’s admin

The decoration of the add_view and user_change_password user admin views with sensitive_post_parameters() did not include method_decorator() (required since the views are methods) resulting in the decorator not being properly applied. This usage has been fixed and sensitive_post_parameters() will now throw an exception if it’s improperly used.

Bugfixes

- Fixed a bug that prevented a QuerySet that uses prefetch_related() from being pickled and unpickled more than once (the second pickling attempt raised an exception) (#21102).

Django 1.5.3 release notes

September 10, 2013

This is Django 1.5.3, the third release in the Django 1.5 series. It addresses one security issue and also contains an opt-in feature to enhance the security of django.contrib.sessions.

Directory traversal vulnerability in ssi template tag

Directory traversal vulnerability in ssi template tag

In previous versions of Django it was possible to bypass the ALLOWED_INCLUDE_ROOTS setting used for security with the ssi template tag by specifying a relative path that starts with one of the allowed roots. For example, if ALLOWED_INCLUDE_ROOTS = ("/var/www",) the following would be possible:

{% ssi "/var/www/../../etc/passwd" %}

In practice this is not a very common problem, as it would require the template author to put the ssi file in a user-controlled variable, but it’s possible in principle.

Mitigating a remote-code execution vulnerability in django.contrib.sessions

django.contrib.sessions currently uses pickle to serialize session data before storing it in the backend. If you’re using the signed cookie session backend and SECRET_KEY is known by an attacker (there isn’t an inherent vulnerability in Django that would cause it to leak), the attacker could insert a string into his session which, when unpickled, executes arbitrary code on the server. The technique for doing so is simple and easily available on the internet. Although the cookie session storage signs the cookie-stored data to prevent tampering, a SECRET_KEY leak immediately escalates to a remote code execution vulnerability.

This attack can be mitigated by serializing session data using JSON rather than pickle. To facilitate this, Django 1.5.3 introduces a new setting, SESSION_SERIALIZER, to customize the session serialization format. For backwards compatibility, this setting defaults to using pickle. While JSON serialization does not support all Python objects like pickle does, we highly recommend switching to JSON-serialized values. Also, as JSON requires string keys, you will likely run into problems if you are using non-string keys in request.session. See the Session serialization documentation for more details.

Django 1.5.2 release notes

August 13, 2013

This is Django 1.5.2, a bugfix and security release for Django 1.5.

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login(), django.contrib.comments, and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) didn’t check if the scheme is http(s) and as such allowed javascript:... URLs to be entered. If a developer relied on is_safe_url() to provide safe redirect targets and put such a URL into a link, they could suffer from a XSS attack. This bug doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there.

XSS vulnerability in django.contrib.admin

If a URLField is used in Django 1.5, it displays the current value of the field and a link to the target on the admin change page. The display routine of this widget was flawed and allowed for XSS.

Bugfixes

- Fixed a crash with prefetch_related() (#19607) as well as some pickle regressions with prefetch_related (#20157 and #20257).

- Fixed a regression in django.contrib.gis in the Google Map output on Python 3 (#20773).

- Made DjangoTestSuiteRunner.setup_databases properly handle aliases for the default database (#19940) and prevented teardown_databases from attempting to tear down aliases (#20681).

- Fixed the django.core.cache.backends.memcached.MemcachedCache backend’s get_many() method on Python 3 (#20722).

- Fixed django.contrib.humanize translation syntax errors. Affected languages: Mexican Spanish, Mongolian, Romanian, Turkish (#20695).

- Added support for wheel packages (#19252).

- The CSRF token now rotates when a user logs in.

- Some Python 3 compatibility fixes including #20212 and #20025.

- Fixed some rare cases where get() exceptions recursed infinitely (#20278).

- makemessages no longer crashes with UnicodeDecodeError (#20354).

- Fixed geojson detection with Spatialite.

- assertContains() once again works with binary content (#20237).

- Fixed ManyToManyField if it has a unicode name parameter (#20207).

- Ensured that the WSGI request’s path is correctly based on the SCRIPT_NAME environment variable or the FORCE_SCRIPT_NAME setting, regardless of whether or not either has a trailing slash (#20169).

- Fixed an obscure bug with the override_settings() decorator. If you hit an AttributeError: 'Settings' object has no attribute '_original_allowed_hosts' exception, it’s probably fixed (#20636).

Django 1.5.1 release notes

March 28, 2013

This is Django 1.5.1, a bugfix release for Django 1.5. It’s completely backwards compatible with Django 1.5, but includes a handful of fixes.

The biggest fix is for a memory leak introduced in Django 1.5. Under certain circumstances, repeated iteration over querysets could leak memory - sometimes quite a bit of it. If you’d like more information, the details are in our ticket tracker (and in a related issue in Python itself).

If you’ve noticed memory problems under Django 1.5, upgrading to 1.5.1 should fix those issues.

Django 1.5.1 also includes a couple smaller fixes:

- Module-level warnings emitted during tests are no longer silently hidden (#18985).

- Prevented filtering on password hashes in the user admin (#20078).

Django 1.5 release notes

February 26, 2013

Welcome to Django 1.5!

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.4 or older versions. We’ve also dropped some features, which are detailed in our deprecation plan, and we’ve begun the deprecation process for some features.

Overview

The biggest new feature in Django 1.5 is the configurable User model. Before Django 1.5, applications that wanted to use Django’s auth framework (django.contrib.auth) were forced to use Django’s definition of a “user”. In Django 1.5, you can now swap out the User model for one that you write yourself. This could be a simple extension to the existing User model – for example, you could add a Twitter or Facebook ID field – or you could completely replace the User with one totally customized for your site.

Django 1.5 is also the first release with Python 3 support! We’re labeling this support “experimental” because we don’t yet consider it production-ready, but everything’s in place for you to start porting your apps to Python 3. Our next release, Django 1.6, will support Python 3 without reservations.

Other notable new features in Django 1.5 include:

- Support for saving a subset of model’s fields - Model.save() now accepts an update_fields argument, letting you specify which fields are written back to the database when you call save(). This can help in high-concurrency operations, and can improve performance.

- Better support for streaming responses via the new StreamingHttpResponse response class.

- GeoDjango now supports PostGIS 2.0.

- ... and more; see below.

Wherever possible we try to introduce new features in a backwards-compatible manner per our API stability policy. However, as with previous releases, Django 1.5 ships with some minor backwards incompatible changes; people upgrading from previous versions of Django should read that list carefully.

One deprecated feature worth noting is the shift to “new-style” url tag. Prior to Django 1.3, syntax like {% url myview %} was interpreted incorrectly (Django considered "myview" to be a literal name of a view, not a template variable named myview). Django 1.3 and above introduced the {% load url from future %} syntax to bring in the corrected behavior where myview was seen as a variable.

The upshot of this is that if you are not using {% load url from future %} in your templates, you’ll need to change tags like {% url myview %} to {% url "myview" %}. If you were using {% load url from future %} you can simply remove that line under Django 1.5

Python compatibility

Django 1.5 requires Python 2.6.5 or above, though we highly recommend Python 2.7.3 or above. Support for Python 2.5 and below has been dropped.

This change should affect only a small number of Django users, as most operating-system vendors today are shipping Python 2.6 or newer as their default version. If you’re still using Python 2.5, however, you’ll need to stick to Django 1.4 until you can upgrade your Python version. Per our support policy, Django 1.4 will continue to receive security support until the release of Django 1.6.

Django 1.5 does not run on a Jython final release, because Jython’s latest release doesn’t currently support Python 2.6. However, Jython currently does offer an alpha release featuring 2.7 support, and Django 1.5 supports that alpha release.

Python 3 support

Django 1.5 introduces support for Python 3 - specifically, Python 3.2 and above. This comes in the form of a single codebase; you don’t need to install a different version of Django on Python 3. This means that you can write applications targeted for just Python 2, just Python 3, or single applications that support both platforms.

However, we’re labeling this support “experimental” for now: although it’s received extensive testing via our automated test suite, it’s received very little real-world testing. We’ve done our best to eliminate bugs, but we can’t be sure we covered all possible uses of Django.

Some features of Django aren’t available because they depend on third-party software that hasn’t been ported to Python 3 yet, including:

- the MySQL database backend (depends on MySQLdb)

- ImageField (depends on PIL)

- LiveServerTestCase (depends on Selenium WebDriver)

Further, Django’s more than a web framework; it’s an ecosystem of pluggable components. At this point, very few third-party applications have been ported to Python 3, so it’s unlikely that a real-world application will have all its dependencies satisfied under Python 3.

Thus, we’re recommending that Django 1.5 not be used in production under Python 3. Instead, use this opportunity to begin porting applications to Python 3. If you’re an author of a pluggable component, we encourage you to start porting now.

We plan to offer first-class, production-ready support for Python 3 in our next release, Django 1.6.

What’s new in Django 1.5

Configurable User model

In Django 1.5, you can now use your own model as the store for user-related data. If your project needs a username with more than 30 characters, or if you want to store user’s names in a format other than first name/last name, or you want to put custom profile information onto your User object, you can now do so.

If you have a third-party reusable application that references the User model, you may need to make some changes to the way you reference User instances. You should also document any specific features of the User model that your application relies upon.

See the documentation on custom User models for more details.

Support for saving a subset of model’s fields

The method Model.save() has a new keyword argument update_fields. By using this argument it is possible to save only a select list of model’s fields. This can be useful for performance reasons or when trying to avoid overwriting concurrent changes.

Deferred instances (those loaded by .only() or .defer()) will automatically save just the loaded fields. If any field is set manually after load, that field will also get updated on save.

See the Model.save() documentation for more details.

Caching of related model instances

When traversing relations, the ORM will avoid re-fetching objects that were previously loaded. For example, with the tutorial’s models:

>>> first_poll = Poll.objects.all()[0]
>>> first_choice = first_poll.choice_set.all()[0]
>>> first_choice.poll is first_poll
True

In Django 1.5, the third line no longer triggers a new SQL query to fetch first_choice.poll; it was set by the second line.

For one-to-one relationships, both sides can be cached. For many-to-one relationships, only the single side of the relationship can be cached. This is particularly helpful in combination with prefetch_related.

Explicit support for streaming responses

Before Django 1.5, it was possible to create a streaming response by passing an iterator to HttpResponse. But this was unreliable: any middleware that accessed the content attribute would consume the iterator prematurely.

You can now explicitly generate a streaming response with the new StreamingHttpResponse class. This class exposes a streaming_content attribute which is an iterator.

Since StreamingHttpResponse does not have a content attribute, middleware that needs access to the response content must test for streaming responses and behave accordingly. See process_response() for more information.

{% verbatim %} template tag

To make it easier to deal with JavaScript templates which collide with Django’s syntax, you can now use the verbatim block tag to avoid parsing the tag’s content.

Retrieval of ContentType instances associated with proxy models

The methods ContentTypeManager.get_for_model() and ContentTypeManager.get_for_models() have a new keyword argument – respectively for_concrete_model and for_concrete_models. By passing False using this argument it is now possible to retrieve the ContentType associated with proxy models.

New view variable in class-based views context

In all generic class-based views (or any class-based view inheriting from ContextMixin), the context dictionary contains a view variable that points to the View instance.

GeoDjango

- LineString and MultiLineString GEOS objects now support the interpolate() and project() methods (so-called linear referencing).

- The wkb and hex properties of GEOSGeometry objects preserve the Z dimension.

- Support for PostGIS 2.0 has been added and support for GDAL < 1.5 has been dropped.

New tutorials

Additions to the docs include a revamped Tutorial 3 and a new tutorial on testing. A new section, “Advanced Tutorials”, offers How to write reusable apps as well as a step-by-step guide for new contributors in Writing your first patch for Django.

Minor features

Django 1.5 also includes several smaller improvements worth noting:

- The template engine now interprets True, False and None as the corresponding Python objects.

- django.utils.timezone provides a helper for converting aware datetimes between time zones. See localtime().

- The generic views support OPTIONS requests.

- Management commands do not raise SystemExit any more when called by code from call_command(). Any exception raised by the command (mostly CommandError) is propagated.

Moreover, when you output errors or messages in your custom commands, you should now use self.stdout.write('message') and self.stderr.write('error') (see the note on management commands output).

- The dumpdata management command outputs one row at a time, preventing out-of-memory errors when dumping large datasets.

- In the localflavor for Canada, “pq” was added to the acceptable codes for Quebec. It’s an old abbreviation.

- The receiver decorator is now able to connect to more than one signal by supplying a list of signals.

- In the admin, you can now filter users by groups which they are members of.

- QuerySet.bulk_create() now has a batch_size argument. By default the batch_size is unlimited except for SQLite where single batch is limited so that 999 parameters per query isn’t exceeded.

- The LOGIN_URL and LOGIN_REDIRECT_URL settings now also accept view function names and named URL patterns. This allows you to reduce configuration duplication. More information can be found in the login_required() documentation.

- Django now provides a mod_wsgi auth handler.

- The QuerySet.delete() and Model.delete() can now take fast-path in some cases. The fast-path allows for less queries and less objects fetched into memory. See QuerySet.delete() for details.

- An instance of ResolverMatch is stored on the request as resolver_match.

- By default, all logging messages reaching the django logger when DEBUG is True are sent to the console (unless you redefine the logger in your LOGGING setting).

- When using RequestContext, it is now possible to look up permissions by using {% if 'someapp.someperm' in perms %} in templates.

- It’s not required any more to have 404.html and 500.html templates in the root templates directory. Django will output some basic error messages for both situations when those templates are not found. Of course, it’s still recommended as good practice to provide those templates in order to present pretty error pages to the user.

- django.contrib.auth provides a new signal that is emitted whenever a user fails to login successfully. See user_login_failed

- The new loaddata --ignorenonexistent option ignore data for fields that no longer exist.

- assertXMLEqual() and assertXMLNotEqual() new assertions allow you to test equality for XML content at a semantic level, without caring for syntax differences (spaces, attribute order, etc.).

- RemoteUserMiddleware now forces logout when the REMOTE_USER header disappears during the same browser session.

- The cache-based session backend can store session data in a non-default cache.

- Multi-column indexes can now be created on models. Read the index_together documentation for more information.

- During Django’s logging configuration verbose Deprecation warnings are enabled and warnings are captured into the logging system. Logged warnings are routed through the console logging handler, which by default requires DEBUG to be True for output to be generated. The result is that DeprecationWarnings should be printed to the console in development environments the way they have been in Python versions < 2.7.

- The API for django.contrib.admin.ModelAdmin.message_user() method has been modified to accept additional arguments adding capabilities similar to django.contrib.messages.add_message(). This is useful for generating error messages from admin actions.

- The admin’s list filters can now be customized per-request thanks to the new django.contrib.admin.ModelAdmin.get_list_filter() method.

Backwards incompatible changes in 1.5

Warning

In addition to the changes outlined in this section, be sure to review the deprecation plan for any features that have been removed. If you haven’t updated your code within the deprecation timeline for a given feature, its removal may appear as a backwards incompatible change.

ALLOWED_HOSTS required in production

The new ALLOWED_HOSTS setting validates the request’s Host header and protects against host-poisoning attacks. This setting is now required whenever DEBUG is False, or else django.http.HttpRequest.get_host() will raise SuspiciousOperation. For more details see the full documentation for the new setting.

Managers on abstract models

Abstract models are able to define a custom manager, and that manager will be inherited by any concrete models extending the abstract model. However, if you try to use the abstract model to call a method on the manager, an exception will now be raised. Previously, the call would have been permitted, but would have failed as soon as any database operation was attempted (usually with a “table does not exist” error from the database).

If you have functionality on a manager that you have been invoking using the abstract class, you should migrate that logic to a Python staticmethod or classmethod on the abstract class.

Context in year archive class-based views

For consistency with the other date-based generic views, YearArchiveView now passes year in the context as a datetime.date rather than a string. If you are using {{ year }} in your templates, you must replace it with {{ year|date:"Y" }}.

next_year and previous_year were also added in the context. They are calculated according to allow_empty and allow_future.

Context in year and month archive class-based views

YearArchiveView and MonthArchiveView were documented to provide a date_list sorted in ascending order in the context, like their function-based predecessors, but it actually was in descending order. In 1.5, the documented order was restored. You may want to add (or remove) the reversed keyword when you’re iterating on date_list in a template:

{% for date in date_list reversed %}

ArchiveIndexView still provides a date_list in descending order.

Context in TemplateView

For consistency with the design of the other generic views, TemplateView no longer passes a params dictionary into the context, instead passing the variables from the URLconf directly into the context.

Non-form data in HTTP requests

request.POST will no longer include data posted via HTTP requests with non form-specific content-types in the header. In prior versions, data posted with content-types other than multipart/form-data or application/x-www-form-urlencoded would still end up represented in the request.POST attribute. Developers wishing to access the raw POST data for these cases, should use the request.body attribute instead.

request_finished signal

Django used to send the request_finished signal as soon as the view function returned a response. This interacted badly with streaming responses that delay content generation.

This signal is now sent after the content is fully consumed by the WSGI gateway. This might be backwards incompatible if you rely on the signal being fired before sending the response content to the client. If you do, you should consider using middleware instead.

Note

Some WSGI servers and middleware do not always call close on the response object after handling a request, most notably uWSGI prior to 1.2.6 and Sentry’s error reporting middleware up to 2.0.7. In those cases the request_finished signal isn’t sent at all. This can result in idle connections to database and memcache servers.

OPTIONS, PUT and DELETE requests in the test client

Unlike GET and POST, these HTTP methods aren’t implemented by web browsers. Rather, they’re used in APIs, which transfer data in various formats such as JSON or XML. Since such requests may contain arbitrary data, Django doesn’t attempt to decode their body.

However, the test client used to build a query string for OPTIONS and DELETE requests like for GET, and a request body for PUT requests like for POST. This encoding was arbitrary and inconsistent with Django’s behavior when it receives the requests, so it was removed in Django 1.5.

If you were using the data parameter in an OPTIONS or a DELETE request, you must convert it to a query string and append it to the path parameter.

If you were using the data parameter in a PUT request without a content_type, you must encode your data before passing it to the test client and set the content_type argument.

System version of simplejson no longer used

As explained below, Django 1.5 deprecates django.utils.simplejson in favor of Python 2.6’s built-in json module. In theory, this change is harmless. Unfortunately, because of incompatibilities between versions of simplejson, it may trigger errors in some circumstances.

JSON-related features in Django 1.4 always used django.utils.simplejson. This module was actually:

- A system version of simplejson, if one was available (ie. import simplejson works), if it was more recent than Django’s built-in copy or it had the C speedups, or

- The json module from the standard library, if it was available (ie. Python 2.6 or greater), or

- A built-in copy of version 2.0.7 of simplejson.

In Django 1.5, those features use Python’s json module, which is based on version 2.0.9 of simplejson.

There are no known incompatibilities between Django’s copy of version 2.0.7 and Python’s copy of version 2.0.9. However, there are some incompatibilities between other versions of simplejson:

- While the simplejson API is documented as always returning unicode strings, the optional C implementation can return a byte string. This was fixed in Python 2.7.

- simplejson.JSONEncoder gained a namedtuple_as_object keyword argument in version 2.2.

More information on these incompatibilities is available in ticket #18023.

The net result is that, if you have installed simplejson and your code uses Django’s serialization internals directly – for instance django.core.serializers.json.DjangoJSONEncoder, the switch from simplejson to json could break your code. (In general, changes to internals aren’t documented; we’re making an exception here.)

At this point, the maintainers of Django believe that using json from the standard library offers the strongest guarantee of backwards-compatibility. They recommend to use it from now on.

String types of hasher method parameters

If you have written a custom password hasher, your encode(), verify() or safe_summary() methods should accept Unicode parameters (password, salt or encoded). If any of the hashing methods need byte strings, you can use the force_bytes() utility to encode the strings.

Validation of previous_page_number and next_page_number

When using object pagination, the previous_page_number() and next_page_number() methods of the Page object did not check if the returned number was inside the existing page range. It does check it now and raises an InvalidPage exception when the number is either too low or too high.

Behavior of autocommit database option on PostgreSQL changed

PostgreSQL’s autocommit option didn’t work as advertised previously. It did work for single transaction block, but after the first block was left the autocommit behavior was never restored. This bug is now fixed in 1.5. While this is only a bug fix, it is worth checking your applications behavior if you are using PostgreSQL together with the autocommit option.

Session not saved on 500 responses

Django’s session middleware will skip saving the session data if the response’s status code is 500.

Email checks on failed admin login

Prior to Django 1.5, if you attempted to log into the admin interface and mistakenly used your email address instead of your username, the admin interface would provide a warning advising that your email address was not your username. In Django 1.5, the introduction of custom User models has required the removal of this warning. This doesn’t change the login behavior of the admin site; it only affects the warning message that is displayed under one particular mode of login failure.

Changes in tests execution

Some changes have been introduced in the execution of tests that might be backward-incompatible for some testing setups:

Database flushing in django.test.TransactionTestCase

Previously, the test database was truncated before each test run in a TransactionTestCase.

In order to be able to run unit tests in any order and to make sure they are always isolated from each other, TransactionTestCase will now reset the database after each test run instead.

No more implicit DB sequences reset

TransactionTestCase tests used to reset primary key sequences automatically together with the database flushing actions described above.

This has been changed so no sequences are implicitly reset. This can cause TransactionTestCase tests that depend on hard-coded primary key values to break.

The new reset_sequences attribute can be used to force the old behavior for TransactionTestCase that might need it.

Ordering of tests

In order to make sure all TestCase code starts with a clean database, tests are now executed in the following order:

- First, all unittests (including unittest.TestCase, SimpleTestCase, TestCase and TransactionTestCase) are run with no particular ordering guaranteed nor enforced among them.

- Then any other tests (e.g. doctests) that may alter the database without restoring it to its original state are run.

This should not cause any problems unless you have existing doctests which assume a TransactionTestCase executed earlier left some database state behind or unit tests that rely on some form of state being preserved after the execution of other tests. Such tests are already very fragile, and must now be changed to be able to run independently.

cleaned_data dictionary kept for invalid forms

The cleaned_data dictionary is now always present after form validation. When the form doesn’t validate, it contains only the fields that passed validation. You should test the success of the validation with the is_valid() method and not with the presence or absence of the cleaned_data attribute on the form.

Behavior of syncdb with multiple databases

syncdb now queries the database routers to determine if content types (when contenttypes is enabled) and permissions (when auth is enabled) should be created in the target database. Previously, it created them in the default database, even when another database was specified with the --database option.

If you use syncdb on multiple databases, you should ensure that your routers allow synchronizing content types and permissions to only one of them. See the docs on the behavior of contrib apps with multiple databases for more information.

XML deserializer will not parse documents with a DTD

In order to prevent exposure to denial-of-service attacks related to external entity references and entity expansion, the XML model deserializer now refuses to parse XML documents containing a DTD (DOCTYPE definition). Since the XML serializer does not output a DTD, this will not impact typical usage, only cases where custom-created XML documents are passed to Django’s model deserializer.

Formsets default max_num

A (default) value of None for the max_num argument to a formset factory no longer defaults to allowing any number of forms in the formset. Instead, in order to prevent memory-exhaustion attacks, it now defaults to a limit of 1000 forms. This limit can be raised by explicitly setting a higher value for max_num.

Miscellaneous

- django.forms.ModelMultipleChoiceField now returns an empty QuerySet as the empty value instead of an empty list.

- int_to_base36() properly raises a TypeError instead of ValueError for non-integer inputs.

- The slugify template filter is now available as a standard python function at django.utils.text.slugify(). Similarly, remove_tags is available at django.utils.html.remove_tags().

- Uploaded files are no longer created as executable by default. If you need them to be executable change FILE_UPLOAD_PERMISSIONS to your needs. The new default value is 0o666 (octal) and the current umask value is first masked out.

- The F expressions supported bitwise operators by & and |. These operators are now available using .bitand() and .bitor() instead. The removal of & and | was done to be consistent with Q() expressions and QuerySet combining where the operators are used as boolean AND and OR operators.

- In a filter() call, when F expressions contained lookups spanning multi-valued relations, they didn’t always reuse the same relations as other lookups along the same chain. This was changed, and now F() expressions will always use the same relations as other lookups within the same filter() call.

- The csrf_token template tag is no longer enclosed in a div. If you need HTML validation against pre-HTML5 Strict DTDs, you should add a div around it in your pages.

- The template tags library adminmedia, which only contained the deprecated template tag {% admin_media_prefix %}, was removed. Attempting to load it with {% load adminmedia %} will fail. If your templates still contain that line you must remove it.

- Because of an implementation oversight, it was possible to use django.contrib.redirects without enabling django.contrib.sites. This isn’t allowed any longer. If you’re using django.contrib.redirects, make sure INSTALLED_APPS contains django.contrib.sites.

- BoundField.label_tag now escapes its contents argument. To avoid the HTML escaping, use django.utils.safestring.mark_safe() on the argument before passing it.

- Accessing reverse one-to-one relations fetched via select_related() now raises DoesNotExist instead of returning None.

Features deprecated in 1.5

django.contrib.localflavor

The localflavor contrib app has been split into separate packages. django.contrib.localflavor itself will be removed in Django 1.6, after an accelerated deprecation.

The new packages are available on GitHub. The core team cannot efficiently maintain these packages in the long term — it spans just a dozen countries at this time; similar to translations, maintenance will be handed over to interested members of the community.

django.contrib.markup

The markup contrib module has been deprecated and will follow an accelerated deprecation schedule. Direct use of Python markup libraries or 3rd party tag libraries is preferred to Django maintaining this functionality in the framework.

AUTH_PROFILE_MODULE

With the introduction of custom User models, there is no longer any need for a built-in mechanism to store user profile data.

You can still define user profiles models that have a one-to-one relation with the User model - in fact, for many applications needing to associate data with a User account, this will be an appropriate design pattern to follow. However, the AUTH_PROFILE_MODULE setting, and the django.contrib.auth.models.User.get_profile() method for accessing the user profile model, should not be used any longer.

Streaming behavior of HttpResponse

Django 1.5 deprecates the ability to stream a response by passing an iterator to HttpResponse. If you rely on this behavior, switch to StreamingHttpResponse. See Explicit support for streaming responses above.

In Django 1.7 and above, the iterator will be consumed immediately by HttpResponse.

django.utils.simplejson

Since Django 1.5 drops support for Python 2.5, we can now rely on the json module being available in Python’s standard library, so we’ve removed our own copy of simplejson. You should now import json instead of django.utils.simplejson.

Unfortunately, this change might have unwanted side-effects, because of incompatibilities between versions of simplejson – see the backwards-incompatible changes section. If you rely on features added to simplejson after it became Python’s json, you should import simplejson explicitly.

django.utils.encoding.StrAndUnicode

The django.utils.encoding.StrAndUnicode mix-in has been deprecated. Define a __str__ method and apply the python_2_unicode_compatible() decorator instead.

django.utils.itercompat.product

The django.utils.itercompat.product function has been deprecated. Use the built-in itertools.product() instead.

cleanup management command

The cleanup management command has been deprecated and replaced by clearsessions.

daily_cleanup.py script

The undocumented daily_cleanup.py script has been deprecated. Use the clearsessions management command instead.

depth keyword argument in select_related

The depth keyword argument in select_related() has been deprecated. You should use field names instead.

Django 1.4.22 release notes

August 18, 2015

Django 1.4.22 fixes a security issue in 1.4.21.

It also fixes support with pip 7+ by disabling wheel support. Older versions of 1.4 would silently build a broken wheel when installed with those versions of pip.

Denial-of-service possibility in logout() view by filling session store

Previously, a session could be created when anonymously accessing the django.contrib.auth.views.logout() view (provided it wasn’t decorated with login_required() as done in the admin). This could allow an attacker to easily create many new session records by sending repeated requests, potentially filling up the session store or causing other users’ session records to be evicted.

The SessionMiddleware has been modified to no longer create empty session records, including when SESSION_SAVE_EVERY_REQUEST is active.

Additionally, the contrib.sessions.backends.base.SessionBase.flush() and cache_db.SessionStore.flush() methods have been modified to avoid creating a new empty session. Maintainers of third-party session backends should check if the same vulnerability is present in their backend and correct it if so.

Django 1.4.21 release notes

July 8, 2015

Django 1.4.21 fixes several security issues in 1.4.20.

Denial-of-service possibility by filling session store

In previous versions of Django, the session backends created a new empty record in the session storage anytime request.session was accessed and there was a session key provided in the request cookies that didn’t already have a session record. This could allow an attacker to easily create many new session records simply by sending repeated requests with unknown session keys, potentially filling up the session store or causing other users’ session records to be evicted.

The built-in session backends now create a session record only if the session is actually modified; empty session records are not created. Thus this potential DoS is now only possible if the site chooses to expose a session-modifying view to anonymous users.

As each built-in session backend was fixed separately (rather than a fix in the core sessions framework), maintainers of third-party session backends should check whether the same vulnerability is present in their backend and correct it if so.

Header injection possibility since validators accept newlines in input

Some of Django’s built-in validators (EmailValidator, most seriously) didn’t prohibit newline characters (due to the usage of $ instead of \Z in the regular expressions). If you use values with newlines in HTTP response or email headers, you can suffer from header injection attacks. Django itself isn’t vulnerable because HttpResponse and the mail sending utilities in django.core.mail prohibit newlines in HTTP and SMTP headers, respectively. While the validators have been fixed in Django, if you’re creating HTTP responses or email messages in other ways, it’s a good idea to ensure that those methods prohibit newlines as well. You might also want to validate that any existing data in your application doesn’t contain unexpected newlines.

validate_ipv4_address(), validate_slug(), and URLValidator and their usage in the corresponding form fields GenericIPAddresseField, IPAddressField, SlugField, and URLField are also affected.

The undocumented, internally unused validate_integer() function is now stricter as it validates using a regular expression instead of simply casting the value using int() and checking if an exception was raised.

Django 1.4.20 release notes

March 18, 2015

Django 1.4.20 fixes one security issue in 1.4.19.

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) accepted URLs with leading control characters and so considered URLs like \x08javascript:... safe. This issue doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there. Browsers we tested also treat URLs prefixed with control characters such as %08//example.com as relative paths so redirection to an unsafe target isn’t a problem either.

However, if a developer relies on is_safe_url() to provide safe redirect targets and puts such a URL into a link, they could suffer from an XSS attack as some browsers such as Google Chrome ignore control characters at the start of a URL in an anchor href.

Django 1.4.19 release notes

January 27, 2015

Django 1.4.19 fixes a regression in the 1.4.18 security release.

Bugfixes

- GZipMiddleware now supports streaming responses. As part of the 1.4.18 security release, the django.views.static.serve() function was altered to stream the files it serves. Unfortunately, the GZipMiddleware consumed the stream prematurely and prevented files from being served properly (#24158).

Django 1.4.18 release notes

January 13, 2015

Django 1.4.18 fixes several security issues in 1.4.17 as well as a regression on Python 2.5 in the 1.4.17 release.

WSGI header spoofing via underscore/dash conflation

When HTTP headers are placed into the WSGI environ, they are normalized by converting to uppercase, converting all dashes to underscores, and prepending HTTP_. For instance, a header X-Auth-User would become HTTP_X_AUTH_USER in the WSGI environ (and thus also in Django’s request.META dictionary).

Unfortunately, this means that the WSGI environ cannot distinguish between headers containing dashes and headers containing underscores: X-Auth-User and X-Auth_User both become HTTP_X_AUTH_USER. This means that if a header is used in a security-sensitive way (for instance, passing authentication information along from a front-end proxy), even if the proxy carefully strips any incoming value for X-Auth-User, an attacker may be able to provide an X-Auth_User header (with underscore) and bypass this protection.

In order to prevent such attacks, both Nginx and Apache 2.4+ strip all headers containing underscores from incoming requests by default. Django’s built-in development server now does the same. Django’s development server is not recommended for production use, but matching the behavior of common production servers reduces the surface area for behavior changes during deployment.

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login() and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) didn’t strip leading whitespace on the tested URL and as such considered URLs like \njavascript:... safe. If a developer relied on is_safe_url() to provide safe redirect targets and put such a URL into a link, they could suffer from a XSS attack. This bug doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there.

Denial-of-service attack against django.views.static.serve

In older versions of Django, the django.views.static.serve() view read the files it served one line at a time. Therefore, a big file with no newlines would result in memory usage equal to the size of that file. An attacker could exploit this and launch a denial-of-service attack by simultaneously requesting many large files. This view now reads the file in chunks to prevent large memory usage.

Note, however, that this view has always carried a warning that it is not hardened for production use and should be used only as a development aid. Now may be a good time to audit your project and serve your files in production using a real front-end web server if you are not doing so.

Bugfixes

- To maintain compatibility with Python 2.5, Django’s vendored version of six, django.utils.six, has been downgraded to 1.8.0 which is the last version to support Python 2.5.

Django 1.4.17 release notes

January 2, 2015

Django 1.4.17 fixes a regression in the 1.4.14 security release.

Additionally, Django’s vendored version of six, django.utils.six, has been upgraded to the latest release (1.9.0).

Bugfixes

- Fixed a regression with dynamically generated inlines and allowed field references in the admin (#23754).

Django 1.4.16 release notes

October 22, 2014

Django 1.4.16 fixes a couple regressions in the 1.4.14 security release and a bug preventing the use of some GEOS versions with GeoDjango.

Bugfixes

- Allowed related many-to-many fields to be referenced in the admin (#23604).

- Allowed inline and hidden references to admin fields (#23431).

- Fixed parsing of the GEOS version string (#20036).

Django 1.4.15 release notes

September 2, 2014

Django 1.4.15 fixes a regression in the 1.4.14 security release.

Bugfixes

- Allowed inherited and m2m fields to be referenced in the admin (#22486)

Django 1.4.14 release notes

August 20, 2014

Django 1.4.14 fixes several security issues in 1.4.13.

reverse() could generate URLs pointing to other hosts

In certain situations, URL reversing could generate scheme-relative URLs (URLs starting with two slashes), which could unexpectedly redirect a user to a different host. An attacker could exploit this, for example, by redirecting users to a phishing site designed to ask for user’s passwords.

To remedy this, URL reversing now ensures that no URL starts with two slashes (//), replacing the second slash with its URL encoded counterpart (%2F). This approach ensures that semantics stay the same, while making the URL relative to the domain and not to the scheme.

File upload denial-of-service

Before this release, Django’s file upload handing in its default configuration may degrade to producing a huge number of os.stat() system calls when a duplicate filename is uploaded. Since stat() may invoke IO, this may produce a huge data-dependent slowdown that slowly worsens over time. The net result is that given enough time, a user with the ability to upload files can cause poor performance in the upload handler, eventually causing it to become very slow simply by uploading 0-byte files. At this point, even a slow network connection and few HTTP requests would be all that is necessary to make a site unavailable.

We’ve remedied the issue by changing the algorithm for generating file names if a file with the uploaded name already exists. Storage.get_available_name() now appends an underscore plus a random 7 character alphanumeric string (e.g. "_x3a1gho"), rather than iterating through an underscore followed by a number (e.g. "_1", "_2", etc.).

RemoteUserMiddleware session hijacking

When using the RemoteUserMiddleware and the RemoteUserBackend, a change to the REMOTE_USER header between requests without an intervening logout could result in the prior user’s session being co-opted by the subsequent user. The middleware now logs the user out on a failed login attempt.

Data leakage via query string manipulation in contrib.admin

In older versions of Django it was possible to reveal any field’s data by modifying the “popup” and “to_field” parameters of the query string on an admin change form page. For example, requesting a URL like /admin/auth/user/?pop=1&t=password and viewing the page’s HTML allowed viewing the password hash of each user. While the admin requires users to have permissions to view the change form pages in the first place, this could leak data if you rely on users having access to view only certain fields on a model.

To address the issue, an exception will now be raised if a to_field value that isn’t a related field to a model that has been registered with the admin is specified.

Django 1.4.13 release notes

May 14, 2014

Django 1.4.13 fixes two security issues in 1.4.12.

Caches may incorrectly be allowed to store and serve private data

In certain situations, Django may allow caches to store private data related to a particular session and then serve that data to requests with a different session, or no session at all. This can lead to information disclosure and can be a vector for cache poisoning.

When using Django sessions, Django will set a Vary: Cookie header to ensure caches do not serve cached data to requests from other sessions. However, older versions of Internet Explorer (most likely only Internet Explorer 6, and Internet Explorer 7 if run on Windows XP or Windows Server 2003) are unable to handle the Vary header in combination with many content types. Therefore, Django would remove the header if the request was made by Internet Explorer.

To remedy this, the special behavior for these older Internet Explorer versions has been removed, and the Vary header is no longer stripped from the response. In addition, modifications to the Cache-Control header for all Internet Explorer requests with a Content-Disposition header have also been removed as they were found to have similar issues.

Malformed redirect URLs from user input not correctly validated

The validation for redirects did not correctly validate some malformed URLs, which are accepted by some browsers. This allows a user to be redirected to an unsafe URL unexpectedly.

Django relies on user input in some cases (e.g. django.contrib.auth.views.login(), django.contrib.comments, and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) did not correctly validate some malformed URLs, such as http:\\\djangoproject.com, which are accepted by some browsers with more liberal URL parsing.

To remedy this, the validation in is_safe_url() has been tightened to be able to handle and correctly validate these malformed URLs.

Django 1.4.12 release notes

April 28, 2014

Django 1.4.12 fixes a regression in the 1.4.11 security release.

Bugfixes

- Restored the ability to reverse() views created using functools.partial() (#22486)

Django 1.4.11 release notes

April 21, 2014

Django 1.4.11 fixes three security issues in 1.4.10. Additionally, Django’s vendored version of six, django.utils.six, has been upgraded to the latest release (1.6.1).

Unexpected code execution using reverse()

Django’s URL handling is based on a mapping of regex patterns (representing the URLs) to callable views, and Django’s own processing consists of matching a requested URL against those patterns to determine the appropriate view to invoke.

Django also provides a convenience function – reverse() – which performs this process in the opposite direction. The reverse() function takes information about a view and returns a URL which would invoke that view. Use of reverse() is encouraged for application developers, as the output of reverse() is always based on the current URL patterns, meaning developers do not need to change other code when making changes to URLs.

One argument signature for reverse() is to pass a dotted Python path to the desired view. In this situation, Django will import the module indicated by that dotted path as part of generating the resulting URL. If such a module has import-time side effects, those side effects will occur.

Thus it is possible for an attacker to cause unexpected code execution, given the following conditions:

1. One or more views are present which construct a URL based on user input (commonly, a “next” parameter in a querystring indicating where to redirect upon successful completion of an action).

2. One or more modules are known to an attacker to exist on the server’s Python import path, which perform code execution with side effects on importing.

To remedy this, reverse() will now only accept and import dotted paths based on the view-containing modules listed in the project’s URL pattern configuration, so as to ensure that only modules the developer intended to be imported in this fashion can or will be imported.

Caching of anonymous pages could reveal CSRF token

Django includes both a caching framework and a system for preventing cross-site request forgery (CSRF) attacks. The CSRF-protection system is based on a random nonce sent to the client in a cookie which must be sent by the client on future requests and, in forms, a hidden value which must be submitted back with the form.

The caching framework includes an option to cache responses to anonymous (i.e., unauthenticated) clients.

When the first anonymous request to a given page is by a client which did not have a CSRF cookie, the cache framework will also cache the CSRF cookie and serve the same nonce to other anonymous clients who do not have a CSRF cookie. This can allow an attacker to obtain a valid CSRF cookie value and perform attacks which bypass the check for the cookie.

To remedy this, the caching framework will no longer cache such responses. The heuristic for this will be:

1. If the incoming request did not submit any cookies, and

2. If the response did send one or more cookies, and

3. If the Vary: Cookie header is set on the response, then the response will not be cached.

MySQL typecasting

The MySQL database is known to “typecast” on certain queries; for example, when querying a table which contains string values, but using a query which filters based on an integer value, MySQL will first silently coerce the strings to integers and return a result based on that.

If a query is performed without first converting values to the appropriate type, this can produce unexpected results, similar to what would occur if the query itself had been manipulated.

Django’s model field classes are aware of their own types and most such classes perform explicit conversion of query arguments to the correct database-level type before querying. However, three model field classes did not correctly convert their arguments:

- FilePathField

- GenericIPAddressField

- IPAddressField

These three fields have been updated to convert their arguments to the correct types before querying.

Additionally, developers of custom model fields are now warned via documentation to ensure their custom field classes will perform appropriate type conversions, and users of the raw() and extra() query methods – which allow the developer to supply raw SQL or SQL fragments – will be advised to ensure they perform appropriate manual type conversions prior to executing queries.

Django 1.4.10 release notes

November 6, 2013

Django 1.4.10 fixes a Python-compatibility bug in the 1.4 series.

Python compatibility

Django 1.4.9 inadvertently introduced issues with Python 2.5 compatibility. Django 1.4.10 restores Python 2.5 compatibility. This was issue #21362 in Django’s Trac.

Django 1.4.9 release notes

October 23, 2013

Django 1.4.9 fixes a security-related bug in the 1.4 series and one other data corruption bug.

Readdressed denial-of-service via password hashers

Django 1.4.8 imposes a 4096-byte limit on passwords in order to mitigate a denial-of-service attack through submission of bogus but extremely large passwords. In Django 1.4.9, we’ve reverted this change and instead improved the speed of our PBKDF2 algorithm by not rehashing the key on every iteration.

Bugfixes

- Fixed a data corruption bug with datetime_safe.datetime.combine (#21256).

Django 1.4.8 release notes

September 14, 2013

Django 1.4.8 fixes two security issues present in previous Django releases in the 1.4 series.

Denial-of-service via password hashers

In previous versions of Django, no limit was imposed on the plaintext length of a password. This allowed a denial-of-service attack through submission of bogus but extremely large passwords, tying up server resources performing the (expensive, and increasingly expensive with the length of the password) calculation of the corresponding hash.

As of 1.4.8, Django’s authentication framework imposes a 4096-byte limit on passwords and will fail authentication with any submitted password of greater length.

Corrected usage of sensitive_post_parameters() in django.contrib.auth’s admin

The decoration of the add_view and user_change_password user admin views with sensitive_post_parameters() did not include method_decorator() (required since the views are methods) resulting in the decorator not being properly applied. This usage has been fixed and sensitive_post_parameters() will now throw an exception if it’s improperly used.

Django 1.4.7 release notes

September 10, 2013

Django 1.4.7 fixes one security issue present in previous Django releases in the 1.4 series.

Directory traversal vulnerability in ssi template tag

Directory traversal vulnerability in ssi template tag

In previous versions of Django it was possible to bypass the ALLOWED_INCLUDE_ROOTS setting used for security with the ssi template tag by specifying a relative path that starts with one of the allowed roots. For example, if ALLOWED_INCLUDE_ROOTS = ("/var/www",) the following would be possible:

{% ssi "/var/www/../../etc/passwd" %}

In practice this is not a very common problem, as it would require the template author to put the ssi file in a user-controlled variable, but it’s possible in principle.

Django 1.4.6 release notes

August 13, 2013

Django 1.4.6 fixes one security issue present in previous Django releases in the 1.4 series, as well as one other bug.

This is the sixth bugfix/security release in the Django 1.4 series.

Mitigated possible XSS attack via user-supplied redirect URLs

Django relies on user input in some cases (e.g. django.contrib.auth.views.login(), django.contrib.comments, and i18n) to redirect the user to an “on success” URL. The security checks for these redirects (namely django.utils.http.is_safe_url()) didn’t check if the scheme is http(s) and as such allowed javascript:... URLs to be entered. If a developer relied on is_safe_url() to provide safe redirect targets and put such a URL into a link, they could suffer from a XSS attack. This bug doesn’t affect Django currently, since we only put this URL into the Location response header and browsers seem to ignore JavaScript there.

Bugfixes

- Fixed an obscure bug with the override_settings() decorator. If you hit an AttributeError: 'Settings' object has no attribute '_original_allowed_hosts' exception, it’s probably fixed (#20636).

Django 1.4.5 release notes

February 20, 2013

Django 1.4.5 corrects a packaging problem with yesterday’s 1.4.4 release.

The release contained stray .pyc files that caused “bad magic number” errors when running with some versions of Python. This releases corrects this, and also fixes a bad documentation link in the project template settings.py file generated by manage.py startproject.

Django 1.4.4 release notes

February 19, 2013

Django 1.4.4 fixes four security issues present in previous Django releases in the 1.4 series, as well as several other bugs and numerous documentation improvements.

This is the fourth bugfix/security release in the Django 1.4 series.

Host header poisoning

Some parts of Django – independent of end-user-written applications – make use of full URLs, including domain name, which are generated from the HTTP Host header. Django’s documentation has for some time contained notes advising users on how to configure webservers to ensure that only valid Host headers can reach the Django application. However, it has been reported to us that even with the recommended webserver configurations there are still techniques available for tricking many common webservers into supplying the application with an incorrect and possibly malicious Host header.

For this reason, Django 1.4.4 adds a new setting, ALLOWED_HOSTS, containing an explicit list of valid host/domain names for this site. A request with a Host header not matching an entry in this list will raise SuspiciousOperation if request.get_host() is called. For full details see the documentation for the ALLOWED_HOSTS setting.

The default value for this setting in Django 1.4.4 is ['*'] (matching any host), for backwards-compatibility, but we strongly encourage all sites to set a more restrictive value.

This host validation is disabled when DEBUG is True or when running tests.

XML deserialization

The XML parser in the Python standard library is vulnerable to a number of attacks via external entities and entity expansion. Django uses this parser for deserializing XML-formatted database fixtures. This deserializer is not intended for use with untrusted data, but in order to err on the side of safety in Django 1.4.4 the XML deserializer refuses to parse an XML document with a DTD (DOCTYPE definition), which closes off these attack avenues.

These issues in the Python standard library are CVE-2013-1664 and CVE-2013-1665. More information available from the Python security team.

Django’s XML serializer does not create documents with a DTD, so this should not cause any issues with the typical round-trip from dumpdata to loaddata, but if you feed your own XML documents to the loaddata management command, you will need to ensure they do not contain a DTD.

Formset memory exhaustion

Previous versions of Django did not validate or limit the form-count data provided by the client in a formset’s management form, making it possible to exhaust a server’s available memory by forcing it to create very large numbers of forms.

In Django 1.4.4, all formsets have a strictly-enforced maximum number of forms (1000 by default, though it can be set higher via the max_num formset factory argument).

Admin history view information leakage

In previous versions of Django, an admin user without change permission on a model could still view the unicode representation of instances via their admin history log. Django 1.4.4 now limits the admin history log view for an object to users with change permission for that model.

Other bugfixes and changes

- Prevented transaction state from leaking from one request to the next (#19707).

- Changed an SQL command syntax to be MySQL 4 compatible (#19702).

- Added backwards-compatibility with old unsalted MD5 passwords (#18144).

- Numerous documentation improvements and fixes.

Django 1.4.3 release notes

December 10, 2012

Django 1.4.3 addresses two security issues present in previous Django releases in the 1.4 series.

Please be aware that this security release is slightly different from previous ones. Both issues addressed here have been dealt with in prior security updates to Django. In one case, we have received ongoing reports of problems, and in the other we’ve chosen to take further steps to tighten up Django’s code in response to independent discovery of potential problems from multiple sources.

Host header poisoning

Several earlier Django security releases focused on the issue of poisoning the HTTP Host header, causing Django to generate URLs pointing to arbitrary, potentially-malicious domains.

In response to further input received and reports of continuing issues following the previous release, we’re taking additional steps to tighten Host header validation. Rather than attempt to accommodate all features HTTP supports here, Django’s Host header validation attempts to support a smaller, but far more common, subset:

- Hostnames must consist of characters [A-Za-z0-9] plus hyphen (‘-‘) or dot (‘.’).

- IP addresses – both IPv4 and IPv6 – are permitted.

- Port, if specified, is numeric.

Any deviation from this will now be rejected, raising the exception django.core.exceptions.SuspiciousOperation.

Redirect poisoning

Also following up on a previous issue: in July of this year, we made changes to Django’s HTTP redirect classes, performing additional validation of the scheme of the URL to redirect to (since, both within Django’s own supplied applications and many third-party applications, accepting a user-supplied redirect target is a common pattern).

Since then, two independent audits of the code turned up further potential problems. So, similar to the Host-header issue, we are taking steps to provide tighter validation in response to reported problems (primarily with third-party applications, but to a certain extent also within Django itself). This comes in two parts:

1. A new utility function, django.utils.http.is_safe_url, is added; this function takes a URL and a hostname, and checks that the URL is either relative, or if absolute matches the supplied hostname. This function is intended for use whenever user-supplied redirect targets are accepted, to ensure that such redirects cannot lead to arbitrary third-party sites.

2. All of Django’s own built-in views – primarily in the authentication system – which allow user-supplied redirect targets now use is_safe_url to validate the supplied URL.

Django 1.4.2 release notes

October 17, 2012

This is the second security release in the Django 1.4 series.

Host header poisoning

Some parts of Django – independent of end-user-written applications – make use of full URLs, including domain name, which are generated from the HTTP Host header. Some attacks against this are beyond Django’s ability to control, and require the web server to be properly configured; Django’s documentation has for some time contained notes advising users on such configuration.

Django’s own built-in parsing of the Host header is, however, still vulnerable, as was reported to us recently. The Host header parsing in Django 1.3.3 and Django 1.4.1 – specifically, django.http.HttpRequest.get_host() – was incorrectly handling username/password information in the header. Thus, for example, the following Host header would be accepted by Django when running on “validsite.com”:

Host: validsite.com:random@evilsite.com

Using this, an attacker can cause parts of Django – particularly the password-reset mechanism – to generate and display arbitrary URLs to users.

To remedy this, the parsing in HttpRequest.get_host() is being modified; Host headers which contain potentially dangerous content (such as username/password pairs) now raise the exception django.core.exceptions.SuspiciousOperation.

Details of this issue were initially posted online as a security advisory.

Backwards incompatible changes

- The newly introduced GenericIPAddressField constructor arguments have been adapted to match those of all other model fields. The first two keyword arguments are now verbose_name and name.

Other bugfixes and changes

- Subclass HTMLParser only for appropriate Python versions (#18239).

- Added batch_size argument to qs.bulk_create() (#17788).

- Fixed a small regression in the admin filters where wrongly formatted dates passed as url parameters caused an unhandled ValidationError (#18530).

- Fixed an endless loop bug when accessing permissions in templates (#18979)

- Fixed some Python 2.5 compatibility issues

- Fixed an issue with quoted filenames in Content-Disposition header (#19006)

- Made the context option in trans and blocktrans tags accept literals wrapped in single quotes (#18881).

- Numerous documentation improvements and fixes.

Django 1.4.1 release notes

July 30, 2012

This is the first security release in the Django 1.4 series, fixing several security issues in Django 1.4. Django 1.4.1 is a recommended upgrade for all users of Django 1.4.

For a full list of issues addressed in this release, see the security advisory.

Django 1.4 release notes

March 23, 2012

Welcome to Django 1.4!

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.3 or older versions. We’ve also dropped some features, which are detailed in our deprecation plan, and we’ve begun the deprecation process for some features.

Overview

The biggest new feature in Django 1.4 is support for time zones when handling date/times. When enabled, this Django will store date/times in UTC, use timezone-aware objects internally, and translate them to users’ local timezones for display.

If you’re upgrading an existing project to Django 1.4, switching to the time- zone aware mode may take some care: the new mode disallows some rather sloppy behavior that used to be accepted. We encourage anyone who’s upgrading to check out the timezone migration guide and the timezone FAQ for useful pointers.

Other notable new features in Django 1.4 include:

- A number of ORM improvements, including SELECT FOR UPDATE support, the ability to bulk insert large datasets for improved performance, and QuerySet.prefetch_related, a method to batch-load related objects in areas where select_related() doesn’t work.

- Some nice security additions, including improved password hashing (featuring PBKDF2 and bcrypt support), new tools for cryptographic signing, several CSRF improvements, and simple clickjacking protection.

- An updated default project layout and manage.py that removes the “magic” from prior versions. And for those who don’t like the new layout, you can use custom project and app templates instead!

- Support for in-browser testing frameworks (like Selenium).

- ... and a whole lot more; see below!

Wherever possible we try to introduce new features in a backwards-compatible manner per our API stability policy policy. However, as with previous releases, Django 1.4 ships with some minor backwards incompatible changes; people upgrading from previous versions of Django should read that list carefully.

Python compatibility

Django 1.4 has dropped support for Python 2.4. Python 2.5 is now the minimum required Python version. Django is tested and supported on Python 2.5, 2.6 and 2.7.

This change should affect only a small number of Django users, as most operating-system vendors today are shipping Python 2.5 or newer as their default version. If you’re still using Python 2.4, however, you’ll need to stick to Django 1.3 until you can upgrade. Per our support policy, Django 1.3 will continue to receive security support until the release of Django 1.5.

Django does not support Python 3.x at this time. At some point before the release of Django 1.4, we plan to publish a document outlining our full timeline for deprecating Python 2.x and moving to Python 3.x.

What’s new in Django 1.4

Support for time zones

In previous versions, Django used “naive” date/times (that is, date/times without an associated time zone), leaving it up to each developer to interpret what a given date/time “really means”. This can cause all sorts of subtle timezone-related bugs.

In Django 1.4, you can now switch Django into a more correct, time-zone aware mode. In this mode, Django stores date and time information in UTC in the database, uses time-zone-aware datetime objects internally and translates them to the end user’s time zone in templates and forms. Reasons for using this feature include:

- Customizing date and time display for users around the world.

- Storing datetimes in UTC for database portability and interoperability. (This argument doesn’t apply to PostgreSQL, because it already stores timestamps with time zone information in Django 1.3.)

- Avoiding data corruption problems around DST transitions.

Time zone support is enabled by default in new projects created with startproject. If you want to use this feature in an existing project, read the migration guide. If you encounter problems, there’s a helpful FAQ.

Support for in-browser testing frameworks

Django 1.4 supports integration with in-browser testing frameworks like Selenium. The new django.test.LiveServerTestCase base class lets you test the interactions between your site’s front and back ends more comprehensively. See the documentation for more details and concrete examples.

Updated default project layout and manage.py

Django 1.4 ships with an updated default project layout and manage.py file for the startproject management command. These fix some issues with the previous manage.py handling of Python import paths that caused double imports, trouble moving from development to deployment, and other difficult-to-debug path issues.

The previous manage.py called functions that are now deprecated, and thus projects upgrading to Django 1.4 should update their manage.py. (The old-style manage.py will continue to work as before until Django 1.6. In 1.5 it will raise DeprecationWarning).

The new recommended manage.py file should look like this:

#!/usr/bin/env python
import os, sys

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")

from django.core.management import execute_from_command_line

execute_from_command_line(sys.argv)

{{ project_name }} should be replaced with the Python package name of the actual project.

If settings, URLconfs and apps within the project are imported or referenced using the project name prefix (e.g. myproject.settings, ROOT_URLCONF = "myproject.urls", etc.), the new manage.py will need to be moved one directory up, so it is outside the project package rather than adjacent to settings.py and urls.py.

For instance, with the following layout:

manage.py
mysite/
__init__.py
settings.py
urls.py
myapp/
__init__.py
models.py

You could import mysite.settings, mysite.urls, and mysite.myapp, but not settings, urls, or myapp as top-level modules.

Anything imported as a top-level module can be placed adjacent to the new manage.py. For instance, to decouple “myapp” from the project module and import it as just myapp, place it outside the mysite/ directory:

manage.py
myapp/
__init__.py
models.py
mysite/
__init__.py
settings.py
urls.py

If the same code is imported inconsistently (some places with the project prefix, some places without it), the imports will need to be cleaned up when switching to the new manage.py.

Custom project and app templates

The startapp and startproject management commands now have a --template option for specifying a path or URL to a custom app or project template.

For example, Django will use the /path/to/my_project_template directory when you run the following command:

django-admin.py startproject --template=/path/to/my_project_template myproject

You can also now provide a destination directory as the second argument to both startapp and startproject:

django-admin.py startapp myapp /path/to/new/app
django-admin.py startproject myproject /path/to/new/project

For more information, see the startapp and startproject documentation.

Improved WSGI support

The startproject management command now adds a wsgi.py module to the initial project layout, containing a simple WSGI application that can be used for deploying with WSGI app servers.

The built-in development server now supports using an externally-defined WSGI callable, which makes it possible to run runserver with the same WSGI configuration that is used for deployment. The new WSGI_APPLICATION setting lets you configure which WSGI callable runserver uses.

(The runfcgi management command also internally wraps the WSGI callable configured via WSGI_APPLICATION.)

SELECT FOR UPDATE support

Django 1.4 includes a QuerySet.select_for_update() method, which generates a SELECT ... FOR UPDATE SQL query. This will lock rows until the end of the transaction, meaning other transactions cannot modify or delete rows matched by a FOR UPDATE query.

For more details, see the documentation for select_for_update().

Model.objects.bulk_create in the ORM

This method lets you create multiple objects more efficiently. It can result in significant performance increases if you have many objects.

Django makes use of this internally, meaning some operations (such as database setup for test suites) have seen a performance benefit as a result.

See the bulk_create() docs for more information.

QuerySet.prefetch_related

Similar to select_related() but with a different strategy and broader scope, prefetch_related() has been added to QuerySet. This method returns a new QuerySet that will prefetch each of the specified related lookups in a single batch as soon as the query begins to be evaluated. Unlike select_related, it does the joins in Python, not in the database, and supports many-to-many relationships, GenericForeignKey and more. This allows you to fix a very common performance problem in which your code ends up doing O(n) database queries (or worse) if objects on your primary QuerySet each have many related objects that you also need to fetch.

Improved password hashing

Django’s auth system (django.contrib.auth) stores passwords using a one-way algorithm. Django 1.3 uses the SHA1 algorithm, but increasing processor speeds and theoretical attacks have revealed that SHA1 isn’t as secure as we’d like. Thus, Django 1.4 introduces a new password storage system: by default Django now uses the PBKDF2 algorithm (as recommended by NIST). You can also easily choose a different algorithm (including the popular bcrypt algorithm). For more details, see How Django stores passwords.

HTML5 doctype

We’ve switched the admin and other bundled templates to use the HTML5 doctype. While Django will be careful to maintain compatibility with older browsers, this change means that you can use any HTML5 features you need in admin pages without having to lose HTML validity or override the provided templates to change the doctype.

List filters in admin interface

Prior to Django 1.4, the admin app let you specify change list filters by specifying a field lookup, but it didn’t allow you to create custom filters. This has been rectified with a simple API (previously used internally and known as “FilterSpec”). For more details, see the documentation for list_filter.

Multiple sort in admin interface

The admin change list now supports sorting on multiple columns. It respects all elements of the ordering attribute, and sorting on multiple columns by clicking on headers is designed to mimic the behavior of desktop GUIs. We also added a get_ordering() method for specifying the ordering dynamically (i.e., depending on the request).

New ModelAdmin methods

We added a save_related() method to ModelAdmin to ease customization of how related objects are saved in the admin.

Two other new ModelAdmin methods, get_list_display() and get_list_display_links() enable dynamic customization of fields and links displayed on the admin change list.

Admin inlines respect user permissions

Admin inlines now only allow those actions for which the user has permission. For ManyToMany relationships with an auto-created intermediate model (which does not have its own permissions), the change permission for the related model determines if the user has the permission to add, change or delete relationships.

Tools for cryptographic signing

Django 1.4 adds both a low-level API for signing values and a high-level API for setting and reading signed cookies, one of the most common uses of signing in Web applications.

See the cryptographic signing docs for more information.

Cookie-based session backend

Django 1.4 introduces a cookie-based session backend that uses the tools for cryptographic signing to store the session data in the client’s browser.

Warning

Session data is signed and validated by the server, but it’s not encrypted. This means a user can view any data stored in the session but cannot change it. Please read the documentation for further clarification before using this backend.

See the cookie-based session backend docs for more information.

New form wizard

The previous FormWizard from django.contrib.formtools has been replaced with a new implementation based on the class-based views introduced in Django 1.3. It features a pluggable storage API and doesn’t require the wizard to pass around hidden fields for every previous step.

Django 1.4 ships with a session-based storage backend and a cookie-based storage backend. The latter uses the tools for cryptographic signing also introduced in Django 1.4 to store the wizard’s state in the user’s cookies.

reverse_lazy

A lazily evaluated version of django.core.urlresolvers.reverse() was added to allow using URL reversals before the project’s URLconf gets loaded.

Translating URL patterns

Django can now look for a language prefix in the URLpattern when using the new i18n_patterns() helper function. It’s also now possible to define translatable URL patterns using ugettext_lazy(). See Internationalization: in URL patterns for more information about the language prefix and how to internationalize URL patterns.

Contextual translation support for {% trans %} and {% blocktrans %}

The contextual translation support introduced in Django 1.3 via the pgettext function has been extended to the trans and blocktrans template tags using the new context keyword.

Customizable SingleObjectMixin URLConf kwargs

Two new attributes, pk_url_kwarg and slug_url_kwarg, have been added to SingleObjectMixin to enable the customization of URLconf keyword arguments used for single object generic views.

Assignment template tags

A new assignment_tag helper function was added to template.Library to ease the creation of template tags that store data in a specified context variable.

*args and **kwargs support for template tag helper functions

The simple_tag, inclusion_tag and newly introduced assignment_tag template helper functions may now accept any number of positional or keyword arguments. For example:

@register.simple_tag
def my_tag(a, b, *args, **kwargs):
warning = kwargs['warning']
profile = kwargs['profile']
...
return ...

Then, in the template, any number of arguments may be passed to the template tag. For example:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

No wrapping of exceptions in TEMPLATE_DEBUG mode

In previous versions of Django, whenever the TEMPLATE_DEBUG setting was True, any exception raised during template rendering (even exceptions unrelated to template syntax) were wrapped in TemplateSyntaxError and re-raised. This was done in order to provide detailed template source location information in the debug 500 page.

In Django 1.4, exceptions are no longer wrapped. Instead, the original exception is annotated with the source information. This means that catching exceptions from template rendering is now consistent regardless of the value of TEMPLATE_DEBUG, and there’s no need to catch and unwrap TemplateSyntaxError in order to catch other errors.

truncatechars template filter

This new filter truncates a string to be no longer than the specified number of characters. Truncated strings end with a translatable ellipsis sequence (”...”). See the documentation for truncatechars for more details.

static template tag

The staticfiles contrib app has a new static template tag to refer to files saved with the STATICFILES_STORAGE storage backend. It uses the storage backend’s url method and therefore supports advanced features such as serving files from a cloud service.

CachedStaticFilesStorage storage backend

The staticfiles contrib app now has a CachedStaticFilesStorage backend that caches the files it saves (when running the collectstatic management command) by appending the MD5 hash of the file’s content to the filename. For example, the file css/styles.css would also be saved as css/styles.55e7cbb9ba48.css

See the CachedStaticFilesStorage docs for more information.

Simple clickjacking protection

We’ve added a middleware to provide easy protection against clickjacking using the X-Frame-Options header. It’s not enabled by default for backwards compatibility reasons, but you’ll almost certainly want to enable it to help plug that security hole for browsers that support the header.

CSRF improvements

We’ve made various improvements to our CSRF features, including the ensure_csrf_cookie() decorator, which can help with AJAX-heavy sites; protection for PUT and DELETE requests; and the CSRF_COOKIE_SECURE and CSRF_COOKIE_PATH settings, which can improve the security and usefulness of CSRF protection. See the CSRF docs for more information.

Error report filtering

We added two function decorators, sensitive_variables() and sensitive_post_parameters(), to allow designating the local variables and POST parameters that may contain sensitive information and should be filtered out of error reports.

All POST parameters are now systematically filtered out of error reports for certain views (login, password_reset_confirm, password_change and add_view in django.contrib.auth.views, as well as user_change_password in the admin app) to prevent the leaking of sensitive information such as user passwords.

You can override or customize the default filtering by writing a custom filter. For more information see the docs on Filtering error reports.

Extended IPv6 support

Django 1.4 can now better handle IPv6 addresses with the new GenericIPAddressField model field, GenericIPAddressField form field and the validators validate_ipv46_address and validate_ipv6_address.

HTML comparisons in tests

The base classes in django.test now have some helpers to compare HTML without tripping over irrelevant differences in whitespace, argument quoting/ordering and closing of self-closing tags. You can either compare HTML directly with the new assertHTMLEqual() and assertHTMLNotEqual() assertions, or use the html=True flag with assertContains() and assertNotContains() to test whether the client’s response contains a given HTML fragment. See the assertions documentation for more.

Two new date format strings

Two new date formats were added for use in template filters, template tags and Format localization:

- e – the name of the timezone of the given datetime object

- o – the ISO 8601 year number

Please make sure to update your custom format files if they contain either e or o in a format string. For example a Spanish localization format previously only escaped the d format character:

DATE_FORMAT = r'j \de F \de Y'

But now it needs to also escape e and o:

DATE_FORMAT = r'j \d\e F \d\e Y'

For more information, see the date documentation.

Minor features

Django 1.4 also includes several smaller improvements worth noting:

- A more usable stacktrace in the technical 500 page. Frames in the stack trace that reference Django’s framework code are dimmed out, while frames in application code are slightly emphasized. This change makes it easier to scan a stacktrace for issues in application code.

- Tablespace support in PostgreSQL.

- Customizable names for simple_tag().

- In the documentation, a helpful security overview page.

- The django.contrib.auth.models.check_password function has been moved to the django.contrib.auth.hashers module. Importing it from the old location will still work, but you should update your imports.

- The collectstatic management command now has a --clear option to delete all files at the destination before copying or linking the static files.

- It’s now possible to load fixtures containing forward references when using MySQL with the InnoDB database engine.

- A new 403 response handler has been added as 'django.views.defaults.permission_denied'. You can set your own handler by setting the value of django.conf.urls.handler403. See the documentation about the 403 (HTTP Forbidden) view for more information.

- The makemessages command uses a new and more accurate lexer, JsLex, for extracting translatable strings from JavaScript files.

- The trans template tag now takes an optional as argument to be able to retrieve a translation string without displaying it but setting a template context variable instead.

- The if template tag now supports {% elif %} clauses.

- If your Django app is behind a proxy, you might find the new SECURE_PROXY_SSL_HEADER setting useful. It solves the problem of your proxy “eating” the fact that a request came in via HTTPS. But only use this setting if you know what you’re doing.

- A new, plain-text, version of the HTTP 500 status code internal error page served when DEBUG is True is now sent to the client when Django detects that the request has originated in JavaScript code. (is_ajax() is used for this.)

Like its HTML counterpart, it contains a collection of different pieces of information about the state of the application.

This should make it easier to read when debugging interaction with client-side JavaScript.

- Added the makemessages --no-location option.

- Changed the locmem cache backend to use pickle.HIGHEST_PROTOCOL for better compatibility with the other cache backends.

- Added support in the ORM for generating SELECT queries containing DISTINCT ON.

The distinct() QuerySet method now accepts an optional list of model field names. If specified, then the DISTINCT statement is limited to these fields. This is only supported in PostgreSQL.

For more details, see the documentation for distinct().

- The admin login page will add a password reset link if you include a URL with the name ‘admin_password_reset’ in your urls.py, so plugging in the built-in password reset mechanism and making it available is now much easier. For details, see Adding a password-reset feature.

- The MySQL database backend can now make use of the savepoint feature implemented by MySQL version 5.0.3 or newer with the InnoDB storage engine.

- It’s now possible to pass initial values to the model forms that are part of both model formsets and inline model formsets as returned from factory functions modelformset_factory and inlineformset_factory respectively just like with regular formsets. However, initial values only apply to extra forms, i.e. those which are not bound to an existing model instance.

- The sitemaps framework can now handle HTTPS links using the new Sitemap.protocol class attribute.

- A new django.test.SimpleTestCase subclass of unittest.TestCase that’s lighter than django.test.TestCase and company. It can be useful in tests that don’t need to hit a database. See Hierarchy of Django unit testing classes.

Backwards incompatible changes in 1.4

SECRET_KEY setting is required

Running Django with an empty or known SECRET_KEY disables many of Django’s security protections and can lead to remote-code-execution vulnerabilities. No Django site should ever be run without a SECRET_KEY.

In Django 1.4, starting Django with an empty SECRET_KEY will raise a DeprecationWarning. In Django 1.5, it will raise an exception and Django will refuse to start. This is slightly accelerated from the usual deprecation path due to the severity of the consequences of running Django with no SECRET_KEY.

django.contrib.admin

The included administration app django.contrib.admin has for a long time shipped with a default set of static files such as JavaScript, images and stylesheets. Django 1.3 added a new contrib app django.contrib.staticfiles to handle such files in a generic way and defined conventions for static files included in apps.

Starting in Django 1.4, the admin’s static files also follow this convention, to make the files easier to deploy. In previous versions of Django, it was also common to define an ADMIN_MEDIA_PREFIX setting to point to the URL where the admin’s static files live on a Web server. This setting has now been deprecated and replaced by the more general setting STATIC_URL. Django will now expect to find the admin static files under the URL <STATIC_URL>/admin/.

If you’ve previously used a URL path for ADMIN_MEDIA_PREFIX (e.g. /media/) simply make sure STATIC_URL and STATIC_ROOT are configured and your Web server serves those files correctly. The development server continues to serve the admin files just like before. Read the static files howto for more details.

If your ADMIN_MEDIA_PREFIX is set to an specific domain (e.g. http://media.example.com/admin/), make sure to also set your STATIC_URL setting to the correct URL – for example, http://media.example.com/.

Warning

If you’re implicitly relying on the path of the admin static files within Django’s source code, you’ll need to update that path. The files were moved from django/contrib/admin/media/ to django/contrib/admin/static/admin/.

Supported browsers for the admin

Django hasn’t had a clear policy on which browsers are supported by the admin app. Our new policy formalizes existing practices: YUI’s A-grade browsers should provide a fully-functional admin experience, with the notable exception of Internet Explorer 6, which is no longer supported.

Released over 10 years ago, IE6 imposes many limitations on modern Web development. The practical implications of this policy are that contributors are free to improve the admin without consideration for these limitations.

Obviously, this new policy has no impact on sites you develop using Django. It only applies to the Django admin. Feel free to develop apps compatible with any range of browsers.

Removed admin icons

As part of an effort to improve the performance and usability of the admin’s change-list sorting interface and horizontal and vertical “filter” widgets, some icon files were removed and grouped into two sprite files.

Specifically: selector-add.gif, selector-addall.gif, selector-remove.gif, selector-removeall.gif, selector_stacked-add.gif and selector_stacked-remove.gif were combined into selector-icons.gif; and arrow-up.gif and arrow-down.gif were combined into sorting-icons.gif.

If you used those icons to customize the admin, then you’ll need to replace them with your own icons or get the files from a previous release.

CSS class names in admin forms

To avoid conflicts with other common CSS class names (e.g. “button”), we added a prefix (“field-”) to all CSS class names automatically generated from the form field names in the main admin forms, stacked inline forms and tabular inline cells. You’ll need to take that prefix into account in your custom style sheets or JavaScript files if you previously used plain field names as selectors for custom styles or JavaScript transformations.

Compatibility with old signed data

Django 1.3 changed the cryptographic signing mechanisms used in a number of places in Django. While Django 1.3 kept fallbacks that would accept hashes produced by the previous methods, these fallbacks are removed in Django 1.4.

So, if you upgrade to Django 1.4 directly from 1.2 or earlier, you may lose/invalidate certain pieces of data that have been cryptographically signed using an old method. To avoid this, use Django 1.3 first for a period of time to allow the signed data to expire naturally. The affected parts are detailed below, with 1) the consequences of ignoring this advice and 2) the amount of time you need to run Django 1.3 for the data to expire or become irrelevant.

- contrib.sessions data integrity check

- Consequences: The user will be logged out, and session data will be lost.

- Time period: Defined by SESSION_COOKIE_AGE.

- contrib.auth password reset hash

- Consequences: Password reset links from before the upgrade will not work.

- Time period: Defined by PASSWORD_RESET_TIMEOUT_DAYS.

Form-related hashes: these have a are much shorter lifetime and are relevant only for the short window where a user might fill in a form generated by the pre-upgrade Django instance and try to submit it to the upgraded Django instance:

- contrib.comments form security hash

- Consequences: The user will see the validation error “Security hash failed.”

- Time period: The amount of time you expect users to take filling out comment forms.

- FormWizard security hash

- Consequences: The user will see an error about the form having expired and will be sent back to the first page of the wizard, losing the data entered so far.

- Time period: The amount of time you expect users to take filling out the affected forms.

- CSRF check

- Note: This is actually a Django 1.1 fallback, not Django 1.2, and it applies only if you’re upgrading from 1.1.

- Consequences: The user will see a 403 error with any CSRF-protected POST form.

- Time period: The amount of time you expect user to take filling out such forms.

- contrib.auth user password hash-upgrade sequence

- Consequences: Each user’s password will be updated to a stronger password hash when it’s written to the database in 1.4. This means that if you upgrade to 1.4 and then need to downgrade to 1.3, version 1.3 won’t be able to read the updated passwords.

- Remedy: Set PASSWORD_HASHERS to use your original password hashing when you initially upgrade to 1.4. After you confirm your app works well with Django 1.4 and you won’t have to roll back to 1.3, enable the new password hashes.

django.contrib.flatpages

Starting in 1.4, the FlatpageFallbackMiddleware only adds a trailing slash and redirects if the resulting URL refers to an existing flatpage. For example, requesting /notaflatpageoravalidurl in a previous version would redirect to /notaflatpageoravalidurl/, which would subsequently raise a 404. Requesting /notaflatpageoravalidurl now will immediately raise a 404.

Also, redirects returned by flatpages are now permanent (with 301 status code), to match the behavior of CommonMiddleware.

Serialization of datetime and time

As a consequence of time-zone support, and according to the ECMA-262 specification, we made changes to the JSON serializer:

- It includes the time zone for aware datetime objects. It raises an exception for aware time objects.

- It includes milliseconds for datetime and time objects. There is still some precision loss, because Python stores microseconds (6 digits) and JSON only supports milliseconds (3 digits). However, it’s better than discarding microseconds entirely.

We changed the XML serializer to use the ISO8601 format for datetimes. The letter T is used to separate the date part from the time part, instead of a space. Time zone information is included in the [+-]HH:MM format.

Though the serializers now use these new formats when creating fixtures, they can still load fixtures that use the old format.

supports_timezone changed to False for SQLite

The database feature supports_timezone used to be True for SQLite. Indeed, if you saved an aware datetime object, SQLite stored a string that included an UTC offset. However, this offset was ignored when loading the value back from the database, which could corrupt the data.

In the context of time-zone support, this flag was changed to False, and datetimes are now stored without time-zone information in SQLite. When USE_TZ is False, if you attempt to save an aware datetime object, Django raises an exception.

MySQLdb-specific exceptions

The MySQL backend historically has raised MySQLdb.OperationalError when a query triggered an exception. We’ve fixed this bug, and we now raise django.db.DatabaseError instead. If you were testing for MySQLdb.OperationalError, you’ll need to update your except clauses.

Database connection’s thread-locality

DatabaseWrapper objects (i.e. the connection objects referenced by django.db.connection and django.db.connections["some_alias"]) used to be thread-local. They are now global objects in order to be potentially shared between multiple threads. While the individual connection objects are now global, the django.db.connections dictionary referencing those objects is still thread-local. Therefore if you just use the ORM or DatabaseWrapper.cursor() then the behavior is still the same as before. Note, however, that django.db.connection does not directly reference the default DatabaseWrapper object anymore and is now a proxy to access that object’s attributes. If you need to access the actual DatabaseWrapper object, use django.db.connections[DEFAULT_DB_ALIAS] instead.

As part of this change, all underlying SQLite connections are now enabled for potential thread-sharing (by passing the check_same_thread=False attribute to pysqlite). DatabaseWrapper however preserves the previous behavior by disabling thread-sharing by default, so this does not affect any existing code that purely relies on the ORM or on DatabaseWrapper.cursor().

Finally, while it’s now possible to pass connections between threads, Django doesn’t make any effort to synchronize access to the underlying backend. Concurrency behavior is defined by the underlying backend implementation. Check their documentation for details.

COMMENTS_BANNED_USERS_GROUP setting

Django’s comments has historically supported excluding the comments of a special user group, but we’ve never documented the feature properly and didn’t enforce the exclusion in other parts of the app such as the template tags. To fix this problem, we removed the code from the feed class.

If you rely on the feature and want to restore the old behavior, use a custom comment model manager to exclude the user group, like this:

from django.conf import settings
from django.contrib.comments.managers import CommentManager

class BanningCommentManager(CommentManager):
def get_query_set(self):
qs = super(BanningCommentManager, self).get_query_set()
if getattr(settings, 'COMMENTS_BANNED_USERS_GROUP', None):
where = ['user_id NOT IN (SELECT user_id FROM auth_user_groups WHERE group_id = %s)']
params = [settings.COMMENTS_BANNED_USERS_GROUP]
qs = qs.extra(where=where, params=params)
return qs

Save this model manager in your custom comment app (e.g., in my_comments_app/managers.py) and add it your custom comment app model:

from django.db import models
from django.contrib.comments.models import Comment

from my_comments_app.managers import BanningCommentManager

class CommentWithTitle(Comment):
title = models.CharField(max_length=300)

objects = BanningCommentManager()

IGNORABLE_404_STARTS and IGNORABLE_404_ENDS settings

Until Django 1.3, it was possible to exclude some URLs from Django’s 404 error reporting by adding prefixes to IGNORABLE_404_STARTS and suffixes to IGNORABLE_404_ENDS.

In Django 1.4, these two settings are superseded by IGNORABLE_404_URLS, which is a list of compiled regular expressions. Django won’t send an email for 404 errors on URLs that match any of them.

Furthermore, the previous settings had some rather arbitrary default values:

IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf')
IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi',
'favicon.ico', '.php')

It’s not Django’s role to decide if your website has a legacy /cgi-bin/ section or a favicon.ico. As a consequence, the default values of IGNORABLE_404_URLS, IGNORABLE_404_STARTS, and IGNORABLE_404_ENDS are all now empty.

If you have customized IGNORABLE_404_STARTS or IGNORABLE_404_ENDS, or if you want to keep the old default value, you should add the following lines in your settings file:

import re
IGNORABLE_404_URLS = (
# for each <prefix> in IGNORABLE_404_STARTS
re.compile(r'^<prefix>'),
# for each <suffix> in IGNORABLE_404_ENDS
re.compile(r'<suffix>$'),
)

Don’t forget to escape characters that have a special meaning in a regular expression, such as periods.

CSRF protection extended to PUT and DELETE

Previously, Django’s CSRF protection provided protection only against POST requests. Since use of PUT and DELETE methods in AJAX applications is becoming more common, we now protect all methods not defined as safe by RFC 2616 – i.e., we exempt GET, HEAD, OPTIONS and TRACE, and we enforce protection on everything else.

If you’re using PUT or DELETE methods in AJAX applications, please see the instructions about using AJAX and CSRF.

Password reset view now accepts subject_template_name

The password_reset view in django.contrib.auth now accepts a subject_template_name parameter, which is passed to the password save form as a keyword argument. If you are using this view with a custom password reset form, then you will need to ensure your form’s save() method accepts this keyword argument.

django.core.template_loaders

This was an alias to django.template.loader since 2005, and we’ve removed it without emitting a warning due to the length of the deprecation. If your code still referenced this, please use django.template.loader instead.

django.db.models.fields.URLField.verify_exists

This functionality has been removed due to intractable performance and security issues. Any existing usage of verify_exists should be removed.

django.core.files.storage.Storage.open

The open method of the base Storage class used to take an obscure parameter mixin that allowed you to dynamically change the base classes of the returned file object. This has been removed. In the rare case you relied on the mixin parameter, you can easily achieve the same by overriding the open method, like this:

from django.core.files import File
from django.core.files.storage import FileSystemStorage

class Spam(File):
"""
Spam, spam, spam, spam and spam.
"""
def ham(self):
return 'eggs'

class SpamStorage(FileSystemStorage):
"""
A custom file storage backend.
"""
def open(self, name, mode='rb'):
return Spam(open(self.path(name), mode))

YAML deserializer now uses yaml.safe_load

yaml.load is able to construct any Python object, which may trigger arbitrary code execution if you process a YAML document that comes from an untrusted source. This feature isn’t necessary for Django’s YAML deserializer, whose primary use is to load fixtures consisting of simple objects. Even though fixtures are trusted data, the YAML deserializer now uses yaml.safe_load for additional security.

Session cookies now have the httponly flag by default

Session cookies now include the httponly attribute by default to help reduce the impact of potential XSS attacks. As a consequence of this change, session cookie data, including sessionid, is no longer accessible from JavaScript in many browsers. For strict backwards compatibility, use SESSION_COOKIE_HTTPONLY = False in your settings file.

The urlize filter no longer escapes every URL

When a URL contains a %xx sequence, where xx are two hexadecimal digits, urlize now assumes that the URL is already escaped and doesn’t apply URL escaping again. This is wrong for URLs whose unquoted form contains a %xx sequence, but such URLs are very unlikely to happen in the wild, because they would confuse browsers too.

assertTemplateUsed and assertTemplateNotUsed as context manager

It’s now possible to check whether a template was used within a block of code with assertTemplateUsed() and assertTemplateNotUsed(). And they can be used as a context manager:

with self.assertTemplateUsed('index.html'):
render_to_string('index.html')
with self.assertTemplateNotUsed('base.html'):
render_to_string('index.html')

See the assertion documentation for more.

Database connections after running the test suite

The default test runner no longer restores the database connections after tests’ execution. This prevents the production database from being exposed to potential threads that would still be running and attempting to create new connections.

If your code relied on connections to the production database being created after tests’ execution, then you can restore the previous behavior by subclassing DjangoTestRunner and overriding its teardown_databases() method.

Output of manage.py help

manage.py help now groups available commands by application. If you depended on the output of this command – if you parsed it, for example – then you’ll need to update your code. To get a list of all available management commands in a script, use manage.py help --commands instead.

extends template tag

Previously, the extends tag used a buggy method of parsing arguments, which could lead to it erroneously considering an argument as a string literal when it wasn’t. It now uses parser.compile_filter, like other tags.

The internals of the tag aren’t part of the official stable API, but in the interests of full disclosure, the ExtendsNode.__init__ definition has changed, which may break any custom tags that use this class.

Loading some incomplete fixtures no longer works

Prior to 1.4, a default value was inserted for fixture objects that were missing a specific date or datetime value when auto_now or auto_now_add was set for the field. This was something that should not have worked, and in 1.4 loading such incomplete fixtures will fail. Because fixtures are a raw import, they should explicitly specify all field values, regardless of field options on the model.

Development Server Multithreading

The development server is now is multithreaded by default. Use the runserver --nothreading option to disable the use of threading in the development server:

django-admin.py runserver --nothreading

Attributes disabled in markdown when safe mode set

Prior to Django 1.4, attributes were included in any markdown output regardless of safe mode setting of the filter. With version > 2.1 of the Python-Markdown library, an enable_attributes option was added. When the safe argument is passed to the markdown filter, both the safe_mode=True and enable_attributes=False options are set. If using a version of the Python-Markdown library less than 2.1, a warning is issued that the output is insecure.

FormMixin get_initial returns an instance-specific dictionary

In Django 1.3, the get_initial method of the django.views.generic.edit.FormMixin class was returning the class initial dictionary. This has been fixed to return a copy of this dictionary, so form instances can modify their initial data without messing with the class variable.

Features deprecated in 1.4

Old styles of calling cache_page decorator

Some legacy ways of calling cache_page() have been deprecated. Please see the documentation for the correct way to use this decorator.

Support for PostgreSQL versions older than 8.2

Django 1.3 dropped support for PostgreSQL versions older than 8.0, and we suggested using a more recent version because of performance improvements and, more importantly, the end of upstream support periods for 8.0 and 8.1 was near (November 2010).

Django 1.4 takes that policy further and sets 8.2 as the minimum PostgreSQL version it officially supports.

Request exceptions are now always logged

When we added logging support in Django in 1.3, the admin error email support was moved into the django.utils.log.AdminEmailHandler, attached to the 'django.request' logger. In order to maintain the established behavior of error emails, the 'django.request' logger was called only when DEBUG was False.

To increase the flexibility of error logging for requests, the 'django.request' logger is now called regardless of the value of DEBUG, and the default settings file for new projects now includes a separate filter attached to django.utils.log.AdminEmailHandler to prevent admin error emails in DEBUG mode:

'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},

If your project was created prior to this change, your LOGGING setting will not include this new filter. In order to maintain backwards-compatibility, Django will detect that your 'mail_admins' handler configuration includes no 'filters' section and will automatically add this filter for you and issue a pending-deprecation warning. This will become a deprecation warning in Django 1.5, and in Django 1.6 the backwards-compatibility shim will be removed entirely.

The existence of any 'filters' key under the 'mail_admins' handler will disable this backward-compatibility shim and deprecation warning.

django.conf.urls.defaults

Until Django 1.3, the functions include(), patterns() and url() plus handler404, handler500 were located in a django.conf.urls.defaults module.

In Django 1.4, they live in django.conf.urls.

django.contrib.databrowse

Databrowse has not seen active development for some time, and this does not show any sign of changing. There had been a suggestion for a GSOC project to integrate the functionality of databrowse into the admin, but no progress was made. While Databrowse has been deprecated, an enhancement of django.contrib.admin providing a similar feature set is still possible.

The code that powers Databrowse is licensed under the same terms as Django itself, so it’s available to be adopted by an individual or group as a third-party project.

django.core.management.setup_environ

This function temporarily modified sys.path in order to make the parent “project” directory importable under the old flat startproject layout. This function is now deprecated, as its path workarounds are no longer needed with the new manage.py and default project layout.

This function was never documented or part of the public API, but it was widely recommended for use in setting up a “Django environment” for a user script. These uses should be replaced by setting the DJANGO_SETTINGS_MODULE environment variable or using django.conf.settings.configure().

django.core.management.execute_manager

This function was previously used by manage.py to execute a management command. It is identical to django.core.management.execute_from_command_line, except that it first calls setup_environ, which is now deprecated. As such, execute_manager is also deprecated; execute_from_command_line can be used instead. Neither of these functions is documented as part of the public API, but a deprecation path is needed due to use in existing manage.py files.

is_safe and needs_autoescape attributes of template filters

Two flags, is_safe and needs_autoescape, define how each template filter interacts with Django’s auto-escaping behavior. They used to be attributes of the filter function:

@register.filter
def noop(value):
return value
noop.is_safe = True

However, this technique caused some problems in combination with decorators, especially @stringfilter. Now, the flags are keyword arguments of @register.filter:

@register.filter(is_safe=True)
def noop(value):
return value

See filters and auto-escaping for more information.

Wildcard expansion of application names in INSTALLED_APPS

Until Django 1.3, INSTALLED_APPS accepted wildcards in application names, like django.contrib.*. The expansion was performed by a filesystem-based implementation of from <package> import *. Unfortunately, this can’t be done reliably.

This behavior was never documented. Since it is unpythonic and not obviously useful, it was removed in Django 1.4. If you relied on it, you must edit your settings file to list all your applications explicitly.

HttpRequest.raw_post_data renamed to HttpRequest.body

This attribute was confusingly named HttpRequest.raw_post_data, but it actually provided the body of the HTTP request. It’s been renamed to HttpRequest.body, and HttpRequest.raw_post_data has been deprecated.

django.contrib.sitemaps bug fix with potential performance implications

In previous versions, Paginator objects used in sitemap classes were cached, which could result in stale site maps. We’ve removed the caching, so each request to a site map now creates a new Paginator object and calls the items() method of the Sitemap subclass. Depending on what your items() method is doing, this may have a negative performance impact. To mitigate the performance impact, consider using the caching framework within your Sitemap subclass.

Versions of Python-Markdown earlier than 2.1

Versions of Python-Markdown earlier than 2.1 do not support the option to disable attributes. As a security issue, earlier versions of this library will not be supported by the markup contrib app in 1.5 under an accelerated deprecation timeline.

Django 1.3.7 release notes

February 20, 2013

Django 1.3.7 corrects a packaging problem with yesterday’s 1.3.6 release.

The release contained stray .pyc files that caused “bad magic number” errors when running with some versions of Python. This releases corrects this, and also fixes a bad documentation link in the project template settings.py file generated by manage.py startproject.

Django 1.3.6 release notes

February 19, 2013

Django 1.3.6 fixes four security issues present in previous Django releases in the 1.3 series.

This is the sixth bugfix/security release in the Django 1.3 series.

Host header poisoning

Some parts of Django – independent of end-user-written applications – make use of full URLs, including domain name, which are generated from the HTTP Host header. Django’s documentation has for some time contained notes advising users on how to configure webservers to ensure that only valid Host headers can reach the Django application. However, it has been reported to us that even with the recommended webserver configurations there are still techniques available for tricking many common webservers into supplying the application with an incorrect and possibly malicious Host header.

For this reason, Django 1.3.6 adds a new setting, ALLOWED_HOSTS, which should contain an explicit list of valid host/domain names for this site. A request with a Host header not matching an entry in this list will raise SuspiciousOperation if request.get_host() is called. For full details see the documentation for the ALLOWED_HOSTS setting.

The default value for this setting in Django 1.3.6 is ['*'] (matching any host), for backwards-compatibility, but we strongly encourage all sites to set a more restrictive value.

This host validation is disabled when DEBUG is True or when running tests.

XML deserialization

The XML parser in the Python standard library is vulnerable to a number of attacks via external entities and entity expansion. Django uses this parser for deserializing XML-formatted database fixtures. The fixture deserializer is not intended for use with untrusted data, but in order to err on the side of safety in Django 1.3.6 the XML deserializer refuses to parse an XML document with a DTD (DOCTYPE definition), which closes off these attack avenues.

These issues in the Python standard library are CVE-2013-1664 and CVE-2013-1665. More information available from the Python security team.

Django’s XML serializer does not create documents with a DTD, so this should not cause any issues with the typical round-trip from dumpdata to loaddata, but if you feed your own XML documents to the loaddata management command, you will need to ensure they do not contain a DTD.

Formset memory exhaustion

Previous versions of Django did not validate or limit the form-count data provided by the client in a formset’s management form, making it possible to exhaust a server’s available memory by forcing it to create very large numbers of forms.

In Django 1.3.6, all formsets have a strictly-enforced maximum number of forms (1000 by default, though it can be set higher via the max_num formset factory argument).

Admin history view information leakage

In previous versions of Django, an admin user without change permission on a model could still view the unicode representation of instances via their admin history log. Django 1.3.6 now limits the admin history log view for an object to users with change permission for that model.

Django 1.3.5 release notes

December 10, 2012

Django 1.3.5 addresses two security issues present in previous Django releases in the 1.3 series.

Please be aware that this security release is slightly different from previous ones. Both issues addressed here have been dealt with in prior security updates to Django. In one case, we have received ongoing reports of problems, and in the other we’ve chosen to take further steps to tighten up Django’s code in response to independent discovery of potential problems from multiple sources.

Host header poisoning

Several earlier Django security releases focused on the issue of poisoning the HTTP Host header, causing Django to generate URLs pointing to arbitrary, potentially-malicious domains.

In response to further input received and reports of continuing issues following the previous release, we’re taking additional steps to tighten Host header validation. Rather than attempt to accommodate all features HTTP supports here, Django’s Host header validation attempts to support a smaller, but far more common, subset:

- Hostnames must consist of characters [A-Za-z0-9] plus hyphen (‘-‘) or dot (‘.’).

- IP addresses – both IPv4 and IPv6 – are permitted.

- Port, if specified, is numeric.

Any deviation from this will now be rejected, raising the exception django.core.exceptions.SuspiciousOperation.

Redirect poisoning

Also following up on a previous issue: in July of this year, we made changes to Django’s HTTP redirect classes, performing additional validation of the scheme of the URL to redirect to (since, both within Django’s own supplied applications and many third-party applications, accepting a user-supplied redirect target is a common pattern).

Since then, two independent audits of the code turned up further potential problems. So, similar to the Host-header issue, we are taking steps to provide tighter validation in response to reported problems (primarily with third-party applications, but to a certain extent also within Django itself). This comes in two parts:

1. A new utility function, django.utils.http.is_safe_url, is added; this function takes a URL and a hostname, and checks that the URL is either relative, or if absolute matches the supplied hostname. This function is intended for use whenever user-supplied redirect targets are accepted, to ensure that such redirects cannot lead to arbitrary third-party sites.

2. All of Django’s own built-in views – primarily in the authentication system – which allow user-supplied redirect targets now use is_safe_url to validate the supplied URL.

Django 1.3.4 release notes

October 17, 2012

This is the fourth release in the Django 1.3 series.

Host header poisoning

Some parts of Django – independent of end-user-written applications – make use of full URLs, including domain name, which are generated from the HTTP Host header. Some attacks against this are beyond Django’s ability to control, and require the web server to be properly configured; Django’s documentation has for some time contained notes advising users on such configuration.

Django’s own built-in parsing of the Host header is, however, still vulnerable, as was reported to us recently. The Host header parsing in Django 1.3.3 and Django 1.4.1 – specifically, django.http.HttpRequest.get_host() – was incorrectly handling username/password information in the header. Thus, for example, the following Host header would be accepted by Django when running on “validsite.com”:

Host: validsite.com:random@evilsite.com

Using this, an attacker can cause parts of Django – particularly the password-reset mechanism – to generate and display arbitrary URLs to users.

To remedy this, the parsing in HttpRequest.get_host() is being modified; Host headers which contain potentially dangerous content (such as username/password pairs) now raise the exception django.core.exceptions.SuspiciousOperation.

Details of this issue were initially posted online as a security advisory.

Django 1.3.3 release notes

August 1, 2012

Following Monday’s security release of Django 1.3.2, we began receiving reports that one of the fixes applied was breaking Python 2.4 compatibility for Django 1.3. Since Python 2.4 is a supported Python version for that release series, this release fixes compatibility with Python 2.4.

Django 1.3.2 release notes

July 30, 2012

This is the second security release in the Django 1.3 series, fixing several security issues in Django 1.3. Django 1.3.2 is a recommended upgrade for all users of Django 1.3.

For a full list of issues addressed in this release, see the security advisory.

Django 1.3.1 release notes

September 9, 2011

Welcome to Django 1.3.1!

This is the first security release in the Django 1.3 series, fixing several security issues in Django 1.3. Django 1.3.1 is a recommended upgrade for all users of Django 1.3.

For a full list of issues addressed in this release, see the security advisory.

Django 1.3 release notes

March 23, 2011

Welcome to Django 1.3!

Nearly a year in the making, Django 1.3 includes quite a few new features and plenty of bug fixes and improvements to existing features. These release notes cover the new features in 1.3, as well as some backwards-incompatible changes you’ll want to be aware of when upgrading from Django 1.2 or older versions.

Overview

Django 1.3’s focus has mostly been on resolving smaller, long-standing feature requests, but that hasn’t prevented a few fairly significant new features from landing, including:

- A framework for writing class-based views.

- Built-in support for using Python’s logging facilities.

- Contrib support for easy handling of static files.

- Django’s testing framework now supports (and ships with a copy of) the unittest2 library.

Wherever possible, of course, new features are introduced in a backwards-compatible manner per our API stability policy policy. As a result of this policy, Django 1.3 begins the deprecation process for some features.

Python compatibility

The release of Django 1.2 was notable for having the first shift in Django’s Python compatibility policy; prior to Django 1.2, Django supported any 2.x version of Python from 2.3 up. As of Django 1.2, the minimum requirement was raised to Python 2.4.

Django 1.3 continues to support Python 2.4, but will be the final Django release series to do so; beginning with Django 1.4, the minimum supported Python version will be 2.5. A document outlining our full timeline for deprecating Python 2.x and moving to Python 3.x will be published shortly after the release of Django 1.3.

What’s new in Django 1.3

Class-based views

Django 1.3 adds a framework that allows you to use a class as a view. This means you can compose a view out of a collection of methods that can be subclassed and overridden to provide common views of data without having to write too much code.

Analogs of all the old function-based generic views have been provided, along with a completely generic view base class that can be used as the basis for reusable applications that can be easily extended.

See the documentation on class-based generic views for more details. There is also a document to help you convert your function-based generic views to class-based views.

Logging

Django 1.3 adds framework-level support for Python’s logging module. This means you can now easily configure and control logging as part of your Django project. A number of logging handlers and logging calls have been added to Django’s own code as well – most notably, the error emails sent on a HTTP 500 server error are now handled as a logging activity. See the documentation on Django’s logging interface for more details.

Extended static files handling

Django 1.3 ships with a new contrib app – django.contrib.staticfiles – to help developers handle the static media files (images, CSS, JavaScript, etc.) that are needed to render a complete web page.

In previous versions of Django, it was common to place static assets in MEDIA_ROOT along with user-uploaded files, and serve them both at MEDIA_URL. Part of the purpose of introducing the staticfiles app is to make it easier to keep static files separate from user-uploaded files. Static assets should now go in static/ subdirectories of your apps or in other static assets directories listed in STATICFILES_DIRS, and will be served at STATIC_URL.

See the reference documentation of the app for more details or learn how to manage static files.

unittest2 support

Python 2.7 introduced some major changes to the unittest library, adding some extremely useful features. To ensure that every Django project can benefit from these new features, Django ships with a copy of unittest2, a copy of the Python 2.7 unittest library, backported for Python 2.4 compatibility.

To access this library, Django provides the django.utils.unittest module alias. If you are using Python 2.7, or you have installed unittest2 locally, Django will map the alias to the installed version of the unittest library. Otherwise, Django will use its own bundled version of unittest2.

To take advantage of this alias, simply use:

from django.utils import unittest

wherever you would have historically used:

import unittest

If you want to continue to use the base unittest library, you can – you just won’t get any of the nice new unittest2 features.

Transaction context managers

Users of Python 2.5 and above may now use transaction management functions as context managers. For example:

with transaction.autocommit():
# ...

Configurable delete-cascade

ForeignKey and OneToOneField now accept an on_delete argument to customize behavior when the referenced object is deleted. Previously, deletes were always cascaded; available alternatives now include set null, set default, set to any value, protect, or do nothing.

For more information, see the on_delete documentation.

Contextual markers and comments for translatable strings

For translation strings with ambiguous meaning, you can now use the pgettext function to specify the context of the string.

And if you just want to add some information for translators, you can also add special translator comments in the source.

For more information, see Contextual markers and Comments for translators.

Improvements to built-in template tags

A number of improvements have been made to Django’s built-in template tags:

- The include tag now accepts a with option, allowing you to specify context variables to the included template

- The include tag now accepts an only option, allowing you to exclude the current context from the included context

- The with tag now allows you to define multiple context variables in a single with block.

- The load tag now accepts a from argument, allowing you to load a single tag or filter from a library.

TemplateResponse

It can sometimes be beneficial to allow decorators or middleware to modify a response after it has been constructed by the view. For example, you may want to change the template that is used, or put additional data into the context.

However, you can’t (easily) modify the content of a basic HttpResponse after it has been constructed. To overcome this limitation, Django 1.3 adds a new TemplateResponse class. Unlike basic HttpResponse objects, TemplateResponse objects retain the details of the template and context that was provided by the view to compute the response. The final output of the response is not computed until it is needed, later in the response process.

For more details, see the documentation on the TemplateResponse class.

Caching changes

Django 1.3 sees the introduction of several improvements to the Django’s caching infrastructure.

Firstly, Django now supports multiple named caches. In the same way that Django 1.2 introduced support for multiple database connections, Django 1.3 allows you to use the new CACHES setting to define multiple named cache connections.

Secondly, versioning, site-wide prefixing and transformation have been added to the cache API.

Thirdly, cache key creation has been updated to take the request query string into account on GET requests.

Finally, support for pylibmc has been added to the memcached cache backend.

For more details, see the documentation on caching in Django.

Permissions for inactive users

If you provide a custom auth backend with supports_inactive_user set to True, an inactive User instance will check the backend for permissions. This is useful for further centralizing the permission handling. See the authentication docs for more details.

GeoDjango

The GeoDjango test suite is now included when running the Django test suite with runtests.py when using spatial database backends.

MEDIA_URL and STATIC_URL must end in a slash

Previously, the MEDIA_URL setting only required a trailing slash if it contained a suffix beyond the domain name.

A trailing slash is now required for MEDIA_URL and the new STATIC_URL setting as long as it is not blank. This ensures there is a consistent way to combine paths in templates.

Project settings which provide either of both settings without a trailing slash will now raise a PendingDeprecationWarning.

In Django 1.4 this same condition will raise DeprecationWarning, and in Django 1.5 will raise an ImproperlyConfigured exception.

Everything else

Django 1.1 and 1.2 added lots of big ticket items to Django, like multiple-database support, model validation, and a session-based messages framework. However, this focus on big features came at the cost of lots of smaller features.

To compensate for this, the focus of the Django 1.3 development process has been on adding lots of smaller, long standing feature requests. These include:

- Improved tools for accessing and manipulating the current Site object in the sites framework.

- A RequestFactory for mocking requests in tests.

- A new test assertion – assertNumQueries() – making it easier to test the database activity associated with a view.

- Support for lookups spanning relations in admin’s list_filter.

- Support for HTTPOnly cookies.

- mail_admins() and mail_managers() now support easily attaching HTML content to messages.

- EmailMessage now supports CC’s.

- Error emails now include more of the detail and formatting of the debug server error page.

- simple_tag() now accepts a takes_context argument, making it easier to write simple template tags that require access to template context.

- A new render() shortcut – an alternative to django.shortcuts.render_to_response() providing a RequestContext by default.

- Support for combining F expressions with timedelta values when retrieving or updating database values.

Backwards-incompatible changes in 1.3

CSRF validation now applies to AJAX requests

Prior to Django 1.2.5, Django’s CSRF-prevention system exempted AJAX requests from CSRF verification; due to security issues reported to us, however, all requests are now subjected to CSRF verification. Consult the Django CSRF documentation for details on how to handle CSRF verification in AJAX requests.

Restricted filters in admin interface

Prior to Django 1.2.5, the Django administrative interface allowed filtering on any model field or relation – not just those specified in list_filter – via query string manipulation. Due to security issues reported to us, however, query string lookup arguments in the admin must be for fields or relations specified in list_filter or date_hierarchy.

Deleting a model doesn’t delete associated files

In earlier Django versions, when a model instance containing a FileField was deleted, FileField took it upon itself to also delete the file from the backend storage. This opened the door to several data-loss scenarios, including rolled-back transactions and fields on different models referencing the same file. In Django 1.3, when a model is deleted the FileField’s delete() method won’t be called. If you need cleanup of orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).

PasswordInput default rendering behavior

The PasswordInput form widget, intended for use with form fields which represent passwords, accepts a boolean keyword argument render_value indicating whether to send its data back to the browser when displaying a submitted form with errors. Prior to Django 1.3, this argument defaulted to True, meaning that the submitted password would be sent back to the browser as part of the form. Developers who wished to add a bit of additional security by excluding that value from the redisplayed form could instantiate a PasswordInput passing render_value=False .

Due to the sensitive nature of passwords, however, Django 1.3 takes this step automatically; the default value of render_value is now False, and developers who want the password value returned to the browser on a submission with errors (the previous behavior) must now explicitly indicate this. For example:

class LoginForm(forms.Form):
username = forms.CharField(max_length=100)
password = forms.CharField(widget=forms.PasswordInput(render_value=True))

Clearable default widget for FileField

Django 1.3 now includes a ClearableFileInput form widget in addition to FileInput. ClearableFileInput renders with a checkbox to clear the field’s value (if the field has a value and is not required); FileInput provided no means for clearing an existing file from a FileField.

ClearableFileInput is now the default widget for a FileField, so existing forms including FileField without assigning a custom widget will need to account for the possible extra checkbox in the rendered form output.

To return to the previous rendering (without the ability to clear the FileField), use the FileInput widget in place of ClearableFileInput. For instance, in a ModelForm for a hypothetical Document model with a FileField named document:

from django import forms
from myapp.models import Document

class DocumentForm(forms.ModelForm):
class Meta:
model = Document
widgets = {'document': forms.FileInput}

New index on database session table

Prior to Django 1.3, the database table used by the database backend for the sessions app had no index on the expire_date column. As a result, date-based queries on the session table – such as the query that is needed to purge old sessions – would be very slow if there were lots of sessions.

If you have an existing project that is using the database session backend, you don’t have to do anything to accommodate this change. However, you may get a significant performance boost if you manually add the new index to the session table. The SQL that will add the index can be found by running the sqlindexes admin command:

python manage.py sqlindexes sessions

No more naughty words

Django has historically provided (and enforced) a list of profanities. The comments app has enforced this list of profanities, preventing people from submitting comments that contained one of those profanities.

Unfortunately, the technique used to implement this profanities list was woefully naive, and prone to the Scunthorpe problem. Improving the built-in filter to fix this problem would require significant effort, and since natural language processing isn’t the normal domain of a web framework, we have “fixed” the problem by making the list of prohibited words an empty list.

If you want to restore the old behavior, simply put a PROFANITIES_LIST setting in your settings file that includes the words that you want to prohibit (see the commit that implemented this change if you want to see the list of words that was historically prohibited). However, if avoiding profanities is important to you, you would be well advised to seek out a better, less naive approach to the problem.

Localflavor changes

Django 1.3 introduces the following backwards-incompatible changes to local flavors:

- Canada (ca) – The province “Newfoundland and Labrador” has had its province code updated to “NL”, rather than the older “NF”. In addition, the Yukon Territory has had its province code corrected to “YT”, instead of “YK”.

- Indonesia (id) – The province “Nanggroe Aceh Darussalam (NAD)” has been removed from the province list in favor of the new official designation “Aceh (ACE)”.

- United States of America (us) – The list of “states” used by USStateField has expanded to include Armed Forces postal codes. This is backwards-incompatible if you were relying on USStateField not including them.

FormSet updates

In Django 1.3 FormSet creation behavior is modified slightly. Historically the class didn’t make a distinction between not being passed data and being passed empty dictionary. This was inconsistent with behavior in other parts of the framework. Starting with 1.3 if you pass in empty dictionary the FormSet will raise a ValidationError.

For example with a FormSet:

>>> class ArticleForm(Form):
...     title = CharField()
...     pub_date = DateField()
>>> ArticleFormSet = formset_factory(ArticleForm)

the following code will raise a ValidationError:

>>> ArticleFormSet({})
Traceback (most recent call last):
...
ValidationError: [u'ManagementForm data is missing or has been tampered with']

if you need to instantiate an empty FormSet, don’t pass in the data or use None:

>>> formset = ArticleFormSet()
>>> formset = ArticleFormSet(data=None)

Callables in templates

Previously, a callable in a template would only be called automatically as part of the variable resolution process if it was retrieved via attribute lookup. This was an inconsistency that could result in confusing and unhelpful behavior:

>>> Template("{{ user.get_full_name }}").render(Context({'user': user}))
u'Joe Bloggs'
>>> Template("{{ full_name }}").render(Context({'full_name': user.get_full_name}))
u'&lt;bound method User.get_full_name of &lt;...

This has been resolved in Django 1.3 - the result in both cases will be u'Joe Bloggs'. Although the previous behavior was not useful for a template language designed for web designers, and was never deliberately supported, it is possible that some templates may be broken by this change.

Use of custom SQL to load initial data in tests

Django provides a custom SQL hooks as a way to inject hand-crafted SQL into the database synchronization process. One of the possible uses for this custom SQL is to insert data into your database. If your custom SQL contains INSERT statements, those insertions will be performed every time your database is synchronized. This includes the synchronization of any test databases that are created when you run a test suite.

However, in the process of testing the Django 1.3, it was discovered that this feature has never completely worked as advertised. When using database backends that don’t support transactions, or when using a TransactionTestCase, data that has been inserted using custom SQL will not be visible during the testing process.

Unfortunately, there was no way to rectify this problem without introducing a backwards incompatibility. Rather than leave SQL-inserted initial data in an uncertain state, Django now enforces the policy that data inserted by custom SQL will not be visible during testing.

This change only affects the testing process. You can still use custom SQL to load data into your production database as part of the syncdb process. If you require data to exist during test conditions, you should either insert it using test fixtures, or using the setUp() method of your test case.

Changed priority of translation loading

Work has been done to simplify, rationalize and properly document the algorithm used by Django at runtime to build translations from the different translations found on disk, namely:

For translatable literals found in Python code and templates ('django' gettext domain):

- Priorities of translations included with applications listed in the INSTALLED_APPS setting were changed. To provide a behavior consistent with other parts of Django that also use such setting (templates, etc.) now, when building the translation that will be made available, the apps listed first have higher precedence than the ones listed later.

- Now it is possible to override the translations shipped with applications by using the LOCALE_PATHS setting whose translations have now higher precedence than the translations of INSTALLED_APPS applications. The relative priority among the values listed in this setting has also been modified so the paths listed first have higher precedence than the ones listed later.

- The locale subdirectory of the directory containing the settings, that usually coincides with and is known as the project directory is being deprecated in this release as a source of translations. (the precedence of these translations is intermediate between applications and LOCALE_PATHS translations). See the corresponding deprecated features section of this document.

For translatable literals found in JavaScript code ('djangojs' gettext domain):

- Similarly to the 'django' domain translations: Overriding of translations shipped with applications by using the LOCALE_PATHS setting is now possible for this domain too. These translations have higher precedence than the translations of Python packages passed to the javascript_catalog view. Paths listed first have higher precedence than the ones listed later.

- Translations under the locale subdirectory of the project directory have never been taken in account for JavaScript translations and remain in the same situation considering the deprecation of such location.

Transaction management

When using managed transactions – that is, anything but the default autocommit mode – it is important when a transaction is marked as “dirty”. Dirty transactions are committed by the commit_on_success decorator or the django.middleware.transaction.TransactionMiddleware, and commit_manually forces them to be closed explicitly; clean transactions “get a pass”, which means they are usually rolled back at the end of a request when the connection is closed.

Until Django 1.3, transactions were only marked dirty when Django was aware of a modifying operation performed in them; that is, either some model was saved, some bulk update or delete was performed, or the user explicitly called transaction.set_dirty(). In Django 1.3, a transaction is marked dirty when any database operation is performed.

As a result of this change, you no longer need to set a transaction dirty explicitly when you execute raw SQL or use a data-modifying SELECT. However, you do need to explicitly close any read-only transactions that are being managed using commit_manually(). For example:

@transaction.commit_manually
def my_view(request, name):
obj = get_object_or_404(MyObject, name__iexact=name)
return render_to_response('template', {'object':obj})

Prior to Django 1.3, this would work without error. However, under Django 1.3, this will raise a TransactionManagementError because the read operation that retrieves the MyObject instance leaves the transaction in a dirty state.

No password reset for inactive users

Prior to Django 1.3, inactive users were able to request a password reset email and reset their password. In Django 1.3 inactive users will receive the same message as a nonexistent account.

Password reset view now accepts from_email

The django.contrib.auth.views.password_reset() view now accepts a from_email parameter, which is passed to the password_reset_form’s save() method as a keyword argument. If you are using this view with a custom password reset form, then you will need to ensure your form’s save() method accepts this keyword argument.

Features deprecated in 1.3

Django 1.3 deprecates some features from earlier releases. These features are still supported, but will be gradually phased out over the next few release cycles.

Code taking advantage of any of the features below will raise a PendingDeprecationWarning in Django 1.3. This warning will be silent by default, but may be turned on using Python’s warnings module, or by running Python with a -Wd or -Wall flag.

In Django 1.4, these warnings will become a DeprecationWarning, which is not silent. In Django 1.5 support for these features will be removed entirely.

See also

For more details, see the documentation Django’s release process and our deprecation timeline.

mod_python support

The mod_python library has not had a release since 2007 or a commit since 2008. The Apache Foundation board voted to remove mod_python from the set of active projects in its version control repositories, and its lead developer has shifted all of his efforts toward the lighter, slimmer, more stable, and more flexible mod_wsgi backend.

If you are currently using the mod_python request handler, you should redeploy your Django projects using another request handler. mod_wsgi is the request handler recommended by the Django project, but FastCGI is also supported. Support for mod_python deployment will be removed in Django 1.5.

Function-based generic views

As a result of the introduction of class-based generic views, the function-based generic views provided by Django have been deprecated. The following modules and the views they contain have been deprecated:

- django.views.generic.create_update

- django.views.generic.date_based

- django.views.generic.list_detail

- django.views.generic.simple

Test client response template attribute

Django’s test client returns Response objects annotated with extra testing information. In Django versions prior to 1.3, this included a template attribute containing information about templates rendered in generating the response: either None, a single Template object, or a list of Template objects. This inconsistency in return values (sometimes a list, sometimes not) made the attribute difficult to work with.

In Django 1.3 the template attribute is deprecated in favor of a new templates attribute, which is always a list, even if it has only a single element or no elements.

DjangoTestRunner

As a result of the introduction of support for unittest2, the features of django.test.simple.DjangoTestRunner (including fail-fast and Ctrl-C test termination) have been made redundant. In view of this redundancy, DjangoTestRunner has been turned into an empty placeholder class, and will be removed entirely in Django 1.5.

Changes to url and ssi

Changes to url and ssi

Most template tags will allow you to pass in either constants or variables as arguments – for example:

{% extends "base.html" %}

allows you to specify a base template as a constant, but if you have a context variable templ that contains the value base.html:

{% extends templ %}

is also legal.

However, due to an accident of history, the url and ssi are different. These tags use the second, quoteless syntax, but interpret the argument as a constant. This means it isn’t possible to use a context variable as the target of a url and ssi tag.

Django 1.3 marks the start of the process to correct this historical accident. Django 1.3 adds a new template library – future – that provides alternate implementations of the url and ssi template tags. This future library implement behavior that makes the handling of the first argument consistent with the handling of all other variables. So, an existing template that contains:

{% url sample %}

should be replaced with:

{% load url from future %}
{% url 'sample' %}

The tags implementing the old behavior have been deprecated, and in Django 1.5, the old behavior will be replaced with the new behavior. To ensure compatibility with future versions of Django, existing templates should be modified to use the new future libraries and syntax.

Changes to the login methods of the admin

In previous version the admin app defined login methods in multiple locations and ignored the almost identical implementation in the already used auth app. A side effect of this duplication was the missing adoption of the changes made in r12634 to support a broader set of characters for usernames.

This release refactors the admin’s login mechanism to use a subclass of the AuthenticationForm instead of a manual form validation. The previously undocumented method 'django.contrib.admin.sites.AdminSite.display_login_form' has been removed in favor of a new login_form attribute.

reset and sqlreset management commands

Those commands have been deprecated. The flush and sqlflush commands can be used to delete everything. You can also use ALTER TABLE or DROP TABLE statements manually.

GeoDjango

- The function-based TEST_RUNNER previously used to execute the GeoDjango test suite, django.contrib.gis.tests.run_gis_tests, was deprecated for the class-based runner, django.contrib.gis.tests.GeoDjangoTestSuiteRunner.

- Previously, calling transform() would silently do nothing when GDAL wasn’t available. Now, a GEOSException is properly raised to indicate possible faulty application code. A warning is now raised if transform() is called when the SRID of the geometry is less than 0 or None.

CZBirthNumberField.clean

Previously this field’s clean() method accepted a second, gender, argument which allowed stronger validation checks to be made, however since this argument could never actually be passed from the Django form machinery it is now pending deprecation.

CompatCookie

Previously, django.http exposed an undocumented CompatCookie class, which was a bugfix wrapper around the standard library SimpleCookie. As the fixes are moving upstream, this is now deprecated - you should use from django.http import SimpleCookie instead.

Loading of project-level translations

This release of Django starts the deprecation process for inclusion of translations located under the so-called project path in the translation building process performed at runtime. The LOCALE_PATHS setting can be used for the same task by adding the filesystem path to a locale directory containing project-level translations to the value of that setting.

Rationale for this decision:

- The project path has always been a loosely defined concept (actually, the directory used for locating project-level translations is the directory containing the settings module) and there has been a shift in other parts of the framework to stop using it as a reference for location of assets at runtime.

- Detection of the locale subdirectory tends to fail when the deployment scenario is more complex than the basic one. e.g. it fails when the settings module is a directory (ticket #10765).

- There are potential strange development- and deployment-time problems like the fact that the project_dir/locale/ subdir can generate spurious error messages when the project directory is added to the Python path (manage.py runserver does this) and then it clashes with the equally named standard library module, this is a typical warning message:

/usr/lib/python2.6/gettext.py:49: ImportWarning: Not importing directory '/path/to/project/locale': missing __init__.py.
import locale, copy, os, re, struct, sys

- This location wasn’t included in the translation building process for JavaScript literals. This deprecation removes such inconsistency.

PermWrapper moved to django.contrib.auth.context_processors

In Django 1.2, we began the process of changing the location of the auth context processor from django.core.context_processors to django.contrib.auth.context_processors. However, the PermWrapper support class was mistakenly omitted from that migration. In Django 1.3, the PermWrapper class has also been moved to django.contrib.auth.context_processors, along with the PermLookupDict support class. The new classes are functionally identical to their old versions; only the module location has changed.

Removal of XMLField

When Django was first released, Django included an XMLField that performed automatic XML validation for any field input. However, this validation function hasn’t been performed since the introduction of newforms, prior to the 1.0 release. As a result, XMLField as currently implemented is functionally indistinguishable from a simple TextField.

For this reason, Django 1.3 has fast-tracked the deprecation of XMLField – instead of a two-release deprecation, XMLField will be removed entirely in Django 1.4.

It’s easy to update your code to accommodate this change – just replace all uses of XMLField with TextField, and remove the schema_path keyword argument (if it is specified).

Django 1.2.7 release notes

September 10, 2011

Welcome to Django 1.2.7!

This is the seventh bugfix/security release in the Django 1.2 series. It replaces Django 1.2.6 due to problems with the 1.2.6 release tarball. Django 1.2.7 is a recommended upgrade for all users of any Django release in the 1.2.X series.

For more information, see the release advisory.

Django 1.2.6 release notes

September 9, 2011

Welcome to Django 1.2.6!

This is the sixth bugfix/security release in the Django 1.2 series, fixing several security issues present in Django 1.2.5. Django 1.2.6 is a recommended upgrade for all users of any Django release in the 1.2.X series.

For a full list of issues addressed in this release, see the security advisory.

Django 1.2.5 release notes

Welcome to Django 1.2.5!

This is the fifth “bugfix” release in the Django 1.2 series, improving the stability and performance of the Django 1.2 codebase.

With four exceptions, Django 1.2.5 maintains backwards compatibility with Django 1.2.4. It also contains a number of fixes and other improvements. Django 1.2.5 is a recommended upgrade for any development or deployment currently using or targeting Django 1.2.

For full details on the new features, backwards incompatibilities, and deprecated features in the 1.2 branch, see the Django 1.2 release notes.

Backwards incompatible changes

CSRF exception for AJAX requests

Django includes a CSRF-protection mechanism, which makes use of a token inserted into outgoing forms. Middleware then checks for the token’s presence on form submission, and validates it.

Prior to Django 1.2.5, our CSRF protection made an exception for AJAX requests, on the following basis:

- Many AJAX toolkits add an X-Requested-With header when using XMLHttpRequest.

- Browsers have strict same-origin policies regarding XMLHttpRequest.

- In the context of a browser, the only way that a custom header of this nature can be added is with XMLHttpRequest.

Therefore, for ease of use, we did not apply CSRF checks to requests that appeared to be AJAX on the basis of the X-Requested-With header. The Ruby on Rails web framework had a similar exemption.

Recently, engineers at Google made members of the Ruby on Rails development team aware of a combination of browser plugins and redirects which can allow an attacker to provide custom HTTP headers on a request to any website. This can allow a forged request to appear to be an AJAX request, thereby defeating CSRF protection which trusts the same-origin nature of AJAX requests.

Michael Koziarski of the Rails team brought this to our attention, and we were able to produce a proof-of-concept demonstrating the same vulnerability in Django’s CSRF handling.

To remedy this, Django will now apply full CSRF validation to all requests, regardless of apparent AJAX origin. This is technically backwards-incompatible, but the security risks have been judged to outweigh the compatibility concerns in this case.

Additionally, Django will now accept the CSRF token in the custom HTTP header X-CSRFTOKEN, as well as in the form submission itself, for ease of use with popular JavaScript toolkits which allow insertion of custom headers into all AJAX requests.

Please see the CSRF docs for example jQuery code that demonstrates this technique, ensuring that you are looking at the documentation for your version of Django, as the exact code necessary is different for some older versions of Django.

FileField no longer deletes files

In earlier Django versions, when a model instance containing a FileField was deleted, FileField took it upon itself to also delete the file from the backend storage. This opened the door to several potentially serious data-loss scenarios, including rolled-back transactions and fields on different models referencing the same file. In Django 1.2.5, FileField will never delete files from the backend storage. If you need cleanup of orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).

Use of custom SQL to load initial data in tests

Django provides a custom SQL hooks as a way to inject hand-crafted SQL into the database synchronization process. One of the possible uses for this custom SQL is to insert data into your database. If your custom SQL contains INSERT statements, those insertions will be performed every time your database is synchronized. This includes the synchronization of any test databases that are created when you run a test suite.

However, in the process of testing the Django 1.3, it was discovered that this feature has never completely worked as advertised. When using database backends that don’t support transactions, or when using a TransactionTestCase, data that has been inserted using custom SQL will not be visible during the testing process.

Unfortunately, there was no way to rectify this problem without introducing a backwards incompatibility. Rather than leave SQL-inserted initial data in an uncertain state, Django now enforces the policy that data inserted by custom SQL will not be visible during testing.

This change only affects the testing process. You can still use custom SQL to load data into your production database as part of the syncdb process. If you require data to exist during test conditions, you should either insert it using test fixtures, or using the setUp() method of your test case.

ModelAdmin.lookup_allowed signature changed

Django 1.2.4 introduced a method lookup_allowed on ModelAdmin, to cope with a security issue (changeset [15033]). Although this method was never documented, it seems some people have overridden lookup_allowed, especially to cope with regressions introduced by that changeset. While the method is still undocumented and not marked as stable, it may be helpful to know that the signature of this function has changed.

Django 1.2.4 release notes

Welcome to Django 1.2.4!

This is the fourth “bugfix” release in the Django 1.2 series, improving the stability and performance of the Django 1.2 codebase.

With one exception, Django 1.2.4 maintains backwards compatibility with Django 1.2.3. It also contains a number of fixes and other improvements. Django 1.2.4 is a recommended upgrade for any development or deployment currently using or targeting Django 1.2.

For full details on the new features, backwards incompatibilities, and deprecated features in the 1.2 branch, see the Django 1.2 release notes.

Backwards incompatible changes

Restricted filters in admin interface

The Django administrative interface, django.contrib.admin, supports filtering of displayed lists of objects by fields on the corresponding models, including across database-level relationships. This is implemented by passing lookup arguments in the querystring portion of the URL, and options on the ModelAdmin class allow developers to specify particular fields or relationships which will generate automatic links for filtering.

One historically-undocumented and -unofficially-supported feature has been the ability for a user with sufficient knowledge of a model’s structure and the format of these lookup arguments to invent useful new filters on the fly by manipulating the querystring.

However, it has been demonstrated that this can be abused to gain access to information outside of an admin user’s permissions; for example, an attacker with access to the admin and sufficient knowledge of model structure and relations could construct query strings which – with repeated use of regular-expression lookups supported by the Django database API – expose sensitive information such as users’ password hashes.

To remedy this, django.contrib.admin will now validate that querystring lookup arguments either specify only fields on the model being viewed, or cross relations which have been explicitly whitelisted by the application developer using the pre-existing mechanism mentioned above. This is backwards-incompatible for any users relying on the prior ability to insert arbitrary lookups.

One new feature

Ordinarily, a point release would not include new features, but in the case of Django 1.2.4, we have made an exception to this rule.

One of the bugs fixed in Django 1.2.4 involves a set of circumstances whereby a running a test suite on a multiple database configuration could cause the original source database (i.e., the actual production database) to be dropped, causing catastrophic loss of data. In order to provide a fix for this problem, it was necessary to introduce a new setting – TEST_DEPENDENCIES – that allows you to define any creation order dependencies in your database configuration.

Most users – even users with multiple-database configurations – need not be concerned about the data loss bug, or the manual configuration of TEST_DEPENDENCIES. See the original problem report documentation on controlling the creation order of test databases for details.

GeoDjango

The function-based TEST_RUNNER previously used to execute the GeoDjango test suite, django.contrib.gis.tests.run_gis_tests, was finally deprecated in favor of a class-based test runner, django.contrib.gis.tests.GeoDjangoTestSuiteRunner, added in this release.

In addition, the GeoDjango test suite is now included when running the Django test suite with runtests.py and using spatial database backends.

Django 1.2.3 release notes

Django 1.2.3 fixed a couple of release problems in the 1.2.2 release and was released two days after 1.2.2.

This release corrects the following problems:

- The patch applied for the security issue covered in Django 1.2.2 caused issues with non-ASCII responses using CSRF tokens.

- The patch also caused issues with some forms, most notably the user-editing forms in the Django administrative interface.

- The packaging manifest did not contain the full list of required files.

Django 1.2.2 release notes

Welcome to Django 1.2.2!

This is the second “bugfix” release in the Django 1.2 series, improving the stability and performance of the Django 1.2 codebase.

Django 1.2.2 maintains backwards compatibility with Django 1.2.1, but contain a number of fixes and other improvements. Django 1.2.2 is a recommended upgrade for any development or deployment currently using or targeting Django 1.2.

For full details on the new features, backwards incompatibilities, and deprecated features in the 1.2 branch, see the Django 1.2 release notes.

One new feature

Ordinarily, a point release would not include new features, but in the case of Django 1.2.2, we have made an exception to this rule.

In order to test a bug fix that forms part of the 1.2.2 release, it was necessary to add a feature – the enforce_csrf_checks flag – to the test client. This flag forces the test client to perform full CSRF checks on forms. The default behavior of the test client hasn’t changed, but if you want to do CSRF checks with the test client, it is now possible to do so.

Django 1.2.1 release notes

Django 1.2.1 was released almost immediately after 1.2.0 to correct two small bugs: one was in the documentation packaging script, the other was a bug that affected datetime form field widgets when localization was enabled.

Django 1.2 release notes

May 17, 2010.

Welcome to Django 1.2!

Nearly a year in the making, Django 1.2 packs an impressive list of new features and lots of bug fixes. These release notes cover the new features, as well as important changes you’ll want to be aware of when upgrading from Django 1.1 or older versions.

Overview

Django 1.2 introduces several large, important new features, including:

- Support for multiple database connections in a single Django instance.

- Model validation inspired by Django’s form validation.

- Vastly improved protection against Cross-Site Request Forgery (CSRF).

- A new user “messages” framework with support for cookie- and session-based message for both anonymous and authenticated users.

- Hooks for object-level permissions, permissions for anonymous users, and more flexible username requirements.

- Customization of email sending via email backends.

- New “smart” if template tag which supports comparison operators.

These are just the highlights; full details and a complete list of features may be found below.

See also

Django Advent covered the release of Django 1.2 with a series of articles and tutorials that cover some of the new features in depth.

Wherever possible these features have been introduced in a backwards-compatible manner per our API stability policy policy.

However, a handful of features have changed in ways that, for some users, will be backwards-incompatible. The big changes are:

- Support for Python 2.3 has been dropped. See the full notes below.

- The new CSRF protection framework is not backwards-compatible with the old system. Users of the old system will not be affected until the old system is removed in Django 1.4.

However, upgrading to the new CSRF protection framework requires a few important backwards-incompatible changes, detailed in CSRF Protection, below.

- Authors of custom Field subclasses should be aware that a number of methods have had a change in prototype, detailed under get_db_prep_*() methods on Field, below.

- The internals of template tags have changed somewhat; authors of custom template tags that need to store state (e.g. custom control flow tags) should ensure that their code follows the new rules for stateful template tags

- The user_passes_test(), login_required(), and permission_required(), decorators from django.contrib.auth only apply to functions and no longer work on methods. There’s a simple one-line fix detailed below.

Again, these are just the big features that will affect the most users. Users upgrading from previous versions of Django are heavily encouraged to consult the complete list of backwards-incompatible changes and the list of deprecated features.

Python compatibility

While not a new feature, it’s important to note that Django 1.2 introduces the first shift in our Python compatibility policy since Django’s initial public debut. Previous Django releases were tested and supported on 2.x Python versions from 2.3 up; Django 1.2, however, drops official support for Python 2.3. As such, the minimum Python version required for Django is now 2.4, and Django is tested and supported on Python 2.4, 2.5 and 2.6, and will be supported on the as-yet-unreleased Python 2.7.

This change should affect only a small number of Django users, as most operating-system vendors today are shipping Python 2.4 or newer as their default version. If you’re still using Python 2.3, however, you’ll need to stick to Django 1.1 until you can upgrade; per our support policy, Django 1.1 will continue to receive security support until the release of Django 1.3.

A roadmap for Django’s overall 2.x Python support, and eventual transition to Python 3.x, is currently being developed, and will be announced prior to the release of Django 1.3.

What’s new in Django 1.2

Support for multiple databases

Django 1.2 adds the ability to use more than one database in your Django project. Queries can be issued at a specific database with the using() method on QuerySet objects. Individual objects can be saved to a specific database by providing a using argument when you call save().

Model validation

Model instances now have support for validating their own data, and both model and form fields now accept configurable lists of validators specifying reusable, encapsulated validation behavior. Note, however, that validation must still be performed explicitly. Simply invoking a model instance’s save() method will not perform any validation of the instance’s data.

Improved CSRF protection

Django now has much improved protection against Cross-Site Request Forgery (CSRF) attacks. This type of attack occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials of a logged-in user who visits the malicious site in their browser. A related type of attack, “login CSRF,” where an attacking site tricks a user’s browser into logging into a site with someone else’s credentials, is also covered.

Messages framework

Django now includes a robust and configurable messages framework with built-in support for cookie- and session-based messaging, for both anonymous and authenticated clients. The messages framework replaces the deprecated user message API and allows you to temporarily store messages in one request and retrieve them for display in a subsequent request (usually the next one).

Object-level permissions

A foundation for specifying permissions at the per-object level has been added. Although there is no implementation of this in core, a custom authentication backend can provide this implementation and it will be used by django.contrib.auth.models.User. See the authentication docs for more information.

Permissions for anonymous users

If you provide a custom auth backend with supports_anonymous_user set to True, AnonymousUser will check the backend for permissions, just like User already did. This is useful for centralizing permission handling - apps can always delegate the question of whether something is allowed or not to the authorization/authentication backend. See the authentication docs for more details.

Relaxed requirements for usernames

The built-in User model’s username field now allows a wider range of characters, including @, +, . and - characters.

Email backends

You can now configure the way that Django sends email. Instead of using SMTP to send all email, you can now choose a configurable email backend to send messages. If your hosting provider uses a sandbox or some other non-SMTP technique for sending mail, you can now construct an email backend that will allow Django’s standard mail sending methods to use those facilities.

This also makes it easier to debug mail sending. Django ships with backend implementations that allow you to send email to a file, to the console, or to memory. You can even configure all email to be thrown away.

“Smart” if tag

The if tag has been upgraded to be much more powerful. First, we’ve added support for comparison operators. No longer will you have to type:

{% ifnotequal a b %}
...
{% endifnotequal %}

You can now do this:

{% if a != b %}
...
{% endif %}

There’s really no reason to use {% ifequal %} or {% ifnotequal %} anymore, unless you’re the nostalgic type.

The operators supported are ==, !=, <, >, <=, >=, in and not in, all of which work like the Python operators, in addition to and, or and not, which were already supported.

Also, filters may now be used in the if expression. For example:

<div
{% if user.email|lower == message.recipient|lower %}
class="highlight"
{% endif %}
>{{ message }}</div>

Template caching

In previous versions of Django, every time you rendered a template, it would be reloaded from disk. In Django 1.2, you can use a cached template loader to load templates once, then cache the result for every subsequent render. This can lead to a significant performance improvement if your templates are broken into lots of smaller subtemplates (using the {% extends %} or {% include %} tags).

As a side effect, it is now much easier to support non-Django template languages.

Class-based template loaders

As part of the changes made to introduce Template caching and following a general trend in Django, the template loaders API has been modified to use template loading mechanisms that are encapsulated in Python classes as opposed to functions, the only method available until Django 1.1.

All the template loaders shipped with Django have been ported to the new API but they still implement the function-based API and the template core machinery still accepts function-based loaders (builtin or third party) so there is no immediate need to modify your TEMPLATE_LOADERS setting in existing projects, things will keep working if you leave it untouched up to and including the Django 1.3 release.

If you have developed your own custom template loaders we suggest to consider porting them to a class-based implementation because the code for backwards compatibility with function-based loaders starts its deprecation process in Django 1.2 and will be removed in Django 1.4. There is a description of the API these loader classes must implement in the template API reference and you can also examine the source code of the loaders shipped with Django.

Natural keys in fixtures

Fixtures can now refer to remote objects using Natural keys. This lookup scheme is an alternative to the normal primary-key based object references in a fixture, improving readability and resolving problems referring to objects whose primary key value may not be predictable or known.

Fast failure for tests

Both the test subcommand of django-admin.py and the runtests.py script used to run Django’s own test suite now support a --failfast option. When specified, this option causes the test runner to exit after encountering a failure instead of continuing with the test run. In addition, the handling of Ctrl-C during a test run has been improved to trigger a graceful exit from the test run that reports details of the tests that were run before the interruption.

BigIntegerField

Models can now use a 64-bit BigIntegerField type.

Improved localization

Django’s internationalization framework has been expanded with locale-aware formatting and form processing. That means, if enabled, dates and numbers on templates will be displayed using the format specified for the current locale. Django will also use localized formats when parsing data in forms. See Format localization for more details.

readonly_fields in ModelAdmin

django.contrib.admin.ModelAdmin.readonly_fields has been added to enable non-editable fields in add/change pages for models and inlines. Field and calculated values can be displayed alongside editable fields.

Customizable syntax highlighting

You can now use a DJANGO_COLORS environment variable to modify or disable the colors used by django-admin.py to provide syntax highlighting.

Syndication feeds as views

Syndication feeds can now be used directly as views in your URLconf. This means that you can maintain complete control over the URL structure of your feeds. Like any other view, feeds views are passed a request object, so you can do anything you would normally do with a view, like user based access control, or making a feed a named URL.

GeoDjango

The most significant new feature for GeoDjango in 1.2 is support for multiple spatial databases. As a result, the following spatial database backends are now included:

- django.contrib.gis.db.backends.postgis

- django.contrib.gis.db.backends.mysql

- django.contrib.gis.db.backends.oracle

- django.contrib.gis.db.backends.spatialite

GeoDjango now supports the rich capabilities added in the PostGIS 1.5 release. New features include support for the geography type and enabling of distance queries with non-point geometries on geographic coordinate systems.

Support for 3D geometry fields was added, and may be enabled by setting the dim keyword to 3 in your GeometryField. The Extent3D aggregate and extent3d() GeoQuerySet method were added as a part of this feature.

The following GeoQuerySet methods are new in 1.2:

- force_rhr()

- reverse_geom()

- geohash()

The GEOS interface was updated to use thread-safe C library functions when available on the platform.

The GDAL interface now allows the user to set a spatial_filter on the features returned when iterating over a Layer.

Finally, GeoDjango’s documentation is now included with Django’s and is no longer hosted separately at geodjango.org.

JavaScript-assisted handling of inline related objects in the admin

If a user has JavaScript enabled in their browser, the interface for inline objects in the admin now allows inline objects to be dynamically added and removed. Users without JavaScript-enabled browsers will see no change in the behavior of inline objects.

New now template tag format specifier characters: c and u

The argument to the now has gained two new format characters: c to specify that a datetime value should be formatted in ISO 8601 format, and u that allows output of the microseconds part of a datetime or time value.

These are also available in others parts like the date and time template filters, the humanize template tag library and the new format localization framework.

Backwards-incompatible changes in 1.2

Wherever possible the new features above have been introduced in a backwards-compatible manner per our API stability policy policy. This means that practically all existing code which worked with Django 1.1 will continue to work with Django 1.2; such code will, however, begin issuing warnings (see below for details).

However, a handful of features have changed in ways that, for some users, will be immediately backwards-incompatible. Those changes are detailed below.

CSRF Protection

We’ve made large changes to the way CSRF protection works, detailed in the CSRF documentation. Here are the major changes you should be aware of:

- CsrfResponseMiddleware and CsrfMiddleware have been deprecated and will be removed completely in Django 1.4, in favor of a template tag that should be inserted into forms.

- All contrib apps use a csrf_protect decorator to protect the view. This requires the use of the csrf_token template tag in the template. If you have used custom templates for contrib views, you MUST READ THE UPGRADE INSTRUCTIONS to fix those templates.

Documentation removed

The upgrade notes have been removed in current Django docs. Please refer to the docs for Django 1.3 or older to find these instructions.

- CsrfViewMiddleware is included in MIDDLEWARE_CLASSES by default. This turns on CSRF protection by default, so views that accept POST requests need to be written to work with the middleware. Instructions on how to do this are found in the CSRF docs.

- All of the CSRF has moved from contrib to core (with backwards compatible imports in the old locations, which are deprecated and will cease to be supported in Django 1.4).

get_db_prep_*() methods on Field

Prior to Django 1.2, a custom Field had the option of defining several functions to support conversion of Python values into database-compatible values. A custom field might look something like:

class CustomModelField(models.Field):
# ...
def db_type(self):
# ...

def get_db_prep_save(self, value):
# ...

def get_db_prep_value(self, value):
# ...

def get_db_prep_lookup(self, lookup_type, value):
# ...

In 1.2, these three methods have undergone a change in prototype, and two extra methods have been introduced:

class CustomModelField(models.Field):
# ...

def db_type(self, connection):
# ...

def get_prep_value(self, value):
# ...

def get_prep_lookup(self, lookup_type, value):
# ...

def get_db_prep_save(self, value, connection):
# ...

def get_db_prep_value(self, value, connection, prepared=False):
# ...

def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
# ...

These changes are required to support multiple databases – db_type and get_db_prep_* can no longer make any assumptions regarding the database for which it is preparing. The connection argument now provides the preparation methods with the specific connection for which the value is being prepared.

The two new methods exist to differentiate general data-preparation requirements from requirements that are database-specific. The prepared argument is used to indicate to the database-preparation methods whether generic value preparation has been performed. If an unprepared (i.e., prepared=False) value is provided to the get_db_prep_*() calls, they should invoke the corresponding get_prep_*() calls to perform generic data preparation.

We’ve provided conversion functions that will transparently convert functions adhering to the old prototype into functions compatible with the new prototype. However, these conversion functions will be removed in Django 1.4, so you should upgrade your Field definitions to use the new prototype as soon as possible.

If your get_db_prep_*() methods made no use of the database connection, you should be able to upgrade by renaming get_db_prep_value() to get_prep_value() and get_db_prep_lookup() to get_prep_lookup(). If you require database specific conversions, then you will need to provide an implementation get_db_prep_* that uses the connection argument to resolve database-specific values.

Stateful template tags

Template tags that store rendering state on their Node subclass have always been vulnerable to thread-safety and other issues; as of Django 1.2, however, they may also cause problems when used with the new cached template loader.

All of the built-in Django template tags are safe to use with the cached loader, but if you’re using custom template tags that come from third party packages, or from your own code, you should ensure that the Node implementation for each tag is thread-safe. For more information, see template tag thread safety considerations.

You may also need to update your templates if you were relying on the implementation of Django’s template tags not being thread safe. The cycle tag is the most likely to be affected in this way, especially when used in conjunction with the include tag. Consider the following template fragment:

{% for object in object_list %}
{% include "subtemplate.html" %}
{% endfor %}

with a subtemplate.html that reads:

{% cycle 'even' 'odd' %}

Using the non-thread-safe, pre-Django 1.2 renderer, this would output:

even odd even odd ...

Using the thread-safe Django 1.2 renderer, you will instead get:

even even even even ...

This is because each rendering of the include tag is an independent rendering. When the cycle tag was not thread safe, the state of the cycle tag would leak between multiple renderings of the same include. Now that the cycle tag is thread safe, this leakage no longer occurs.

user_passes_test, login_required and permission_required

django.contrib.auth.decorators provides the decorators login_required, permission_required and user_passes_test. Previously it was possible to use these decorators both on functions (where the first argument is ‘request’) and on methods (where the first argument is ‘self’, and the second argument is ‘request’). Unfortunately, flaws were discovered in the code supporting this: it only works in limited circumstances, and produces errors that are very difficult to debug when it does not work.

For this reason, the ‘auto adapt’ behavior has been removed, and if you are using these decorators on methods, you will need to manually apply django.utils.decorators.method_decorator() to convert the decorator to one that works with methods. For example, you would change code from this:

class MyClass(object):

@login_required
def my_view(self, request):
pass

to this:

from django.utils.decorators import method_decorator

class MyClass(object):

@method_decorator(login_required)
def my_view(self, request):
pass

or:

from django.utils.decorators import method_decorator

login_required_m = method_decorator(login_required)

class MyClass(object):

@login_required_m
def my_view(self, request):
pass

For those of you who’ve been following the development trunk, this change also applies to other decorators introduced since 1.1, including csrf_protect, cache_control and anything created using decorator_from_middleware.

if tag changes

Due to new features in the if template tag, it no longer accepts ‘and’, ‘or’ and ‘not’ as valid variable names. Previously, these strings could be used as variable names. Now, the keyword status is always enforced, and template code such as {% if not %} or {% if and %} will throw a TemplateSyntaxError. Also, in is a new keyword and so is not a valid variable name in this tag.

LazyObject

LazyObject is an undocumented-but-often-used utility class used for lazily wrapping other objects of unknown type.

In Django 1.1 and earlier, it handled introspection in a non-standard way, depending on wrapped objects implementing a public method named get_all_members(). Since this could easily lead to name clashes, it has been changed to use the standard Python introspection method, involving __members__ and __dir__().

If you used LazyObject in your own code and implemented the get_all_members() method for wrapped objects, you’ll need to make a couple of changes:

First, if your class does not have special requirements for introspection (i.e., you have not implemented __getattr__() or other methods that allow for attributes not discoverable by normal mechanisms), you can simply remove the get_all_members() method. The default implementation on LazyObject will do the right thing.

If you have more complex requirements for introspection, first rename the get_all_members() method to __dir__(). This is the standard introspection method for Python 2.6 and above. If you require support for Python versions earlier than 2.6, add the following code to the class:

__members__ = property(lambda self: self.__dir__())

__dict__ on model instances

Historically, the __dict__ attribute of a model instance has only contained attributes corresponding to the fields on a model.

In order to support multiple database configurations, Django 1.2 has added a _state attribute to object instances. This attribute will appear in __dict__ for a model instance. If your code relies on iterating over __dict__ to obtain a list of fields, you must now be prepared to handle or filter out the _state attribute.

Test runner exit status code

The exit status code of the test runners (tests/runtests.py and python manage.py test) no longer represents the number of failed tests, because a failure of 256 or more tests resulted in a wrong exit status code. The exit status code for the test runner is now 0 for success (no failing tests) and 1 for any number of test failures. If needed, the number of test failures can be found at the end of the test runner’s output.

Cookie encoding

To fix bugs with cookies in Internet Explorer, Safari, and possibly other browsers, our encoding of cookie values was changed so that the comma and semicolon are treated as non-safe characters, and are therefore encoded as \054 and \073 respectively. This could produce backwards incompatibilities, especially if you are storing comma or semi-colon in cookies and have JavaScript code that parses and manipulates cookie values client-side.

ModelForm.is_valid() and ModelForm.errors

Much of the validation work for ModelForms has been moved down to the model level. As a result, the first time you call ModelForm.is_valid(), access ModelForm.errors or otherwise trigger form validation, your model will be cleaned in-place. This conversion used to happen when the model was saved. If you need an unmodified instance of your model, you should pass a copy to the ModelForm constructor.

BooleanField on MySQL

In previous versions of Django, a model’s BooleanField under MySQL would return its value as either 1 or 0, instead of True or False; for most people this wasn’t a problem because bool is a subclass of int in Python. In Django 1.2, however, BooleanField on MySQL correctly returns a real bool. The only time this should ever be an issue is if you were expecting the repr of a BooleanField to print 1 or 0.

Changes to the interpretation of max_num in FormSets

As part of enhancements made to the handling of FormSets, the default value and interpretation of the max_num parameter to the django.forms.formsets.formset_factory() and django.forms.models.modelformset_factory() functions has changed slightly. This change also affects the way the max_num argument is used for inline admin objects.

Previously, the default value for max_num was 0 (zero). FormSets then used the boolean value of max_num to determine if a limit was to be imposed on the number of generated forms. The default value of 0 meant that there was no default limit on the number of forms in a FormSet.

Starting with 1.2, the default value for max_num has been changed to None, and FormSets will differentiate between a value of None and a value of 0. A value of None indicates that no limit on the number of forms is to be imposed; a value of 0 indicates that a maximum of 0 forms should be imposed. This doesn’t necessarily mean that no forms will be displayed – see the ModelFormSet documentation for more details.

If you were manually specifying a value of 0 for max_num, you will need to update your FormSet and/or admin definitions.

See also

JavaScript-assisted handling of inline related objects in the admin

email_re

An undocumented regular expression for validating email addresses has been moved from django.form.fields to django.core.validators. You will need to update your imports if you are using it.

Features deprecated in 1.2

Finally, Django 1.2 deprecates some features from earlier releases. These features are still supported, but will be gradually phased out over the next few release cycles.

Code taking advantage of any of the features below will raise a PendingDeprecationWarning in Django 1.2. This warning will be silent by default, but may be turned on using Python’s warnings module, or by running Python with a -Wd or -Wall flag.

In Django 1.3, these warnings will become a DeprecationWarning, which is not silent. In Django 1.4 support for these features will be removed entirely.

See also

For more details, see the documentation Django’s release process and our deprecation timeline.`

Specifying databases

Prior to Django 1.2, Django used a number of settings to control access to a single database. Django 1.2 introduces support for multiple databases, and as a result the way you define database settings has changed.

Any existing Django settings file will continue to work as expected until Django 1.4. Until then, old-style database settings will be automatically translated to the new-style format.

In the old-style (pre 1.2) format, you had a number of DATABASE_ settings in your settings file. For example:

DATABASE_NAME = 'test_db'
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_USER = 'myusername'
DATABASE_PASSWORD = 's3krit'

These settings are now in a dictionary named DATABASES. Each item in the dictionary corresponds to a single database connection, with the name 'default' describing the default database connection. The setting names have also been shortened. The previous sample settings would now look like this:

DATABASES = {
'default': {
'NAME': 'test_db',
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'USER': 'myusername',
'PASSWORD': 's3krit',
}
}

This affects the following settings:

Old setting

New Setting

DATABASE_ENGINE

ENGINE

DATABASE_HOST

HOST

DATABASE_NAME

NAME

DATABASE_OPTIONS

OPTIONS

DATABASE_PASSWORD

PASSWORD

DATABASE_PORT

PORT

DATABASE_USER

USER

TEST_DATABASE_CHARSET

TEST_CHARSET

TEST_DATABASE_COLLATION

TEST_COLLATION

TEST_DATABASE_NAME

TEST_NAME

These changes are also required if you have manually created a database connection using DatabaseWrapper() from your database backend of choice.

In addition to the change in structure, Django 1.2 removes the special handling for the built-in database backends. All database backends must now be specified by a fully qualified module name (i.e., django.db.backends.postgresql_psycopg2, rather than just postgresql_psycopg2).

postgresql database backend

The psycopg1 library has not been updated since October 2005. As a result, the postgresql database backend, which uses this library, has been deprecated.

If you are currently using the postgresql backend, you should migrate to using the postgresql_psycopg2 backend. To update your code, install the psycopg2 library and change the ENGINE setting to use django.db.backends.postgresql_psycopg2.

CSRF response-rewriting middleware

CsrfResponseMiddleware, the middleware that automatically inserted CSRF tokens into POST forms in outgoing pages, has been deprecated in favor of a template tag method (see above), and will be removed completely in Django 1.4. CsrfMiddleware, which includes the functionality of CsrfResponseMiddleware and CsrfViewMiddleware, has likewise been deprecated.

Also, the CSRF module has moved from contrib to core, and the old imports are deprecated, as described in the upgrading notes.

Documentation removed

The upgrade notes have been removed in current Django docs. Please refer to the docs for Django 1.3 or older to find these instructions.

SMTPConnection

The SMTPConnection class has been deprecated in favor of a generic email backend API. Old code that explicitly instantiated an instance of an SMTPConnection:

from django.core.mail import SMTPConnection
connection = SMTPConnection()
messages = get_notification_email()
connection.send_messages(messages)

...should now call get_connection() to instantiate a generic email connection:

from django.core.mail import get_connection
connection = get_connection()
messages = get_notification_email()
connection.send_messages(messages)

Depending on the value of the EMAIL_BACKEND setting, this may not return an SMTP connection. If you explicitly require an SMTP connection with which to send email, you can explicitly request an SMTP connection:

from django.core.mail import get_connection
connection = get_connection('django.core.mail.backends.smtp.EmailBackend')
messages = get_notification_email()
connection.send_messages(messages)

If your call to construct an instance of SMTPConnection required additional arguments, those arguments can be passed to the get_connection() call:

connection = get_connection('django.core.mail.backends.smtp.EmailBackend', hostname='localhost', port=1234)

User Messages API

The API for storing messages in the user Message model (via user.message_set.create) is now deprecated and will be removed in Django 1.4 according to the standard release process.

To upgrade your code, you need to replace any instances of this:

user.message_set.create('a message')

...with the following:

from django.contrib import messages
messages.add_message(request, messages.INFO, 'a message')

Additionally, if you make use of the method, you need to replace the following:

for message in user.get_and_delete_messages():
...

...with:

from django.contrib import messages
for message in messages.get_messages(request):
...

For more information, see the full messages documentation. You should begin to update your code to use the new API immediately.

Date format helper functions

django.utils.translation.get_date_formats() and django.utils.translation.get_partial_date_formats() have been deprecated in favor of the appropriate calls to django.utils.formats.get_format(), which is locale-aware when USE_L10N is set to True, and falls back to default settings if set to False.

To get the different date formats, instead of writing this:

from django.utils.translation import get_date_formats
date_format, datetime_format, time_format = get_date_formats()

...use:

from django.utils import formats
date_format = formats.get_format('DATE_FORMAT')
datetime_format = formats.get_format('DATETIME_FORMAT')
time_format = formats.get_format('TIME_FORMAT')

Or, when directly formatting a date value:

from django.utils import formats
value_formatted = formats.date_format(value, 'DATETIME_FORMAT')

The same applies to the globals found in django.forms.fields:

- DEFAULT_DATE_INPUT_FORMATS

- DEFAULT_TIME_INPUT_FORMATS

- DEFAULT_DATETIME_INPUT_FORMATS

Use django.utils.formats.get_format() to get the appropriate formats.

Function-based test runners

Django 1.2 changes the test runner tools to use a class-based approach. Old style function-based test runners will still work, but should be updated to use the new class-based runners.

Feed in django.contrib.syndication.feeds

The django.contrib.syndication.feeds.Feed class has been replaced by the django.contrib.syndication.views.Feed class. The old feeds.Feed class is deprecated, and will be removed in Django 1.4.

The new class has an almost identical API, but allows instances to be used as views. For example, consider the use of the old framework in the following URLconf:

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

feeds = {
'latest': LatestEntries,
'categories': LatestEntriesByCategory,
}

urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)

Using the new Feed class, these feeds can be deployed directly as views:

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

urlpatterns = patterns('',
# ...
(r'^feeds/latest/$', LatestEntries()),
(r'^feeds/categories/(?P<category_id>\d+)/$', LatestEntriesByCategory()),
# ...
)

If you currently use the feed() view, the LatestEntries class would often not need to be modified apart from subclassing the new Feed class. The exception is if Django was automatically working out the name of the template to use to render the feed’s description and title elements (if you were not specifying the title_template and description_template attributes). You should ensure that you always specify title_template and description_template attributes, or provide item_title() and item_description() methods.

However, LatestEntriesByCategory uses the get_object() method with the bits argument to specify a specific category to show. In the new Feed class, get_object() method takes a request and arguments from the URL, so it would look like this:

from django.contrib.syndication.views import Feed
from django.shortcuts import get_object_or_404
from myproject.models import Category

class LatestEntriesByCategory(Feed):
def get_object(self, request, category_id):
return get_object_or_404(Category, id=category_id)

# ...

Additionally, the get_feed() method on Feed classes now take different arguments, which may impact you if you use the Feed classes directly. Instead of just taking an optional url argument, it now takes two arguments: the object returned by its own get_object() method, and the current request object.

To take into account Feed classes not being initialized for each request, the __init__() method now takes no arguments by default. Previously it would have taken the slug from the URL and the request object.

In accordance with RSS best practices, RSS feeds will now include an atom:link element. You may need to update your tests to take this into account.

For more information, see the full syndication framework documentation.

Technical message IDs

Up to version 1.1 Django used technical message IDs to provide localizers the possibility to translate date and time formats. They were translatable translation strings that could be recognized because they were all upper case (for example DATETIME_FORMAT, DATE_FORMAT, TIME_FORMAT). They have been deprecated in favor of the new Format localization infrastructure that allows localizers to specify that information in a formats.py file in the corresponding django/conf/locale/<locale name>/ directory.

GeoDjango

To allow support for multiple databases, the GeoDjango database internals were changed substantially. The largest backwards-incompatible change is that the module django.contrib.gis.db.backend was renamed to django.contrib.gis.db.backends, where the full-fledged spatial database backends now exist. The following sections provide information on the most-popular APIs that were affected by these changes.

SpatialBackend

Prior to the creation of the separate spatial backends, the django.contrib.gis.db.backend.SpatialBackend object was provided as an abstraction to introspect on the capabilities of the spatial database. All of the attributes and routines provided by SpatialBackend are now a part of the ops attribute of the database backend.

The old module django.contrib.gis.db.backend is still provided for backwards-compatibility access to a SpatialBackend object, which is just an alias to the ops module of the default spatial database connection.

Users that were relying on undocumented modules and objects within django.contrib.gis.db.backend, rather the abstractions provided by SpatialBackend, are required to modify their code. For example, the following import which would work in 1.1 and below:

from django.contrib.gis.db.backend.postgis import PostGISAdaptor

Would need to be changed:

from django.db import connection
PostGISAdaptor = connection.ops.Adapter

SpatialRefSys and GeometryColumns models

In previous versions of GeoDjango, django.contrib.gis.db.models had SpatialRefSys and GeometryColumns models for querying the OGC spatial metadata tables spatial_ref_sys and geometry_columns, respectively.

While these aliases are still provided, they are only for the default database connection and exist only if the default connection is using a supported spatial database backend.

Note

Because the table structure of the OGC spatial metadata tables differs across spatial databases, the SpatialRefSys and GeometryColumns models can no longer be associated with the gis application name. Thus, no models will be returned when using the get_models method in the following example:

>>> from django.db.models import get_app, get_models
>>> get_models(get_app('gis'))
[]

To get the correct SpatialRefSys and GeometryColumns for your spatial database use the methods provided by the spatial backend:

>>> from django.db import connections
>>> SpatialRefSys = connections['my_spatialite'].ops.spatial_ref_sys()
>>> GeometryColumns = connections['my_postgis'].ops.geometry_columns()

Note

When using the models returned from the spatial_ref_sys() and geometry_columns() method, you’ll still need to use the correct database alias when querying on the non-default connection. In other words, to ensure that the models in the example above use the correct database:

sr_qs = SpatialRefSys.objects.using('my_spatialite').filter(...)
gc_qs = GeometryColumns.objects.using('my_postgis').filter(...)

Language code no

The currently used language code for Norwegian Bokmål no is being replaced by the more common language code nb.

Function-based template loaders

Django 1.2 changes the template loading mechanism to use a class-based approach. Old style function-based template loaders will still work, but should be updated to use the new class-based template loaders.

Django 1.1.4 release notes

Welcome to Django 1.1.4!

This is the fourth “bugfix” release in the Django 1.1 series, improving the stability and performance of the Django 1.1 codebase.

With one exception, Django 1.1.4 maintains backwards compatibility with Django 1.1.3. It also contains a number of fixes and other improvements. Django 1.1.4 is a recommended upgrade for any development or deployment currently using or targeting Django 1.1.

For full details on the new features, backwards incompatibilities, and deprecated features in the 1.1 branch, see the Django 1.1 release notes.

Backwards incompatible changes

CSRF exception for AJAX requests

Django includes a CSRF-protection mechanism, which makes use of a token inserted into outgoing forms. Middleware then checks for the token’s presence on form submission, and validates it.

Prior to Django 1.2.5, our CSRF protection made an exception for AJAX requests, on the following basis:

- Many AJAX toolkits add an X-Requested-With header when using XMLHttpRequest.

- Browsers have strict same-origin policies regarding XMLHttpRequest.

- In the context of a browser, the only way that a custom header of this nature can be added is with XMLHttpRequest.

Therefore, for ease of use, we did not apply CSRF checks to requests that appeared to be AJAX on the basis of the X-Requested-With header. The Ruby on Rails web framework had a similar exemption.

Recently, engineers at Google made members of the Ruby on Rails development team aware of a combination of browser plugins and redirects which can allow an attacker to provide custom HTTP headers on a request to any website. This can allow a forged request to appear to be an AJAX request, thereby defeating CSRF protection which trusts the same-origin nature of AJAX requests.

Michael Koziarski of the Rails team brought this to our attention, and we were able to produce a proof-of-concept demonstrating the same vulnerability in Django’s CSRF handling.

To remedy this, Django will now apply full CSRF validation to all requests, regardless of apparent AJAX origin. This is technically backwards-incompatible, but the security risks have been judged to outweigh the compatibility concerns in this case.

Additionally, Django will now accept the CSRF token in the custom HTTP header X-CSRFTOKEN, as well as in the form submission itself, for ease of use with popular JavaScript toolkits which allow insertion of custom headers into all AJAX requests.

Please see the CSRF docs for example jQuery code that demonstrates this technique, ensuring that you are looking at the documentation for your version of Django, as the exact code necessary is different for some older versions of Django.

Django 1.1.3 release notes

Welcome to Django 1.1.3!

This is the third “bugfix” release in the Django 1.1 series, improving the stability and performance of the Django 1.1 codebase.

With one exception, Django 1.1.3 maintains backwards compatibility with Django 1.1.2. It also contains a number of fixes and other improvements. Django 1.1.2 is a recommended upgrade for any development or deployment currently using or targeting Django 1.1.

For full details on the new features, backwards incompatibilities, and deprecated features in the 1.1 branch, see the Django 1.1 release notes.

Backwards incompatible changes

Restricted filters in admin interface

The Django administrative interface, django.contrib.admin, supports filtering of displayed lists of objects by fields on the corresponding models, including across database-level relationships. This is implemented by passing lookup arguments in the querystring portion of the URL, and options on the ModelAdmin class allow developers to specify particular fields or relationships which will generate automatic links for filtering.

One historically-undocumented and -unofficially-supported feature has been the ability for a user with sufficient knowledge of a model’s structure and the format of these lookup arguments to invent useful new filters on the fly by manipulating the querystring.

However, it has been demonstrated that this can be abused to gain access to information outside of an admin user’s permissions; for example, an attacker with access to the admin and sufficient knowledge of model structure and relations could construct query strings which – with repeated use of regular-expression lookups supported by the Django database API – expose sensitive information such as users’ password hashes.

To remedy this, django.contrib.admin will now validate that querystring lookup arguments either specify only fields on the model being viewed, or cross relations which have been explicitly whitelisted by the application developer using the pre-existing mechanism mentioned above. This is backwards-incompatible for any users relying on the prior ability to insert arbitrary lookups.

Django 1.1.2 release notes

Welcome to Django 1.1.2!

This is the second “bugfix” release in the Django 1.1 series, improving the stability and performance of the Django 1.1 codebase.

Django 1.1.2 maintains backwards compatibility with Django 1.1.0, but contain a number of fixes and other improvements. Django 1.1.2 is a recommended upgrade for any development or deployment currently using or targeting Django 1.1.

For full details on the new features, backwards incompatibilities, and deprecated features in the 1.1 branch, see the Django 1.1 release notes.

Backwards-incompatible changes in 1.1.2

Test runner exit status code

The exit status code of the test runners (tests/runtests.py and python manage.py test) no longer represents the number of failed tests, since a failure of 256 or more tests resulted in a wrong exit status code. The exit status code for the test runner is now 0 for success (no failing tests) and 1 for any number of test failures. If needed, the number of test failures can be found at the end of the test runner’s output.

Cookie encoding

To fix bugs with cookies in Internet Explorer, Safari, and possibly other browsers, our encoding of cookie values was changed so that the characters comma and semi-colon are treated as non-safe characters, and are therefore encoded as \054 and \073 respectively. This could produce backwards incompatibilities, especially if you are storing comma or semi-colon in cookies and have JavaScript code that parses and manipulates cookie values client-side.

One new feature

Ordinarily, a point release would not include new features, but in the case of Django 1.1.2, we have made an exception to this rule. Django 1.2 (the next major release of Django) will contain a feature that will improve protection against Cross-Site Request Forgery (CSRF) attacks. This feature requires the use of a new csrf_token template tag in all forms that Django renders.

To make it easier to support both 1.1.X and 1.2.X versions of Django with the same templates, we have decided to introduce the csrf_token template tag to the 1.1.X branch. In the 1.1.X branch, csrf_token does nothing - it has no effect on templates or form processing. However, it means that the same template will work with Django 1.2.

Django 1.1 release notes

July 29, 2009

Welcome to Django 1.1!

Django 1.1 includes a number of nifty new features, lots of bug fixes, and an easy upgrade path from Django 1.0.

Backwards-incompatible changes in 1.1

Django has a policy of API stability. This means that, in general, code you develop against Django 1.0 should continue to work against 1.1 unchanged. However, we do sometimes make backwards-incompatible changes if they’re necessary to resolve bugs, and there are a handful of such (minor) changes between Django 1.0 and Django 1.1.

Before upgrading to Django 1.1 you should double-check that the following changes don’t impact you, and upgrade your code if they do.

Changes to constraint names

Django 1.1 modifies the method used to generate database constraint names so that names are consistent regardless of machine word size. This change is backwards incompatible for some users.

If you are using a 32-bit platform, you’re off the hook; you’ll observe no differences as a result of this change.

However, users on 64-bit platforms may experience some problems using the reset management command. Prior to this change, 64-bit platforms would generate a 64-bit, 16 character digest in the constraint name; for example:

ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_5e8f10c132091d1e FOREIGN KEY ...

Following this change, all platforms, regardless of word size, will generate a 32-bit, 8 character digest in the constraint name; for example:

ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_32091d1e FOREIGN KEY ...

As a result of this change, you will not be able to use the reset management command on any table made by a 64-bit machine. This is because the new generated name will not match the historically generated name; as a result, the SQL constructed by the reset command will be invalid.

If you need to reset an application that was created with 64-bit constraints, you will need to manually drop the old constraint prior to invoking reset.

Test cases are now run in a transaction

Django 1.1 runs tests inside a transaction, allowing better test performance (see test performance improvements for details).

This change is slightly backwards incompatible if existing tests need to test transactional behavior, if they rely on invalid assumptions about the test environment, or if they require a specific test case ordering.

For these cases, TransactionTestCase can be used instead. This is a just a quick fix to get around test case errors revealed by the new rollback approach; in the long-term tests should be rewritten to correct the test case.

Removed SetRemoteAddrFromForwardedFor middleware

For convenience, Django 1.0 included an optional middleware class – django.middleware.http.SetRemoteAddrFromForwardedFor – which updated the value of REMOTE_ADDR based on the HTTP X-Forwarded-For header commonly set by some proxy configurations.

It has been demonstrated that this mechanism cannot be made reliable enough for general-purpose use, and that (despite documentation to the contrary) its inclusion in Django may lead application developers to assume that the value of REMOTE_ADDR is “safe” or in some way reliable as a source of authentication.

While not directly a security issue, we’ve decided to remove this middleware with the Django 1.1 release. It has been replaced with a class that does nothing other than raise a DeprecationWarning.

If you’ve been relying on this middleware, the easiest upgrade path is:

- Examine the code as it existed before it was removed.

- Verify that it works correctly with your upstream proxy, modifying it to support your particular proxy (if necessary).

- Introduce your modified version of SetRemoteAddrFromForwardedFor as a piece of middleware in your own project.

Names of uploaded files are available later

In Django 1.0, files uploaded and stored in a model’s FileField were saved to disk before the model was saved to the database. This meant that the actual file name assigned to the file was available before saving. For example, it was available in a model’s pre-save signal handler.

In Django 1.1 the file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.

Changes to how model formsets are saved

In Django 1.1, BaseModelFormSet now calls ModelForm.save().

This is backwards-incompatible if you were modifying self.initial in a model formset’s __init__, or if you relied on the internal _total_form_count or _initial_form_count attributes of BaseFormSet. Those attributes are now public methods.

Fixed the join filter’s escaping behavior

The join filter no longer escapes the literal value that is passed in for the connector.

This is backwards incompatible for the special situation of the literal string containing one of the five special HTML characters. Thus, if you were writing {{ foo|join:"&" }}, you now have to write {{ foo|join:"&amp;" }}.

The previous behavior was a bug and contrary to what was documented and expected.

Permanent redirects and the redirect_to() generic view

Django 1.1 adds a permanent argument to the django.views.generic.simple.redirect_to() view. This is technically backwards-incompatible if you were using the redirect_to view with a format-string key called ‘permanent’, which is highly unlikely.

Features deprecated in 1.1

One feature has been marked as deprecated in Django 1.1:

- You should no longer use AdminSite.root() to register that admin views. That is, if your URLconf contains the line:

(r'^admin/(.*)', admin.site.root),

You should change it to read:

(r'^admin/', include(admin.site.urls)),

You should begin to remove use of this feature from your code immediately.

AdminSite.root will raise a PendingDeprecationWarning if used in Django 1.1. This warning is hidden by default. In Django 1.2, this warning will be upgraded to a DeprecationWarning, which will be displayed loudly. Django 1.3 will remove AdminSite.root() entirely.

For more details on our deprecation policies and strategy, see Django’s release process.

What’s new in Django 1.1

Quite a bit: since Django 1.0, we’ve made 1,290 code commits, fixed 1,206 bugs, and added roughly 10,000 lines of documentation.

The major new features in Django 1.1 are:

ORM improvements

Two major enhancements have been added to Django’s object-relational mapper (ORM): aggregate support, and query expressions.

Aggregate support

It’s now possible to run SQL aggregate queries (i.e. COUNT(), MAX(), MIN(), etc.) from within Django’s ORM. You can choose to either return the results of the aggregate directly, or else annotate the objects in a QuerySet with the results of the aggregate query.

This feature is available as new aggregate() and annotate() methods, and is covered in detail in the ORM aggregation documentation.

Query expressions

Queries can now refer to a another field on the query and can traverse relationships to refer to fields on related models. This is implemented in the new F object; for full details, including examples, consult the F expressions documentation.

Model improvements

A number of features have been added to Django’s model layer:

“Unmanaged” models

You can now control whether or not Django manages the life-cycle of the database tables for a model using the managed model option. This defaults to True, meaning that Django will create the appropriate database tables in syncdb and remove them as part of the reset command. That is, Django manages the database table’s lifecycle.

If you set this to False, however, no database table creating or deletion will be automatically performed for this model. This is useful if the model represents an existing table or a database view that has been created by some other means.

For more details, see the documentation for the managed option.

Proxy models

You can now create proxy models: subclasses of existing models that only add Python-level (rather than database-level) behavior and aren’t represented by a new table. That is, the new model is a proxy for some underlying model, which stores all the real data.

All the details can be found in the proxy models documentation. This feature is similar on the surface to unmanaged models, so the documentation has an explanation of how proxy models differ from unmanaged models.

Deferred fields

In some complex situations, your models might contain fields which could contain a lot of data (for example, large text fields), or require expensive processing to convert them to Python objects. If you know you don’t need those particular fields, you can now tell Django not to retrieve them from the database.

You’ll do this with the new queryset methods defer() and only().

Testing improvements

A few notable improvements have been made to the testing framework.

Test performance improvements

Tests written using Django’s testing framework now run dramatically faster (as much as 10 times faster in many cases).

This was accomplished through the introduction of transaction-based tests: when using django.test.TestCase, your tests will now be run in a transaction which is rolled back when finished, instead of by flushing and re-populating the database. This results in an immense speedup for most types of unit tests. See the documentation for TestCase and TransactionTestCase for a full description, and some important notes on database support.

Test client improvements

A couple of small – but highly useful – improvements have been made to the test client:

- The test Client now can automatically follow redirects with the follow argument to Client.get() and Client.post(). This makes testing views that issue redirects simpler.

- It’s now easier to get at the template context in the response returned the test client: you’ll simply access the context as request.context[key]. The old way, which treats request.context as a list of contexts, one for each rendered template in the inheritance chain, is still available if you need it.

New admin features

Django 1.1 adds a couple of nifty new features to Django’s admin interface:

Editable fields on the change list

You can now make fields editable on the admin list views via the new list_editable admin option. These fields will show up as form widgets on the list pages, and can be edited and saved in bulk.

Admin “actions”

You can now define admin actions that can perform some action to a group of models in bulk. Users will be able to select objects on the change list page and then apply these bulk actions to all selected objects.

Django ships with one pre-defined admin action to delete a group of objects in one fell swoop.

Conditional view processing

Django now has much better support for conditional view processing using the standard ETag and Last-Modified HTTP headers. This means you can now easily short-circuit view processing by testing less-expensive conditions. For many views this can lead to a serious improvement in speed and reduction in bandwidth.

URL namespaces

Django 1.1 improves named URL patterns with the introduction of URL “namespaces.”

In short, this feature allows the same group of URLs, from the same application, to be included in a Django URLConf multiple times, with varying (and potentially nested) named prefixes which will be used when performing reverse resolution. In other words, reusable applications like Django’s admin interface may be registered multiple times without URL conflicts.

For full details, see the documentation on defining URL namespaces.

GeoDjango

In Django 1.1, GeoDjango (i.e. django.contrib.gis) has several new features:

- Support for SpatiaLite – a spatial database for SQLite – as a spatial backend.

- Geographic aggregates (Collect, Extent, MakeLine, Union) and F expressions.

- New GeoQuerySet methods: collect, geojson, and snap_to_grid.

- A new list interface methods for GEOSGeometry objects.

For more details, see the GeoDjango documentation.

Other improvements

Other new features and changes introduced since Django 1.0 include:

- The CSRF protection middleware has been split into two classes – CsrfViewMiddleware checks incoming requests, and CsrfResponseMiddleware processes outgoing responses. The combined CsrfMiddleware class (which does both) remains for backwards-compatibility, but using the split classes is now recommended in order to allow fine-grained control of when and where the CSRF processing takes place.

- reverse() and code which uses it (e.g., the {% url %} template tag) now works with URLs in Django’s administrative site, provided that the admin URLs are set up via include(admin.site.urls) (sending admin requests to the admin.site.root view still works, but URLs in the admin will not be “reversible” when configured this way).

- The include() function in Django URLconf modules can now accept sequences of URL patterns (generated by patterns()) in addition to module names.

- Instances of Django forms (see the forms overview) now have two additional methods, hidden_fields() and visible_fields(), which return the list of hidden – i.e., <input type="hidden"> – and visible fields on the form, respectively.

- The redirect_to generic view now accepts an additional keyword argument permanent. If permanent is True, the view will emit an HTTP permanent redirect (status code 301). If False, the view will emit an HTTP temporary redirect (status code 302).

- A new database lookup type – week_day – has been added for DateField and DateTimeField. This type of lookup accepts a number between 1 (Sunday) and 7 (Saturday), and returns objects where the field value matches that day of the week. See the full list of lookup types for details.

- The {% for %} tag in Django’s template language now accepts an optional {% empty %} clause, to be displayed when {% for %} is asked to loop over an empty sequence. See the list of built-in template tags for examples of this.

- The dumpdata management command now accepts individual model names as arguments, allowing you to export the data just from particular models.

- There’s a new safeseq template filter which works just like safe for lists, marking each item in the list as safe.

- Cache backends now support incr() and decr() commands to increment and decrement the value of a cache key. On cache backends that support atomic increment/decrement – most notably, the memcached backend – these operations will be atomic, and quite fast.

- Django now can easily delegate authentication to the Web server via a new authentication backend that supports the standard REMOTE_USER environment variable used for this purpose.

- There’s a new django.shortcuts.redirect() function that makes it easier to issue redirects given an object, a view name, or a URL.

- The postgresql_psycopg2 backend now supports native PostgreSQL autocommit. This is an advanced, PostgreSQL-specific feature, that can make certain read-heavy applications a good deal faster.

What’s next?

We’ll take a short break, and then work on Django 1.2 will begin – no rest for the weary! If you’d like to help, discussion of Django development, including progress toward the 1.2 release, takes place daily on the django-developers mailing list:

- https://groups.google.com/group/django-developers

... and in the #django-dev IRC channel on irc.freenode.net. Feel free to join the discussions!

Django’s online documentation also includes pointers on how to contribute to Django:

- How to contribute to Django

Contributions on any level – developing code, writing documentation or simply triaging tickets and helping to test proposed bugfixes – are always welcome and appreciated.

And that’s the way it is.

Django 1.0.2 release notes

Welcome to Django 1.0.2!

This is the second “bugfix” release in the Django 1.0 series, improving the stability and performance of the Django 1.0 codebase. As such, Django 1.0.2 contains no new features (and, pursuant to our compatibility policy, maintains backwards compatibility with Django 1.0.0), but does contain a number of fixes and other improvements. Django 1.0.2 is a recommended upgrade for any development or deployment currently using or targeting Django 1.0.

Fixes and improvements in Django 1.0.2

The primary reason behind this release is to remedy an issue in the recently-released Django 1.0.1; the packaging scripts used for Django 1.0.1 omitted some directories from the final release package, including one directory required by django.contrib.gis and part of Django’s unit-test suite.

Django 1.0.2 contains updated packaging scripts, and the release package contains the directories omitted from Django 1.0.1. As such, this release contains all of the fixes and improvements from Django 1.0.1; see the Django 1.0.1 release notes for details.

Additionally, in the period since Django 1.0.1 was released:

- Updated Hebrew and Danish translations have been added.

- The default __repr__ method of Django models has been made more robust in the face of bad Unicode data coming from the __unicode__ method; rather than raise an exception in such cases, repr() will now contain the string “[Bad Unicode data]” in place of the invalid Unicode.

- A bug involving the interaction of Django’s SafeUnicode class and the MySQL adapter has been resolved; SafeUnicode instances (generated, for example, by template rendering) can now be assigned to model attributes and saved to MySQL without requiring an explicit intermediate cast to unicode.

- A bug affecting filtering on a nullable DateField in SQLite has been resolved.

- Several updates and improvements have been made to Django’s documentation.

Django 1.0.1 release notes

Welcome to Django 1.0.1!

This is the first “bugfix” release in the Django 1.0 series, improving the stability and performance of the Django 1.0 codebase. As such, Django 1.0.1 contains no new features (and, pursuant to our compatibility policy, maintains backwards compatibility with Django 1.0), but does contain a number of fixes and other improvements. Django 1.0.1 is a recommended upgrade for any development or deployment currently using or targeting Django 1.0.

Fixes and improvements in Django 1.0.1

Django 1.0.1 contains over two hundred fixes to the original Django 1.0 codebase; full details of every fix are available in the history of the 1.0.X branch, but here are some of the highlights:

- Several fixes in django.contrib.comments, pertaining to RSS feeds of comments, default ordering of comments and the XHTML and internationalization of the default templates for comments.

- Multiple fixes for Django’s support of Oracle databases, including pagination support for GIS QuerySets, more efficient slicing of results and improved introspection of existing databases.

- Several fixes for query support in the Django object-relational mapper, including repeated setting and resetting of ordering and fixes for working with INSERT-only queries.

- Multiple fixes for inline forms in formsets.

- Multiple fixes for unique and unique_together model constraints in automatically-generated forms.

- Fixed support for custom callable upload_to declarations when handling file uploads through automatically-generated forms.

- Fixed support for sorting an admin change list based on a callable attributes in list_display.

- A fix to the application of autoescaping for literal strings passed to the join template filter. Previously, literal strings passed to join were automatically escaped, contrary to the documented behavior for autoescaping and literal strings. Literal strings passed to join are no longer automatically escaped, meaning you must now manually escape them; this is an incompatibility if you were relying on this bug, but not if you were relying on escaping behaving as documented.

- Improved and expanded translation files for many of the languages Django supports by default.

- And as always, a large number of improvements to Django’s documentation, including both corrections to existing documents and expanded and new documentation.

Django 1.0 release notes

Welcome to Django 1.0!

We’ve been looking forward to this moment for over three years, and it’s finally here. Django 1.0 represents the largest milestone in Django’s development to date: a Web framework that a group of perfectionists can truly be proud of.

Django 1.0 represents over three years of community development as an Open Source project. Django’s received contributions from hundreds of developers, been translated into fifty languages, and today is used by developers on every continent and in every kind of job.

An interesting historical note: when Django was first released in July 2005, the initial released version of Django came from an internal repository at revision number 8825. Django 1.0 represents revision 8961 of our public repository. It seems fitting that our 1.0 release comes at the moment where community contributions overtake those made privately.

Stability and forwards-compatibility

The release of Django 1.0 comes with a promise of API stability and forwards-compatibility. In a nutshell, this means that code you develop against Django 1.0 will continue to work against 1.1 unchanged, and you should need to make only minor changes for any 1.X release.

See the API stability guide for full details.

Backwards-incompatible changes

Django 1.0 has a number of backwards-incompatible changes from Django 0.96. If you have apps written against Django 0.96 that you need to port, see our detailed porting guide:

- Porting your apps from Django 0.96 to 1.0

A complete list of backwards-incompatible changes can be found at https://code.djangoproject.com/wiki/BackwardsIncompatibleChanges.

What’s new in Django 1.0

A lot!

Since Django 0.96, we’ve made over 4,000 code commits, fixed more than 2,000 bugs, and edited, added, or removed around 350,000 lines of code. We’ve also added 40,000 lines of new documentation, and greatly improved what was already there.

In fact, new documentation is one of our favorite features of Django 1.0, so we might as well start there. First, there’s a new documentation site:

- https://docs.djangoproject.com/

The documentation has been greatly improved, cleaned up, and generally made awesome. There’s now dedicated search, indexes, and more.

We can’t possibly document everything that’s new in 1.0, but the documentation will be your definitive guide. Anywhere you see something like:

New in Django 1.0:
This feature is new in Django 1.0

You’ll know that you’re looking at something new or changed.

The other major highlights of Django 1.0 are:

Re-factored admin application

The Django administrative interface (django.contrib.admin) has been completely refactored; admin definitions are now completely decoupled from model definitions (no more class Admin declaration in models!), rewritten to use Django’s new form-handling library (introduced in the 0.96 release as django.newforms, and now available as simply django.forms) and redesigned with extensibility and customization in mind. Full documentation for the admin application is available online in the official Django documentation:

See the admin reference for details

Improved Unicode handling

Django’s internals have been refactored to use Unicode throughout; this drastically simplifies the task of dealing with non-Western-European content and data in Django. Additionally, utility functions have been provided to ease interoperability with third-party libraries and systems which may or may not handle Unicode gracefully. Details are available in Django’s Unicode-handling documentation.

See Unicode data.

An improved ORM

Django’s object-relational mapper – the component which provides the mapping between Django model classes and your database, and which mediates your database queries – has been dramatically improved by a massive refactoring. For most users of Django this is backwards-compatible; the public-facing API for database querying underwent a few minor changes, but most of the updates took place in the ORM’s internals. A guide to the changes, including backwards-incompatible modifications and mentions of new features opened up by this refactoring, is available on the Django wiki.

Automatic escaping of template variables

To provide improved security against cross-site scripting (XSS) vulnerabilities, Django’s template system now automatically escapes the output of variables. This behavior is configurable, and allows both variables and larger template constructs to be marked as safe (requiring no escaping) or unsafe (requiring escaping). A full guide to this feature is in the documentation for the autoescape tag.

django.contrib.gis (GeoDjango)

A project over a year in the making, this adds world-class GIS (Geographic Information Systems) support to Django, in the form of a contrib application. Its documentation is currently being maintained externally, and will be merged into the main Django documentation shortly. Huge thanks go to Justin Bronn, Jeremy Dunck, Brett Hoerner and Travis Pinney for their efforts in creating and completing this feature.

See http://geodjango.org/ for details.

Pluggable file storage

Django’s built-in FileField and ImageField now can take advantage of pluggable file-storage backends, allowing extensive customization of where and how uploaded files get stored by Django. For details, see the files documentation; big thanks go to Marty Alchin for putting in the hard work to get this completed.

Jython compatibility

Thanks to a lot of work from Leo Soto during a Google Summer of Code project, Django’s codebase has been refactored to remove incompatibilities with Jython, an implementation of Python written in Java, which runs Python code on the Java Virtual Machine. Django is now compatible with the forthcoming Jython 2.5 release.

See Running Django on Jython.

Generic relations in forms and admin

Classes are now included in django.contrib.contenttypes which can be used to support generic relations in both the admin interface and in end-user forms. See the documentation for generic relations for details.

INSERT/UPDATE distinction

Although Django’s default behavior of having a model’s save() method automatically determine whether to perform an INSERT or an UPDATE at the SQL level is suitable for the majority of cases, there are occasional situations where forcing one or the other is useful. As a result, models can now support an additional parameter to save() which can force a specific operation.

See Forcing an INSERT or UPDATE for details.

Split CacheMiddleware

Django’s CacheMiddleware has been split into three classes: CacheMiddleware itself still exists and retains all of its previous functionality, but it is now built from two separate middleware classes which handle the two parts of caching (inserting into and reading from the cache) separately, offering additional flexibility for situations where combining these functions into a single middleware posed problems.

Full details, including updated notes on appropriate use, are in the caching documentation.

Refactored django.contrib.comments

As part of a Google Summer of Code project, Thejaswi Puthraya carried out a major rewrite and refactoring of Django’s bundled comment system, greatly increasing its flexibility and customizability.

Removal of deprecated features

A number of features and methods which had previously been marked as deprecated, and which were scheduled for removal prior to the 1.0 release, are no longer present in Django. These include imports of the form library from django.newforms (now located simply at django.forms), the form_for_model and form_for_instance helper functions (which have been replaced by ModelForm) and a number of deprecated features which were replaced by the dispatcher, file-uploading and file-storage refactorings introduced in the Django 1.0 alpha releases.

Known issues

We’ve done our best to make Django 1.0 as solid as possible, but unfortunately there are a couple of issues that we know about in the release.

Multi-table model inheritance with to_field

If you’re using multiple table model inheritance, be aware of this caveat: child models using a custom parent_link and to_field will cause database integrity errors. A set of models like the following are not valid:

class Parent(models.Model):
name = models.CharField(max_length=10)
other_value = models.IntegerField(unique=True)

class Child(Parent):
father = models.OneToOneField(Parent, primary_key=True, to_field="other_value", parent_link=True)
value = models.IntegerField()

This bug will be fixed in the next release of Django.

Caveats with support of certain databases

Django attempts to support as many features as possible on all database backends. However, not all database backends are alike, and in particular many of the supported database differ greatly from version to version. It’s a good idea to checkout our notes on supported database:

- MySQL notes

- SQLite notes

- Oracle notes

Porting your apps from Django 0.96 to 1.0

Django 1.0 breaks compatibility with 0.96 in some areas.

This guide will help you port 0.96 projects and apps to 1.0. The first part of this document includes the common changes needed to run with 1.0. If after going through the first part your code still breaks, check the section Less-common Changes for a list of a bunch of less-common compatibility issues.

See also

The 1.0 release notes. That document explains the new features in 1.0 more deeply; the porting guide is more concerned with helping you quickly update your code.

Common changes

This section describes the changes between 0.96 and 1.0 that most users will need to make.

Use Unicode

Change string literals ('foo') into Unicode literals (u'foo'). Django now uses Unicode strings throughout. In most places, raw strings will continue to work, but updating to use Unicode literals will prevent some obscure problems.

See Unicode data for full details.

Models

Common changes to your models file:

Rename maxlength to max_length

Rename your maxlength argument to max_length (this was changed to be consistent with form fields):

Replace __str__ with __unicode__

Replace your model’s __str__ function with a __unicode__ method, and make sure you use Unicode (u'foo') in that method.

Remove prepopulated_from

Remove the prepopulated_from argument on model fields. It’s no longer valid and has been moved to the ModelAdmin class in admin.py. See the admin, below, for more details about changes to the admin.

Remove core

Remove the core argument from your model fields. It is no longer necessary, since the equivalent functionality (part of inline editing) is handled differently by the admin interface now. You don’t have to worry about inline editing until you get to the admin section, below. For now, remove all references to core.

Replace class Admin: with admin.py

Remove all your inner class Admin declarations from your models. They won’t break anything if you leave them, but they also won’t do anything. To register apps with the admin you’ll move those declarations to an admin.py file; see the admin below for more details.

See also

A contributor to djangosnippets has written a script that’ll scan your models.py and generate a corresponding admin.py.

Example

Below is an example models.py file with all the changes you’ll need to make:

Old (0.96) models.py:

class Author(models.Model):
first_name = models.CharField(maxlength=30)
last_name = models.CharField(maxlength=30)
slug = models.CharField(maxlength=60, prepopulate_from=('first_name', 'last_name'))

class Admin:
list_display = ['first_name', 'last_name']

def __str__(self):
return '%s %s' % (self.first_name, self.last_name)

New (1.0) models.py:

class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
slug = models.CharField(max_length=60)

def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)

New (1.0) admin.py:

from django.contrib import admin
from models import Author

class AuthorAdmin(admin.ModelAdmin):
list_display = ['first_name', 'last_name']
prepopulated_fields = {
'slug': ('first_name', 'last_name')
}

admin.site.register(Author, AuthorAdmin)

The Admin

One of the biggest changes in 1.0 is the new admin. The Django administrative interface (django.contrib.admin) has been completely refactored; admin definitions are now completely decoupled from model definitions, the framework has been rewritten to use Django’s new form-handling library and redesigned with extensibility and customization in mind.

Practically, this means you’ll need to rewrite all of your class Admin declarations. You’ve already seen in models above how to replace your class Admin with a admin.site.register() call in an admin.py file. Below are some more details on how to rewrite that Admin declaration into the new syntax.

Use new inline syntax

The new edit_inline options have all been moved to admin.py. Here’s an example:

Old (0.96):

class Parent(models.Model):
...

class Child(models.Model):
parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)

New (1.0):

class ChildInline(admin.StackedInline):
model = Child
extra = 3

class ParentAdmin(admin.ModelAdmin):
model = Parent
inlines = [ChildInline]

admin.site.register(Parent, ParentAdmin)

See InlineModelAdmin objects for more details.

Simplify fields, or use fieldsets

The old fields syntax was quite confusing, and has been simplified. The old syntax still works, but you’ll need to use fieldsets instead.

Old (0.96):

class ModelOne(models.Model):
...

class Admin:
fields = (
(None, {'fields': ('foo','bar')}),
)

class ModelTwo(models.Model):
...

class Admin:
fields = (
('group1', {'fields': ('foo','bar'),   'classes': 'collapse'}),
('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}),
)

New (1.0):

class ModelOneAdmin(admin.ModelAdmin):
fields = ('foo', 'bar')

class ModelTwoAdmin(admin.ModelAdmin):
fieldsets = (
('group1', {'fields': ('foo','bar'),   'classes': 'collapse'}),
('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}),
)

See also

- More detailed information about the changes and the reasons behind them can be found on the NewformsAdminBranch wiki page

- The new admin comes with a ton of new features; you can read about them in the admin documentation.

URLs

Update your root urls.py

If you’re using the admin site, you need to update your root urls.py.

Old (0.96) urls.py:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),

# ... the rest of your URLs here ...
)

New (1.0) urls.py:

from django.conf.urls.defaults import *

# The next two lines enable the admin and load each admin.py file:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
(r'^admin/(.*)', admin.site.root),

# ... the rest of your URLs here ...
)

Views

Use django.forms instead of newforms

Replace django.newforms with django.forms – Django 1.0 renamed the newforms module (introduced in 0.96) to plain old forms. The oldforms module was also removed.

If you’re already using the newforms library, and you used our recommended import statement syntax, all you have to do is change your import statements.

Old:

from django import newforms as forms

New:

from django import forms

If you’re using the old forms system (formerly known as django.forms and django.oldforms), you’ll have to rewrite your forms. A good place to start is the forms documentation

Handle uploaded files using the new API

Replace use of uploaded files – that is, entries in request.FILES – as simple dictionaries with the new UploadedFile. The old dictionary syntax no longer works.

Thus, in a view like:

def my_view(request):
f = request.FILES['file_field_name']
...

...you’d need to make the following changes:

Old (0.96)

New (1.0)

f['content']

f.read()

f['filename']

f.name

f['content-type']

f.content_type

Work with file fields using the new API

The internal implementation of django.db.models.FileField have changed. A visible result of this is that the way you access special attributes (URL, filename, image size, etc.) of these model fields has changed. You will need to make the following changes, assuming your model’s FileField is called myfile:

Old (0.96)

New (1.0)

myfile.get_content_filename()

myfile.content.path

myfile.get_content_url()

myfile.content.url

myfile.get_content_size()

myfile.content.size

myfile.save_content_file()

myfile.content.save()

myfile.get_content_width()

myfile.content.width

myfile.get_content_height()

myfile.content.height

Note that the width and height attributes only make sense for ImageField fields. More details can be found in the model API documentation.

Use Paginator instead of ObjectPaginator

The ObjectPaginator in 0.96 has been removed and replaced with an improved version, django.core.paginator.Paginator.

Templates

Learn to love autoescaping

By default, the template system now automatically HTML-escapes the output of every variable. To learn more, see Automatic HTML escaping.

To disable auto-escaping for an individual variable, use the safe filter:

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

To disable auto-escaping for an entire template, wrap the template (or just a particular section of the template) in the autoescape tag:

{% autoescape off %}
... unescaped template content here ...
{% endautoescape %}

Less-common changes

The following changes are smaller, more localized changes. They should only affect more advanced users, but it’s probably worth reading through the list and checking your code for these things.

Signals

- Add **kwargs to any registered signal handlers.

- Connect, disconnect, and send signals via methods on the Signal object instead of through module methods in django.dispatch.dispatcher.

- Remove any use of the Anonymous and Any sender options; they no longer exist. You can still receive signals sent by any sender by using sender=None

- Make any custom signals you’ve declared into instances of django.dispatch.Signal instead of anonymous objects.

Here’s quick summary of the code changes you’ll need to make:

Old (0.96)

New (1.0)

def callback(sender)

def callback(sender, **kwargs)

sig = object()

sig = django.dispatch.Signal()

dispatcher.connect(callback, sig)

sig.connect(callback)

dispatcher.send(sig, sender)

sig.send(sender)

dispatcher.connect(callback, sig, sender=Any)

sig.connect(callback, sender=None)

Comments

If you were using Django 0.96’s django.contrib.comments app, you’ll need to upgrade to the new comments app introduced in 1.0. See the upgrade guide for details.

Template tags

spaceless tag

The spaceless template tag now removes all spaces between HTML tags, instead of preserving a single space.

Local flavors

U.S. local flavor

django.contrib.localflavor.usa has been renamed to django.contrib.localflavor.us. This change was made to match the naming scheme of other local flavors. To migrate your code, all you need to do is change the imports.

Sessions

Getting a new session key

SessionBase.get_new_session_key() has been renamed to _get_new_session_key(). get_new_session_object() no longer exists.

Fixtures

Loading a row no longer calls save()

Previously, loading a row automatically ran the model’s save() method. This is no longer the case, so any fields (for example: timestamps) that were auto-populated by a save() now need explicit values in any fixture.

Settings

Better exceptions

The old EnvironmentError has split into an ImportError when Django fails to find the settings module and a RuntimeError when you try to reconfigure settings after having already used them.

LOGIN_URL has moved

The LOGIN_URL constant moved from django.contrib.auth into the settings module. Instead of using from django.contrib.auth import LOGIN_URL refer to settings.LOGIN_URL.

APPEND_SLASH behavior has been updated

In 0.96, if a URL didn’t end in a slash or have a period in the final component of its path, and APPEND_SLASH was True, Django would redirect to the same URL, but with a slash appended to the end. Now, Django checks to see whether the pattern without the trailing slash would be matched by something in your URL patterns. If so, no redirection takes place, because it is assumed you deliberately wanted to catch that pattern.

For most people, this won’t require any changes. Some people, though, have URL patterns that look like this:

r'/some_prefix/(.*)$'

Previously, those patterns would have been redirected to have a trailing slash. If you always want a slash on such URLs, rewrite the pattern as:

r'/some_prefix/(.*/)$'

Smaller model changes

Different exception from get()

Managers now return a MultipleObjectsReturned exception instead of AssertionError:

Old (0.96):

try:
Model.objects.get(...)
except AssertionError:
handle_the_error()

New (1.0):

try:
Model.objects.get(...)
except Model.MultipleObjectsReturned:
handle_the_error()

LazyDate has been fired

The LazyDate helper class no longer exists.

Default field values and query arguments can both be callable objects, so instances of LazyDate can be replaced with a reference to datetime.datetime.now:

Old (0.96):

class Article(models.Model):
title = models.CharField(maxlength=100)
published = models.DateField(default=LazyDate())

New (1.0):

import datetime

class Article(models.Model):
title = models.CharField(max_length=100)
published = models.DateField(default=datetime.datetime.now)

DecimalField is new, and FloatField is now a proper float

Old (0.96):

class MyModel(models.Model):
field_name = models.FloatField(max_digits=10, decimal_places=3)
...

New (1.0):

class MyModel(models.Model):
field_name = models.DecimalField(max_digits=10, decimal_places=3)
...

If you forget to make this change, you will see errors about FloatField not taking a max_digits attribute in __init__, because the new FloatField takes no precision-related arguments.

If you’re using MySQL or PostgreSQL, no further changes are needed. The database column types for DecimalField are the same as for the old FloatField.

If you’re using SQLite, you need to force the database to view the appropriate columns as decimal types, rather than floats. To do this, you’ll need to reload your data. Do this after you have made the change to using DecimalField in your code and updated the Django code.

Warning

Back up your database first!

For SQLite, this means making a copy of the single file that stores the database (the name of that file is the DATABASE_NAME in your settings.py file).

To upgrade each application to use a DecimalField, you can do the following, replacing <app> in the code below with each app’s name:

$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml

Notes:

1. It’s important that you remember to use XML format in the first step of this process. We are exploiting a feature of the XML data dumps that makes porting floats to decimals with SQLite possible.

2. In the second step you will be asked to confirm that you are prepared to lose the data for the application(s) in question. Say yes; we’ll restore this data in the third step, of course.

3. DecimalField is not used in any of the apps shipped with Django prior to this change being made, so you do not need to worry about performing this procedure for any of the standard Django models.

If something goes wrong in the above process, just copy your backed up database file over the original file and start again.

Internationalization

django.views.i18n.set_language() now requires a POST request

Previously, a GET request was used. The old behavior meant that state (the locale used to display the site) could be changed by a GET request, which is against the HTTP specification’s recommendations. Code calling this view must ensure that a POST request is now made, instead of a GET. This means you can no longer use a link to access the view, but must use a form submission of some kind (e.g. a button).

_() is no longer in builtins

_() (the callable object whose name is a single underscore) is no longer monkeypatched into builtins – that is, it’s no longer available magically in every module.

If you were previously relying on _() always being present, you should now explicitly import ugettext or ugettext_lazy, if appropriate, and alias it to _ yourself:

from django.utils.translation import ugettext as _

HTTP request/response objects

Dictionary access to HttpRequest

HttpRequest objects no longer directly support dictionary-style access; previously, both GET and POST data were directly available on the HttpRequest object (e.g., you could check for a piece of form data by using if 'some_form_key' in request or by reading request['some_form_key']. This is no longer supported; if you need access to the combined GET and POST data, use request.REQUEST instead.

It is strongly suggested, however, that you always explicitly look in the appropriate dictionary for the type of request you expect to receive (request.GET or request.POST); relying on the combined request.REQUEST dictionary can mask the origin of incoming data.

Accessing HTTPResponse headers

django.http.HttpResponse.headers has been renamed to _headers and HttpResponse now supports containment checking directly. So use if header in response: instead of if header in response.headers:.

Generic relations

Generic relations have been moved out of core

The generic relation classes – GenericForeignKey and GenericRelation – have moved into the django.contrib.contenttypes module.

Testing

django.test.Client.login() has changed

Old (0.96):

from django.test import Client
c = Client()
c.login('/path/to/login','myuser','mypassword')

New (1.0):

# ... same as above, but then:
c.login(username='myuser', password='mypassword')

Management commands

Running management commands from your code

django.core.management has been greatly refactored.

Calls to management services in your code now need to use call_command. For example, if you have some test code that calls flush and load_data:

from django.core import management
management.flush(verbosity=0, interactive=False)
management.load_data(['test_data'], verbosity=0)

...you’ll need to change this code to read:

from django.core import management
management.call_command('flush', verbosity=0, interactive=False)
management.call_command('loaddata', 'test_data', verbosity=0)

Subcommands must now precede options

django-admin.py and manage.py now require subcommands to precede options. So:

$ django-admin.py --settings=foo.bar runserver

...no longer works and should be changed to:

$ django-admin.py runserver --settings=foo.bar

Syndication

Feed.__init__ has changed

The __init__() method of the syndication framework’s Feed class now takes an HttpRequest object as its second parameter, instead of the feed’s URL. This allows the syndication framework to work without requiring the sites framework. This only affects code that subclasses Feed and overrides the __init__() method, and code that calls Feed.__init__() directly.

Data structures

SortedDictFromList is gone

django.newforms.forms.SortedDictFromList was removed. django.utils.datastructures.SortedDict can now be instantiated with a sequence of tuples.

To update your code:

1. Use django.utils.datastructures.SortedDict wherever you were using django.newforms.forms.SortedDictFromList.

2. Because django.utils.datastructures.SortedDict.copy doesn’t return a deepcopy as SortedDictFromList.copy() did, you will need to update your code if you were relying on a deepcopy. Do this by using copy.deepcopy directly.

Database backend functions

Database backend functions have been renamed

Almost all of the database backend-level functions have been renamed and/or relocated. None of these were documented, but you’ll need to change your code if you’re using any of these functions, all of which are in django.db:

Old (0.96)

New (1.0)

backend.get_autoinc_sql

connection.ops.autoinc_sql

backend.get_date_extract_sql

connection.ops.date_extract_sql

backend.get_date_trunc_sql

connection.ops.date_trunc_sql

backend.get_datetime_cast_sql

connection.ops.datetime_cast_sql

backend.get_deferrable_sql

connection.ops.deferrable_sql

backend.get_drop_foreignkey_sql

connection.ops.drop_foreignkey_sql

backend.get_fulltext_search_sql

connection.ops.fulltext_search_sql

backend.get_last_insert_id

connection.ops.last_insert_id

backend.get_limit_offset_sql

connection.ops.limit_offset_sql

backend.get_max_name_length

connection.ops.max_name_length

backend.get_pk_default_value

connection.ops.pk_default_value

backend.get_random_function_sql

connection.ops.random_function_sql

backend.get_sql_flush

connection.ops.sql_flush

backend.get_sql_sequence_reset

connection.ops.sequence_reset_sql

backend.get_start_transaction_sql

connection.ops.start_transaction_sql

backend.get_tablespace_sql

connection.ops.tablespace_sql

backend.quote_name

connection.ops.quote_name

backend.get_query_set_class

connection.ops.query_set_class

backend.get_field_cast_sql

connection.ops.field_cast_sql

backend.get_drop_sequence

connection.ops.drop_sequence_sql

backend.OPERATOR_MAPPING

connection.operators

backend.allows_group_by_ordinal

connection.features.allows_group_by_ordinal

backend.allows_unique_and_pk

connection.features.allows_unique_and_pk

backend.autoindexes_primary_keys

connection.features.autoindexes_primary_keys

backend.needs_datetime_string_cast

connection.features.needs_datetime_string_cast

backend.needs_upper_for_iops

connection.features.needs_upper_for_iops

backend.supports_constraints

connection.features.supports_constraints

backend.supports_tablespaces

connection.features.supports_tablespaces

backend.uses_case_insensitive_names

connection.features.uses_case_insensitive_names

backend.uses_custom_queryset

connection.features.uses_custom_queryset

Django version 0.96 release notes

Welcome to Django 0.96!

The primary goal for 0.96 is a cleanup and stabilization of the features introduced in 0.95. There have been a few small backwards-incompatible changes since 0.95, but the upgrade process should be fairly simple and should not require major changes to existing applications.

However, we’re also releasing 0.96 now because we have a set of backwards-incompatible changes scheduled for the near future. Once completed, they will involve some code changes for application developers, so we recommend that you stick with Django 0.96 until the next official release; then you’ll be able to upgrade in one step instead of needing to make incremental changes to keep up with the development version of Django.

Backwards-incompatible changes

The following changes may require you to update your code when you switch from 0.95 to 0.96:

MySQLdb version requirement

Due to a bug in older versions of the MySQLdb Python module (which Django uses to connect to MySQL databases), Django’s MySQL backend now requires version 1.2.1p2 or higher of MySQLdb, and will raise exceptions if you attempt to use an older version.

If you’re currently unable to upgrade your copy of MySQLdb to meet this requirement, a separate, backwards-compatible backend, called “mysql_old”, has been added to Django. To use this backend, change the DATABASE_ENGINE setting in your Django settings file from this:

DATABASE_ENGINE = "mysql"

to this:

DATABASE_ENGINE = "mysql_old"

However, we strongly encourage MySQL users to upgrade to a more recent version of MySQLdb as soon as possible, The “mysql_old” backend is provided only to ease this transition, and is considered deprecated; aside from any necessary security fixes, it will not be actively maintained, and it will be removed in a future release of Django.

Also, note that some features, like the new DATABASE_OPTIONS setting (see the databases documentation for details), are only available on the “mysql” backend, and will not be made available for “mysql_old”.

Database constraint names changed

The format of the constraint names Django generates for foreign key references have changed slightly. These names are generally only used when it is not possible to put the reference directly on the affected column, so they are not always visible.

The effect of this change is that running manage.py reset and similar commands against an existing database may generate SQL with the new form of constraint name, while the database itself contains constraints named in the old form; this will cause the database server to raise an error message about modifying non-existent constraints.

If you need to work around this, there are two methods available:

1. Redirect the output of manage.py to a file, and edit the generated SQL to use the correct constraint names before executing it.

2. Examine the output of manage.py sqlall to see the new-style constraint names, and use that as a guide to rename existing constraints in your database.

Name changes in manage.py

A few of the options to manage.py have changed with the addition of fixture support:

- There are new dumpdata and loaddata commands which, as you might expect, will dump and load data to/from the database. These commands can operate against any of Django’s supported serialization formats.

- The sqlinitialdata command has been renamed to sqlcustom to emphasize that loaddata should be used for data (and sqlcustom for other custom SQL – views, stored procedures, etc.).

- The vestigial install command has been removed. Use syncdb.

Backslash escaping changed

The Django database API now escapes backslashes given as query parameters. If you have any database API code that matches backslashes, and it was working before (despite the lack of escaping), you’ll have to change your code to “unescape” the slashes one level.

For example, this used to work:

# Find text containing a single backslash
MyModel.objects.filter(text__contains='\\\\')

The above is now incorrect, and should be rewritten as:

# Find text containing a single backslash
MyModel.objects.filter(text__contains='\\')

Removed ENABLE_PSYCO setting

The ENABLE_PSYCO setting no longer exists. If your settings file includes ENABLE_PSYCO it will have no effect; to use Psyco, we recommend writing a middleware class to activate it.

What’s new in 0.96?

This revision represents over a thousand source commits and over four hundred bug fixes, so we can’t possibly catalog all the changes. Here, we describe the most notable changes in this release.

New forms library

django.newforms is Django’s new form-handling library. It’s a replacement for django.forms, the old form/manipulator/validation framework. Both APIs are available in 0.96, but over the next two releases we plan to switch completely to the new forms system, and deprecate and remove the old system.

There are three elements to this transition:

- We’ve copied the current django.forms to django.oldforms. This allows you to upgrade your code now rather than waiting for the backwards-incompatible change and rushing to fix your code after the fact. Just change your import statements like this:

from django import forms             # 0.95-style
from django import oldforms as forms # 0.96-style

- The next official release of Django will move the current django.newforms to django.forms. This will be a backwards-incompatible change, and anyone still using the old version of django.forms at that time will need to change their import statements as described above.

- The next release after that will completely remove django.oldforms.

Although the newforms library will continue to evolve, it’s ready for use for most common cases. We recommend that anyone new to form handling skip the old forms system and start with the new.

For more information about django.newforms, read the newforms documentation.

URLconf improvements

You can now use any callable as the callback in URLconfs (previously, only strings that referred to callables were allowed). This allows a much more natural use of URLconfs. For example, this URLconf:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
('^myview/$', 'mysite.myapp.views.myview')
)

can now be rewritten as:

from django.conf.urls.defaults import *
from mysite.myapp.views import myview

urlpatterns = patterns('',
('^myview/$', myview)
)

One useful application of this can be seen when using decorators; this change allows you to apply decorators to views in your URLconf. Thus, you can make a generic view require login very easily:

from django.conf.urls.defaults import *
from django.contrib.auth.decorators import login_required
from django.views.generic.list_detail import object_list
from mysite.myapp.models import MyModel

info = {
"queryset" : MyModel.objects.all(),
}

urlpatterns = patterns('',
('^myview/$', login_required(object_list), info)
)

Note that both syntaxes (strings and callables) are valid, and will continue to be valid for the foreseeable future.

The test framework

Django now includes a test framework so you can start transmuting fear into boredom (with apologies to Kent Beck). You can write tests based on doctest or unittest and test your views with a simple test client.

There is also new support for “fixtures” – initial data, stored in any of the supported serialization formats, that will be loaded into your database at the start of your tests. This makes testing with real data much easier.

See the testing documentation for the full details.

Improvements to the admin interface

A small change, but a very nice one: dedicated views for adding and updating users have been added to the admin interface, so you no longer need to worry about working with hashed passwords in the admin.

Thanks

Since 0.95, a number of people have stepped forward and taken a major new role in Django’s development. We’d like to thank these people for all their hard work:

- Russell Keith-Magee and Malcolm Tredinnick for their major code contributions. This release wouldn’t have been possible without them.

- Our new release manager, James Bennett, for his work in getting out 0.95.1, 0.96, and (hopefully) future release.

- Our ticket managers Chris Beaven (aka SmileyChris), Simon Greenhill, Michael Radziej, and Gary Wilson. They agreed to take on the monumental task of wrangling our tickets into nicely cataloged submission. Figuring out what to work on is now about a million times easier; thanks again, guys.

- Everyone who submitted a bug report, patch or ticket comment. We can’t possibly thank everyone by name – over 200 developers submitted patches that went into 0.96 – but everyone who’s contributed to Django is listed in AUTHORS.

Django version 0.95 release notes

Welcome to the Django 0.95 release.

This represents a significant advance in Django development since the 0.91 release in January 2006. The details of every change in this release would be too extensive to list in full, but a summary is presented below.

Suitability and API stability

This release is intended to provide a stable reference point for developers wanting to work on production-level applications that use Django.

However, it’s not the 1.0 release, and we’ll be introducing further changes before 1.0. For a clear look at which areas of the framework will change (and which ones will not change) before 1.0, see the api-stability.txt file, which lives in the docs/ directory of the distribution.

You may have a need to use some of the features that are marked as “subject to API change” in that document, but that’s OK with us as long as it’s OK with you, and as long as you understand APIs may change in the future.

Fortunately, most of Django’s core APIs won’t be changing before version 1.0. There likely won’t be as big of a change between 0.95 and 1.0 versions as there was between 0.91 and 0.95.

Changes and new features

The major changes in this release (for developers currently using the 0.91 release) are a result of merging the ‘magic-removal’ branch of development. This branch removed a number of constraints in the way Django code had to be written that were a consequence of decisions made in the early days of Django, prior to its open-source release. It’s now possible to write more natural, Pythonic code that works as expected, and there’s less “black magic” happening behind the scenes.

Aside from that, another main theme of this release is a dramatic increase in usability. We’ve made countless improvements in error messages, documentation, etc., to improve developers’ quality of life.

The new features and changes introduced in 0.95 include:

- Django now uses a more consistent and natural filtering interface for retrieving objects from the database.

- User-defined models, functions and constants now appear in the module namespace they were defined in. (Previously everything was magically transferred to the django.models.* namespace.)

- Some optional applications, such as the FlatPage, Sites and Redirects apps, have been decoupled and moved into django.contrib. If you don’t want to use these applications, you no longer have to install their database tables.

- Django now has support for managing database transactions.

- We’ve added the ability to write custom authentication and authorization backends for authenticating users against alternate systems, such as LDAP.

- We’ve made it easier to add custom table-level functions to models, through a new “Manager” API.

- It’s now possible to use Django without a database. This simply means that the framework no longer requires you to have a working database set up just to serve dynamic pages. In other words, you can just use URLconfs/views on their own. Previously, the framework required that a database be configured, regardless of whether you actually used it.

- It’s now more explicit and natural to override save() and delete() methods on models, rather than needing to hook into the pre_save() and post_save() method hooks.

- Individual pieces of the framework now can be configured without requiring the setting of an environment variable. This permits use of, for example, the Django templating system inside other applications.

- More and more parts of the framework have been internationalized, as we’ve expanded internationalization (i18n) support. The Django codebase, including code and templates, has now been translated, at least in part, into 31 languages. From Arabic to Chinese to Hungarian to Welsh, it is now possible to use Django’s admin site in your native language.

The number of changes required to port from 0.91-compatible code to the 0.95 code base are significant in some cases. However, they are, for the most part, reasonably routine and only need to be done once. A list of the necessary changes is described in the Removing The Magic wiki page. There is also an easy checklist for reference when undertaking the porting operation.

Problem reports and getting help

Need help resolving a problem with Django? The documentation in the distribution is also available online at the Django website. The FAQ document is especially recommended, as it contains a number of issues that come up time and again.

For more personalized help, the django-users mailing list is a very active list, with more than 2,000 subscribers who can help you solve any sort of Django problem. We recommend you search the archives first, though, because many common questions appear with some regularity, and any particular problem may already have been answered.

Finally, for those who prefer the more immediate feedback offered by IRC, there’s a #django channel on irc.freenode.net that is regularly populated by Django users and developers from around the world. Friendly people are usually available at any hour of the day – to help, or just to chat.

Thanks for using Django!

The Django Team July 2006

Archive of security issues

Django’s development team is strongly committed to responsible reporting and disclosure of security-related issues, as outlined in Django’s security policies.

As part of that commitment, we maintain the following historical list of issues which have been fixed and disclosed. For each issue, the list below includes the date, a brief description, the CVE identifier if applicable, a list of affected versions, a link to the full disclosure and links to the appropriate patch(es).

Some important caveats apply to this information:

- Lists of affected versions include only those versions of Django which had stable, security-supported releases at the time of disclosure. This means older versions (whose security support had expired) and versions which were in pre-release (alpha/beta/RC) states at the time of disclosure may have been affected, but are not listed.

- The Django project has on occasion issued security advisories, pointing out potential security problems which can arise from improper configuration or from other issues outside of Django itself. Some of these advisories have received CVEs; when that is the case, they are listed here, but as they have no accompanying patches or releases, only the description, disclosure and CVE will be listed.

Issues prior to Django’s security process

Some security issues were handled before Django had a formalized security process in use. For these, new releases may not have been issued at the time and CVEs may not have been assigned.

August 16, 2006 - CVE-2007-0404

CVE-2007-0404: Filename validation issue in translation framework. Full description

Versions affected

- Django 0.90 (patch)

- Django 0.91 (patch)

- Django 0.95 (patch) (released January 21 2007)

January 21, 2007 - CVE-2007-0405

CVE-2007-0405: Apparent “caching” of authenticated user. Full description

Versions affected

- Django 0.95 (patch)

Issues under Django’s security process

All other security issues have been handled under versions of Django’s security process. These are listed below.

October 26, 2007 - CVE-2007-5712

CVE-2007-5712: Denial-of-service via arbitrarily-large Accept-Language header. Full description

Versions affected

- Django 0.91 (patch)

- Django 0.95 (patch)

- Django 0.96 (patch)

May 14, 2008 - CVE-2008-2302

CVE-2008-2302: XSS via admin login redirect. Full description

Versions affected

- Django 0.91 (patch)

- Django 0.95 (patch)

- Django 0.96 (patch)

September 2, 2008 - CVE-2008-3909

CVE-2008-3909: CSRF via preservation of POST data during admin login. Full description

Versions affected

- Django 0.91 (patch)

- Django 0.95 (patch)

- Django 0.96 (patch)

July 28, 2009 - CVE-2009-2659

CVE-2009-2659: Directory-traversal in development server media handler. Full description

Versions affected

- Django 0.96 (patch)

- Django 1.0 (patch)

October 9, 2009 - CVE-2009-3965

CVE-2009-3965: Denial-of-service via pathological regular expression performance. Full description

Versions affected

- Django 1.0 (patch)

- Django 1.1 (patch)

September 8, 2010 - CVE-2010-3082

CVE-2010-3082: XSS via trusting unsafe cookie value. Full description

Versions affected

- Django 1.2 (patch)

December 22, 2010 - CVE-2010-4534

CVE-2010-4534: Information leakage in administrative interface. Full description

Versions affected

- Django 1.1 (patch)

- Django 1.2 (patch)

December 22, 2010 - CVE-2010-4535

CVE-2010-4535: Denial-of-service in password-reset mechanism. Full description

Versions affected

- Django 1.1 (patch)

- Django 1.2 (patch)

February 8, 2011 - CVE-2011-0696

CVE-2011-0696: CSRF via forged HTTP headers. Full description

Versions affected

- Django 1.1 (patch)

- Django 1.2 (patch)

February 8, 2011 - CVE-2011-0697

CVE-2011-0697: XSS via unsanitized names of uploaded files. Full description

Versions affected

- Django 1.1 (patch)

- Django 1.2 (patch)

February 8, 2011 - CVE-2011-0698

CVE-2011-0698: Directory-traversal on Windows via incorrect path-separator handling. Full description

Versions affected

- Django 1.1 (patch)

- Django 1.2 (patch)

September 9, 2011 - CVE-2011-4136

CVE-2011-4136: Session manipulation when using memory-cache-backed session. Full description

Versions affected

- Django 1.2 (patch)

- Django 1.3 (patch)

September 9, 2011 - CVE-2011-4137

CVE-2011-4137: Denial-of-service via URLField.verify_exists. Full description

Versions affected

- Django 1.2 (patch)

- Django 1.3 (patch)

September 9, 2011 - CVE-2011-4138

CVE-2011-4138: Information leakage/arbitrary request issuance via URLField.verify_exists. Full description

Versions affected

- Django 1.2: (patch)

- Django 1.3: (patch)

September 9, 2011 - CVE-2011-4139

CVE-2011-4139: Host header cache poisoning. Full description

Versions affected

- Django 1.2 (patch)

- Django 1.3 (patch)

September 9, 2011 - CVE-2011-4140

CVE-2011-4140: Potential CSRF via Host header. Full description

Versions affected

This notification was an advisory only, so no patches were issued.

- Django 1.2

- Django 1.3

July 30, 2012 - CVE-2012-3442

CVE-2012-3442: XSS via failure to validate redirect scheme. Full description

Versions affected

- Django 1.3: (patch)

- Django 1.4: (patch)

July 30, 2012 - CVE-2012-3443

CVE-2012-3443: Denial-of-service via compressed image files. Full description

Versions affected

- Django 1.3: (patch)

- Django 1.4: (patch)

July 30, 2012 - CVE-2012-3444

CVE-2012-3444: Denial-of-service via large image files. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

October 17, 2012 - CVE-2012-4520

CVE-2012-4520: Host header poisoning. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

December 10, 2012 - No CVE 1

Additional hardening of Host header handling. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

December 10, 2012 - No CVE 2

Additional hardening of redirect validation. Full description

Versions affected

- Django 1.3: (patch)

- Django 1.4: (patch)

February 19, 2013 - No CVE

Additional hardening of Host header handling. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

February 19, 2013 - CVE-2013-1664/1665

CVE-2013-1664 and CVE-2013-1665: Entity-based attacks against Python XML libraries. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

February 19, 2013 - CVE-2013-0305

CVE-2013-0305: Information leakage via admin history log. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

February 19, 2013 - CVE-2013-0306

CVE-2013-0306: Denial-of-service via formset max_num bypass. Full description

Versions affected

- Django 1.3 (patch)

- Django 1.4 (patch)

August 13, 2013 - CVE-2013-4249

CVE-2013-4249: XSS via admin trusting URLField values. Full description

Versions affected

- Django 1.5 (patch)

August 13, 2013 - CVE-2013-6044

CVE-2013-6044: Possible XSS via unvalidated URL redirect schemes. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

September 10, 2013 - CVE-2013-4315

CVE-2013-4315 Directory-traversal via ssi template tag. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

September 14, 2013 - CVE-2013-1443

CVE-2013-1443: Denial-of-service via large passwords. Full description

Versions affected

- Django 1.4 (patch and Python compatibility fix)

- Django 1.5 (patch)

April 21, 2014 - CVE-2014-0472

CVE-2014-0472: Unexpected code execution using reverse(). Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

April 21, 2014 - CVE-2014-0473

CVE-2014-0473: Caching of anonymous pages could reveal CSRF token. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

April 21, 2014 - CVE-2014-0474

CVE-2014-0474: MySQL typecasting causes unexpected query results. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

May 18, 2014 - CVE-2014-1418

CVE-2014-1418: Caches may be allowed to store and serve private data. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

May 18, 2014 - CVE-2014-3730

CVE-2014-3730: Malformed URLs from user input incorrectly validated. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

August 20, 2014 - CVE-2014-0480

CVE-2014-0480: reverse() can generate URLs pointing to other hosts. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

August 20, 2014 - CVE-2014-0481

CVE-2014-0481: File upload denial of service. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

August 20, 2014 - CVE-2014-0482

CVE-2014-0482: RemoteUserMiddleware session hijacking. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

August 20, 2014 - CVE-2014-0483

CVE-2014-0483: Data leakage via querystring manipulation in admin. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.5 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

January 13, 2015 - CVE-2015-0219

CVE-2015-0219: WSGI header spoofing via underscore/dash conflation. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

January 13, 2015 - CVE-2015-0220

CVE-2015-0220: Mitigated possible XSS attack via user-supplied redirect URLs. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

January 13, 2015 - CVE-2015-0221

CVE-2015-0221: Denial-of-service attack against django.views.static.serve(). Full description

Versions affected

- Django 1.4 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

January 13, 2015 - CVE-2015-0222

CVE-2015-0222: Database denial-of-service with ModelMultipleChoiceField. Full description

Versions affected

- Django 1.6 (patch)

- Django 1.7 (patch)

March 9, 2015 - CVE-2015-2241

CVE-2015-2241: XSS attack via properties in ModelAdmin.readonly_fields. Full description

Versions affected

- Django 1.7 (patch)

- Django 1.8 (patch)

March 18, 2015 - CVE-2015-2316

CVE-2015-2316: Denial-of-service possibility with strip_tags(). Full description

Versions affected

- Django 1.6 (patch)

- Django 1.7 (patch)

- Django 1.8 (patch)

March 18, 2015 - CVE-2015-2317

CVE-2015-2317: Mitigated possible XSS attack via user-supplied redirect URLs. Full description

Versions affected

- Django 1.4 (patch)

- Django 1.6 (patch)

- Django 1.7 (patch)

- Django 1.8 (patch)

May 20, 2015 - CVE-2015-3982

CVE-2015-3982: Fixed session flushing in the cached_db backend. Full description

Versions affected

- Django 1.8 (patch)

July 8, 2015 - CVE-2015-5143

CVE-2015-5143: Denial-of-service possibility by filling session store. Full description

Versions affected

- Django 1.8 (patch)

- Django 1.7 (patch)

- Django 1.4 (patch)

July 8, 2015 - CVE-2015-5144

CVE-2015-5144: Header injection possibility since validators accept newlines in input. Full description

Versions affected

- Django 1.8 (patch)

- Django 1.7 (patch)

- Django 1.4 (patch)

July 8, 2015 - CVE-2015-5145

CVE-2015-5145: Denial-of-service possibility in URL validation. Full description

Versions affected

- Django 1.8 (patch)

August 18, 2015 - CVE-2015-5963/CVE-2015-5964

CVE-2015-5963 and CVE-2015-5964: Denial-of-service possibility in logout() view by filling session store. Full description

Versions affected

- Django 1.8 (patch)

- Django 1.7 (patch)

- Django 1.4 (patch)

November 24, 2015 - CVE-2015-8213

CVE-2015-8213: Settings leak possibility in date template filter. Full description

Versions affected

- Django 1.8 (patch)

- Django 1.7 (patch)

February 1, 2016 - CVE-2016-2048

CVE-2016-2048: User with “change” but not “add” permission can create objects for ModelAdmin’s with save_as=True. Full description

Versions affected

- Django 1.9 (patch)

March 1, 2016 - CVE-2016-2512

CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth. Full description

Versions affected

- Django 1.9 (patch)

- Django 1.8 (patch)

March 1, 2016 - CVE-2016-2513

CVE-2016-2513: User enumeration through timing difference on password hasher work factor upgrade. Full description

Versions affected

- Django 1.9 (patch)

- Django 1.8 (patch)

July 18, 2016 - CVE-2016-6186

CVE-2016-6186: XSS in admin’s add/change related popup. Full description

Versions affected

- Django 1.9 (patch)

- Django 1.8 (patch)

Django internals

Documentation for people hacking on Django itself. This is the place to go if you’d like to help improve Django or learn about how Django is managed.

- Contributing to Django

- Advice for new contributors

- Reporting bugs and requesting features

- Triaging tickets

- Writing code

- Writing documentation

- Localizing Django

- Committing code

- Mailing lists

- django-users

- django-core-mentorship

- django-developers

- django-i18n

- django-announce

- django-updates

- Organization of the Django Project

- Principles

- Core team

- Technical board

- Changing the organization

- Django team

- The original team

- The current team

- Past team members

- Roles

- Technical board

- Committers

- Security team

- Releasers

- Ops team

- Django’s security policies

- Reporting security issues

- Supported versions

- How Django discloses security issues

- Who receives advance notification

- Requesting notifications

- Django’s release process

- Official releases

- Release cadence

- Deprecation policy

- Supported versions

- Release process

- Django Deprecation Timeline

- 2.0

- 1.10

- 1.9

- 1.8

- 1.7

- 1.6

- 1.5

- 1.4

- 1.3

- The Django source code repository

- High-level overview

- The master branch

- Other branches

- Tags

- How is Django Formed?

- Overview

- Prerequisites

- Pre-release tasks

- Preparing for release

- Actually rolling the release

- Making the release(s) available to the public

- Post-release

- New stable branch tasks

- Notes on setting the VERSION tuple

Contributing to Django

Django is a community that lives on its volunteers. As it keeps growing, we always need more people to help others. As soon as you learn Django, you can contribute in many ways:

- Join the django-users mailing list and answer questions. This mailing list has a huge audience, and we really want to maintain a friendly and helpful atmosphere. If you’re new to the Django community, you should read the posting guidelines.

- Join the #django IRC channel on Freenode and answer questions. By explaining Django to other users, you’re going to learn a lot about the framework yourself.

- Blog about Django. We syndicate all the Django blogs we know about on the community page; if you’d like to see your blog on that page you can register it here.

- Contribute to open-source Django projects, write some documentation, or release your own code as an open-source pluggable application. The ecosystem of pluggable applications is a big strength of Django, help us build it!

If you think working with Django is fun, wait until you start working on it. We’re passionate about helping Django users make the jump to contributing members of the community, so there are several ways you can help Django’s development:

- Report bugs in our ticket tracker.

- Join the django-developers mailing list and share your ideas for how to improve Django. We’re always open to suggestions.

- Submit patches for new and/or fixed behavior. If you’re looking for an easy way to start contributing to Django read the Writing your first patch for Django tutorial and have a look at the easy pickings tickets. The Patch review checklist will also be helpful.

- Improve the documentation or write unit tests.

- Triage tickets and review patches created by other users.

Really, ANYONE can do something to help make Django better and greater!

Browse the following sections to find out how:

- Advice for new contributors

- First steps

- Guidelines

- FAQ

- Reporting bugs and requesting features

- Reporting bugs

- Reporting user interface bugs and features

- Requesting features

- How we make decisions

- Triaging tickets

- Triage workflow

- Triage stages

- Other triage attributes

- Closing Tickets

- How can I help with triaging?

- Bisecting a regression

- Writing code

- Coding style

- Unit tests

- Submitting patches

- Working with Git and GitHub

- JavaScript

- Writing documentation

- Getting the raw documentation

- Getting started with Sphinx

- How the documentation is organized

- Writing style

- Commonly used terms

- Django-specific terminology

- Guidelines for reStructuredText files

- Django-specific markup

- Documenting new features

- Minimizing images

- An example

- Improving the documentation

- Spelling check

- Translating documentation

- django-admin man page

- Localizing Django

- Translations

- Formats

- Documentation

- Committing code

- Handling pull requests

- Committing guidelines

- Reverting commits

Advice for new contributors

New contributor and not sure what to do? Want to help but just don’t know how to get started? This is the section for you.

Basic tools and workflow

If you are new to contributing to Django, the Writing your first patch for Django tutorial will give you an introduction to the tools and the workflow.

First steps

Start with these easy tasks to discover Django’s development process.

- Sign the Contributor License Agreement

The code that you write belongs to you or your employer. If your contribution is more than one or two lines of code, you need to sign the CLA. See the Contributor License Agreement FAQ for a more thorough explanation.

- Triage tickets

If an unreviewed ticket reports a bug, try and reproduce it. If you can reproduce it and it seems valid, make a note that you confirmed the bug and accept the ticket. Make sure the ticket is filed under the correct component area. Consider writing a patch that adds a test for the bug’s behavior, even if you don’t fix the bug itself. See more at How can I help with triaging?

- Look for tickets that are accepted and review patches to build familiarity with the codebase and the process

Mark the appropriate flags if a patch needs docs or tests. Look through the changes a patch makes, and keep an eye out for syntax that is incompatible with older but still supported versions of Python. Run the tests and make sure they pass. Where possible and relevant, try them out on a database other than SQLite. Leave comments and feedback!

- Keep old patches up to date

Oftentimes the codebase will change between a patch being submitted and the time it gets reviewed. Make sure it still applies cleanly and functions as expected. Simply updating a patch is both useful and important! See more on Submitting patches.

- Write some documentation

Django’s documentation is great but it can always be improved. Did you find a typo? Do you think that something should be clarified? Go ahead and suggest a documentation patch! See also the guide on Writing documentation, in particular the tips for Improving the documentation.

Note

The reports page contains links to many useful Trac queries, including several that are useful for triaging tickets and reviewing patches as suggested above.

Guidelines

As a newcomer on a large project, it’s easy to experience frustration. Here’s some advice to make your work on Django more useful and rewarding.

- Pick a subject area that you care about, that you are familiar with, or that you want to learn about

You don’t already have to be an expert on the area you want to work on; you become an expert through your ongoing contributions to the code.

- Analyze tickets’ context and history

Trac isn’t an absolute; the context is just as important as the words. When reading Trac, you need to take into account who says things, and when they were said. Support for an idea two years ago doesn’t necessarily mean that the idea will still have support. You also need to pay attention to who hasn’t spoken – for example, if a core team member hasn’t been recently involved in a discussion, then a ticket may not have the support required to get into trunk.

- Start small

It’s easier to get feedback on a little issue than on a big one. See the easy pickings.

- If you’re going to engage in a big task, make sure that your idea has support first

This means getting someone else to confirm that a bug is real before you fix the issue, and ensuring that the core team supports a proposed feature before you go implementing it.

- Be bold! Leave feedback!

Sometimes it can be scary to put your opinion out to the world and say “this ticket is correct” or “this patch needs work”, but it’s the only way the project moves forward. The contributions of the broad Django community ultimately have a much greater impact than that of the core team. We can’t do it without you!

- Err on the side of caution when marking things Ready For Check-in

If you’re really not certain if a ticket is ready, don’t mark it as such. Leave a comment instead, letting others know your thoughts. If you’re mostly certain, but not completely certain, you might also try asking on IRC to see if someone else can confirm your suspicions.

- Wait for feedback, and respond to feedback that you receive

Focus on one or two tickets, see them through from start to finish, and repeat. The shotgun approach of taking on lots of tickets and letting some fall by the wayside ends up doing more harm than good.

- Be rigorous

When we say “PEP 8, and must have docs and tests”, we mean it. If a patch doesn’t have docs and tests, there had better be a good reason. Arguments like “I couldn’t find any existing tests of this feature” don’t carry much weight–while it may be true, that means you have the extra-important job of writing the very first tests for that feature, not that you get a pass from writing tests altogether.

FAQ

1. This ticket I care about has been ignored for days/weeks/months! What can I do to get it committed?

First off, it’s not personal. Django is entirely developed by volunteers (even the core team), and sometimes folks just don’t have time. The best thing to do is to send a gentle reminder to the django-developers mailing list asking for review on the ticket, or to bring it up in the #django-dev IRC channel.

2. I’m sure my ticket is absolutely 100% perfect, can I mark it as RFC myself?

Short answer: No. It’s always better to get another set of eyes on a ticket. If you’re having trouble getting that second set of eyes, see question 1, above.

Reporting bugs and requesting features

Important

Please report security issues only to security@djangoproject.com. This is a private list only open to long-time, highly trusted Django developers, and its archives are not public. For further details, please see our security policies.

Otherwise, before reporting a bug or requesting a new feature, please consider these general points:

- Check that someone hasn’t already filed the bug or feature request by searching or running custom queries in the ticket tracker.

- Don’t use the ticket system to ask support questions. Use the django-users list or the #django IRC channel for that.

- Don’t reopen issues that have been marked “wontfix” by a core developer. This mark means that the decision has been made that we can’t or won’t fix this particular issue. If you’re not sure why, please ask on django-developers.

- Don’t use the ticket tracker for lengthy discussions, because they’re likely to get lost. If a particular ticket is controversial, please move the discussion to django-developers.

Reporting bugs

Well-written bug reports are incredibly helpful. However, there’s a certain amount of overhead involved in working with any bug tracking system so your help in keeping our ticket tracker as useful as possible is appreciated. In particular:

- Do read the FAQ to see if your issue might be a well-known question.

- Do ask on django-users or #django first if you’re not sure if what you’re seeing is a bug.

- Do write complete, reproducible, specific bug reports. You must include a clear, concise description of the problem, and a set of instructions for replicating it. Add as much debug information as you can: code snippets, test cases, exception backtraces, screenshots, etc. A nice small test case is the best way to report a bug, as it gives us an easy way to confirm the bug quickly.

- Don’t post to django-developers just to announce that you have filed a bug report. All the tickets are mailed to another list, django-updates, which is tracked by developers and interested community members; we see them as they are filed.

To understand the lifecycle of your ticket once you have created it, refer to Triaging tickets.

Reporting user interface bugs and features

If your bug or feature request touches on anything visual in nature, there are a few additional guidelines to follow:

- Include screenshots in your ticket which are the visual equivalent of a minimal testcase. Show off the issue, not the crazy customizations you’ve made to your browser.

- If the issue is difficult to show off using a still image, consider capturing a brief screencast. If your software permits it, capture only the relevant area of the screen.

- If you’re offering a patch which changes the look or behavior of Django’s UI, you must attach before and after screenshots/screencasts. Tickets lacking these are difficult for triagers and core developers to assess quickly.

- Screenshots don’t absolve you of other good reporting practices. Make sure to include URLs, code snippets, and step-by-step instructions on how to reproduce the behavior visible in the screenshots.

- Make sure to set the UI/UX flag on the ticket so interested parties can find your ticket.

Requesting features

We’re always trying to make Django better, and your feature requests are a key part of that. Here are some tips on how to make a request most effectively:

- Make sure the feature actually requires changes in Django’s core. If your idea can be developed as an independent application or module — for instance, you want to support another database engine — we’ll probably suggest that you to develop it independently. Then, if your project gathers sufficient community support, we may consider it for inclusion in Django.

- First request the feature on the django-developers list, not in the ticket tracker. It’ll get read more closely if it’s on the mailing list. This is even more important for large-scale feature requests. We like to discuss any big changes to Django’s core on the mailing list before actually working on them.

- Describe clearly and concisely what the missing feature is and how you’d like to see it implemented. Include example code (non-functional is OK) if possible.

- Explain why you’d like the feature. In some cases this is obvious, but since Django is designed to help real developers get real work done, you’ll need to explain it, if it isn’t obvious why the feature would be useful.

If core developers agree on the feature, then it’s appropriate to create a ticket. Include a link the discussion on django-developers in the ticket description.

As with most open-source projects, code talks. If you are willing to write the code for the feature yourself or, even better, if you’ve already written it, it’s much more likely to be accepted. Just fork Django on GitHub, create a feature branch, and show us your work!

See also: Documenting new features.

How we make decisions

Whenever possible, we strive for a rough consensus. To that end, we’ll often have informal votes on django-developers about a feature. In these votes we follow the voting style invented by Apache and used on Python itself, where votes are given as +1, +0, -0, or -1. Roughly translated, these votes mean:

- +1: “I love the idea and I’m strongly committed to it.”

- +0: “Sounds OK to me.”

- -0: “I’m not thrilled, but I won’t stand in the way.”

- -1: “I strongly disagree and would be very unhappy to see the idea turn into reality.”

Although these votes on django-developers are informal, they’ll be taken very seriously. After a suitable voting period, if an obvious consensus arises we’ll follow the votes.

However, consensus is not always possible. If consensus cannot be reached, or if the discussion towards a consensus fizzles out without a concrete decision, any core team member may defer the decision to the technical board.

Internally, the technical board will use the same voting mechanism. A proposition will be considered carried if:

- There are at least three “+1” votes from members of the technical board.

- There is no “-1” vote from any member of the technical board.

Votes should be submitted within a week.

Since this process allows any technical board member to veto a proposal, a “-1” vote should be accompanied by an explanation of what it would take to convert that “-1” into at least a “+0”.

Votes on technical matters should be announced and held in public on the django-developers mailing list.

Triaging tickets

Django uses Trac for managing the work on the code base. Trac is a community-tended garden of the bugs people have found and the features people would like to see added. As in any garden, sometimes there are weeds to be pulled and sometimes there are flowers and vegetables that need picking. We need your help to sort out one from the other, and in the end we all benefit together.

Like all gardens, we can aspire to perfection but in reality there’s no such thing. Even in the most pristine garden there are still snails and insects. In a community garden there are also helpful people who – with the best of intentions – fertilize the weeds and poison the roses. It’s the job of the community as a whole to self-manage, keep the problems to a minimum, and educate those coming into the community so that they can become valuable contributing members.

Similarly, while we aim for Trac to be a perfect representation of the state of Django’s progress, we acknowledge that this simply will not happen. By distributing the load of Trac maintenance to the community, we accept that there will be mistakes. Trac is “mostly accurate”, and we give allowances for the fact that sometimes it will be wrong. That’s okay. We’re perfectionists with deadlines.

We rely on the community to keep participating, keep tickets as accurate as possible, and raise issues for discussion on our mailing lists when there is confusion or disagreement.

Django is a community project, and every contribution helps. We can’t do this without you!

Triage workflow

Unfortunately, not all bug reports and feature requests in the ticket tracker provide all the required details. A number of tickets have patches, but those patches don’t meet all the requirements of a good patch.

One way to help out is to triage tickets that have been created by other users. The core team and several community members work on this regularly, but more help is always appreciated.

Most of the workflow is based around the concept of a ticket’s triage stages. Each stage describes where in its lifetime a given ticket is at any time. Along with a handful of flags, this attribute easily tells us what and who each ticket is waiting on.

Since a picture is worth a thousand words, let’s start there:

We’ve got two roles in this diagram:

- Committers (also called core developers): people with commit access who are responsible for making decisions and integrating the contributions of the community.

- Ticket triagers: anyone in the Django community who chooses to become involved in Django’s development process. Our Trac installation is intentionally left open to the public, and anyone can triage tickets. Django is a community project, and we encourage triage by the community.

By way of example, here we see the lifecycle of an average ticket:

- Alice creates a ticket, and uploads an incomplete patch (no tests, incorrect implementation).

- Bob reviews the patch, marks it “Accepted”, “needs tests”, and “patch needs improvement”, and leaves a comment telling Alice how the patch could be improved.

- Alice updates the patch, adding tests (but not changing the implementation). She removes the two flags.

- Charlie reviews the patch and resets the “patch needs improvement” flag with another comment about improving the implementation.

- Alice updates the patch, fixing the implementation. She removes the “patch needs improvement” flag.

- Daisy reviews the patch, and marks it RFC.

- Jacob, a core developer, reviews the RFC patch, applies it to his checkout, and commits it.

Some tickets require much less feedback than this, but then again some tickets require much much more.

Triage stages

Below we describe in more detail the various stages that a ticket may flow through during its lifetime.

Unreviewed

The ticket has not been reviewed by anyone who felt qualified to make a judgment about whether the ticket contained a valid issue, a viable feature, or ought to be closed for any of the various reasons.

Accepted

The big gray area! The absolute meaning of “accepted” is that the issue described in the ticket is valid and is in some stage of being worked on. Beyond that there are several considerations:

- Accepted + No Flags

The ticket is valid, but no one has submitted a patch for it yet. Often this means you could safely start writing a patch for it. This is generally more true for the case of accepted bugs than accepted features. A ticket for a bug that has been accepted means that the issue has been verified by at least one triager as a legitimate bug - and should probably be fixed if possible. An accepted new feature may only mean that one triager thought the feature would be good to have, but this alone does not represent a consensus view or imply with any certainty that a patch will be accepted for that feature. Seek more feedback before writing an extensive patch if you are in doubt.

- Accepted + Has Patch

The ticket is waiting for people to review the supplied patch. This means downloading the patch and trying it out, verifying that it contains tests and docs, running the test suite with the included patch, and leaving feedback on the ticket.

- Accepted + Has Patch + Needs ...

This means the ticket has been reviewed, and has been found to need further work. “Needs tests” and “Needs documentation” are self-explanatory. “Patch needs improvement” will generally be accompanied by a comment on the ticket explaining what is needed to improve the code.

Ready For Checkin

The ticket was reviewed by any member of the community other than the person who supplied the patch and found to meet all the requirements for a commit-ready patch. A committer now needs to give the patch a final review prior to being committed. See the New contributors’ FAQ for “My ticket has been in RFC forever! What should I do?”

Someday/Maybe

This stage isn’t shown on the diagram. It’s only used by core developers to keep track of high-level ideas or long term feature requests.

These tickets are uncommon and overall less useful since they don’t describe concrete actionable issues. They are enhancement requests that we might consider adding someday to the framework if an excellent patch is submitted. They are not a high priority.

Other triage attributes

A number of flags, appearing as checkboxes in Trac, can be set on a ticket:

Has patch

This means the ticket has an associated patch. These will be reviewed to see if the patch is “good”.

The following three fields (Needs documentation, Needs tests, Patch needs improvement) apply only if a patch has been supplied.

Needs documentation

This flag is used for tickets with patches that need associated documentation. Complete documentation of features is a prerequisite before we can check them into the codebase.

Needs tests

This flags the patch as needing associated unit tests. Again, this is a required part of a valid patch.

Patch needs improvement

This flag means that although the ticket has a patch, it’s not quite ready for checkin. This could mean the patch no longer applies cleanly, there is a flaw in the implementation, or that the code doesn’t meet our standards.

Easy pickings

Tickets that would require small, easy, patches.

Type

Tickets should be categorized by type between:

- New Feature

For adding something new.

- Bug

For when an existing thing is broken or not behaving as expected.

- Cleanup/optimization

For when nothing is broken but something could be made cleaner, better, faster, stronger.

Component

Tickets should be classified into components indicating which area of the Django codebase they belong to. This makes tickets better organized and easier to find.

Severity

The severity attribute is used to identify blockers, that is, issues which should get fixed before releasing the next version of Django. Typically those issues are bugs causing regressions from earlier versions or potentially causing severe data losses. This attribute is quite rarely used and the vast majority of tickets have a severity of “Normal”.

Version

It is possible to use the version attribute to indicate in which version the reported bug was identified.

UI/UX

This flag is used for tickets that relate to User Interface and User Experiences questions. For example, this flag would be appropriate for user-facing features in forms or the admin interface.

Cc

You may add your username or email address to this field to be notified when new contributions are made to the ticket.

Keywords

With this field you may label a ticket with multiple keywords. This can be useful, for example, to group several tickets of a same theme. Keywords can either be comma or space separated. Keyword search finds the keyword string anywhere in the keywords. For example, clicking on a ticket with the keyword “form” will yield similar tickets tagged with keywords containing strings such as “formset”, “modelformset”, and “ManagementForm”.

Closing Tickets

When a ticket has completed its useful lifecycle, it’s time for it to be closed. Closing a ticket is a big responsibility, though. You have to be sure that the issue is really resolved, and you need to keep in mind that the reporter of the ticket may not be happy to have their ticket closed (unless it’s fixed, of course). If you’re not certain about closing a ticket, just leave a comment with your thoughts instead.

If you do close a ticket, you should always make sure of the following:

- Be certain that the issue is resolved.

- Leave a comment explaining the decision to close the ticket.

- If there is a way they can improve the ticket to reopen it, let them know.

- If the ticket is a duplicate, reference the original ticket. Also cross-reference the closed ticket by leaving a comment in the original one – this allows to access more related information about the reported bug or requested feature.

- Be polite. No one likes having their ticket closed. It can be frustrating or even discouraging. The best way to avoid turning people off from contributing to Django is to be polite and friendly and to offer suggestions for how they could improve this ticket and other tickets in the future.

A ticket can be resolved in a number of ways:

- fixed

Used by the core developers once a patch has been rolled into Django and the issue is fixed.

- invalid

Used if the ticket is found to be incorrect. This means that the issue in the ticket is actually the result of a user error, or describes a problem with something other than Django, or isn’t a bug report or feature request at all (for example, some new users submit support queries as tickets).

- wontfix

Used when a core developer decides that this request is not appropriate for consideration in Django. This is usually chosen after discussion in the django-developers mailing list. Feel free to start or join in discussions of “wontfix” tickets on the django-developers mailing list, but please do not reopen tickets closed as “wontfix” by a core developer.

- duplicate

Used when another ticket covers the same issue. By closing duplicate tickets, we keep all the discussion in one place, which helps everyone.

- worksforme

Used when the ticket doesn’t contain enough detail to replicate the original bug.

- needsinfo

Used when the ticket does not contain enough information to replicate the reported issue but is potentially still valid. The ticket should be reopened when more information is supplied.

If you believe that the ticket was closed in error – because you’re still having the issue, or it’s popped up somewhere else, or the triagers have made a mistake – please reopen the ticket and provide further information. Again, please do not reopen tickets that have been marked as “wontfix” by core developers and bring the issue to django-developers instead.

How can I help with triaging?

The triage process is primarily driven by community members. Really, ANYONE can help.

Core developers may provide feedback on issues they’re familiar with, or make decisions on controversial ones, but they aren’t responsible for triaging tickets in general.

To get involved, start by creating an account on Trac. If you have an account but have forgotten your password, you can reset it using the password reset page.

Then, you can help out by:

- Closing “Unreviewed” tickets as “invalid”, “worksforme” or “duplicate.”

- Closing “Unreviewed” tickets as “needsinfo” when the description is too sparse to be actionable, or when they’re feature requests requiring a discussion on django-developers.

- Correcting the “Needs tests”, “Needs documentation”, or “Has patch” flags for tickets where they are incorrectly set.

- Setting the “Easy pickings” flag for tickets that are small and relatively straightforward.

- Set the type of tickets that are still uncategorized.

- Checking that old tickets are still valid. If a ticket hasn’t seen any activity in a long time, it’s possible that the problem has been fixed but the ticket hasn’t yet been closed.

- Identifying trends and themes in the tickets. If there are a lot of bug reports about a particular part of Django, it may indicate we should consider refactoring that part of the code. If a trend is emerging, you should raise it for discussion (referencing the relevant tickets) on django-developers.

- Verify if patches submitted by other users are correct. If they are correct and also contain appropriate documentation and tests then move them to the “Ready for Checkin” stage. If they are not correct then leave a comment to explain why and set the corresponding flags (“Patch needs improvement”, “Needs tests” etc.).

Note

The Reports page contains links to many useful Trac queries, including several that are useful for triaging tickets and reviewing patches as suggested above.

You can also find more Advice for new contributors.

However, we do ask the following of all general community members working in the ticket database:

- Please don’t close tickets as “wontfix.” The core developers will make the final determination of the fate of a ticket, usually after consultation with the community.

- Please don’t promote your own tickets to “Ready for checkin”. You may mark other people’s tickets which you’ve reviewed as “Ready for checkin”, but you should get at minimum one other community member to review a patch that you submit.

- Please don’t reverse a decision that has been made by a core developer. If you disagree with a decision that has been made, please post a message to django-developers.

- If you’re unsure if you should be making a change, don’t make the change but instead leave a comment with your concerns on the ticket, or post a message to django-developers. It’s okay to be unsure, but your input is still valuable.

Bisecting a regression

A regression is a bug that’s present in some newer version of Django but not in an older one. An extremely helpful piece of information is the commit that introduced the regression. Knowing the commit that caused the change in behavior helps identify if the change was intentional or if it was an inadvertent side-effect. Here’s how you can determine this.

Begin by writing a regression test for Django’s test suite for the issue. For example, we’ll pretend we’re debugging a regression in migrations. After you’ve written the test and confirmed that it fails on the latest master, put it in a separate file that you can run standalone. For our example, we’ll pretend we created tests/migrations/test_regression.py, which can be run with:

$ ./runtests.py migrations.test_regression

Next, we mark the current point in history as being “bad” since the test fails:

$ git bisect bad
You need to start by "git bisect start"
Do you want me to do it for you [Y/n]? y

Now, we need to find a point in git history before the regression was introduced (i.e. a point where the test passes). Use something like git checkout HEAD~100 to checkout an earlier revision (100 commits earlier, in this case). Check if the test fails. If so, mark that point as “bad” (git bisect bad), then checkout an earlier revision and recheck. Once you find a revision where your test passes, mark it as “good”:

$ git bisect good
Bisecting: X revisions left to test after this (roughly Y steps)
...

Now we’re ready for the fun part: using git bisect run to automate the rest of the process:

$ git bisect run python runtests.py migrations.test_regression

You should see git bisect use a binary search to automatically checkout revisions between the good and bad commits until it finds the first “bad” commit where the test fails.

Now, report your results on the Trac ticket, and please include the regression test as an attachment. When someone writes a fix for the bug, they’ll already have your test as a starting point.

Writing code

So you’d like to write some code to improve Django. Awesome! Browse the following sections to find out how to give your code patches the best chances to be included in Django core:

- Coding style

- Unit tests

- Submitting patches

- Working with Git and GitHub

- JavaScript

Coding style

Please follow these coding standards when writing code for inclusion in Django.

Python style

- Please conform to the indentation style dictated in the .editorconfig file. We recommend using a text editor with EditorConfig support to avoid indentation and whitespace issues. The Python files use 4 spaces for indentation and the HTML files use 2 spaces.

- Unless otherwise specified, follow PEP 8.

Use flake8 to check for problems in this area. Note that our setup.cfg file contains some excluded files (deprecated modules we don’t care about cleaning up and some third-party code that Django vendors) as well as some excluded errors that we don’t consider as gross violations. Remember that PEP 8 is only a guide, so respect the style of the surrounding code as a primary goal.

An exception to PEP 8 is our rules on line lengths. Don’t limit lines of code to 79 characters if it means the code looks significantly uglier or is harder to read. We allow up to 119 characters as this is the width of GitHub code review; anything longer requires horizontal scrolling which makes review more difficult. This check is included when you run flake8. Documentation, comments, and docstrings should be wrapped at 79 characters, even though PEP 8 suggests 72.

- Use four spaces for indentation.

- Use underscores, not camelCase, for variable, function and method names (i.e. poll.get_unique_voters(), not poll.getUniqueVoters).

- Use InitialCaps for class names (or for factory functions that return classes).

- In docstrings, follow PEP 257. For example:

def foo():
"""
Calculate something and return the result.
"""
...

- In tests, use assertRaisesMessage() instead of assertRaises() so you can check the exception message. Use assertRaisesRegex() (six.assertRaisesRegex() as long as we support Python 2) only if you need to use regular expression matching.

Imports

- Use isort to automate import sorting using the guidelines below.

Quick start:

$ pip install isort
$ isort -rc .

This runs isort recursively from your current directory, modifying any files that don’t conform to the guidelines. If you need to have imports out of order (to avoid a circular import, for example) use a comment like this:

import module  # isort:skip

- Put imports in these groups: future, standard library, third-party libraries, other Django components, local Django component, try/excepts. Sort lines in each group alphabetically by the full module name. Place all import module statements before from module import objects in each section. Use absolute imports for other Django components and relative imports for local components.

- On each line, alphabetize the items with the upper case items grouped before the lower case items.

- Break long lines using parentheses and indent continuation lines by 4 spaces. Include a trailing comma after the last import and put the closing parenthesis on its own line.

Use a single blank line between the last import and any module level code, and use two blank lines above the first function or class.

For example (comments are for explanatory purposes only):

django/contrib/admin/example.py

# future
from __future__ import unicode_literals

# standard library
import json
from itertools import chain

# third-party
import bcrypt

# Django
from django.http import Http404
from django.http.response import (
Http404, HttpResponse, HttpResponseNotAllowed, StreamingHttpResponse,
cookie,
)

# local Django
from .models import LogEntry

# try/except
try:
import pytz
except ImportError:
pytz = None

CONSTANT = 'foo'

class Example(object):
# ...

- Use convenience imports whenever available. For example, do this:

from django.views.generic import View

instead of:

from django.views.generic.base import View

Template style

- In Django template code, put one (and only one) space between the curly brackets and the tag contents.

Do this:

{{ foo }}

Don’t do this:

{{foo}}

View style

- In Django views, the first parameter in a view function should be called request.

Do this:

def my_view(request, foo):
# ...

Don’t do this:

def my_view(req, foo):
# ...

Model style

- Field names should be all lowercase, using underscores instead of camelCase.

Do this:

class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

Don’t do this:

class Person(models.Model):
FirstName = models.CharField(max_length=20)
Last_Name = models.CharField(max_length=40)

- The class Meta should appear after the fields are defined, with a single blank line separating the fields and the class definition.

Do this:

class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

class Meta:
verbose_name_plural = 'people'

Don’t do this:

class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)
class Meta:
verbose_name_plural = 'people'

Don’t do this, either:

class Person(models.Model):
class Meta:
verbose_name_plural = 'people'

first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

- If you define a __str__ method (previously __unicode__ before Python 3 was supported), decorate the model class with python_2_unicode_compatible().

- The order of model inner classes and standard methods should be as follows (noting that these are not all required):

- All database fields

- Custom manager attributes

- class Meta

- def __str__()

- def save()

- def get_absolute_url()

- Any custom methods

- If choices is defined for a given model field, define each choice as a tuple of tuples, with an all-uppercase name as a class attribute on the model. Example:

class MyModel(models.Model):
DIRECTION_UP = 'U'
DIRECTION_DOWN = 'D'
DIRECTION_CHOICES = (
(DIRECTION_UP, 'Up'),
(DIRECTION_DOWN, 'Down'),
)

Use of django.conf.settings

Modules should not in general use settings stored in django.conf.settings at the top level (i.e. evaluated when the module is imported). The explanation for this is as follows:

Manual configuration of settings (i.e. not relying on the DJANGO_SETTINGS_MODULE environment variable) is allowed and possible as follows:

from django.conf import settings

settings.configure({}, SOME_SETTING='foo')

However, if any setting is accessed before the settings.configure line, this will not work. (Internally, settings is a LazyObject which configures itself automatically when the settings are accessed if it has not already been configured).

So, if there is a module containing some code as follows:

from django.conf import settings
from django.core.urlresolvers import get_callable

default_foo_view = get_callable(settings.FOO_VIEW)

...then importing this module will cause the settings object to be configured. That means that the ability for third parties to import the module at the top level is incompatible with the ability to configure the settings object manually, or makes it very difficult in some circumstances.

Instead of the above code, a level of laziness or indirection must be used, such as django.utils.functional.LazyObject, django.utils.functional.lazy() or lambda.

Miscellaneous

- Mark all strings for internationalization; see the i18n documentation for details.

- Remove import statements that are no longer used when you change code. flake8 will identify these imports for you. If an unused import needs to remain for backwards-compatibility, mark the end of with # NOQA to silence the flake8 warning.

- Systematically remove all trailing whitespaces from your code as those add unnecessary bytes, add visual clutter to the patches and can also occasionally cause unnecessary merge conflicts. Some IDE’s can be configured to automatically remove them and most VCS tools can be set to highlight them in diff outputs.

- Please don’t put your name in the code you contribute. Our policy is to keep contributors’ names in the AUTHORS file distributed with Django – not scattered throughout the codebase itself. Feel free to include a change to the AUTHORS file in your patch if you make more than a single trivial change.

JavaScript style

For details about the JavaScript code style used by Django, see JavaScript.

Unit tests

Django comes with a test suite of its own, in the tests directory of the code base. It’s our policy to make sure all tests pass at all times.

We appreciate any and all contributions to the test suite!

The Django tests all use the testing infrastructure that ships with Django for testing applications. See Writing and running tests for an explanation of how to write new tests.

Running the unit tests

Quickstart

If you are on Python 2, you’ll first need to install a backport of the unittest.mock module that’s available in Python 3. See Running all the tests for details on installing mock and the other optional test dependencies.

Running the tests requires a Django settings module that defines the databases to use. To make it easy to get started, Django provides and uses a sample settings module that uses the SQLite database. To run the tests:

$ git clone https://github.com/django/django.git django-repo
$ cd django-repo/tests
$ PYTHONPATH=..:$PYTHONPATH ./runtests.py

Windows users

We recommend something like Git Bash to run the tests using the above approach.

You can avoid typing the PYTHONPATH bit each time by adding your Django checkout to your PYTHONPATH or by installing the source checkout using pip. See Installing the development version.

Having problems? See Troubleshooting for some common issues.

Using another settings module

The included settings module allows you to run the test suite using SQLite. If you want to test behavior using a different database (and if you’re proposing patches for Django, it’s a good idea to test across databases), you may need to define your own settings file.

To run the tests with different settings, ensure that the module is on your PYTHONPATH and pass the module with --settings.

The DATABASES setting in any test settings module needs to define two databases:

- A default database. This database should use the backend that you want to use for primary testing.

- A database with the alias other. The other database is used to establish that queries can be directed to different databases. As a result, this database can use any backend you want. It doesn’t need to use the same backend as the default database (although it can use the same backend if you want to). It cannot be the same database as the default.

If you’re using a backend that isn’t SQLite, you will need to provide other details for each database:

- The USER option needs to specify an existing user account for the database. That user needs permission to execute CREATE DATABASE so that the test database can be created.

- The PASSWORD option needs to provide the password for the USER that has been specified.

Test databases get their names by prepending test_ to the value of the NAME settings for the databases defined in DATABASES. These test databases are deleted when the tests are finished.

You will also need to ensure that your database uses UTF-8 as the default character set. If your database server doesn’t use UTF-8 as a default charset, you will need to include a value for CHARSET in the test settings dictionary for the applicable database.

Running only some of the tests

Django’s entire test suite takes a while to run, and running every single test could be redundant if, say, you just added a test to Django that you want to run quickly without running everything else. You can run a subset of the unit tests by appending the names of the test modules to runtests.py on the command line.

For example, if you’d like to run tests only for generic relations and internationalization, type:

$ ./runtests.py --settings=path.to.settings generic_relations i18n

How do you find out the names of individual tests? Look in tests/ — each directory name there is the name of a test.

If you just want to run a particular class of tests, you can specify a list of paths to individual test classes. For example, to run the TranslationTests of the i18n module, type:

$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests

Going beyond that, you can specify an individual test method like this:

$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects

Running the Selenium tests

Some tests require Selenium and a Web browser (Firefox, Google Chrome, or Internet Explorer). To allow those tests to be run rather than skipped, you must install the selenium package into your Python path and run the tests with the --selenium option:

$ ./runtests.py --settings=test_sqlite --selenium admin_inlines

Running all the tests

If you want to run the full suite of tests, you’ll need to install a number of dependencies:

- bcrypt

- docutils

- geoip2

- jinja2 2.7+

- numpy

- Pillow

- PyYAML

- pytz

- setuptools

- memcached, plus a supported Python binding

- mock (for Python 2)

- gettext (gettext on Windows)

- selenium

- sqlparse

You can find these dependencies in pip requirements files inside the tests/requirements directory of the Django source tree and install them like so:

$ pip install -r tests/requirements/py3.txt  # Python 2: py2.txt

You can also install the database adapter(s) of your choice using oracle.txt, mysql.txt, or postgres.txt.

If you want to test the memcached cache backend, you’ll also need to define a CACHES setting that points at your memcached instance.

To run the GeoDjango tests, you will need to setup a spatial database and install the Geospatial libraries.

Each of these dependencies is optional. If you’re missing any of them, the associated tests will be skipped.

Code coverage

Contributors are encouraged to run coverage on the test suite to identify areas that need additional tests. The coverage tool installation and use is described in testing code coverage.

Coverage should be run in a single process to obtain accurate statistics. To run coverage on the Django test suite using the standard test settings:

$ coverage run ./runtests.py --settings=test_sqlite --parallel=1

After running coverage, generate the html report by running:

$ coverage html

When running coverage for the Django tests, the included .coveragerc settings file defines coverage_html as the output directory for the report and also excludes several directories not relevant to the results (test code or external code included in Django).

Contrib apps

Tests for contrib apps can be found in the tests/ directory, typically under <app_name>_tests. For example, tests for contrib.auth are located in tests/auth_tests.

Troubleshooting

Many test failures with UnicodeEncodeError

If the locales package is not installed, some tests will fail with a UnicodeEncodeError.

You can resolve this on Debian-based systems, for example, by running:

$ apt-get install locales
$ dpkg-reconfigure locales

Tests that only fail in combination

In case a test passes when run in isolation but fails within the whole suite, we have some tools to help analyze the problem.

The --bisect option of runtests.py will run the failing test while halving the test set it is run together with on each iteration, often making it possible to identify a small number of tests that may be related to the failure.

For example, suppose that the failing test that works on its own is ModelTest.test_eq, then using:

$ ./runtests.py --bisect basic.tests.ModelTest.test_eq

will try to determine a test that interferes with the given one. First, the test is run with the first half of the test suite. If a failure occurs, the first half of the test suite is split in two groups and each group is then run with the specified test. If there is no failure with the first half of the test suite, the second half of the test suite is run with the specified test and split appropriately as described earlier. The process repeats until the set of failing tests is minimized.

The --pair option runs the given test alongside every other test from the suite, letting you check if another test has side-effects that cause the failure. So:

$ ./runtests.py --pair basic.tests.ModelTest.test_eq

will pair test_eq with every test label.

With both --bisect and --pair, if you already suspect which cases might be responsible for the failure, you may limit tests to be cross-analyzed by specifying further test labels after the first one:

$ ./runtests.py --pair basic.tests.ModelTest.test_eq queries transactions

You can also try running any set of tests in reverse using the --reverse option in order to verify that executing tests in a different order does not cause any trouble:

$ ./runtests.py basic --reverse

Seeing the SQL queries run during a test

If you wish to examine the SQL being run in failing tests, you can turn on SQL logging using the --debug-sql option. If you combine this with --verbosity=2, all SQL queries will be output:

$ ./runtests.py basic --debug-sql

New in Django 1.8:
The --reverse and --debug-sql options were added.

Seeing the full traceback of a test failure

By default tests are run in parallel with one process per core. When the tests are run in parallel, however, you’ll only see a truncated traceback for any test failures. You can adjust this behavior with the --parallel option:

$ ./runtests.py basic --parallel=1

You can also use the DJANGO_TEST_PROCESSES environment variable for this purpose.

New in Django 1.9:
Support for running tests in parallel and the --parallel option were added.

Submitting patches

We’re always grateful for patches to Django’s code. Indeed, bug reports with associated patches will get fixed far more quickly than those without patches.

Typo fixes and trivial documentation changes

If you are fixing a really trivial issue, for example changing a word in the documentation, the preferred way to provide the patch is using GitHub pull requests without a Trac ticket.

See the Working with Git and GitHub for more details on how to use pull requests.

“Claiming” tickets

In an open-source project with hundreds of contributors around the world, it’s important to manage communication efficiently so that work doesn’t get duplicated and contributors can be as effective as possible.

Hence, our policy is for contributors to “claim” tickets in order to let other developers know that a particular bug or feature is being worked on.

If you have identified a contribution you want to make and you’re capable of fixing it (as measured by your coding ability, knowledge of Django internals and time availability), claim it by following these steps:

- Login using your GitHub account or create an account in our ticket system. If you have an account but have forgotten your password, you can reset it using the password reset page.

- If a ticket for this issue doesn’t exist yet, create one in our ticket tracker.

- If a ticket for this issue already exists, make sure nobody else has claimed it. To do this, look at the “Owned by” section of the ticket. If it’s assigned to “nobody,” then it’s available to be claimed. Otherwise, somebody else may be working on this ticket. Either find another bug/feature to work on, or contact the developer working on the ticket to offer your help. If a ticket has been assigned for weeks or months without any activity, it’s probably safe to reassign it to yourself.

- Log into your account, if you haven’t already, by clicking “GitHub Login” or “DjangoProject Login” in the upper left of the ticket page.

- Claim the ticket by clicking the “assign to myself” radio button under “Action” near the bottom of the page, then click “Submit changes.”

Note

The Django software foundation requests that anyone contributing more than a trivial patch to Django sign and submit a Contributor License Agreement, this ensures that the Django Software Foundation has clear license to all contributions allowing for a clear license for all users.

Ticket claimers’ responsibility

Once you’ve claimed a ticket, you have a responsibility to work on that ticket in a reasonably timely fashion. If you don’t have time to work on it, either unclaim it or don’t claim it in the first place!

If there’s no sign of progress on a particular claimed ticket for a week or two, another developer may ask you to relinquish the ticket claim so that it’s no longer monopolized and somebody else can claim it.

If you’ve claimed a ticket and it’s taking a long time (days or weeks) to code, keep everybody updated by posting comments on the ticket. If you don’t provide regular updates, and you don’t respond to a request for a progress report, your claim on the ticket may be revoked.

As always, more communication is better than less communication!

Which tickets should be claimed?

Of course, going through the steps of claiming tickets is overkill in some cases.

In the case of small changes, such as typos in the documentation or small bugs that will only take a few minutes to fix, you don’t need to jump through the hoops of claiming tickets. Just submit your patch and be done with it.

Of course, it is always acceptable, regardless whether someone has claimed it or not, to submit patches to a ticket if you happen to have a patch ready.

Patch style

Make sure that any contribution you do fulfills at least the following requirements:

- The code required to fix a problem or add a feature is an essential part of a patch, but it is not the only part. A good patch should also include a regression test to validate the behavior that has been fixed and to prevent the problem from arising again. Also, if some tickets are relevant to the code that you’ve written, mention the ticket numbers in some comments in the test so that one can easily trace back the relevant discussions after your patch gets committed, and the tickets get closed.

- If the code associated with a patch adds a new feature, or modifies behavior of an existing feature, the patch should also contain documentation.

When you think your work is ready to be reviewed, send a GitHub pull request. Please review the patch yourself using our patch review checklist first.

If you can’t send a pull request for some reason, you can also use patches in Trac. When using this style, follow these guidelines.

- Submit patches in the format returned by the git diff command.

- Attach patches to a ticket in the ticket tracker, using the “attach file” button. Please don’t put the patch in the ticket description or comment unless it’s a single line patch.

- Name the patch file with a .diff extension; this will let the ticket tracker apply correct syntax highlighting, which is quite helpful.

Regardless of the way you submit your work, follow these steps.

- Make sure your code fulfills the requirements in our patch review checklist.

- Check the “Has patch” box on the ticket and make sure the “Needs documentation”, “Needs tests”, and “Patch needs improvement” boxes aren’t checked. This makes the ticket appear in the “Patches needing review” queue on the Development dashboard.

Non-trivial patches

A “non-trivial” patch is one that is more than a simple bug fix. It’s a patch that introduces Django functionality and makes some sort of design decision.

If you provide a non-trivial patch, include evidence that alternatives have been discussed on django-developers.

If you’re not sure whether your patch should be considered non-trivial, just ask.

Deprecating a feature

There are a couple reasons that code in Django might be deprecated:

- If a feature has been improved or modified in a backwards-incompatible way, the old feature or behavior will be deprecated.

- Sometimes Django will include a backport of a Python library that’s not included in a version of Python that Django currently supports. When Django no longer needs to support the older version of Python that doesn’t include the library, the library will be deprecated in Django.

As the deprecation policy describes, the first release of Django that deprecates a feature (A.B) should raise a RemovedInDjangoXXWarning (where XX is the Django version where the feature will be removed) when the deprecated feature is invoked. Assuming we have good test coverage, these warnings are converted to errors when running the test suite with warnings enabled: python -Wall runtests.py. Thus, when adding a RemovedInDjangoXXWarning you need to eliminate or silence any warnings generated when running the tests.

The first step is to remove any use of the deprecated behavior by Django itself. Next you can silence warnings in tests that actually test the deprecated behavior by using the ignore_warnings decorator, either at the test or class level:

1. In a particular test:

from django.test import ignore_warnings
from django.utils.deprecation import RemovedInDjangoXXWarning

@ignore_warnings(category=RemovedInDjangoXXWarning)
def test_foo(self):
...

2. For an entire test case:

from django.test import ignore_warnings
from django.utils.deprecation import RemovedInDjangoXXWarning

@ignore_warnings(category=RemovedInDjangoXXWarning)
class MyDeprecatedTests(unittest.TestCase):
...

Changed in Django 1.8:
Previous versions of Django had some Ignore*DeprecationWarningsMixin classes to prevent warnings from appearing. These have been replaced by the ignore_warnings decorator.

You can also add a test for the deprecation warning. You’ll have to disable the “warning as error” behavior in your test by doing:

import warnings

def test_foo_deprecation_warning(self):
with warnings.catch_warnings(record=True) as warns:
warnings.simplefilter('always')  # prevent warnings from appearing as errors
# invoke deprecated behavior

self.assertEqual(len(warns), 1)
msg = str(warns[0].message)
self.assertEqual(msg, 'Expected deprecation message')

Finally, there are a couple of updates to Django’s documentation to make:

1. If the existing feature is documented, mark it deprecated in documentation using the .. deprecated:: A.B annotation. Include a short description and a note about the upgrade path if applicable.

2. Add a description of the deprecated behavior, and the upgrade path if applicable, to the current release notes (docs/releases/A.B.txt) under the “Features deprecated in A.B” heading.

3. Add an entry in the deprecation timeline (docs/internals/deprecation.txt) under the appropriate version describing what code will be removed.

Once you have completed these steps, you are finished with the deprecation. In each feature release, all RemovedInDjangoXXWarnings matching the new version are removed.

JavaScript patches

For information on JavaScript patches, see the JavaScript patches documentation.

Patch review checklist

Use this checklist to review a pull request. If you are reviewing a pull request that is not your own and it passes all the criteria below, please set the “Triage Stage” on the corresponding Trac ticket to “Ready for checkin”. If you’ve left comments for improvement on the pull request, please tick the appropriate flags on the Trac ticket based on the results of your review: “Patch needs improvement”, “Needs documentation”, and/or “Needs tests”. As time and interest permits, core developers do final reviews of “Ready for checkin” tickets and will either commit the patch or bump it back to “Accepted” if further works need to be done. If you’re looking to become a core developer, doing thorough reviews of patches is a great way to earn trust.

Looking for a patch to review? Check out the “Patches needing review” section of the Django Development Dashboard. Looking to get your patch reviewed? Ensure the Trac flags on the ticket are set so that the ticket appears in that queue.

Documentation

- Does the documentation build without any errors (make html, or make.bat html on Windows, from the docs directory)?

- Does the documentation follow the writing style guidelines in Writing documentation?

- Are there any spelling errors?

Bugs

- Is there a proper regression test (the test should fail before the fix is applied)?

New Features

- Are there tests to “exercise” all of the new code?

- Is there a release note in docs/releases/A.B.txt?

- Is there documentation for the feature and is it annotated appropriately with .. versionadded:: A.B or .. versionchanged:: A.B?

Deprecating a feature

See the Deprecating a feature guide.

All code changes

- Does the coding style conform to our guidelines? Are there any flake8 errors?

- If the change is backwards incompatible in any way, is there a note in the release notes (docs/releases/A.B.txt)?

- Is Django’s test suite passing? Ask in #django-dev for a core dev to build the pull request against our continuous integration server.

All tickets

- Is the pull request a single squashed commit with a message that follows our commit message format?

- Are you the patch author and a new contributor? Please add yourself to the AUTHORS file and submit a Contributor License Agreement.

Working with Git and GitHub

This section explains how the community can contribute code to Django via pull requests. If you’re interested in how core developers handle them, see Committing code.

Below, we are going to show how to create a GitHub pull request containing the changes for Trac ticket #xxxxx. By creating a fully-ready pull request you will make the reviewer’s job easier, meaning that your work is more likely to be merged into Django.

You could also upload a traditional patch to Trac, but it’s less practical for reviews.

Installing Git

Django uses Git for its source control. You can download Git, but it’s often easier to install with your operating system’s package manager.

Django’s Git repository is hosted on GitHub, and it is recommended that you also work using GitHub.

After installing Git the first thing you should do is setup your name and email:

$ git config --global user.name "Your Real Name"
$ git config --global user.email "you@email.com"

Note that user.name should be your real name, not your GitHub nick. GitHub should know the email you use in the user.email field, as this will be used to associate your commits with your GitHub account.

Setting up local repository

When you have created your GitHub account, with the nick “GitHub_nick”, and forked Django’s repository, create a local copy of your fork:

git clone git@github.com:GitHub_nick/django.git

This will create a new directory “django”, containing a clone of your GitHub repository. The rest of the git commands on this page need to be run within the cloned directory so switch to it now:

cd django

Your GitHub repository will be called “origin” in Git.

You should also setup django/django as an “upstream” remote (that is, tell git that the reference Django repository was the source of your fork of it):

git remote add upstream git@github.com:django/django.git
git fetch upstream

You can add other remotes similarly, for example:

git remote add akaariai git@github.com:akaariai/django.git

Working on a ticket

When working on a ticket create a new branch for the work, and base that work on upstream/master:

git checkout -b ticket_xxxxx upstream/master

The -b flag creates a new branch for you locally. Don’t hesitate to create new branches even for the smallest things - that’s what they are there for.

If instead you were working for a fix on the 1.4 branch, you would do:

git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x

Assume the work is carried on ticket_xxxxx branch. Make some changes and commit them:

git commit

When writing the commit message, follow the commit message guidelines to ease the work of the committer. If you’re uncomfortable with English, try at least to describe precisely what the commit does.

If you need to do additional work on your branch, commit as often as necessary:

git commit -m 'Added two more tests for edge cases'

Publishing work

You can publish your work on GitHub just by doing:

git push origin ticket_xxxxx

When you go to your GitHub page you will notice a new branch has been created.

If you are working on a Trac ticket, you should mention in the ticket that your work is available from branch ticket_xxxxx of your GitHub repo. Include a link to your branch.

Note that the above branch is called a “topic branch” in Git parlance. You are free to rewrite the history of this branch, by using git rebase for example. Other people shouldn’t base their work on such a branch, because their clone would become corrupt when you edit commits.

There are also “public branches”. These are branches other people are supposed to fork, so the history of these branches should never change. Good examples of public branches are the master and stable/A.B.x branches in the django/django repository.

When you think your work is ready to be pulled into Django, you should create a pull request at GitHub. A good pull request means:

- commits with one logical change in each, following the coding style,

- well-formed messages for each commit: a summary line and then paragraphs wrapped at 72 characters thereafter – see the committing guidelines for more details,

- documentation and tests, if needed – actually tests are always needed, except for documentation changes.

The test suite must pass and the documentation must build without warnings.

Once you have created your pull request, you should add a comment in the related Trac ticket explaining what you’ve done. In particular you should note the environment in which you ran the tests, for instance: “all tests pass under SQLite and MySQL”.

Pull requests at GitHub have only two states: open and closed. The committer who will deal with your pull request has only two options: merge it or close it. For this reason, it isn’t useful to make a pull request until the code is ready for merging – or sufficiently close that a committer will finish it himself.

Rebasing branches

In the example above you created two commits, the “Fixed ticket_xxxxx” commit and “Added two more tests” commit.

We do not want to have the entire history of your working process in your repository. Your commit “Added two more tests” would be unhelpful noise. Instead, we would rather only have one commit containing all your work.

To rework the history of your branch you can squash the commits into one by using interactive rebase:

git rebase -i HEAD~2

The HEAD~2 above is shorthand for two latest commits. The above command will open an editor showing the two commits, prefixed with the word “pick”.

Change “pick” on the second line to “squash” instead. This will keep the first commit, and squash the second commit into the first one. Save and quit the editor. A second editor window should open, so you can reword the commit message for the commit now that it includes both your steps.

You can also use the “edit” option in rebase. This way you can change a single commit, for example to fix a typo in a docstring:

git rebase -i HEAD~3
# Choose edit, pick, pick for the commits
# Now you are able to rework the commit (use git add normally to add changes)
# When finished, commit work with "--amend" and continue
git commit --amend
# reword the commit message if needed
git rebase --continue
# The second and third commits should be applied.

If your topic branch is already published at GitHub, for example if you’re making minor changes to take into account a review, you will need to force- push the changes:

git push -f origin ticket_xxxxx

Note that this will rewrite history of ticket_xxxxx - if you check the commit hashes before and after the operation at GitHub you will notice that the commit hashes do not match any more. This is acceptable, as the branch is merely a topic branch, and nobody should be basing their work on it.

After upstream has changed

When upstream (django/django) has changed, you should rebase your work. To do this, use:

git fetch upstream
git rebase

The work is automatically rebased using the branch you forked on, in the example case using upstream/master.

The rebase command removes all your local commits temporarily, applies the upstream commits, and then applies your local commits again on the work.

If there are merge conflicts you will need to resolve them and then use git rebase --continue. At any point you can use git rebase --abort to return to the original state.

Note that you want to rebase on upstream, not merge the upstream.

The reason for this is that by rebasing, your commits will always be on top of the upstream’s work, not mixed in with the changes in the upstream. This way your branch will contain only commits related to its topic, which makes squashing easier.

After review

It is unusual to get any non-trivial amount of code into core without changes requested by reviewers. In this case, it is often a good idea to add the changes as one incremental commit to your work. This allows the reviewer to easily check what changes you have done.

In this case, do the changes required by the reviewer. Commit as often as necessary. Before publishing the changes, rebase your work. If you added two commits, you would run:

git rebase -i HEAD~2

Squash the second commit into the first. Write a commit message along the lines of:

Made changes asked in review by <reviewer>

- Fixed whitespace errors in foobar
- Reworded the docstring of bar()

Finally push your work back to your GitHub repository. Since you didn’t touch the public commits during the rebase, you should not need to force-push:

git push origin ticket_xxxxx

Your pull request should now contain the new commit too.

Note that the committer is likely to squash the review commit into the previous commit when committing the code.

Working on a patch

One of the ways that developers can contribute to Django is by reviewing patches. Those patches will typically exist as pull requests on GitHub and can be easily integrated into your local repository:

git checkout -b pull_xxxxx upstream/master
curl https://github.com/django/django/pull/xxxxx.patch | git am

This will create a new branch and then apply the changes from the pull request to it. At this point you can run the tests or do anything else you need to do to investigate the quality of the patch.

For more detail on working with pull requests see the guidelines for committers.

Summary

- Work on GitHub if you can.

- Announce your work on the Trac ticket by linking to your GitHub branch.

- When you have something ready, make a pull request.

- Make your pull requests as good as you can.

- When doing fixes to your work, use git rebase -i to squash the commits.

- When upstream has changed, do git fetch upstream; git rebase.

JavaScript

While most of Django core is Python, the admin and gis contrib apps contain JavaScript code.

Please follow these coding standards when writing JavaScript code for inclusion in Django.

Code style

- Please conform to the indentation style dictated in the .editorconfig file. We recommend using a text editor with EditorConfig support to avoid indentation and whitespace issues. Most of the JavaScript files use 4 spaces for indentation, but there are some exceptions.

- When naming variables, use camelCase instead of underscore_case. Different JavaScript files sometimes use a different code style. Please try to conform to the code style of each file.

- Use the JSHint code linter to check your code for bugs and style errors. JSHint will be run when you run the JavaScript tests. We also recommended installing a JSHint plugin in your text editor.

JavaScript patches

Django’s admin system leverages the jQuery framework to increase the capabilities of the admin interface. In conjunction, there is an emphasis on admin JavaScript performance and minimizing overall admin media file size. Serving compressed or “minified” versions of JavaScript files is considered best practice in this regard.

To that end, patches for JavaScript files should include both the original code for future development (e.g. foo.js), and a compressed version for production use (e.g. foo.min.js). Any links to the file in the codebase should point to the compressed version.

Compressing JavaScript

To simplify the process of providing optimized JavaScript code, Django includes a handy Python script which should be used to create a “minified” version. To run it:

$ pip install closure
$ python django/contrib/admin/bin/compress.py

Behind the scenes, compress.py is a front-end for Google’s Closure Compiler which is written in Java. The Closure Compiler library is not bundled with Django, but you can install it using pip as done above. The Closure Compiler library requires Java 7 or higher.

Please don’t forget to run compress.py and include the diff of the minified scripts when submitting patches for Django’s JavaScript.

JavaScript tests

Django’s JavaScript tests can be run in a browser or from the command line. The tests are located in a top level js_tests directory.

Writing tests

Django’s JavaScript tests use QUnit. Here is an example test module:

module('magicTricks', {
beforeEach: function() {
var $ = django.jQuery;
$('#qunit-fixture').append('<button class="button"></button>');
}
});

test('removeOnClick removes button on click', function(assert) {
var $ = django.jQuery;
removeOnClick('.button');
assert.equal($('.button').length === 1);
$('.button').click();
assert.equal($('.button').length === 0);
});

test('copyOnClick adds button on click', function(assert) {
var $ = django.jQuery;
copyOnClick('.button');
assert.equal($('.button').length === 1);
$('.button').click();
assert.equal($('.button').length === 2);
});

Please consult the QUnit documentation for information on the types of assertions supported by QUnit.

Running tests

The JavaScript tests may be run from a web browser or from the command line.

Testing from a web browser

To run the tests from a web browser, open up js_tests/tests.html in your browser.

To measure code coverage when running the tests, you need to view that file over HTTP. To view code coverage:

- Execute python -m http.server (or python -m SimpleHTTPServer on Python 2) from the root directory (not from inside js_tests).

- Open http://localhost:8000/js_tests/tests.html in your web browser.

Testing from the command line

To run the tests from the command line, you need to have Node.js installed.

After installing Node.js, install the JavaScript test dependencies by running the following from the root of your Django checkout:

$ npm install

Then run the tests with:

$ npm test

Writing documentation

We place a high importance on consistency and readability of documentation. After all, Django was created in a journalism environment! So we treat our documentation like we treat our code: we aim to improve it as often as possible.

Documentation changes generally come in two forms:

- General improvements: typo corrections, error fixes and better explanations through clearer writing and more examples.

- New features: documentation of features that have been added to the framework since the last release.

This section explains how writers can craft their documentation changes in the most useful and least error-prone ways.

Getting the raw documentation

Though Django’s documentation is intended to be read as HTML at https://docs.djangoproject.com/, we edit it as a collection of text files for maximum flexibility. These files live in the top-level docs/ directory of a Django release.

If you’d like to start contributing to our docs, get the development version of Django from the source code repository (see Installing the development version). The development version has the latest-and-greatest documentation, just as it has latest-and-greatest code. We also backport documentation fixes and improvements, at the discretion of the committer, to the last release branch. That’s because it’s highly advantageous to have the docs for the last release be up-to-date and correct (see Differences between versions).

Getting started with Sphinx

Django’s documentation uses the Sphinx documentation system, which in turn is based on docutils. The basic idea is that lightly-formatted plain-text documentation is transformed into HTML, PDF, and any other output format.

To actually build the documentation locally, you’ll currently need to install Sphinx – pip install Sphinx should do the trick.

Then, building the HTML is easy; just make html (or make.bat html on Windows) from the docs directory.

To get started contributing, you’ll want to read the reStructuredText Primer. After that, you’ll want to read about the Sphinx-specific markup that’s used to manage metadata, indexing, and cross-references.

How the documentation is organized

The documentation is organized into several categories:

- Tutorials take the reader by the hand through a series of steps to create something.

The important thing in a tutorial is to help the reader achieve something useful, preferably as early as possible, in order to give them confidence.

Explain the nature of the problem we’re solving, so that the reader understands what we’re trying to achieve. Don’t feel that you need to begin with explanations of how things work - what matters is what the reader does, not what you explain. It can be helpful to refer back to what you’ve done and explain afterwards.

- Topic guides aim to explain a concept or subject at a fairly high level.

Link to reference material rather than repeat it. Use examples and don’t be reluctant to explain things that seem very basic to you - it might be the explanation someone else needs.

Providing background context helps a newcomer connect the topic to things that they already know.

- Reference guides contain technical reference for APIs. They describe the functioning of Django’s internal machinery and instruct in its use.

Keep reference material tightly focused on the subject. Assume that the reader already understands the basic concepts involved but needs to know or be reminded of how Django does it.

Reference guides aren’t the place for general explanation. If you find yourself explaining basic concepts, you may want to move that material to a topic guide.

- How-to guides are recipes that take the reader through steps in key subjects.

What matters most in a how-to guide is what a user wants to achieve. A how-to should always be result-oriented rather than focused on internal details of how Django implements whatever is being discussed.

These guides are more advanced than tutorials and assume some knowledge about how Django works. Assume that the reader has followed the tutorials and don’t hesitate to refer the reader back to the appropriate tutorial rather than repeat the same material.

Writing style

When using pronouns in reference to a hypothetical person, such as “a user with a session cookie”, gender neutral pronouns (they/their/them) should be used. Instead of:

- he or she... use they.

- him or her... use them.

- his or her... use their.

- his or hers... use theirs.

- himself or herself... use themselves.

Commonly used terms

Here are some style guidelines on commonly used terms throughout the documentation:

- Django – when referring to the framework, capitalize Django. It is lowercase only in Python code and in the djangoproject.com logo.

- email – no hyphen.

- MySQL, PostgreSQL, SQLite

- SQL – when referring to SQL, the expected pronunciation should be “Ess Queue Ell” and not “sequel”. Thus in a phrase like “Returns an SQL expression”, “SQL” should be preceded by “an” and not “a”.

- Python – when referring to the language, capitalize Python.

- realize, customize, initialize, etc. – use the American “ize” suffix, not “ise.”

- subclass – it’s a single word without a hyphen, both as a verb (“subclass that model”) and as a noun (“create a subclass”).

- Web, World Wide Web, the Web – note Web is always capitalized when referring to the World Wide Web.

- website – use one word, without capitalization.

Django-specific terminology

- model – it’s not capitalized.

- template – it’s not capitalized.

- URLconf – use three capitalized letters, with no space before “conf.”

- view – it’s not capitalized.

Guidelines for reStructuredText files

These guidelines regulate the format of our reST (reStructuredText) documentation:

- In section titles, capitalize only initial words and proper nouns.

- Wrap the documentation at 80 characters wide, unless a code example is significantly less readable when split over two lines, or for another good reason.

- The main thing to keep in mind as you write and edit docs is that the more semantic markup you can add the better. So:

Add ``django.contrib.auth`` to your ``INSTALLED_APPS``...

Isn’t nearly as helpful as:

Add :mod:`django.contrib.auth` to your :setting:`INSTALLED_APPS`...

This is because Sphinx will generate proper links for the latter, which greatly helps readers. There’s basically no limit to the amount of useful markup you can add.

- Use intersphinx to reference Python’s and Sphinx’ documentation.

- Use these heading styles:

===
One
===

Two
===

Three
-----

Four
~~~~

Five
^^^^

Django-specific markup

Besides the Sphinx built-in markup, Django’s docs defines some extra description units:

- Settings:

.. setting:: INSTALLED_APPS

To link to a setting, use :setting:`INSTALLED_APPS`.

- Template tags:

.. templatetag:: regroup

To link, use :ttag:`regroup`.

- Template filters:

.. templatefilter:: linebreaksbr

To link, use :tfilter:`linebreaksbr`.

- Field lookups (i.e. Foo.objects.filter(bar__exact=whatever)):

.. fieldlookup:: exact

To link, use :lookup:`exact`.

- django-admin commands:

.. django-admin:: migrate

To link, use :djadmin:`migrate`.

- django-admin command-line options:

.. django-admin-option:: --traceback

To link, use :option:`command_name --traceback` (or omit command_name for the options shared by all commands like --verbosity).

- Links to Trac tickets (typically reserved for patch release notes):

:ticket:`12345`

Documenting new features

Our policy for new features is:

All documentation of new features should be written in a way that clearly designates the features are only available in the Django development version. Assume documentation readers are using the latest release, not the development version.

Our preferred way for marking new features is by prefacing the features’ documentation with: “.. versionadded:: X.Y”, followed by a mandatory blank line and an optional description (indented).

General improvements, or other changes to the APIs that should be emphasized should use the “.. versionchanged:: X.Y” directive (with the same format as the versionadded mentioned above.

These versionadded and versionchanged blocks should be “self-contained.” In other words, since we only keep these annotations around for two releases, it’s nice to be able to remove the annotation and its contents without having to reflow, reindent, or edit the surrounding text. For example, instead of putting the entire description of a new or changed feature in a block, do something like this:

.. class:: Author(first_name, last_name, middle_name=None)

A person who writes books.

``first_name`` is ...

...

``middle_name`` is ...

.. versionchanged:: A.B

The ``middle_name`` argument was added.

Put the changed annotation notes at the bottom of a section, not the top.

Also, avoid referring to a specific version of Django outside a versionadded or versionchanged block. Even inside a block, it’s often redundant to do so as these annotations render as “New in Django A.B:” and “Changed in Django A.B”, respectively.

If a function, attribute, etc. is added, it’s also okay to use a versionadded annotation like this:

.. attribute:: Author.middle_name

.. versionadded:: A.B

An author's middle name.

We can simply remove the .. versionadded:: A.B annotation without any indentation changes when the time comes.

Minimizing images

Optimize image compression where possible. For PNG files, use OptiPNG and AdvanceCOMP’s advpng:

$ cd docs/
$ optipng -o7 -zm1-9 -i0 -strip all `find . -type f -not -path "./_build/*" -name "*.png"`
$ advpng -z4 `find . -type f -not -path "./_build/*" -name "*.png"`

This is based on OptiPNG version 0.7.5. Older versions may complain about the --strip all option being lossy.

An example

For a quick example of how it all fits together, consider this hypothetical example:

- First, the ref/settings.txt document could have an overall layout like this:

========
Settings
========

...

.. _available-settings:

Available settings
==================

...

.. _deprecated-settings:

Deprecated settings
===================

...

- Next, the topics/settings.txt document could contain something like this:

You can access a :ref:`listing of all available settings
<available-settings>`. For a list of deprecated settings see
:ref:`deprecated-settings`.

You can find both in the :doc:`settings reference document
</ref/settings>`.

We use the Sphinx doc cross reference element when we want to link to another document as a whole and the ref element when we want to link to an arbitrary location in a document.

- Next, notice how the settings are annotated:

.. setting:: ADMINS

ADMINS
======

Default: ``[]`` (Empty list)

A list of all the people who get code error notifications. When
``DEBUG=False`` and a view raises an exception, Django will email these people
with the full exception information. Each member of the list should be a tuple
of (Full name, email address). Example::

[('John', 'john@example.com'), ('Mary', 'mary@example.com')]

Note that Django will email *all* of these people whenever an error happens.
See :doc:`/howto/error-reporting` for more information.

This marks up the following header as the “canonical” target for the setting ADMINS. This means any time I talk about ADMINS, I can reference it using :setting:`ADMINS`.

That’s basically how everything fits together.

Improving the documentation

A few small improvements can be made to make the documentation read and look better:

- Most of the various index.txt documents have very short or even non-existent intro text. Each of those documents needs a good short intro the content below that point.

- The glossary is very perfunctory. It needs to be filled out.

- Add more metadata targets. Lots of places look like:

``File.close()``
~~~~~~~~~~~~~~~~

... these should be:

.. method:: File.close()

That is, use metadata instead of titles.

- Whenever possible, use links. So, use :setting:`ADMINS` instead of ``ADMINS``.

- Use directives where appropriate. Some directives (e.g. .. setting::) are prefix-style directives; they go before the unit they’re describing. These are known as “crossref” directives. Others (e.g. .. class::) generate their own markup; these should go inside the section they’re describing. These are called “description units”.

You can tell which are which by looking at in _ext/djangodocs.py; it registers roles as one of the other.

- Add .. code-block:: <lang> to literal blocks so that they get highlighted.

- When referring to classes/functions/modules, etc., you’ll want to use the fully-qualified name of the target (:class:`django.contrib.contenttypes.models.ContentType`).

Since this doesn’t look all that awesome in the output – it shows the entire path to the object – you can prefix the target with a ~ (that’s a tilde) to get just the “last bit” of that path. So :class:`~django.contrib.contenttypes.models.ContentType` will just display a link with the title “ContentType”.

Spelling check

Before you commit your docs, it’s a good idea to run the spelling checker. You’ll need to install a couple packages first:

- pyenchant (which requires enchant)

- sphinxcontrib-spelling

Then from the docs directory, run make spelling. Wrong words (if any) along with the file and line number where they occur will be saved to _build/spelling/output.txt.

If you encounter false-positives (error output that actually is correct), do one of the following:

- Surround inline code or brand/technology names with grave accents (`).

- Find synonyms that the spell checker recognizes.

- If, and only if, you are sure the word you are using is correct - add it to docs/spelling_wordlist (please keep the list in alphabetical order).

Translating documentation

See Localizing the Django documentation if you’d like to help translate the documentation into another language.

django-admin man page

Sphinx can generate a manual page for the django-admin command. This is configured in docs/conf.py. Unlike other documentation output, this man page should be included in the Django repository and the releases as docs/man/django-admin.1. There isn’t a need to update this file when updating the documentation, as it’s updated once as part of the release process.

To generate an updated version of the man page, run make man in the docs directory. The new man page will be written in docs/_build/man/django-admin.1.

Localizing Django

Various parts of Django, such as the admin site and validation error messages, are internationalized. This means they display differently depending on each user’s language or country. For this, Django uses the same internationalization and localization infrastructure available to Django applications, described in the i18n documentation.

Translations

Translations are contributed by Django users worldwide. The translation work is coordinated at Transifex.

If you find an incorrect translation or want to discuss specific translations, go to the Django project page. If you would like to help out with translating or add a language that isn’t yet translated, here’s what to do:

- Join the Django i18n mailing list and introduce yourself.

- Make sure you read the notes about Specialties of Django translation.

- Sign up at Transifex and visit the Django project page.

- On the Django project page, choose the language you want to work on, or – in case the language doesn’t exist yet – request a new language team by clicking on the “Request language” link and selecting the appropriate language.

- Then, click the “Join this Team” button to become a member of this team. Every team has at least one coordinator who is responsible to review your membership request. You can of course also contact the team coordinator to clarify procedural problems and handle the actual translation process.

- Once you are a member of a team choose the translation resource you want to update on the team page. For example the “core” resource refers to the translation catalog that contains all non-contrib translations. Each of the contrib apps also have a resource (prefixed with “contrib”).

Note

For more information about how to use Transifex, read the Transifex User Guide.

Translations from Transifex are only integrated into the Django repository at the time of a new feature release. We try to update them a second time during one of the following patch releases, but that depends on the translation manager’s availability. So don’t miss the string freeze period (between the release candidate and the feature release) to take the opportunity to complete and fix the translations for your language!

Formats

You can also review conf/locale/<locale>/formats.py. This file describes the date, time and numbers formatting particularities of your locale. See Format localization for details.

The format files aren’t managed by the use of Transifex. To change them, you must create a patch against the Django source tree, as for any code change:

- Create a diff against the current Git master branch.

- Open a ticket in Django’s ticket system, set its Component field to Translations, and attach the patch to it.

Documentation

There is also an opportunity to translate the documentation, though this is a huge undertaking to complete entirely (you have been warned!). We use the same Transifex tool. The translations will appear at https://docs.djangoproject.com/<language_code>/ when at least the docs/intro/* files are fully translated in your language.

Committing code

This section is addressed to the Committers and to anyone interested in knowing how code gets committed into Django core. If you’re a community member who wants to contribute code to Django, have a look at Working with Git and GitHub instead.

Handling pull requests

Since Django is now hosted at GitHub, most patches are provided in the form of pull requests.

When committing a pull request, make sure each individual commit matches the commit guidelines described below. Contributors are expected to provide the best pull requests possible. In practice however, committers - who will likely be more familiar with the commit guidelines - may decide to bring a commit up to standard themselves.

Note

Before merging, but after reviewing, have Jenkins test the pull request by commenting “buildbot, test this please” on the PR. See our Jenkins wiki page for more details.

An easy way to checkout a pull request locally is to add an alias to your ~/.gitconfig (upstream is assumed to be django/django):

[alias]
pr = !sh -c \"git fetch upstream pull/${1}/head:pr/${1} && git checkout pr/${1}\"

Now you can simply run git pr #### to checkout the corresponding pull request.

At this point, you can work on the code. Use git rebase -i and git commit --amend to make sure the commits have the expected level of quality. Once you’re ready:

$ # Pull in the latest changes from master.
$ git checkout master
$ git pull upstream master
$ # Rebase the pull request on master.
$ git checkout pr/####
$ git rebase master
$ git checkout master
$ # Merge the work as "fast-forward" to master to avoid a merge commit.
$ # (in practice, you can omit "--ff-only" since you just rebased)
$ git merge --ff-only pr/XXXX
$ # If you're not sure if you did things correctly, check that only the
$ # changes you expect will be pushed to upstream.
$ git push --dry-run upstream master
$ # Push!
$ git push upstream master
$ # Delete the pull request branch.
$ git branch -d pr/xxxx

For changes on your own branches, force push to your fork after rebasing on master but before merging and pushing to upstream. This allows the commit hashes on master and your branch to match which automatically closes the pull request. Since you can’t push to other contributors’ branches, comment on the pull request “Merged in XXXXXXX” (replacing with the commit hash) after you merge it. Trac checks for this message format to indicate on the ticket page whether or not a pull request is merged.

Avoid using GitHub’s “Merge pull request” button on the website as it creates an ugly “merge commit” and makes navigating history more difficult.

When rewriting the commit history of a pull request, the goal is to make Django’s commit history as usable as possible:

- If a patch contains back-and-forth commits, then rewrite those into one. For example, if a commit adds some code and a second commit fixes stylistic issues introduced in the first commit, those commits should be squashed before merging.

- Separate changes to different commits by logical grouping: if you do a stylistic cleanup at the same time as you do other changes to a file, separating the changes into two different commits will make reviewing history easier.

- Beware of merges of upstream branches in the pull requests.

- Tests should pass and docs should build after each commit. Neither the tests nor the docs should emit warnings.

- Trivial and small patches usually are best done in one commit. Medium to large work may be split into multiple commits if it makes sense.

Practicality beats purity, so it is up to each committer to decide how much history mangling to do for a pull request. The main points are engaging the community, getting work done, and having a usable commit history.

Committing guidelines

In addition, please follow the following guidelines when committing code to Django’s Git repository:

- Never change the published history of django/django branches! Never force- push your changes to django/django. If you absolutely must (for security reasons for example) first discuss the situation with the core team.

- For any medium-to-big changes, where “medium-to-big” is according to your judgment, please bring things up on the django-developers mailing list before making the change.

If you bring something up on django-developers and nobody responds, please don’t take that to mean your idea is great and should be implemented immediately because nobody contested it. Django’s core developers don’t have a lot of time to read mailing-list discussions immediately, so you may have to wait a couple of days before getting a response.

- Write detailed commit messages in the past tense, not present tense.

- Good: “Fixed Unicode bug in RSS API.”

- Bad: “Fixes Unicode bug in RSS API.”

- Bad: “Fixing Unicode bug in RSS API.”

The commit message should be in lines of 72 chars maximum. There should be a subject line, separated by a blank line and then paragraphs of 72 char lines. The limits are soft. For the subject line, shorter is better. In the body of the commit message more detail is better than less:

Fixed #18307 -- Added git workflow guidelines

Refactored the Django's documentation to remove mentions of SVN
specific tasks. Added guidelines of how to use Git, GitHub, and
how to use pull request together with Trac instead.

If the patch wasn’t a pull request, you should credit the contributors in the commit message: “Thanks A for report, B for the patch and C for the review.”

- For commits to a branch, prefix the commit message with the branch name. For example: “[1.4.x] Fixed #xxxxx – Added support for mind reading.”

- Limit commits to the most granular change that makes sense. This means, use frequent small commits rather than infrequent large commits. For example, if implementing feature X requires a small change to library Y, first commit the change to library Y, then commit feature X in a separate commit. This goes a long way in helping all Django core developers follow your changes.

- Separate bug fixes from feature changes. Bugfixes may need to be backported to the stable branch, according to the backwards-compatibility policy.

- If your commit closes a ticket in the Django ticket tracker, begin your commit message with the text “Fixed #xxxxx”, where “xxxxx” is the number of the ticket your commit fixes. Example: “Fixed #123 – Added whizbang feature.”. We’ve rigged Trac so that any commit message in that format will automatically close the referenced ticket and post a comment to it with the full commit message.

If your commit closes a ticket and is in a branch, use the branch name first, then the “Fixed #xxxxx.” For example: “[1.4.x] Fixed #123 – Added whizbang feature.”

For the curious, we’re using a Trac plugin for this.

Note

Note that the Trac integration doesn’t know anything about pull requests. So if you try to close a pull request with the phrase “closes #400” in your commit message, GitHub will close the pull request, but the Trac plugin will also close the same numbered ticket in Trac.

- If your commit references a ticket in the Django ticket tracker but does not close the ticket, include the phrase “Refs #xxxxx”, where “xxxxx” is the number of the ticket your commit references. This will automatically post a comment to the appropriate ticket.

- Write commit messages for backports using this pattern:

[<Django version>] Fixed <ticket> -- <description>

Backport of <revision> from <branch>.

For example:

[1.3.x] Fixed #17028 -- Changed diveintopython.org -> diveintopython.net.

Backport of 80c0cbf1c97047daed2c5b41b296bbc56fe1d7e3 from master.

There’s a script on the wiki to automate this.

Reverting commits

Nobody’s perfect; mistakes will be committed.

But try very hard to ensure that mistakes don’t happen. Just because we have a reversion policy doesn’t relax your responsibility to aim for the highest quality possible. Really: double-check your work, or have it checked by another committer, before you commit it in the first place!

When a mistaken commit is discovered, please follow these guidelines:

- If possible, have the original author revert their own commit.

- Don’t revert another author’s changes without permission from the original author.

- Use git revert – this will make a reverse commit, but the original commit will still be part of the commit history.

- If the original author can’t be reached (within a reasonable amount of time – a day or so) and the problem is severe – crashing bug, major test failures, etc. – then ask for objections on the django-developers mailing list then revert if there are none.

- If the problem is small (a feature commit after feature freeze, say), wait it out.

- If there’s a disagreement between the committer and the reverter-to-be then try to work it out on the django-developers mailing list. If an agreement can’t be reached then it should be put to a vote.

- If the commit introduced a confirmed, disclosed security vulnerability then the commit may be reverted immediately without permission from anyone.

- The release branch maintainer may back out commits to the release branch without permission if the commit breaks the release branch.

- If you mistakenly push a topic branch to django/django, just delete it. For instance, if you did: git push upstream feature_antigravity, just do a reverse push: git push upstream :feature_antigravity.

Mailing lists

Important

Please report security issues only to security@djangoproject.com. This is a private list only open to long-time, highly trusted Django developers, and its archives are not public. For further details, please see our security policies.

Django has several official mailing lists on Google Groups that are open to anyone.

django-users

This is the right place if you are looking to ask any question regarding the installation, usage, or debugging of Django.

Note

If it’s the first time you send an email to this list, your email must be accepted first so don’t worry if your message does not appear instantly.

- django-users mailing archive

- django-users subscription email address

- django-users posting email

django-core-mentorship

The Django Core Mentorship list is intended to provide a welcoming introductory environment for community members interested in contributing to the Django Project.

- django-core-mentorship mailing archive

- django-core-mentorship subscription email address

- django-core-mentorship posting email

django-developers

The discussion about the development of Django itself takes place here.

Note

Please make use of django-users mailing list if you want to ask for tech support, doing so in this list is inappropriate.

- django-developers mailing archive

- django-developers subscription email address

- django-developers posting email

django-i18n

This is the place to discuss the internationalization and localization of Django’s components.

- django-i18n mailing archive

- django-i18n subscription email address

- django-i18n posting email

django-announce

A (very) low-traffic list for announcing new releases of Django and important bugfixes.

- django-announce mailing archive

- django-announce subscription email address

- django-announce posting email

django-updates

All the ticket updates are mailed automatically to this list, which is tracked by developers and interested community members.

- django-updates mailing archive

- django-updates subscription email address

- django-updates posting email

Organization of the Django Project

Principles

The Django Project is managed by a team of volunteers pursuing three goals:

- Driving the development of the Django Web Framework,

- Fostering the ecosystem of Django-related software,

- Leading the Django community in accordance with the values described in the Django Code of Conduct.

The Django Project isn’t a legal entity. The Django Software Foundation, a non-profit organization, handles financial and legal matters related to the Django Project. Other than that, the Django Software Foundation lets the Django Project manage the development of the Django framework, its ecosystem and its community.

The Django core team makes the decisions, nominates its new members, and elects its technical board. While it holds decision power in theory, it aims at using it as rarely as possible in practice. Rough consensus should be the norm and formal voting an exception.

Core team

Role

The core team is the group of trusted volunteers who manage the Django Project. They assume many roles required to achieve the project’s goals, especially those that require a high level of trust. They make the decisions that shape the future of the project.

Core team members are expected to act as role models for the community and custodians of the project, on behalf of the community and all those who rely on Django.

They will intervene, where necessary, in online discussions or at official Django events on the rare occasions that a situation arises that requires intervention.

They have authority over the Django Project infrastructure, including the Django Project website itself, the Django GitHub organization and repositories, the Trac bug tracker, the mailing lists, IRC channels, etc.

Prerogatives

Core team members may participate in formal votes, typically to nominate new team members and to elect the technical board.

Some contributions don’t require commit access. Depending on the reasons why a contributor joins the team, they may or may not have commit permissions to the Django code repository.

However, should the need arise, any team member may ask for commit access by writing to the core team’s mailing list. Access will be granted unless the person withdraws their request or the technical board vetoes the proposal.

Core team members who have commit access are referred to as “committers” or “core developers”.

Other permissions, such as access to the servers, are granted to those who need them through the same process.

Membership

The core team finds its origins with the four people who created Django. It has grown to a few dozen people by co-opting volunteers who demonstrate:

- a good grasp of the philosophy of the Django Project

- a solid track record of being constructive and helpful

- significant contributions to the project’s goals, in any form

- willingness to dedicate some time to improving Django

As the project matures, contributions go way beyond code. Here’s an incomplete list of areas where contributions may be considered for joining the core team, in no particular order:

- Working on community management and outreach

- Providing support on the mailing-lists and on IRC

- Triaging tickets

- Writing patches (code, docs, or tests)

- Reviewing patches (code, docs, or tests)

- Participating in design decisions

- Providing expertise in a particular domain (security, i18n, etc.)

- Managing the continuous integration infrastructure

- Managing the servers (website, tracker, documentation, etc.)

- Maintaining related projects (djangoproject.com site, ex-contrib apps, etc.)

- Creating visual designs

Very few areas are reserved to core team members:

- Reviewing security reports

- Merging patches (code, docs, or tests)

- Packaging releases

Core team membership acknowledges sustained and valuable efforts that align well with the philosophy and the goals of the Django Project.

It is granted by a four fifths majority of votes cast in a core team vote and no veto by the technical board.

Core team members are always looking for promising contributors, teaching them how the project is managed, and submitting their names to the core team’s vote when they’re ready. If you would like to join the core team, you can contact a core team member privately or ask for guidance on the Django Core Mentorship mailing-list.

There’s no time limit on core team membership. However, in order to provide the general public with a reasonable idea of how many people maintain Django, core team members who have stopped contributing are encouraged to declare themselves as “past team members”. Those who haven’t made any non-trivial contribution in two years may be asked to move themselves to this category, and moved there if they don’t respond. Past team members lose their privileges such as voting rights and commit access.

Technical board

Role

The technical board is a group of experienced and active committers who steer technical choices. Their main concern is to maintain the quality and stability of the Django Web Framework.

Prerogatives

The technical board holds two prerogatives:

- Making major technical decisions when no consensus is found otherwise. This happens on the django-developers mailing-list.

- Veto a grant of commit access or remove commit access. This happens on the django-core mailing-list.

In both cases, the technical board is a last resort. In these matters, it fulfills a similar function to the former Benevolent Dictators For Life.

When the board wants to exercise one of these prerogatives, it must hold a private, simple majority vote on the resolution. The quorum is the full committee — each member must cast a vote or abstain explicitly. Then the board communicates the result, and if possible the reasons, on the appropriate mailing-list. There’s no appeal for such decisions.

In addition, at its discretion, the technical board may act in an advisory capacity on non-technical decisions.

Membership

The technical board is an elected group of five committers. They’re expected to be experienced but there’s no formal seniority requirement. Its current composition is published here.

A new board is elected after each feature release of Django. The election process is managed by a returns officer nominated by the outgoing technical board. The election process works as follows:

1. Candidates advertise their application for the technical board to the team.

They must be committers already. There’s no term limit for technical board members.

2. Each team member can vote for zero to five people among the candidates. Candidates are ranked by the total number of votes they received.

In case of a tie, the person who joined the core team earlier wins.

Both the application and the voting period last between one and two weeks, at the outgoing board’s discretion.

Changing the organization

Changes to this document require a four fifths majority of votes cast in a core team vote and no veto by the technical board.

Django team

The original team

Django originally started at World Online, the Web department of the Lawrence Journal-World of Lawrence, Kansas, USA.

Adrian Holovaty

Adrian is a Web developer with a background in journalism. He’s known in journalism circles as one of the pioneers of “journalism via computer programming”, and in technical circles as “the guy who invented Django.”

He was lead developer at World Online for 2.5 years, during which time Django was developed and implemented on World Online’s sites. He was the leader and founder of EveryBlock, a “news feed for your block.” He now develops Soundslice.

Adrian lives in Chicago, USA.

Simon Willison

Simon is a well-respected Web developer from England. He had a one-year internship at World Online, during which time he and Adrian developed Django from scratch. The most enthusiastic Brit you’ll ever meet, he’s passionate about best practices in Web development and maintains a well-read web-development blog.

Simon lives in Brighton, England.

Jacob Kaplan-Moss

Jacob is Director of Platform Security at Heroku. He worked at World Online for four years, where he helped open source Django and found the Django Software Foundation. Jacob lives on a hobby farm outside of Lawrence where he spends his weekends playing with dirt and power tools.

Wilson Miner

Wilson’s design-fu is what makes Django look so nice. He created the design that was used for nearly the first ten years on the Django Project website, as well as the current design for Django’s acclaimed admin interface. Wilson was the designer for EveryBlock and Rdio. He now designs for Facebook.

Wilson lives in San Francisco, USA.

The current team

These are the folks who have a long history of contributions, a solid track record of being helpful on the mailing lists, and a proven desire to dedicate serious time to Django. In return, they’ve been invited to join the core team.

Luke Plant

At University Luke studied physics and Materials Science and also met Michael Meeks who introduced him to Linux and Open Source, re-igniting an interest in programming. Since then he has contributed to a number of Open Source projects and worked professionally as a developer.

Luke has contributed many excellent improvements to Django, including database-level improvements, the CSRF middleware and many unit tests.

Luke currently works for a church in Bradford, UK, and part-time as a freelance developer.

Russell Keith-Magee

Russell studied physics as an undergraduate, and studied neural networks for his PhD. His first job was with a startup in the defense industry developing simulation frameworks. Over time, mostly through work with Django, he’s become more involved in Web development.

Russell has helped with several major aspects of Django, including a couple major internal refactorings, creation of the test system, and more.

Russell lives in the most isolated capital city in the world — Perth, Australia.

James Bennett

James is one of Django’s release managers, and also contributes to the documentation and provide the occasional bugfix.

James came to Web development from philosophy when he discovered that programmers get to argue just as much while collecting much better pay. He lives in Lawrence, Kansas and previously worked at World Online; currently, he’s part of the Web development team at Mozilla.

He keeps a blog, and enjoys fine port and talking to his car.

Justin Bronn

Justin Bronn is a computer scientist and attorney specializing in legal topics related to intellectual property and spatial law.

In 2007, Justin began developing django.contrib.gis in a branch, a.k.a. GeoDjango, which was merged in time for Django 1.0. While implementing GeoDjango, Justin obtained a deep knowledge of Django’s internals including the ORM, the admin, and Oracle support.

Justin lives in Houston, TX.

Karen Tracey

Karen has a background in distributed operating systems (graduate school), communications software (industry) and crossword puzzle construction (freelance). The last of these brought her to Django, in late 2006, when she set out to put a Web front-end on her crossword puzzle database. That done, she stuck around in the community answering questions, debugging problems, etc. – because coding puzzles are as much fun as word puzzles.

Karen lives in Apex, NC, USA.

Jannis Leidel

Jannis graduated in media design from Bauhaus-University Weimar, is the author of a number of pluggable Django apps and likes to contribute to Open Source projects like virtualenv and pip.

He has worked on Django’s auth, admin and staticfiles apps as well as the form, core, internationalization and test systems. He currently works at Mozilla.

Jannis lives in Berlin, Germany.

Andrew Godwin

Andrew is a freelance Python developer and tinkerer, and has been developing against Django since 2007. He graduated from Oxford University with a degree in Computer Science, and has become most well known in the Django community for his work on South, the schema migrations library.

Andrew lives in San Francisco, CA, USA.

Carl Meyer

Carl has been a Django user since 2007 (long enough to remember queryset-refactor, but not magic-removal), and builds web apps at OddBird. He became a Django contributor by accident, because fixing bugs is more interesting than working around them.

Carl lives in Rapid City, SD, USA.

Ramiro Morales

Ramiro has been reading Django source code and submitting patches since mid-2006 after researching for a Python Web tool with matching awesomeness and being pointed to it by an old ninja.

A software developer in the electronic transactions industry, he is a living proof of the fact that anyone with enough enthusiasm can contribute to Django, learning a lot and having fun in the process.

Ramiro lives in Córdoba, Argentina.

Chris Beaven

Chris has been submitting patches and suggesting crazy ideas for Django since early 2006. An advocate for community involvement and a long-term triager, he is still often found answering questions in the #django IRC channel.

Chris lives in Napier, New Zealand (adding to the pool of Oceanic core developers). He works remotely as a developer for Lincoln Loop.

Honza Král

Honza first discovered Django in 2006 and started using it right away, first for school and personal projects and later in his full-time job. He contributed various patches and fixes mostly to the newforms library, newforms admin and, through participation in the Google Summer of Code project, assisted in creating the model validation functionality.

He is currently working for Whiskey Media in San Francisco developing awesome sites running on pure Django.

Tim Graham

When exploring Web frameworks for an independent study project in the fall of 2008, Tim discovered Django and was lured to it by the documentation. He enjoys contributing to the docs because they’re awesome.

Tim works as a software engineer and lives in Philadelphia, PA, USA.

Idan Gazit

As a self-professed design geek, Idan was initially attracted to Django sometime between magic-removal and queryset-refactor. Formally trained as a software engineer, Idan straddles the worlds of design and code, jack of two trades and master of none. He is passionate about usability and finding novel ways to extract meaning from data, and is a longtime photographer.

Idan previously accepted freelance work under the Pixane imprint, but now splits his days between his startup, Skills, and beautifying all things Django and Python.

Paul McMillan

Paul found Django in 2008 while looking for a more structured approach to web programming. He stuck around after figuring out that the developers of Django had already invented many of the wheels he needed. His passion for breaking (and then fixing) things led to his current role working to maintain and improve the security of Django.

Julien Phalip

Julien has a background in software engineering and human-computer interaction. As a Web developer, he enjoys tinkering with the backend as much as designing and coding user interfaces. Julien discovered Django in 2007 while doing his PhD in Computing Sciences. Since then he has contributed patches to various components of the framework, in particular the admin. Julien was a co-founder of the Interaction Consortium. He now works at Odopod, a digital agency based in San Francisco, CA, USA.

Aymeric Augustin

Aymeric is an engineer with a background in mathematics and computer science. He chose Django because he believes that software should be simple, explicit and tested. His perfectionist tendencies quickly led him to triage tickets and contribute patches.

Aymeric has a pragmatic approach to software engineering, can’t live without a continuous integration server, and likes proving that Django is a good choice for enterprise software.

He’s the CTO of Oscaro, an e-commerce company based in Paris, France.

Claude Paroz

Claude is a former teacher who fell in love with free software at the beginning of the 21st century. He’s now working as freelancer in Web development in his native Switzerland. He has found in Django a perfect match for his needs of a stable, clean, documented and well-maintained Web framework.

He’s also helping the GNOME Translation Project as maintainer of the Django-based l10n.gnome.org.

Anssi Kääriäinen

Anssi works as a developer at Finnish National Institute for Health and Welfare. He is also a computer science student at Aalto University. In his work he uses Django for developing internal business applications and sees Django as a great match for that use case.

Anssi is interested in developing the object relational mapper (ORM) and all related features. He’s also a fan of benchmarking and he tries keep Django as fast as possible.

Florian Apolloner

Florian is currently studying Physics at the Graz University of Technology. Soon after he started using Django he joined the Ubuntuusers webteam to work on Inyoka, the software powering the whole Ubuntuusers site.

For the time being he lives in Graz, Austria (not Australia ;)).

Jeremy Dunck

Jeremy was rescued from corporate IT drudgery by Free Software and, in part, Django. Many of Jeremy’s interests center around access to information.

Jeremy was the lead developer of Pegasus News, one of the first uses of Django outside World Online, and has since joined Votizen, a startup intent on reducing the influence of money in politics.

He serves as DSF Secretary, organizes and helps organize sprints, cares about the health and equity of the Django community. He has gone an embarrassingly long time without a working blog.

Jeremy lives in Mountain View, CA, USA.

Bryan Veloso

Bryan found Django 0.96 through a fellow designer who was evangelizing its use. It was his first foray outside of the land that was PHP-based templating. Although he has only ever used Django for personal projects, it is the very reason he considers himself a designer/developer hybrid and is working to further design within the Django community.

Bryan works as a designer at GitHub by day, and masquerades as a vlogger and shoutcaster in the after-hours. Bryan lives in Los Angeles, CA, USA.

Simon Charette

Simon is a mathematics student who discovered Django while searching for a replacement framework to an in-house PHP entity. Since that faithful day Django has been a big part of his life. So far, he’s been involved in some ORM and forms API fixes.

Apart from contributing to multiple open source projects he spends most of his spare-time playing Ultimate Frisbee and working part-time at this awesome place called Reptiletech.

Simon lives in Montréal, Québec, Canada.

Donald Stufft

Donald found Python and Django in 2007 while trying to find a language, and web framework that he really enjoyed using after many years of PHP. He fell in love with the beauty of Python and the way Django made tasks simple and easy. His contributions to Django focus primarily on ensuring that it is and remains a secure web framework.

Donald currently works at Nebula Inc as a Software Engineer for their security team and lives in the Greater Philadelphia Area.

Marc Tamlyn

Marc started life on the web using Django 1.2 back in 2010, and has never looked back. He was involved with rewriting the class-based view documentation at DjangoCon EU 2012, and also helped to develop CCBV, an additional class-based view reference tool.

Marc is currently a full-time parent, part-time developer, and lives in Oxford, UK.

Shai Berger

Shai started working with Python back in 1998, and with Django just before 1.0. He is a Free Software enthusiast, but life happens, and he was driven by consulting gigs to contribute to the Oracle and SQL Server backends of South, and then the Oracle backend of Django itself. Finally, he joined core to help maintain the Oracle backend.

Shai works for Platonix, a small consulting company he started with a few friends in 1996, and lives near Tel Aviv, Israel.

Baptiste Mispelon

Baptiste discovered Django around the 1.2 version and promptly switched away from his homegrown PHP framework. He started getting more involved in the project after attending DjangoCon EU 2012, mostly by triaging tickets and submitting small patches.

Baptiste currently lives in Budapest, Hungary and works for M2BPO, a small French company providing services to architects.

Daniele Procida

Daniele unexpectedly became a Django developer on 29th April 2009. Since then he has relied daily on Django’s documentation, which has been a constant companion to him. More recently he has been able to contribute back to the project by helping improve the documentation itself.

He is the author of Arkestra and Don’t be afraid to commit. He lives in Cardiff, Wales, and works for Divio.

Erik Romijn

Erik started using Django in the days of 1.2. His largest contribution to Django was GenericIPAddressField, and he has worked on all sorts of patches since. While developing with Django, he always keeps a little list of even the slightest Django frustrations, to tackle them at a later time and prevent other developers from having to deal with the same issues.

Erik is an independent app maker, mostly developing web and mobile apps, as Solid Links. He also enjoys helping ordinary developers to build safer web apps, for which Django is already a great start, and developed Erik’s Pony Checkup with that goal in mind. Erik lives in Amsterdam, The Netherlands.

Loïc Bistuer

Loïc studied telecommunications engineering and works as an independent software developer and consultant.

He discovered Django in 2008 shortly before the 1.0 release and has been hooked ever since. He contributes mostly to Django’s ORM and Form components. His main contributions include advanced query prefetching, streamlining QuerySet and Manager to improve query reusability, and a significant refactor of forms error handling.

Loïc is originally from the South of France and currently lives in Bangkok, Thailand.

Michael Manfre

Michael started running Django on Windows against a Microsoft SQL Server (MSSQL) database in 2008. He quickly became the maintainer of the django-mssql 3rd party database backend. Much of his involvement with Django relates to the ORM, the private 3rd party database API, and using Django on Windows.

Michael lives in Cary, NC, USA.

Collin Anderson

Collin found Django in November 2006. He was in awe of the admin and ORM and was amazed that the documentation was teaching him best web practices like redirecting after a successful POST request. Why had he never learned this before? No one knows to this day.

He enjoys helping people on the django-users mailing list and making Django simple and easy for newcomers.

Collin lives in South Bend, IN, USA where he uses Django to increase unity.

Tom Christie

Tom has background in speech recognition, networking, and web development. He has a particular interest in Web API design and is the original author of Django REST framework.

Tom lives in the seaside city of Brighton, UK.

Curtis Maloney

Curtis is a self-taught programmer from Melbourne, Australia, who eschews specialization. Upon finding Django when it was first open sourced, he realized it was possible to enjoy web development.

He spends a lot of time helping people on the #django IRC channel, and has authored and released a number of smaller django apps.

Markus Holtermann

Markus is a Master of Science student in Computer Science at Technical University of Berlin. He started working with Django in 2010 when he joined the ubuntuusers.de web team to work on Inyoka. Markus made his first contribution to the Django project during DjangoCon Europe 2013 in Warsaw. He was the web team leader for the EuroPython 2014 website.

Markus lives in Berlin, Germany.

Josh Smeaton

Josh was given the opportunity to work on a new Django app around version 1.1 after working with a homegrown PHP reporting framework. The simplicity of the ORM and the power of the Admin were extremely liberating.

Still being involved with custom reporting applications, he decided to try his hand at improving the ORM support for analytics. His contributions focus on giving more power to users of the ORM.

Josh lives in Melbourne, Australia where he heads up development for a SaaS telecommunications company.

Preston Timmons

Preston is a software developer with a background in mathematics. He enjoys Django because it enables consistent, simple, and tested systems to be built that even new programmers can quickly dive into. Preston lives in Dallas, TX.

Tomek Paczkowski

Tomek started using Django in 2007 as a tool for quickly dealing with university projects. Since then, he worked with various technologies like Ruby on Rails, JavaScript and Android but always returned to Python and Django.

Tomek loves the Django community. He organized multiple Django sprints, co-organized DjangoCon Europe 2013 and has mentored at many Django Girls events.

Originally from Poland, Tomek currently lives in London, where he works at Squirrel.

Ola Sitarska

Ola started working with Django in 2009, when she discovered the power of the Django admin and quickly fell in love with the beauty of Python.

She co-organized DjangoCon Europe 2013 in Warsaw and co-authored the Django Girls Tutorial, the most beginner friendly Django tutorial out there. Together with Ola Sendecka, she started Django Girls, a community and series of Django workshops for women who’ve never programmed before.

In 2015, she became a Django Software Foundation board member. Ola was also a part of the team responsible for shipping the djangoproject.com redesign.

Originally from Poland, Ola currently lives in London, where she works with friends at Potato.

Past team members

Georg “Hugo” Bauer

Georg created Django’s internationalization system, managed i18n contributions and made a ton of excellent tweaks, feature additions and bug fixes.

Robert Wittams

Robert was responsible for the first refactoring of Django’s admin application to allow for easier reuse and has made a ton of excellent tweaks, feature additions and bug fixes.

Alex Gaynor

Alex was involved in many parts of Django, he contributed to the ORM, forms, admin, amongst others; he is most known for his work on multiple-database support in Django.

Alex lives in Washington, DC, USA.

Simon Meers

Simon discovered Django 0.96 during his Computer Science PhD research and has been developing with it full-time ever since. His core code contributions are mostly in Django’s admin application.

Simon works as a freelance developer based in Wollongong, Australia.

Gabriel Hurley

Gabriel has been working with Django since 2008, shortly after the 1.0 release. Convinced by his business partner that Python and Django were the right direction for the company, he couldn’t have been more happy with the decision. His contributions range across many areas in Django, but years of copy-editing and an eye for detail lead him to be particularly at home while working on Django’s documentation.

Gabriel works as a developer in the SF Bay Area, CA, USA.

Malcolm Tredinnick

Malcolm originally wanted to be a mathematician and somehow ended up a software developer. He contributed to many Open Source projects, served on the board of the GNOME foundation, and was a great chess player.

Malcolm was deeply involved in many part of Django - most notably, the ORM, but many other internals bear his fingerprints. Django’s support for unicode and autoescaping in templates can both be almost entirely attributed to Malcolm.

He was an International Man of Mystery and lived in Sydney, Australia.

Malcolm passed away on March 17, 2013.

Preston Holmes

Preston is a recovering neuroscientist who originally discovered Django as part of a sweeping move to Python from a grab bag of half a dozen languages. He was drawn to Django’s balance of practical batteries included philosophy, care and thought in code design, and strong open source community. Currently working in the rent-your-infra space (aka Cloud), he is always looking for opportunities to volunteer for community oriented education projects, such as for kids and scientists (e.g. Software Carpentry).

Preston lives with his family and animal menagerie in Santa Barbara, CA, USA.

Matt Boersma

Matt helped with Django’s Oracle support.

Ian Kelly

Ian also helped with Oracle support.

Joseph Kocherhans

Joseph was the director of lead development at EveryBlock and previously developed at the Lawrence Journal-World. He often disappears for several days into the woods, attempts to teach himself computational linguistics, and annoys his neighbors with his Charango playing.

Joseph’s first contribution to Django was a series of improvements to the authorization system leading up to support for pluggable authorization. Since then, he’s worked on the new forms system, its use in the admin, and many other smaller improvements.

Joseph lives in Chicago, USA.

Gary Wilson

Gary starting contributing patches to Django in 2006 while developing Web applications for The University of Texas (UT). Since, he has made contributions to the email and forms systems, as well as many other improvements and code cleanups throughout the code base.

Gary lives in Austin, Texas, USA.

Brian Rosner

Brian enjoys learning more about programming languages and system architectures and contributing to open source projects.

He helped immensely in getting Django’s “newforms-admin” branch finished in time for Django 1.0.

Brian lives in Denver, Colorado, USA.

James Tauber

James is the lead developer of Pinax and the CEO and founder of Eldarion. He has been doing open source software since 1993, Python since 1998 and Django since 2006. He serves on the board of the Python Software Foundation and is currently on a leave of absence from a PhD in linguistics.

James currently lives in Boston, MA, USA but originally hails from Perth, Western Australia where he attended the same high school as Russell Keith-Magee.

Roles

Technical board

The technical board for the 1.9 release cycle is:

- Aymeric Augustin

- Andrew Godwin

- Russell Keith-Magee

- Jannis Leidel

- Carl Meyer

Committers

Most core team members have commit access. They’re called “committers” or “core developers”.

Being part of the core team is a pre-requisite for having commit access.

Security team

The security team is responsible for Django’s security policies. It handles private reports of security issues.

The current security team members are:

- Florian Apolloner

- James Bennett

- Jeremy Dunck

- Adrian Holovaty

- Jacob Kaplan-Moss

- Russell Keith-Magee

- Paul McMillan

- Carl Meyer

- Donald Stufft

Releasers

Releasers take care of building Django releases.

The current releasers are:

- James Bennett

- Jacob Kaplan-Moss

- Tim Graham

Ops team

The ops team maintains Django’s infrastructure like the Django Project server, Trac instance, and continuous integration infrastructure.

- Florian Apolloner

- Aymeric Augustin

- Tim Graham

- Jannis Leidel

Django’s security policies

Django’s development team is strongly committed to responsible reporting and disclosure of security-related issues. As such, we’ve adopted and follow a set of policies which conform to that ideal and are geared toward allowing us to deliver timely security updates to the official distribution of Django, as well as to third-party distributions.

Reporting security issues

Short version: please report security issues by emailing security@djangoproject.com.

Most normal bugs in Django are reported to our public Trac instance, but due to the sensitive nature of security issues, we ask that they not be publicly reported in this fashion.

Instead, if you believe you’ve found something in Django which has security implications, please send a description of the issue via email to security@djangoproject.com. Mail sent to that address reaches a subset of the core team, who can forward security issues into the private committers’ mailing list for broader discussion if needed.

Once you’ve submitted an issue via email, you should receive an acknowledgment from a member of the security team within 48 hours, and depending on the action to be taken, you may receive further followup emails.

Note

If you want to send an encrypted email (optional), the public key ID for security@djangoproject.com is 0xfcb84b8d1d17f80b, and this public key is available from most commonly-used keyservers.

Supported versions

At any given time, the Django team provides official security support for several versions of Django:

- The master development branch, hosted on GitHub, which will become the next release of Django, receives security support.

- The two most recent Django release series receive security support. For example, during the development cycle leading to the release of Django 1.5, support will be provided for Django 1.4 and Django 1.3. Upon the release of Django 1.5, Django 1.3’s security support will end.

- Long-term support releases will receive security updates for a specified period.

When new releases are issued for security reasons, the accompanying notice will include a list of affected versions. This list is comprised solely of supported versions of Django: older versions may also be affected, but we do not investigate to determine that, and will not issue patches or new releases for those versions.

How Django discloses security issues

Our process for taking a security issue from private discussion to public disclosure involves multiple steps.

Approximately one week before full public disclosure, we will send advance notification of the issue to a list of people and organizations, primarily composed of operating-system vendors and other distributors of Django. This notification will consist of an email message, signed with the Django release key, containing:

- A full description of the issue and the affected versions of Django.

- The steps we will be taking to remedy the issue.

- The patch(es), if any, that will be applied to Django.

- The date on which the Django team will apply these patches, issue new releases and publicly disclose the issue.

Simultaneously, the reporter of the issue will receive notification of the date on which we plan to take the issue public.

On the day of disclosure, we will take the following steps:

1. Apply the relevant patch(es) to Django’s codebase. The commit messages for these patches will indicate that they are for security issues, but will not describe the issue in any detail; instead, they will warn of upcoming disclosure.

2. Issue the relevant release(s), by placing new packages on the Python Package Index and on the Django website, and tagging the new release(s) in Django’s git repository.

3. Post a public entry on the official Django development blog, describing the issue and its resolution in detail, pointing to the relevant patches and new releases, and crediting the reporter of the issue (if the reporter wishes to be publicly identified).

4. Post a notice to the django-announce and oss-security@lists.openwall.com mailing lists that links to the blog post.

If a reported issue is believed to be particularly time-sensitive – due to a known exploit in the wild, for example – the time between advance notification and public disclosure may be shortened considerably.

Additionally, if we have reason to believe that an issue reported to us affects other frameworks or tools in the Python/web ecosystem, we may privately contact and discuss those issues with the appropriate maintainers, and coordinate our own disclosure and resolution with theirs.

The Django team also maintains an archive of security issues disclosed in Django.

Who receives advance notification

The full list of people and organizations who receive advance notification of security issues is not and will not be made public.

We also aim to keep this list as small as effectively possible, in order to better manage the flow of confidential information prior to disclosure. As such, our notification list is not simply a list of users of Django, and merely being a user of Django is not sufficient reason to be placed on the notification list.

In broad terms, recipients of security notifications fall into three groups:

1. Operating-system vendors and other distributors of Django who provide a suitably-generic (i.e., not an individual’s personal email address) contact address for reporting issues with their Django package, or for general security reporting. In either case, such addresses must not forward to public mailing lists or bug trackers. Addresses which forward to the private email of an individual maintainer or security-response contact are acceptable, although private security trackers or security-response groups are strongly preferred.

2. On a case-by-case basis, individual package maintainers who have demonstrated a commitment to responding to and responsibly acting on these notifications.

3. On a case-by-case basis, other entities who, in the judgment of the Django development team, need to be made aware of a pending security issue. Typically, membership in this group will consist of some of the largest and/or most likely to be severely impacted known users or distributors of Django, and will require a demonstrated ability to responsibly receive, keep confidential and act on these notifications.

Requesting notifications

If you believe that you, or an organization you are authorized to represent, fall into one of the groups listed above, you can ask to be added to Django’s notification list by emailing security@djangoproject.com. Please use the subject line “Security notification request”.

Your request must include the following information:

- Your full, real name and the name of the organization you represent, if applicable, as well as your role within that organization.

- A detailed explanation of how you or your organization fit at least one set of criteria listed above.

- A detailed explanation of why you are requesting security notifications. Again, please keep in mind that this is not simply a list for users of Django, and the overwhelming majority of users of Django should not request notifications and will not be added to our notification list if they do.

- The email address you would like to have added to our notification list.

- An explanation of who will be receiving/reviewing mail sent to that address, as well as information regarding any automated actions that will be taken (i.e., filing of a confidential issue in a bug tracker).

- For individuals, the ID of a public key associated with your address which can be used to verify email received from you and encrypt email sent to you, as needed.

Once submitted, your request will be considered by the Django development team; you will receive a reply notifying you of the result of your request within 30 days.

Please also bear in mind that for any individual or organization, receiving security notifications is a privilege granted at the sole discretion of the Django development team, and that this privilege can be revoked at any time, with or without explanation.

If you are added to the notification list, security-related emails will be sent to you by Django’s release team, and all notification emails will be signed with a key authorized to issue Django releases. The list of authorized keys is in the Django releasers file.

Django’s release process

Official releases

Since version 1.0, Django’s release numbering works as follows:

- Versions are numbered in the form A.B or A.B.C.

- A.B is the feature release version number. Each version will be mostly backwards compatible with the previous release. Exceptions to this rule will be listed in the release notes.

- C is the patch release version number, which is incremented for bugfix and security releases. These releases will be 100% backwards-compatible with the previous patch release. The only exception is when a security or data loss issue can’t be fixed without breaking backwards-compatibility. If this happens, the release notes will provide detailed upgrade instructions.

- Before a new feature release, we’ll make alpha, beta, and release candidate releases. These are of the form A.B alpha/beta/rc N, which means the Nth alpha/beta/release candidate of version A.B.

In git, each Django release will have a tag indicating its version number, signed with the Django release key. Additionally, each release series has its own branch, called stable/A.B.x, and bugfix/security releases will be issued from those branches.

For more information about how the Django project issues new releases for security purposes, please see our security policies.

Feature release

Feature releases (A.B, A.B+1, etc.) will happen roughly every eight months – see release process for details. These releases will contain new features, improvements to existing features, and such.

Patch release

Patch releases (A.B.C, A.B.C+1, etc.) will be issued as needed, to fix bugs and/or security issues.

These releases will be 100% compatible with the associated feature release, unless this is impossible for security reasons or to prevent data loss. So the answer to “should I upgrade to the latest patch release?” will always be “yes.”

Long-term support release

Certain feature releases will be designated as long-term support (LTS) releases. These releases will get security and data loss fixes applied for a guaranteed period of time, typically three years.

See the download page for the releases that have been designated for long-term support.

Release cadence

Starting with Django 2.0, version numbers will use a loose form of semantic versioning such that each version following an LTS will bump to the next “dot zero” version. For example: 2.0, 2.1, 2.2 (LTS), 3.0, 3.1, 3.2 (LTS), etc.

SemVer makes it easier to see at a glance how compatible releases are with each other. It also helps to anticipate when compatibility shims will be removed. It’s not a pure form of SemVer as each feature release will continue to have a few documented backwards incompatibilities where a deprecation path isn’t possible or not worth the cost. Also, deprecations started in an LTS release (X.2) will be dropped in a non-dot-zero release (Y.1) to accommodate our policy of keeping deprecation shims for at least two feature releases. Read on to the next section for an example.

Deprecation policy

A feature release may deprecate certain features from previous releases. If a feature is deprecated in feature release A.x, it will continue to work in all A.x versions (for all versions of x) but raise warnings. Deprecated features will be removed in the B.0 release, or B.1 for features deprecated in the last A.x feature release to ensure deprecations are done over at least 2 feature releases.

So, for example, if we decided to start the deprecation of a function in Django 4.2:

- Django 4.2 will contain a backwards-compatible replica of the function which will raise a RemovedInDjango51Warning. This warning is silent by default; you can turn on display of these warnings with the -Wd option of Python.

- Django 5.0 (the version that follows 4.2) will still contain the backwards-compatible replica. This warning becomes loud by default and will likely be quite annoying.

- Django 5.1 will remove the feature outright.

A more generic example:

- X.0

- X.1

- X.2 LTS

- Y.0: Drop deprecation shims added in X.0 and X.1.

- Y.1: Drop deprecation shims added in X.2.

- Y.2 LTS: No deprecation shims dropped (while Y.0 is no longer supported, third-party apps need to maintain compatibility back to X.2 LTS to ease LTS to LTS upgrades).

- Z.0: Drop deprecation shims added in Y.0 and Y.1.

Supported versions

At any moment in time, Django’s developer team will support a set of releases to varying levels. See the supported versions section of the download page for the current state of support for each version.

- The current development master will get new features and bug fixes requiring non-trivial refactoring.

- Patches applied to the master branch must also be applied to the last feature release branch, to be released in the next patch release of that feature series, when they fix critical problems:

- Security issues.

- Data loss bugs.

- Crashing bugs.

- Major functionality bugs in newly-introduced features.

The rule of thumb is that fixes will be backported to the last feature release for bugs that would have prevented a release in the first place (release blockers).

- Security fixes and data loss bugs will be applied to the current master, the last two feature release branches, and any other supported long-term support release branches.

- Documentation fixes generally will be more freely backported to the last release branch. That’s because it’s highly advantageous to have the docs for the last release be up-to-date and correct, and the risk of introducing regressions is much less of a concern.

As a concrete example, consider a moment in time halfway between the release of Django 5.1 and 5.2. At this point in time:

- Features will be added to development master, to be released as Django 5.2.

- Critical bug fixes will be applied to the stable/5.1.x branch, and released as 5.1.1, 5.1.2, etc.

- Security fixes and bug fixes for data loss issues will be applied to master and to the stable/5.1.x, stable/5.0.x, and stable/4.2.x (LTS) branches. They will trigger the release of 5.1.1, 5.0.5, 4.2.8, etc.

- Documentation fixes will be applied to master, and, if easily backported, to the latest stable branch, 5.1.x.

Release process

Django uses a time-based release schedule, with feature releases every eight months or so.

After each feature release, the release manager will announce a timeline for the next feature release.

Release cycle

Each release cycle consists of three parts:

Phase one: feature proposal

The first phase of the release process will include figuring out what major features to include in the next version. This should include a good deal of preliminary work on those features – working code trumps grand design.

Major features for an upcoming release will be added to the wiki roadmap page, e.g. https://code.djangoproject.com/wiki/Version1.9Roadmap.

Phase two: development

The second part of the release schedule is the “heads-down” working period. Using the roadmap produced at the end of phase one, we’ll all work very hard to get everything on it done.

At the end of phase two, any unfinished features will be postponed until the next release.

Phase two will culminate with an alpha release. At this point, the stable/A.B.x branch will be forked from master.

Phase three: bugfixes

The last part of a release cycle is spent fixing bugs – no new features will be accepted during this time. We’ll try to release a beta release one month after the alpha and a release candidate one month after the beta.

The release candidate marks the string freeze, and it happens at least two weeks before the final release. After this point, new translatable strings must not be added.

During this phase, committers will be more and more conservative with backports, to avoid introducing regressions. After the release candidate, only release blockers and documentation fixes should be backported.

In parallel to this phase, master can receive new features, to be released in the A.B+1 cycle.

Bug-fix releases

After a feature release (e.g. A.B), the previous release will go into bugfix mode.

The branch for the previous feature release (e.g. stable/A.B-1.x) will include bugfixes. Critical bugs fixed on master must also be fixed on the bugfix branch; this means that commits need to cleanly separate bug fixes from feature additions. The developer who commits a fix to master will be responsible for also applying the fix to the current bugfix branch.

Django Deprecation Timeline

This document outlines when various pieces of Django will be removed or altered in a backward incompatible way, following their deprecation, as per the deprecation policy. More details about each item can often be found in the release notes of two versions prior.

2.0

See the Django 1.9 release notes for more details on these changes.

- The weak argument to django.dispatch.signals.Signal.disconnect() will be removed.

- The django.forms.extras package will be removed.

- The assignment_tag helper will be removed.

- The host argument to assertsRedirects will be removed. The compatibility layer which allows absolute URLs to be considered equal to relative ones when the path is identical will also be removed.

- Field.rel will be removed.

- Field.remote_field.to attribute will be removed.

- The on_delete argument for ForeignKey and OneToOneField will be required.

- django.db.models.fields.add_lazy_relation() will be removed.

- When time zone support is enabled, database backends that don’t support time zones won’t convert aware datetimes to naive values in UTC anymore when such values are passed as parameters to SQL queries executed outside of the ORM, e.g. with cursor.execute().

- The django.contrib.auth.tests.utils.skipIfCustomUser() decorator will be removed.

- The GeoManager and GeoQuerySet classes will be removed.

- The django.contrib.gis.geoip module will be removed.

- The supports_recursion check for template loaders will be removed from:

- django.template.engine.Engine.find_template()

- django.template.loader_tags.ExtendsNode.find_template()

- django.template.loaders.base.Loader.supports_recursion()

- django.template.loaders.cached.Loader.supports_recursion()

- The load_template() and load_template_sources() template loader methods will be removed.

- The template_dirs argument for template loaders will be removed:

- django.template.loaders.base.Loader.get_template()

- django.template.loaders.cached.Loader.cache_key()

- django.template.loaders.cached.Loader.get_template()

- django.template.loaders.cached.Loader.get_template_sources()

- django.template.loaders.filesystem.Loader.get_template_sources()

- The django.template.loaders.base.Loader.__call__() method will be removed.

- Support for custom error views with a single positional parameter will be dropped.

- The mime_type attribute of django.utils.feedgenerator.Atom1Feed and django.utils.feedgenerator.RssFeed will be removed in favor of content_type.

- The app_name argument to include() will be removed.

- Support for passing a 3-tuple as the first argument to include() will be removed.

- Support for setting a URL instance namespace without an application namespace will be removed.

- Field._get_val_from_obj() will be removed in favor of Field.value_from_object().

- django.template.loaders.eggs.Loader will be removed.

- The current_app parameter to the contrib.auth views will be removed.

- The callable_obj keyword argument to SimpleTestCase.assertRaisesMessage() will be removed.

- Support for the allow_tags attribute on ModelAdmin methods will be removed.

- The enclosure keyword argument to SyndicationFeed.add_item() will be removed.

- The django.template.loader.LoaderOrigin and django.template.base.StringOrigin aliases for django.template.base.Origin will be removed.

1.10

See the Django 1.8 release notes for more details on these changes.

- Support for calling a SQLCompiler directly as an alias for calling its quote_name_unless_alias method will be removed.

- cycle and firstof template tags will be removed from the future template tag library (used during the 1.6/1.7 deprecation period).

- django.conf.urls.patterns() will be removed.

- Support for the prefix argument to django.conf.urls.i18n.i18n_patterns() will be removed.

- SimpleTestCase.urls will be removed.

- Using an incorrect count of unpacked values in the for template tag will raise an exception rather than fail silently.

- The ability to reverse() URLs using a dotted Python path will be removed.

- The ability to use a dotted Python path for the LOGIN_URL and LOGIN_REDIRECT_URL settings will be removed.

- Support for optparse will be dropped for custom management commands (replaced by argparse).

- The class NoArgsCommand will be removed. Use BaseCommand instead, which takes no arguments by default.

- django.core.context_processors module will be removed.

- django.db.models.sql.aggregates module will be removed.

- django.contrib.gis.db.models.sql.aggregates module will be removed.

- The following methods and properties of django.db.sql.query.Query will be removed:

- Properties: aggregates and aggregate_select

- Methods: add_aggregate, set_aggregate_mask, and append_aggregate_mask.

- django.template.resolve_variable will be removed.

- The following private APIs will be removed from django.db.models.options.Options (Model._meta):

- get_field_by_name()

- get_all_field_names()

- get_fields_with_model()

- get_concrete_fields_with_model()

- get_m2m_with_model()

- get_all_related_objects()

- get_all_related_objects_with_model()

- get_all_related_many_to_many_objects()

- get_all_related_m2m_objects_with_model()

- The error_message argument of django.forms.RegexField will be removed.

- The unordered_list filter will no longer support old style lists.

- Support for string view arguments to url() will be removed.

- The backward compatible shim to rename django.forms.Form._has_changed() to has_changed() will be removed.

- The removetags template filter will be removed.

- The remove_tags() and strip_entities() functions in django.utils.html will be removed.

- The is_admin_site argument to django.contrib.auth.views.password_reset() will be removed.

- django.db.models.field.subclassing.SubfieldBase will be removed.

- django.utils.checksums will be removed; its functionality is included in django-localflavor 1.1+.

- The original_content_type_id attribute on django.contrib.admin.helpers.InlineAdminForm will be removed.

- The backwards compatibility shim to allow FormMixin.get_form() to be defined with no default value for its form_class argument will be removed.

- The following settings will be removed:

- ALLOWED_INCLUDE_ROOTS

- TEMPLATE_CONTEXT_PROCESSORS

- TEMPLATE_DEBUG

- TEMPLATE_DIRS

- TEMPLATE_LOADERS

- TEMPLATE_STRING_IF_INVALID

- The backwards compatibility alias django.template.loader.BaseLoader will be removed.

- Django template objects returned by get_template() and select_template() won’t accept a Context in their render() method anymore.

- Template response APIs will enforce the use of dict and backend-dependent template objects instead of Context and Template respectively.

- The current_app parameter for the following function and classes will be removed:

- django.shortcuts.render()

- django.template.Context()

- django.template.RequestContext()

- django.template.response.TemplateResponse()

- The dictionary and context_instance parameters for the following functions will be removed:

- django.shortcuts.render()

- django.shortcuts.render_to_response()

- django.template.loader.render_to_string()

- The dirs parameter for the following functions will be removed:

- django.template.loader.get_template()

- django.template.loader.select_template()

- django.shortcuts.render()

- django.shortcuts.render_to_response()

- Session verification will be enabled regardless of whether or not 'django.contrib.auth.middleware.SessionAuthenticationMiddleware' is in MIDDLEWARE_CLASSES.

- Private attribute django.db.models.Field.related will be removed.

- The --list option of the migrate management command will be removed.

- The ssi template tag will be removed.

- Support for the = comparison operator in the if template tag will be removed.

- The backwards compatibility shims to allow Storage.get_available_name() and Storage.save() to be defined without a max_length argument will be removed.

- Support for the legacy %(<foo>)s syntax in ModelFormMixin.success_url will be removed.

- GeoQuerySet aggregate methods collect(), extent(), extent3d(), make_line(), and unionagg() will be removed.

- Ability to specify ContentType.name when creating a content type instance will be removed.

- Support for the old signature of allow_migrate will be removed. It changed from allow_migrate(self, db, model) to allow_migrate(self, db, app_label, model_name=None, **hints).

- Support for the syntax of {% cycle %} that uses comma-separated arguments will be removed.

- The warning that Signer issues when given an invalid separator will become an exception.

1.9

See the Django 1.7 release notes for more details on these changes.

- django.utils.dictconfig will be removed.

- django.utils.importlib will be removed.

- django.utils.tzinfo will be removed.

- django.utils.unittest will be removed.

- The syncdb command will be removed.

- django.db.models.signals.pre_syncdb and django.db.models.signals.post_syncdb will be removed.

- allow_syncdb on database routers will no longer automatically become allow_migrate.

- Automatic syncing of apps without migrations will be removed. Migrations will become compulsory for all apps unless you pass the --run-syncdb option to migrate.

- The SQL management commands for apps without migrations, sql, sqlall, sqlclear, sqldropindexes, and sqlindexes, will be removed.

- Support for automatic loading of initial_data fixtures and initial SQL data will be removed.

- All models will need to be defined inside an installed application or declare an explicit app_label. Furthermore, it won’t be possible to import them before their application is loaded. In particular, it won’t be possible to import models inside the root package of their application.

- The model and form IPAddressField will be removed. A stub field will remain for compatibility with historical migrations.

- AppCommand.handle_app() will no longer be supported.

- RequestSite and get_current_site() will no longer be importable from django.contrib.sites.models.

- FastCGI support via the runfcgi management command will be removed. Please deploy your project using WSGI.

- django.utils.datastructures.SortedDict will be removed. Use collections.OrderedDict from the Python standard library instead.

- ModelAdmin.declared_fieldsets will be removed.

- Instances of util.py in the Django codebase have been renamed to utils.py in an effort to unify all util and utils references. The modules that provided backwards compatibility will be removed:

- django.contrib.admin.util

- django.contrib.gis.db.backends.util

- django.db.backends.util

- django.forms.util

- ModelAdmin.get_formsets will be removed.

- The backward compatibility shim introduced to rename the BaseMemcachedCache._get_memcache_timeout() method to get_backend_timeout() will be removed.

- The --natural and -n options for dumpdata will be removed.

- The use_natural_keys argument for serializers.serialize() will be removed.

- Private API django.forms.forms.get_declared_fields() will be removed.

- The ability to use a SplitDateTimeWidget with DateTimeField will be removed.

- The WSGIRequest.REQUEST property will be removed.

- The class django.utils.datastructures.MergeDict will be removed.

- The zh-cn and zh-tw language codes will be removed and have been replaced by the zh-hans and zh-hant language code respectively.

- The internal django.utils.functional.memoize will be removed.

- django.core.cache.get_cache will be removed. Add suitable entries to CACHES and use django.core.cache.caches instead.

- django.db.models.loading will be removed.

- Passing callable arguments to querysets will no longer be possible.

- BaseCommand.requires_model_validation will be removed in favor of requires_system_checks. Admin validators will be replaced by admin checks.

- The ModelAdmin.validator_class and default_validator_class attributes will be removed.

- ModelAdmin.validate() will be removed.

- django.db.backends.DatabaseValidation.validate_field will be removed in favor of the check_field method.

- The validate management command will be removed.

- django.utils.module_loading.import_by_path will be removed in favor of django.utils.module_loading.import_string.

- ssi and url template tags will be removed from the future template tag library (used during the 1.3/1.4 deprecation period).

- django.utils.text.javascript_quote will be removed.

- Database test settings as independent entries in the database settings, prefixed by TEST_, will no longer be supported.

- The cache_choices option to ModelChoiceField and ModelMultipleChoiceField will be removed.

- The default value of the RedirectView.permanent attribute will change from True to False.

- django.contrib.sitemaps.FlatPageSitemap will be removed in favor of django.contrib.flatpages.sitemaps.FlatPageSitemap.

- Private API django.test.utils.TestTemplateLoader will be removed.

- The django.contrib.contenttypes.generic module will be removed.

- Private APIs django.db.models.sql.where.WhereNode.make_atom() and django.db.models.sql.where.Constraint will be removed.

1.8

See the Django 1.6 release notes for more details on these changes.

- django.contrib.comments will be removed.

- The following transaction management APIs will be removed:

- TransactionMiddleware,

- the decorators and context managers autocommit, commit_on_success, and commit_manually, defined in django.db.transaction,

- the functions commit_unless_managed and rollback_unless_managed, also defined in django.db.transaction,

- the TRANSACTIONS_MANAGED setting.

- The cycle and firstof template tags will auto-escape their arguments. In 1.6 and 1.7, this behavior is provided by the version of these tags in the future template tag library.

- The SEND_BROKEN_LINK_EMAILS setting will be removed. Add the django.middleware.common.BrokenLinkEmailsMiddleware middleware to your MIDDLEWARE_CLASSES setting instead.

- django.middleware.doc.XViewMiddleware will be removed. Use django.contrib.admindocs.middleware.XViewMiddleware instead.

- Model._meta.module_name was renamed to model_name.

- Remove the backward compatible shims introduced to rename get_query_set and similar queryset methods. This affects the following classes: BaseModelAdmin, ChangeList, BaseCommentNode, GenericForeignKey, Manager, SingleRelatedObjectDescriptor and ReverseSingleRelatedObjectDescriptor.

- Remove the backward compatible shims introduced to rename the attributes ChangeList.root_query_set and ChangeList.query_set.

- django.views.defaults.shortcut will be removed, as part of the goal of removing all django.contrib references from the core Django codebase. Instead use django.contrib.contenttypes.views.shortcut. django.conf.urls.shortcut will also be removed.

- Support for the Python Imaging Library (PIL) module will be removed, as it no longer appears to be actively maintained & does not work on Python 3. You are advised to install Pillow, which should be used instead.

- The following private APIs will be removed:

- django.db.backend

- django.db.close_connection()

- django.db.backends.creation.BaseDatabaseCreation.set_autocommit()

- django.db.transaction.is_managed()

- django.db.transaction.managed()

- django.forms.widgets.RadioInput will be removed in favor of django.forms.widgets.RadioChoiceInput.

- The module django.test.simple and the class django.test.simple.DjangoTestSuiteRunner will be removed. Instead use django.test.runner.DiscoverRunner.

- The module django.test._doctest will be removed. Instead use the doctest module from the Python standard library.

- The CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting will be removed.

- Usage of the hard-coded Hold down “Control”, or “Command” on a Mac, to select more than one. string to override or append to user-provided help_text in forms for ManyToMany model fields will not be performed by Django anymore either at the model or forms layer.

- The Model._meta.get_(add|change|delete)_permission methods will be removed.

- The session key django_language will no longer be read for backwards compatibility.

- Geographic Sitemaps will be removed (django.contrib.gis.sitemaps.views.index and django.contrib.gis.sitemaps.views.sitemap).

- django.utils.html.fix_ampersands, the fix_ampersands template filter and django.utils.html.clean_html will be removed following an accelerated deprecation.

1.7

See the Django 1.5 release notes for more details on these changes.

- The module django.utils.simplejson will be removed. The standard library provides json which should be used instead.

- The function django.utils.itercompat.product will be removed. The Python builtin version should be used instead.

- Auto-correction of INSTALLED_APPS and TEMPLATE_DIRS settings when they are specified as a plain string instead of a tuple will be removed and raise an exception.

- The mimetype argument to the __init__ methods of HttpResponse, SimpleTemplateResponse, and TemplateResponse, will be removed. content_type should be used instead. This also applies to the render_to_response() shortcut and the sitemap views, index() and sitemap().

- When HttpResponse is instantiated with an iterator, or when content is set to an iterator, that iterator will be immediately consumed.

- The AUTH_PROFILE_MODULE setting, and the get_profile() method on the User model, will be removed.

- The cleanup management command will be removed. It’s replaced by clearsessions.

- The daily_cleanup.py script will be removed.

- The depth keyword argument will be removed from select_related().

- The undocumented get_warnings_state()/restore_warnings_state() functions from django.test.utils and the save_warnings_state()/ restore_warnings_state() django.test.*TestCase methods are deprecated. Use the warnings.catch_warnings context manager available starting with Python 2.6 instead.

- The undocumented check_for_test_cookie method in AuthenticationForm will be removed following an accelerated deprecation. Users subclassing this form should remove calls to this method, and instead ensure that their auth related views are CSRF protected, which ensures that cookies are enabled.

- The version of django.contrib.auth.views.password_reset_confirm() that supports base36 encoded user IDs (django.contrib.auth.views.password_reset_confirm_uidb36) will be removed. If your site has been running Django 1.6 for more than PASSWORD_RESET_TIMEOUT_DAYS, this change will have no effect. If not, then any password reset links generated before you upgrade to Django 1.7 won’t work after the upgrade.

- The django.utils.encoding.StrAndUnicode mix-in will be removed. Define a __str__ method and apply the python_2_unicode_compatible() decorator instead.

1.6

See the Django 1.4 release notes for more details on these changes.

- django.contrib.databrowse will be removed.

- django.contrib.localflavor will be removed following an accelerated deprecation.

- django.contrib.markup will be removed following an accelerated deprecation.

- The compatibility modules django.utils.copycompat and django.utils.hashcompat as well as the functions django.utils.itercompat.all and django.utils.itercompat.any will be removed. The Python builtin versions should be used instead.

- The csrf_response_exempt and csrf_view_exempt decorators will be removed. Since 1.4 csrf_response_exempt has been a no-op (it returns the same function), and csrf_view_exempt has been a synonym for django.views.decorators.csrf.csrf_exempt, which should be used to replace it.

- The django.core.cache.backends.memcached.CacheClass backend was split into two in Django 1.3 in order to introduce support for PyLibMC. The historical CacheClass will be removed in favor of django.core.cache.backends.memcached.MemcachedCache.

- The UK-prefixed objects of django.contrib.localflavor.uk will only be accessible through their GB-prefixed names (GB is the correct ISO 3166 code for United Kingdom).

- The IGNORABLE_404_STARTS and IGNORABLE_404_ENDS settings have been superseded by IGNORABLE_404_URLS in the 1.4 release. They will be removed.

- The form wizard has been refactored to use class-based views with pluggable backends in 1.4. The previous implementation will be removed.

- Legacy ways of calling cache_page() will be removed.

- The backward-compatibility shim to automatically add a debug-false filter to the 'mail_admins' logging handler will be removed. The LOGGING setting should include this filter explicitly if it is desired.

- The builtin truncation functions django.utils.text.truncate_words() and django.utils.text.truncate_html_words() will be removed in favor of the django.utils.text.Truncator class.

- The GeoIP class was moved to django.contrib.gis.geoip in 1.4 – the shortcut in django.contrib.gis.utils will be removed.

- django.conf.urls.defaults will be removed. The functions include(), patterns() and url() plus handler404, handler500, are now available through django.conf.urls .

- The functions setup_environ() and execute_manager() will be removed from django.core.management. This also means that the old (pre-1.4) style of manage.py file will no longer work.

- Setting the is_safe and needs_autoescape flags as attributes of template filter functions will no longer be supported.

- The attribute HttpRequest.raw_post_data was renamed to HttpRequest.body in 1.4. The backward compatibility will be removed – HttpRequest.raw_post_data will no longer work.

- The value for the post_url_continue parameter in ModelAdmin.response_add() will have to be either None (to redirect to the newly created object’s edit page) or a pre-formatted url. String formats, such as the previous default '../%s/', will not be accepted any more.

1.5

See the Django 1.3 release notes for more details on these changes.

- Starting Django without a SECRET_KEY will result in an exception rather than a DeprecationWarning. (This is accelerated from the usual deprecation path; see the Django 1.4 release notes.)

- The mod_python request handler will be removed. The mod_wsgi handler should be used instead.

- The template attribute on django.test.client.Response objects returned by the test client will be removed. The templates attribute should be used instead.

- The django.test.simple.DjangoTestRunner will be removed. Instead use a unittest-native class. The features of the django.test.simple.DjangoTestRunner (including fail-fast and Ctrl-C test termination) can currently be provided by the unittest-native TextTestRunner.

- The undocumented function django.contrib.formtools.utils.security_hash will be removed, instead use django.contrib.formtools.utils.form_hmac

- The function-based generic view modules will be removed in favor of their class-based equivalents, outlined here.

- The django.core.servers.basehttp.AdminMediaHandler will be removed. In its place use django.contrib.staticfiles.handlers.StaticFilesHandler.

- The template tags library adminmedia and the template tag {% admin_media_prefix %} will be removed in favor of the generic static files handling. (This is faster than the usual deprecation path; see the Django 1.4 release notes.)

- The url and ssi template tags will be modified so that the first argument to each tag is a template variable, not an implied string. In 1.4, this behavior is provided by a version of the tag in the future template tag library.

- The reset and sqlreset management commands will be removed.

- Authentication backends will need to support an inactive user being passed to all methods dealing with permissions. The supports_inactive_user attribute will no longer be checked and can be removed from custom backends.

- transform() will raise a GEOSException when called on a geometry with no SRID value.

- django.http.CompatCookie will be removed in favor of django.http.SimpleCookie.

- django.core.context_processors.PermWrapper and django.core.context_processors.PermLookupDict will be removed in favor of the corresponding django.contrib.auth.context_processors.PermWrapper and django.contrib.auth.context_processors.PermLookupDict, respectively.

- The MEDIA_URL or STATIC_URL settings will be required to end with a trailing slash to ensure there is a consistent way to combine paths in templates.

- django.db.models.fields.URLField.verify_exists will be removed. The feature was deprecated in 1.3.1 due to intractable security and performance issues and will follow a slightly accelerated deprecation timeframe.

- Translations located under the so-called project path will be ignored during the translation building process performed at runtime. The LOCALE_PATHS setting can be used for the same task by including the filesystem path to a locale directory containing non-app-specific translations in its value.

- The Markup contrib app will no longer support versions of Python-Markdown library earlier than 2.1. An accelerated timeline was used as this was a security related deprecation.

- The CACHE_BACKEND setting will be removed. The cache backend(s) should be specified in the CACHES setting.

1.4

See the Django 1.2 release notes for more details on these changes.

- CsrfResponseMiddleware and CsrfMiddleware will be removed. Use the {% csrf_token %} template tag inside forms to enable CSRF protection. CsrfViewMiddleware remains and is enabled by default.

- The old imports for CSRF functionality (django.contrib.csrf.*), which moved to core in 1.2, will be removed.

- The django.contrib.gis.db.backend module will be removed in favor of the specific backends.

- SMTPConnection will be removed in favor of a generic Email backend API.

- The many to many SQL generation functions on the database backends will be removed.

- The ability to use the DATABASE_* family of top-level settings to define database connections will be removed.

- The ability to use shorthand notation to specify a database backend (i.e., sqlite3 instead of django.db.backends.sqlite3) will be removed.

- The get_db_prep_save, get_db_prep_value and get_db_prep_lookup methods will have to support multiple databases.

- The Message model (in django.contrib.auth), its related manager in the User model (user.message_set), and the associated methods (user.message_set.create() and user.get_and_delete_messages()), will be removed. The messages framework should be used instead. The related messages variable returned by the auth context processor will also be removed. Note that this means that the admin application will depend on the messages context processor.

- Authentication backends will need to support the obj parameter for permission checking. The supports_object_permissions attribute will no longer be checked and can be removed from custom backends.

- Authentication backends will need to support the AnonymousUser class being passed to all methods dealing with permissions. The supports_anonymous_user variable will no longer be checked and can be removed from custom backends.

- The ability to specify a callable template loader rather than a Loader class will be removed, as will the load_template_source functions that are included with the built in template loaders for backwards compatibility.

- django.utils.translation.get_date_formats() and django.utils.translation.get_partial_date_formats(). These functions will be removed; use the locale-aware django.utils.formats.get_format() to get the appropriate formats.

- In django.forms.fields, the constants: DEFAULT_DATE_INPUT_FORMATS, DEFAULT_TIME_INPUT_FORMATS and DEFAULT_DATETIME_INPUT_FORMATS will be removed. Use django.utils.formats.get_format() to get the appropriate formats.

- The ability to use a function-based test runner will be removed, along with the django.test.simple.run_tests() test runner.

- The views.feed() view and feeds.Feed class in django.contrib.syndication will be removed. The class-based view views.Feed should be used instead.

- django.core.context_processors.auth. This release will remove the old method in favor of the new method in django.contrib.auth.context_processors.auth.

- The postgresql database backend will be removed, use the postgresql_psycopg2 backend instead.

- The no language code will be removed and has been replaced by the nb language code.

- Authentication backends will need to define the boolean attribute supports_inactive_user until version 1.5 when it will be assumed that all backends will handle inactive users.

- django.db.models.fields.XMLField will be removed. This was deprecated as part of the 1.3 release. An accelerated deprecation schedule has been used because the field hasn’t performed any role beyond that of a simple TextField since the removal of oldforms. All uses of XMLField can be replaced with TextField.

- The undocumented mixin parameter to the open() method of django.core.files.storage.Storage (and subclasses) will be removed.

1.3

See the Django 1.1 release notes for more details on these changes.

- AdminSite.root(). This method of hooking up the admin URLs will be removed in favor of including admin.site.urls.

- Authentication backends need to define the boolean attributes supports_object_permissions and supports_anonymous_user until version 1.4, at which point it will be assumed that all backends will support these options.

The Django source code repository

When deploying a Django application into a real production environment, you will almost always want to use an official packaged release of Django.

However, if you’d like to try out in-development code from an upcoming release or contribute to the development of Django, you’ll need to obtain a clone of Django’s source code repository.

This document covers the way the code repository is laid out and how to work with and find things in it.

High-level overview

The Django source code repository uses Git to track changes to the code over time, so you’ll need a copy of the Git client (a program called git) on your computer, and you’ll want to familiarize yourself with the basics of how Git works.

Git’s website offers downloads for various operating systems. The site also contains vast amounts of documentation.

The Django Git repository is located online at github.com/django/django. It contains the full source code for all Django releases, which you can browse online.

The Git repository includes several branches:

- master contains the main in-development code which will become the next packaged release of Django. This is where most development activity is focused.

- stable/A.B.x are the branches where release preparation work happens. They are also used for bugfix and security releases which occur as necessary after the initial release of a feature version.

- soc20XX/<project> branches were used by students who worked on Django during the 2009 and 2010 Google Summer of Code programs.

- attic/<project> branches were used to develop major or experimental new features without affecting the rest of Django’s code.

The Git repository also contains tags. These are the exact revisions from which packaged Django releases were produced, since version 1.0.

The source code for the Djangoproject.com website can be found at github.com/django/djangoproject.com.

The master branch

If you’d like to try out the in-development code for the next release of Django, or if you’d like to contribute to Django by fixing bugs or developing new features, you’ll want to get the code from the master branch.

Note that this will get all of Django: in addition to the top-level django module containing Python code, you’ll also get a copy of Django’s documentation, test suite, packaging scripts and other miscellaneous bits. Django’s code will be present in your clone as a directory named django.

To try out the in-development code with your own applications, simply place the directory containing your clone on your Python import path. Then import statements which look for Django will find the django module within your clone.

If you’re going to be working on Django’s code (say, to fix a bug or develop a new feature), you can probably stop reading here and move over to the documentation for contributing to Django, which covers things like the preferred coding style and how to generate and submit a patch.

Other branches

Django uses branches to prepare for releases of Django.

In the past when Django was hosted on Subversion, branches were also used for feature development. Now Django is hosted on Git and feature development is done on contributor’s forks, but the Subversion feature branches remain in Git for historical reference.

Stable branches

These branches can be found in the repository as stable/A.B.x branches and will be created right after the first alpha is tagged.

For example, immediately after Django 1.5 alpha 1 was tagged, the branch stable/1.5.x was created and all further work on preparing the code for the final 1.5 release was done there.

These branches also provide limited bugfix support for the most recent released version of Django and security support for the two most recently-released versions of Django.

For example, after the release of Django 1.5, the branch stable/1.5.x receives only fixes for security and critical stability bugs, which are eventually released as Django 1.5.1 and so on, stable/1.4.x receives only security fixes, and stable/1.3.x no longer receives any updates.

Historical information

This policy for handling stable/A.B.x branches was adopted starting with the Django 1.5 release cycle.

Previously, these branches weren’t created until right after the releases and the stabilization work occurred on the main repository branch. Thus, no new features development work for the next release of Django could be committed until the final release happened.

For example, shortly after the release of Django 1.3 the branch stable/1.3.x was created. Official support for that release has expired, and so it no longer receives direct maintenance from the Django project. However, that and all other similarly named branches continue to exist and interested community members have occasionally used them to provide unofficial support for old Django releases.

Feature-development branches

Historical information

Since Django moved to Git in 2012, anyone can clone the repository and create their own branches, alleviating the need for official branches in the source code repository.

The following section is mostly useful if you’re exploring the repository’s history, for example if you’re trying to understand how some features were designed.

Feature-development branches tend by their nature to be temporary. Some produce successful features which are merged back into Django’s master to become part of an official release, but others do not; in either case there comes a time when the branch is no longer being actively worked on by any developer. At this point the branch is considered closed.

Unfortunately, Django used to be maintained with the Subversion revision control system, that has no standard way of indicating this. As a workaround, branches of Django which are closed and no longer maintained were moved into attic.

For reference, the following are branches whose code eventually became part of Django itself, and so are no longer separately maintained:

- boulder-oracle-sprint: Added support for Oracle databases to Django’s object-relational mapper. This has been part of Django since the 1.0 release.

- gis: Added support for geographic/spatial queries to Django’s object-relational mapper. This has been part of Django since the 1.0 release, as the bundled application django.contrib.gis.

- i18n: Added internationalization support to Django. This has been part of Django since the 0.90 release.

- magic-removal: A major refactoring of both the internals and public APIs of Django’s object-relational mapper. This has been part of Django since the 0.95 release.

- multi-auth: A refactoring of Django’s bundled authentication framework which added support for authentication backends. This has been part of Django since the 0.95 release.

- new-admin: A refactoring of Django’s bundled administrative application. This became part of Django as of the 0.91 release, but was superseded by another refactoring (see next listing) prior to the Django 1.0 release.

- newforms-admin: The second refactoring of Django’s bundled administrative application. This became part of Django as of the 1.0 release, and is the basis of the current incarnation of django.contrib.admin.

- queryset-refactor: A refactoring of the internals of Django’s object-relational mapper. This became part of Django as of the 1.0 release.

- unicode: A refactoring of Django’s internals to consistently use Unicode-based strings in most places within Django and Django applications. This became part of Django as of the 1.0 release.

When Django moved from SVN to Git, the information about branch merges wasn’t preserved in the source code repository. This means that the master branch of Django doesn’t contain merge commits for the above branches.

However, this information is available as a grafts file. You can restore it by putting the following lines in .git/info/grafts in your local clone:

ac64e91a0cadc57f4bc5cd5d66955832320ca7a1 553a20075e6991e7a60baee51ea68c8adc520d9a 0cb8e31823b2e9f05c4ae868c19f5f38e78a5f2e
79e68c225b926302ebb29c808dda8afa49856f5c d0f57e7c7385a112cb9e19d314352fc5ed5b0747 aa239e3e5405933af6a29dac3cf587b59a099927
5cf8f684237ab5addaf3549b2347c3adf107c0a7 cb45fd0ae20597306cd1f877efc99d9bd7cbee98 e27211a0deae2f1d402537f0ebb64ad4ccf6a4da
f69cf70ed813a8cd7e1f963a14ae39103e8d5265 d5dbeaa9be359a4c794885c2e9f1b5a7e5e51fb8 d2fcbcf9d76d5bb8a661ee73dae976c74183098b
aab3a418ac9293bb4abd7670f65d930cb0426d58 4ea7a11659b8a0ab07b0d2e847975f7324664f10 adf4b9311d5d64a2bdd58da50271c121ea22e397
ff60c5f9de3e8690d1e86f3e9e3f7248a15397c8 7ef212af149540aa2da577a960d0d87029fd1514 45b4288bb66a3cda401b45901e85b645674c3988
9dda4abee1225db7a7b195b84c915fdd141a7260 4fe5c9b7ee09dc25921918a6dbb7605edb374bc9 3a7c14b583621272d4ef53061287b619ce3c290d
a19ed8aea395e8e07164ff7d85bd7dff2f24edca dc375fb0f3b7fbae740e8cfcd791b8bccb8a4e66 42ea7a5ce8aece67d16c6610a49560c1493d4653
9c52d56f6f8a9cdafb231adf9f4110473099c9b5 c91a30f00fd182faf8ca5c03cd7dbcf8b735b458 4a5c5c78f2ecd4ed8859cd5ac773ff3a01bccf96
953badbea5a04159adbfa970f5805c0232b6a401 4c958b15b250866b70ded7d82aa532f1e57f96ae 5664a678b29ab04cad425c15b2792f4519f43928
471596fc1afcb9c6258d317c619eaf5fd394e797 4e89105d64bb9e04c409139a41e9c7aac263df4c 3e9035a9625c8a8a5e88361133e87ce455c4fc13
9233d0426537615e06b78d28010d17d5a66adf44 6632739e94c6c38b4c5a86cf5c80c48ae50ac49f 18e151bc3f8a85f2766d64262902a9fcad44d937

Additionally, the following branches are closed, but their code was never merged into Django and the features they aimed to implement were never finished:

- full-history

- generic-auth

- multiple-db-support

- per-object-permissions

- schema-evolution

- schema-evolution-ng

- search-api

- sqlalchemy

All of the above-mentioned branches now reside in attic.

Finally, the repository contains soc2009/xxx and soc2010/xxx feature branches, used for Google Summer of Code projects.

Tags

Each Django release is tagged and signed by a releaser.

The tags can be found on GitHub’s tags page.

How is Django Formed?

This document explains how to release Django.

Please, keep these instructions up-to-date if you make changes! The point here is to be descriptive, not prescriptive, so feel free to streamline or otherwise make changes, but update this document accordingly!

Overview

There are three types of releases that you might need to make:

- Security releases: disclosing and fixing a vulnerability. This’ll generally involve two or three simultaneous releases – e.g. 1.5.x, 1.6.x, and, depending on timing, perhaps a 1.7 alpha/beta/rc.

- Regular version releases: either a final release (e.g. 1.5) or a bugfix update (e.g. 1.5.1).

- Pre-releases: e.g. 1.6 alpha, beta, or rc.

The short version of the steps involved is:

1. If this is a security release, pre-notify the security distribution list one week before the actual release.

2. Proofread the release notes, looking for organization and writing errors. Draft a blog post and email announcement.

3. Update version numbers and create the release package(s).

4. Upload the package(s) to the djangoproject.com server.

5. Upload the new version(s) to PyPI.

6. Declare the new version in the admin on djangoproject.com.

7. Post the blog entry and send out the email announcements.

8. Update version numbers post-release.

There are a lot of details, so please read on.

Prerequisites

You’ll need a few things before getting started:

- A GPG key. If the key you want to use is not your default signing key, you’ll need to add -u you@example.com to every GPG signing command below, where you@example.com is the email address associated with the key you want to use.

- An install of some required Python packages:

$ pip install wheel twine

- Access to Django’s record on PyPI. Create a file with your credentials:

~/.pypirc

[pypi]
username:YourUsername
password:YourPassword

- Access to the djangoproject.com server to upload files.

- Access to the admin on djangoproject.com as a “Site maintainer”.

- Access to post to django-announce.

- If this is a security release, access to the pre-notification distribution list.

If this is your first release, you’ll need to coordinate with James and/or Jacob to get all these things lined up.

Pre-release tasks

A few items need to be taken care of before even beginning the release process. This stuff starts about a week before the release; most of it can be done any time leading up to the actual release:

1. If this is a security release, send out pre-notification one week before the release. We maintain a list of who gets these pre-notification emails in the private django-core repository. Send the mail to security@djangoproject.com and BCC the pre-notification recipients. This email should be signed by the key you’ll use for the release, and should include patches for each issue being fixed.

2. As the release approaches, watch Trac to make sure no release blockers are left for the upcoming release.

3. Check with the other committers to make sure they don’t have any uncommitted changes for the release.

4. Proofread the release notes, including looking at the online version to catch any broken links or reST errors, and make sure the release notes contain the correct date.

5. Double-check that the release notes mention deprecation timelines for any APIs noted as deprecated, and that they mention any changes in Python version support.

6. Double-check that the release notes index has a link to the notes for the new release; this will be in docs/releases/index.txt.

7. If this is a feature release, ensure translations from Transifex have been integrated. This is typically done by a separate translation’s manager rather than the releaser, but here are the steps. Provided you have an account on Transifex:

$ python scripts/manage_translations.py fetch

and then commit the changed/added files (both .po and .mo). Sometimes there are validation errors which need to be debugged, so avoid doing this task immediately before a release is needed.

8. Update the django-admin manual page:

$ cd docs
$ make man
$ man _build/man/django-admin.1  # do a quick sanity check
$ cp _build/man/django-admin.1 man/django-admin.1

and then commit the changed man page.

Preparing for release

Write the announcement blog post for the release. You can enter it into the admin at any time and mark it as inactive. Here are a few examples: example security release announcement, example regular release announcement, example pre-release announcement.

Actually rolling the release

OK, this is the fun part, where we actually push out a release!

1. Check Jenkins is green for the version(s) you’re putting out. You probably shouldn’t issue a release until it’s green.

2. A release always begins from a release branch, so you should make sure you’re on a stable branch and up-to-date. For example:

$ git checkout stable/1.5.x
$ git pull

3. If this is a security release, merge the appropriate patches from django-private. Rebase these patches as necessary to make each one a simple commit on the release branch rather than a merge commit. To ensure this, merge them with the --ff-only flag; for example:

$ git checkout stable/1.5.x
$ git merge --ff-only security/1.5.x

(This assumes security/1.5.x is a branch in the django-private repo containing the necessary security patches for the next release in the 1.5 series.)

If git refuses to merge with --ff-only, switch to the security-patch branch and rebase it on the branch you are about to merge it into (git checkout security/1.5.x; git rebase stable/1.5.x) and then switch back and do the merge. Make sure the commit message for each security fix explains that the commit is a security fix and that an announcement will follow (example security commit).

4. For a feature release, remove the UNDER DEVELOPMENT header at the top of the release notes and add the release date on the next line. For a patch release, replace *Under Development* with the release date. Make this change on all branches where the release notes for a particular version are located.

5. Update the version number in django/__init__.py for the release. Please see notes on setting the VERSION tuple below for details on VERSION.

In 1.4, the version number in docs/conf.py and setup.py should also be updated. Here’s an example commit updating version numbers for that.

6. If this is a pre-release package, update the “Development Status” trove classifier in setup.py to reflect this. Otherwise, make sure the classifier is set to Development Status :: 5 - Production/Stable.

7. Tag the release using git tag. For example:

$ git tag --sign --message="Tag 1.5.1" 1.5.1

You can check your work by running git tag --verify <tag>.

8. Push your work, including the tag: git push --tags.

9. Make sure you have an absolutely clean tree by running git clean -dfx.

10. Run make -f extras/Makefile to generate the release packages. This will create the release packages in a dist/ directory. Note that we don’t publish wheel files for 1.4.

11. Generate the hashes of the release packages:

$ cd dist
$ md5sum *
$ sha1sum *
$ sha256sum *

12. Create a “checksums” file, Django-<<VERSION>>.checksum.txt containing the hashes and release information. Start with this template and insert the correct version, date, GPG key ID (from gpg --list-keys --keyid-format LONG), release URL, and checksums:

This file contains MD5, SHA1, and SHA256 checksums for the source-code
tarball of Django <<VERSION>>, released <<DATE>>.

To use this file, you will need a working install of PGP or other
compatible public-key encryption software. You will also need to have
the Django release manager's public key in your keyring; this key has
the ID ``XXXXXXXXXXXXXXXX`` and can be imported from the MIT
keyserver. For example, if using the open-source GNU Privacy Guard
implementation of PGP:

gpg --keyserver pgp.mit.edu --recv-key XXXXXXXXXXXXXXXX

Once the key is imported, verify this file::

gpg --verify <<THIS FILENAME>>

Once you have verified this file, you can use normal MD5, SHA1, or SHA256
checksumming applications to generate the checksums of the Django
package and compare them to the checksums listed below.

Release packages:
=================

Django <<VERSION>> (tar.tgz): https://www.djangoproject.com/m/releases/<<RELEASE TAR.GZ FILENAME>>
Django <<VERSION>> (.whl): https://www.djangoproject.com/m/releases/<<RELEASE WHL FILENAME>>

MD5 checksums:
==============

<<MD5SUM>>  <<RELEASE TAR.GZ FILENAME>>
<<MD5SUM>>  <<RELEASE WHL FILENAME>>

SHA1 checksums:
===============

<<SHA1SUM>>  <<RELEASE TAR.GZ FILENAME>>
<<SHA1SUM>>  <<RELEASE WHL FILENAME>>

SHA256 checksums:
=================

<<SHA256SUM>>  <<RELEASE TAR.GZ FILENAME>>
<<SHA256SUM>>  <<RELEASE WHL FILENAME>>

13. Sign the checksum file (gpg --clearsign --digest-algo SHA256 Django-<version>.checksum.txt). This generates a signed document, Django-<version>.checksum.txt.asc which you can then verify using gpg --verify Django-<version>.checksum.txt.asc.

If you’re issuing multiple releases, repeat these steps for each release.

Making the release(s) available to the public

Now you’re ready to actually put the release out there. To do this:

1. Upload the release package(s) to the djangoproject server, replacing A.B. with the appropriate version number, e.g. 1.5 for a 1.5.x release:

$ scp Django-* djangoproject.com:/home/www/www/media/releases/A.B

2. Upload the checksum file(s):

$ scp Django-A.B.C.checksum.txt.asc djangoproject.com:/home/www/www/media/pgp/Django-A.B.C.checksum.txt

3. Test that the release packages install correctly using easy_install and pip. Here’s one method (which requires virtualenvwrapper):

$ RELEASE_VERSION='1.7.2'
$ MAJOR_VERSION=`echo $RELEASE_VERSION| cut -c 1-3`

$ mktmpenv
$ easy_install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION.tar.gz
$ deactivate
$ mktmpenv
$ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION.tar.gz
$ deactivate
$ mktmpenv
$ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION-py2.py3-none-any.whl
$ deactivate

This just tests that the tarballs are available (i.e. redirects are up) and that they install correctly, but it’ll catch silly mistakes.

4. Ask a few people on IRC to verify the checksums by visiting the checksums file (e.g. https://www.djangoproject.com/m/pgp/Django-1.5b1.checksum.txt) and following the instructions in it. For bonus points, they can also unpack the downloaded release tarball and verify that its contents appear to be correct (proper version numbers, no stray .pyc or other undesirable files).

5. Upload the release packages to PyPI (for pre-releases, only upload the wheel file):

$ twine upload -s dist/*

6. Go to the Add release page in the admin, enter the new release number exactly as it appears in the name of the tarball (Django-<version>.tar.gz). So for example enter “1.5.1” or “1.4c2”, etc. If the release is part of an LTS branch, mark it so.

7. Make the blog post announcing the release live.

8. For a new version release (e.g. 1.5, 1.6), update the default stable version of the docs by flipping the is_default flag to True on the appropriate DocumentRelease object in the docs.djangoproject.com database (this will automatically flip it to False for all others); you can do this using the site’s admin.

9. Post the release announcement to the django-announce, django-developers, and django-users mailing lists. This should include a link to the announcement blog post. If this is a security release, also include oss-security@lists.openwall.com.

Post-release

You’re almost done! All that’s left to do now is:

1. Update the VERSION tuple in django/__init__.py again, incrementing to whatever the next expected release will be. For example, after releasing 1.5.1, update VERSION to VERSION = (1, 5, 2, 'alpha', 0).

2. Add the release in Trac’s versions list if necessary (and make it the default if it’s a final release). Not all versions are declared; take example on previous releases.

3. If this was a security release, update Archive of security issues with details of the issues addressed.

New stable branch tasks

There are several items to do in the time following the creation of a new stable branch (often following an alpha release). Some of these tasks don’t need to be done by the releaser.

1. Create a new DocumentRelease object in the docs.djangoproject.com database for the new version’s docs, and update the docs/fixtures/doc_releases.json JSON fixture, so people without access to the production DB can still run an up-to-date copy of the docs site.

2. Create a stub release note for the new feature version. Use the stub from the previous feature release version or copy the contents from the previous feature version and delete most of the contents leaving only the headings.

3. Increase the default PBKDF2 iterations in django.contrib.auth.hashers.PBKDF2PasswordHasher by about 20% (pick a round number). Run the tests, and update the 3 failing hasher tests with the new values. Make sure this gets noted in the release notes (see the 1.8 release notes for an example).

4. Remove features that have reached the end of their deprecation cycle. Each removal should be done in a separate commit for clarity. In the commit message, add a “refs #XXXX” to the original ticket where the deprecation began if possible.

5. Remove .. versionadded::, .. versionadded::, and .. deprecated:: annotations in the documentation from two releases ago. For example, in Django 1.9, notes for 1.7 will be removed.

6. Add the new branch to Read the Docs. Since the automatically generated version names (“stable-A.B.x”) differ from the version numbers we’ve used historically in Read the Docs (“A.B.x”), we currently ask Eric Holscher to add the version for us. Someday the alias functionality may be built-in to the Read the Docs UI.

Notes on setting the VERSION tuple

Django’s version reporting is controlled by the VERSION tuple in django/__init__.py. This is a five-element tuple, whose elements are:

1. Major version.

2. Minor version.

3. Micro version.

4. Status – can be one of “alpha”, “beta”, “rc” or “final”.

5. Series number, for alpha/beta/RC packages which run in sequence (allowing, for example, “beta 1”, “beta 2”, etc.).

For a final release, the status is always “final” and the series number is always 0. A series number of 0 with an “alpha” status will be reported as “pre-alpha”.

Some examples:

- (1, 2, 1, 'final', 0) → “1.2.1”

- (1, 3, 0, 'alpha', 0) → “1.3 pre-alpha”

- (1, 3, 0, 'beta', 2) → “1.3 beta 2”

Python Module Index

a | c | d | f | h | m | s | t | u | v

a

django.apps

c

django.conf

django.conf.urls

django.conf.urls.i18n

django.contrib

django.contrib.admin

Django's admin site.

django.contrib.admindocs

Django's admin documentation generator.

django.contrib.auth

Django's authentication framework.

django.contrib.auth.backends

Django's built-in authentication backend classes.

django.contrib.auth.forms

django.contrib.auth.hashers

django.contrib.auth.middleware

Authentication middleware.

django.contrib.auth.password_validation

django.contrib.auth.signals

django.contrib.auth.views

django.contrib.contenttypes

Provides generic interface to installed models.

django.contrib.contenttypes.admin

django.contrib.contenttypes.fields

django.contrib.contenttypes.forms

django.contrib.flatpages

A framework for managing simple ?flat? HTML content in a database.

django.contrib.gis

Geographic Information System (GIS) extensions for Django

django.contrib.gis.admin

GeoDjango's extensions to the admin site.

django.contrib.gis.db.backends

GeoDjango's spatial database backends.

django.contrib.gis.db.models

GeoDjango model and field API.

django.contrib.gis.db.models.functions

Geographic Database Functions

django.contrib.gis.feeds

GeoDjango's framework for generating spatial feeds.

django.contrib.gis.forms

GeoDjango forms API.

django.contrib.gis.gdal

GeoDjango's high-level interface to the GDAL library.

django.contrib.gis.geoip

High-level Python interface for MaxMind's GeoIP C library.

django.contrib.gis.geoip2

Python interface for MaxMind's GeoIP2 databases.

django.contrib.gis.geos

GeoDjango's high-level interface to the GEOS library.

django.contrib.gis.measure

GeoDjango's distance and area measurement objects.

django.contrib.gis.serializers.geojson

Serialization of GeoDjango models in the GeoJSON format.

django.contrib.gis.utils

GeoDjango's collection of utilities.

django.contrib.gis.utils.layermapping

Spatial data import utility for GeoDjango models.

django.contrib.gis.utils.ogrinspect

Utilities for inspecting OGR data sources.

django.contrib.gis.widgets

GeoDjango widgets API.

django.contrib.humanize

A set of Django template filters useful for adding a "human touch" to data.

django.contrib.messages

Provides cookie- and session-based temporary message storage.

django.contrib.messages.middleware

Message middleware.

django.contrib.postgres

PostgreSQL-specific fields and features

django.contrib.postgres.aggregates

PostgreSQL specific aggregation functions

django.contrib.postgres.validators

django.contrib.redirects

A framework for managing redirects.

django.contrib.sessions

Provides session management for Django projects.

django.contrib.sessions.middleware

Session middleware.

django.contrib.sitemaps

A framework for generating Google sitemap XML files.

django.contrib.sites

Lets you operate multiple websites from the same database and Django project

django.contrib.sites.middleware

Site middleware.

django.contrib.staticfiles

An app for handling static files.

django.contrib.syndication

A framework for generating syndication feeds, in RSS and Atom, quite easily.

django.contrib.webdesign

Helpers and utilities targeted primarily at Web *designers* rather than Web *developers*.

django.core

django.core.checks

django.core.exceptions

Django core exceptions

django.core.files

File handling and storage

django.core.files.storage

django.core.files.uploadedfile

Classes representing uploaded files.

django.core.files.uploadhandler

Django's handlers for file uploads.

django.core.mail

Helpers to easily send email.

django.core.management

django.core.paginator

Classes to help you easily manage paginated data.

django.core.signals

Core signals sent by the request/response system.

django.core.signing

Django's signing framework.

django.core.urlresolvers

django.core.validators

Validation utilities and base classes

d

django.db

django.db.backends

Core signals sent by the database wrapper.

django.db.backends.base.schema

django.db.migrations

Schema migration support for Django models

django.db.migrations.operations

django.db.models

django.db.models.fields

Built-in field types.

django.db.models.fields.related

Related field types

django.db.models.functions

Database Functions

django.db.models.lookups

Lookups API

django.db.models.options

Model meta-class layer

django.db.models.signals

Signals sent by the model system.

django.db.transaction

django.dispatch

Signal dispatch

f

django.forms

django.forms.fields

Django's built-in form fields.

django.forms.formsets

An abstraction for working with multiple forms on the same page.

django.forms.models

ModelForm and ModelFormset.

django.forms.widgets

Django's built-in form widgets.

h

django.http

Classes dealing with HTTP requests and responses.

m

django.middleware

Django's built-in middleware classes.

django.middleware.cache

Middleware for the site-wide cache.

django.middleware.clickjacking

Clickjacking protection

django.middleware.common

Middleware adding "common" conveniences for perfectionists.

django.middleware.csrf

Middleware adding protection against Cross Site Request Forgeries.

django.middleware.gzip

Middleware to serve GZipped content for performance.

django.middleware.http

Middleware handling advanced HTTP features.

django.middleware.locale

Middleware to enable language selection based on the request.

django.middleware.security

Security middleware.

s

django.shortcuts

Convenience shortcuts that span multiple levels of Django's MVC stack.

t

django.template

Django's template system

django.template.backends

django.template.backends.django

django.template.backends.jinja2

django.template.loader

django.template.response

Classes dealing with lazy-rendered HTTP responses.

django.test

Testing tools for Django applications.

django.test.signals

Signals sent during testing.

django.test.utils

Helpers to write custom test runners.

u

django.utils

Django's built-in utilities.

django.utils.cache

Helper functions for controlling caching.

django.utils.dateparse

Functions to parse datetime objects.

django.utils.decorators

Functions that help with creating decorators for views.

django.utils.encoding

A series of helper functions to manage character encoding.

django.utils.feedgenerator

Syndication feed generation library -- used for generating RSS, etc.

django.utils.functional

Functional programming tools.

django.utils.html

HTML helper functions

django.utils.http

HTTP helper functions. (URL encoding, cookie handling, ...)

django.utils.log

Logging tools for Django applications

django.utils.module_loading

Functions for working with Python modules.

django.utils.safestring

Functions and classes for working with strings that can be displayed safely without further escaping in HTML.

django.utils.six

django.utils.text

Text manipulation.

django.utils.timezone

Timezone support.

django.utils.translation

v

django.views

Django's built-in views.

django.views.decorators.cache

django.views.decorators.csrf

django.views.decorators.gzip

django.views.decorators.http

django.views.decorators.vary

django.views.generic.dates

django.views.i18n

Index

Symbols | _ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z

Symbols

--addrport ADDRPORT

testserver command line option

--admins

sendtestemail command line option

--all

diffsettings command line option

--all, -a

dumpdata command line option

makemessages command line option

--app APP_LABEL

loaddata command line option

--backwards

sqlmigrate command line option

--blank BLANK

ogrinspect command line option

--clear, -c

collectstatic command line option

--database DATABASE

changepassword command line option

createcachetable command line option

createsuperuser command line option

dbshell command line option

dumpdata command line option

flush command line option

inspectdb command line option

loaddata command line option

migrate command line option

showmigrations command line option

sqlflush command line option

sqlmigrate command line option

sqlsequencereset command line option

--debug-sql, -d

test command line option

--decimal DECIMAL

ogrinspect command line option

--deploy

check command line option

--domain DOMAIN, -d DOMAIN

makemessages command line option

--dry-run

createcachetable command line option

makemigrations command line option

--dry-run, -n

collectstatic command line option

--email EMAIL

createsuperuser command line option

--empty

makemigrations command line option

--exclude EXCLUDE, -e EXCLUDE

dumpdata command line option

--exclude EXCLUDE, -x EXCLUDE

compilemessages command line option

makemessages command line option

--exit, -e

makemigrations command line option

--extension EXTENSIONS, -e EXTENSIONS

makemessages command line option

startapp command line option

startproject command line option

--failfast

test command line option

--fake

migrate command line option

--fake-initial

migrate command line option

--format FORMAT

dumpdata command line option

--geom-name GEOM_NAME

ogrinspect command line option

--ignore PATTERN, -i PATTERN

collectstatic command line option

makemessages command line option

--ignorenonexistent, -i

loaddata command line option

--indent INDENT

dumpdata command line option

--insecure

runserver command line option

--interface {ipython,bpython}, -i {ipython,bpython}

shell command line option

--ipv6, -6

runserver command line option

--keep-pot

makemessages command line option

--keepdb, -k

test command line option

--layer LAYER_KEY

ogrinspect command line option

--link, -l

collectstatic command line option

--list, -l

migrate command line option

showmigrations command line option

--list-tags

check command line option

--liveserver LIVESERVER

test command line option

--locale LOCALE, -l LOCALE

compilemessages command line option

makemessages command line option

--managers

sendtestemail command line option

--mapping

ogrinspect command line option

--merge

makemigrations command line option

--multi-geom

ogrinspect command line option

--name FILES, -n FILES

startapp command line option

startproject command line option

--name NAME, -n NAME

makemigrations command line option

--name-field NAME_FIELD

ogrinspect command line option

--natural-foreign

dumpdata command line option

--natural-primary

dumpdata command line option

--no-color

command line option

--no-default-ignore

collectstatic command line option

makemessages command line option

--no-imports

ogrinspect command line option

--no-location

makemessages command line option

--no-optimize

squashmigrations command line option

--no-post-process

collectstatic command line option

--no-wrap

makemessages command line option

--noinput, --no-input

collectstatic command line option

flush command line option

makemigrations command line option

migrate command line option

squashmigrations command line option

test command line option

testserver command line option

--noreload

runserver command line option

--nostartup

shell command line option

--nostatic

runserver command line option

--nothreading

runserver command line option

--null NULL

ogrinspect command line option

--output OUTPUT, -o OUTPUT

dumpdata command line option

--parallel [N]

test command line option

--pks PRIMARY_KEYS

dumpdata command line option

--plain

shell command line option

--plan, -p

showmigrations command line option

--pythonpath PYTHONPATH

command line option

--reverse, -r

test command line option

--run-syncdb

migrate command line option

--settings SETTINGS

command line option

--srid SRID

ogrinspect command line option

--symlinks, -s

makemessages command line option

--tag TAGS, -t TAGS

check command line option

--template TEMPLATE

startapp command line option

startproject command line option

--testrunner TESTRUNNER

test command line option

--traceback

command line option

--use-fuzzy, -f

compilemessages command line option

--username USERNAME

createsuperuser command line option

--verbosity {0,1,2,3}, --v {0,1,2,3}

command line option

_

__contains__() (backends.base.SessionBase method)

(QueryDict method)

__delitem__() (backends.base.SessionBase method)

(HttpResponse method)

__eq__() (Model method)

__getattr__() (Area method)

(Distance method)

__getitem__() (backends.base.SessionBase method)

(HttpResponse method)

(OGRGeometry method)

(QueryDict method)

(SpatialReference method)

__hash__() (Model method)

__init__() (HttpResponse method)

(QueryDict method)

(SimpleTemplateResponse method)

(SyndicationFeed method)

(TemplateResponse method)

(requests.RequestSite method)

__iter__() (File method)

(HttpRequest method)

(OGRGeometry method)

__len__() (OGRGeometry method)

__setitem__() (backends.base.SessionBase method)

(HttpResponse method)

(QueryDict method)

__str__() (Model method)

_open() (in module django.core.files.storage)

_save() (in module django.core.files.storage)

A

A (class in django.contrib.gis.measure)

ABSOLUTE_URL_OVERRIDES

setting

abstract (Options attribute)

accessed_time() (Storage method)

AccessMixin (class in django.contrib.auth.mixins)

action_flag (LogEntry attribute)

action_time (LogEntry attribute)

actions (ModelAdmin attribute)

actions_on_bottom (ModelAdmin attribute)

actions_on_top (ModelAdmin attribute)

actions_selection_counter (ModelAdmin attribute)

activate() (in module django.utils.timezone)

(in module django.utils.translation)

add

template filter

add() (GeometryCollection method)

(RelatedManager method)

add_action() (AdminSite method)

add_arguments() (BaseCommand method)

(django.test.runner.DiscoverRunner class method)

add_error() (Form method)

add_field() (BaseDatabaseSchemaEditor method)

add_form_template (ModelAdmin attribute)

add_item() (SyndicationFeed method)

add_item_elements() (SyndicationFeed method)

add_message() (in module django.contrib.messages)

add_never_cache_headers() (in module django.utils.cache)

add_post_render_callback() (SimpleTemplateResponse method)

add_root_elements() (SyndicationFeed method)

add_view() (ModelAdmin method)

AddField (class in django.db.migrations.operations)

addslashes

template filter

AdminEmailHandler (class in django.utils.log)

AdminPasswordChangeForm (class in django.contrib.auth.forms)

ADMINS

setting

AdminSite (class in django.contrib.admin)

Aggregate (class in django.db.models)

aggregate() (in module django.db.models.query.QuerySet)

all() (in module django.db.models.query.QuerySet)

allow_database_queries (SimpleTestCase attribute)

allow_empty (BaseDateListView attribute)

(django.views.generic.list.MultipleObjectMixin attribute)

allow_files (FilePathField attribute), [1]

allow_folders (FilePathField attribute), [1]

allow_future (DateMixin attribute)

allow_lazy() (in module django.utils.functional)

allow_migrate()

allow_relation()

allow_unicode (SlugField attribute), [1]

ALLOWED_HOSTS

setting

ALLOWED_INCLUDE_ROOTS

setting

alter_db_table() (BaseDatabaseSchemaEditor method)

alter_db_tablespace() (BaseDatabaseSchemaEditor method)

alter_field() (BaseDatabaseSchemaEditor method)

alter_index_together() (BaseDatabaseSchemaEditor method)

alter_unique_together() (BaseDatabaseSchemaEditor method)

AlterField (class in django.db.migrations.operations)

AlterIndexTogether (class in django.db.migrations.operations)

AlterModelManagers (class in django.db.migrations.operations)

AlterModelOptions (class in django.db.migrations.operations)

AlterModelTable (class in django.db.migrations.operations)

AlterOrderWithRespectTo (class in django.db.migrations.operations)

AlterUniqueTogether (class in django.db.migrations.operations)

angular_name (SpatialReference attribute)

angular_units (SpatialReference attribute)

annotate() (in module django.db.models.query.QuerySet)

apnumber

template filter

app_directories.Loader (class in django.template.loaders)

app_index_template (AdminSite attribute)

app_label (ContentType attribute)

(Options attribute)

app_name (ResolverMatch attribute)

app_names (ResolverMatch attribute)

AppCommand (class in django.core.management)

AppConfig (class in django.apps)

APPEND_SLASH

setting

appendlist() (QueryDict method)

application namespace

apps (in module django.apps)

apps.AdminConfig (class in django.contrib.admin)

apps.SimpleAdminConfig (class in django.contrib.admin)

ArchiveIndexView (built-in class)

(class in django.views.generic.dates)

Area (class in django.contrib.gis.db.models.functions)

(class in django.contrib.gis.measure)

area (GEOSGeometry attribute)

(OGRGeometry attribute)

area() (GeoQuerySet method)

arg_joiner (Func attribute)

args (BaseCommand attribute)

(ResolverMatch attribute)

ArrayAgg (class in django.contrib.postgres.aggregates)

ArrayField (class in django.contrib.postgres.fields)

arrayfield.contained_by

field lookup type

arrayfield.contains

field lookup type

arrayfield.index

field lookup type

arrayfield.len

field lookup type

arrayfield.overlap

field lookup type

arrayfield.slice

field lookup type

as_data() (Form.errors method)

as_datetime() (Field method)

as_double() (Field method)

as_hidden() (BoundField method)

as_int() (Field method)

as_json() (Form.errors method)

as_manager() (in module django.db.models.query.QuerySet)

as_p() (Form method)

as_sql() (in module django.db.models)

as_string() (Field method)

as_table() (Form method)

as_ul() (Form method)

as_vendorname() (in module django.db.models)

as_view() (django.views.generic.base.View class method)

as_widget() (BoundField method)

asc() (Expression method)

AsGeoJSON (class in django.contrib.gis.db.models.functions)

AsGML (class in django.contrib.gis.db.models.functions)

AsKML (class in django.contrib.gis.db.models.functions)

assertContains() (SimpleTestCase method)

assertFieldOutput() (SimpleTestCase method)

assertFormError() (SimpleTestCase method)

assertFormsetError() (SimpleTestCase method)

assertHTMLEqual() (SimpleTestCase method)

assertHTMLNotEqual() (SimpleTestCase method)

assertInHTML() (SimpleTestCase method)

assertJSONEqual() (SimpleTestCase method)

assertJSONNotEqual() (SimpleTestCase method)

assertNotContains() (SimpleTestCase method)

assertNumQueries() (TransactionTestCase method)

assertQuerysetEqual() (TransactionTestCase method)

assertRaisesMessage() (SimpleTestCase method)

assertRedirects() (SimpleTestCase method)

assertTemplateNotUsed() (SimpleTestCase method)

assertTemplateUsed() (SimpleTestCase method)

assertXMLEqual() (SimpleTestCase method)

assertXMLNotEqual() (SimpleTestCase method)

assignment_tag() (django.template.Library method)

AsSVG (class in django.contrib.gis.db.models.functions)

Atom1Feed (class in django.utils.feedgenerator)

atomic() (in module django.db.transaction)

attr_value() (SpatialReference method)

attrs (Widget attribute)

auth() (in module django.contrib.auth.context_processors)

auth_code() (SpatialReference method)

auth_name() (SpatialReference method)

AUTH_PASSWORD_VALIDATORS

setting

AUTH_USER_MODEL

setting

authenticate() (in module django.contrib.auth)

(ModelBackend method)

(RemoteUserBackend method)

AUTHENTICATION_BACKENDS

setting

AuthenticationForm (class in django.contrib.auth.forms)

AuthenticationMiddleware (class in django.contrib.auth.middleware)

auto_created (Field attribute)

auto_id (BoundField attribute)

(Form attribute)

auto_now (DateField attribute)

auto_now_add (DateField attribute)

autodiscover() (in module django.contrib.admin)

autoescape

template tag

AutoField (class in django.db.models)

available_apps (TransactionTestCase attribute)

Avg (class in django.db.models)

B

backends.base.SessionBase (class in django.contrib.sessions)

backends.cached_db.SessionStore (class in django.contrib.sessions)

backends.db.SessionStore (class in django.contrib.sessions)

backends.smtp.EmailBackend (class in django.core.mail)

bands (GDALRaster attribute)

base36_to_int() (in module django.utils.http)

base_field (ArrayField attribute)

(RangeField attribute)

(SimpleArrayField attribute)

(SplitArrayField attribute)

(django.contrib.postgres.forms.BaseRangeField attribute)

base_session.AbstractBaseSession (class in django.contrib.sessions)

base_session.BaseSessionManager (class in django.contrib.sessions)

base_url (FileSystemStorage attribute)

base_widget (RangeWidget attribute)

BaseArchiveIndexView (class in django.views.generic.dates)

BaseCommand (class in django.core.management)

BaseDatabaseSchemaEditor (class in django.db.backends.base.schema)

BaseDateDetailView (class in django.views.generic.dates)

BaseDateListView (class in django.views.generic.dates)

BaseDayArchiveView (class in django.views.generic.dates)

BaseFormSet (class in django.forms.formsets)

BaseGenericInlineFormSet (class in django.contrib.contenttypes.forms)

BaseGeometryWidget (class in django.contrib.gis.widgets)

BaseMonthArchiveView (class in django.views.generic.dates)

BaseTodayArchiveView (class in django.views.generic.dates)

BaseWeekArchiveView (class in django.views.generic.dates)

BaseYearArchiveView (class in django.views.generic.dates)

bbcontains

field lookup type

bboverlaps

field lookup type

BigIntegerField (class in django.db.models)

BigIntegerRangeField (class in django.contrib.postgres.fields)

bilateral (Transform attribute)

BinaryField (class in django.db.models)

BitAnd (class in django.contrib.postgres.aggregates)

BitOr (class in django.contrib.postgres.aggregates)

blank (Field attribute)

block

template tag

blocktrans

template tag

body (HttpRequest attribute)

BoolAnd (class in django.contrib.postgres.aggregates)

BooleanField (class in django.db.models)

(class in django.forms)

BoolOr (class in django.contrib.postgres.aggregates)

boundary (GEOSGeometry attribute)

boundary() (OGRGeometry method)

BoundField (class in django.forms)

BoundingCircle (class in django.contrib.gis.db.models.functions)

BrokenLinkEmailsMiddleware (class in django.middleware.common)

buffer() (GEOSGeometry method)

build_absolute_uri() (HttpRequest method)

build_suite() (DiscoverRunner method)

bulk_create() (in module django.db.models.query.QuerySet)

byteorder (WKBWriter attribute)

C

cache

template tag

cache_key_prefix (backends.cached_db.SessionStore attribute)

CACHE_MIDDLEWARE_ALIAS

setting

CACHE_MIDDLEWARE_KEY_PREFIX

setting

CACHE_MIDDLEWARE_SECONDS

setting

cached.Loader (class in django.template.loaders)

cached_property (class in django.utils.functional)

CACHES

setting

CACHES-BACKEND

setting

CACHES-KEY_FUNCTION

setting

CACHES-KEY_PREFIX

setting

CACHES-LOCATION

setting

CACHES-OPTIONS

setting

CACHES-TIMEOUT

setting

CACHES-VERSION

setting

CallbackFilter (class in django.utils.log)

can_delete (BaseFormSet attribute)

(InlineModelAdmin attribute)

can_import_settings (BaseCommand attribute)

can_order (BaseFormSet attribute)

capfirst

template filter

CASCADE (in module django.db.models)

cascaded_union (MultiPolygon attribute)

Case (class in django.db.models.expressions)

center

template filter

Centroid (class in django.contrib.gis.db.models.functions)

centroid (GEOSGeometry attribute)

(Polygon attribute)

centroid() (GeoQuerySet method)

change_form_template (ModelAdmin attribute)

change_list_template (ModelAdmin attribute)

change_message (LogEntry attribute)

change_view() (ModelAdmin method)

changed_data (Form attribute)

changed_objects (models.BaseModelFormSet attribute)

changefreq (Sitemap attribute)

changelist_view() (ModelAdmin method)

changepassword

django-admin command

changepassword command line option

--database DATABASE

CharField (class in django.db.models)

(class in django.forms)

charset (HttpResponse attribute)

(UploadedFile attribute)

check

django-admin command

check command line option

--deploy

--list-tags

--tag TAGS, -t TAGS

check() (BaseCommand method)

check_for_language() (in module django.utils.translation)

check_password() (in module django.contrib.auth.hashers)

(models.AbstractBaseUser method)

(models.User method)

check_test (CheckboxInput attribute)

CheckboxInput (class in django.forms)

CheckboxSelectMultiple (class in django.forms)

CheckMessage (class in django.core.checks)

ChoiceField (class in django.forms)

choices (ChoiceField attribute)

(Field attribute)

(MultipleHiddenInput attribute)

(Select attribute)

chunk_size (FileUploadHandler attribute)

chunks() (File method)

(UploadedFile method)

city() (GeoIP method)

(GeoIP2 method)

city_info (GeoIP attribute)

clean() (Field method)

(Form method)

(Model method)

clean_fields() (Model method)

clean_savepoints() (in module django.db.transaction)

clean_username() (RemoteUserBackend method)

cleaned_data (Form attribute)

clear() (backends.base.SessionBase method)

(RelatedManager method)

clear_cache() (ContentTypeManager method)

clear_expired() (backends.base.SessionBase method)

ClearableFileInput (class in django.forms)

clearsessions

django-admin command

Client (class in django.test)

client (Response attribute)

(SimpleTestCase attribute)

client.RedirectCycleError

client_class (SimpleTestCase attribute)

clone() (GEOSGeometry method)

(OGRGeometry method)

(SpatialReference method)

close() (FieldFile method)

(File method)

close_rings() (OGRGeometry method)

closed (HttpResponse attribute)

Coalesce (class in django.db.models.functions)

code (EmailValidator attribute)

(RegexValidator attribute)

codename (models.Permission attribute)

coerce (TypedChoiceField attribute)

Collect (class in django.contrib.gis.db.models)

collect() (GeoQuerySet method)

collectstatic

django-admin command

collectstatic command line option

--clear, -c

--dry-run, -n

--ignore PATTERN, -i PATTERN

--link, -l

--no-default-ignore

--no-post-process

--noinput, --no-input

ComboField (class in django.forms)

command line option

--no-color

--pythonpath PYTHONPATH

--settings SETTINGS

--traceback

--verbosity {0,1,2,3}, --v {0,1,2,3}

CommandError

CommaSeparatedIntegerField (class in django.db.models)

comment

template tag

commit() (in module django.db.transaction)

CommonMiddleware (class in django.middleware.common)

CommonPasswordValidator (class in django.contrib.auth.password_validation)

compilemessages

django-admin command

compilemessages command line option

--exclude EXCLUDE, -x EXCLUDE

--locale LOCALE, -l LOCALE

--use-fuzzy, -f

compress() (MultiValueField method)

Concat (class in django.db.models.functions)

concrete (Field attribute)

concrete model

condition() (in module django.views.decorators.http)

conditional_escape() (in module django.utils.html)

ConditionalGetMiddleware (class in django.middleware.http)

configure_user() (RemoteUserBackend method)

confirm_login_allowed() (AuthenticationForm method)

CONN_MAX_AGE

setting

connect() (Signal method)

connection (SchemaEditor attribute)

contained

field lookup type

contains

field lookup type

contains() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

contains_aggregate (Expression attribute)

contains_properly

field lookup type

contains_properly() (PreparedGeometry method)

content (HttpResponse attribute)

(Response attribute)

content_type (django.views.generic.base.TemplateResponseMixin attribute)

(LogEntry attribute)

(UploadedFile attribute)

(models.Permission attribute)

content_type_extra (UploadedFile attribute)

ContentFile (class in django.core.files.base)

ContentType (class in django.contrib.contenttypes.models)

ContentTypeManager (class in django.contrib.contenttypes.models)

Context (class in django.template)

context (Response attribute)

context_data (SimpleTemplateResponse attribute)

context_object_name (django.views.generic.detail.SingleObjectMixin attribute)

(django.views.generic.list.MultipleObjectMixin attribute)

ContextPopException

convert_value() (Expression method)

convex_hull (GEOSGeometry attribute)

(OGRGeometry attribute)

cookie_date() (in module django.utils.http)

cookies (Client attribute)

COOKIES (HttpRequest attribute)

coord_dim (OGRGeometry attribute)

coords (GEOSGeometry attribute)

(OGRGeometry attribute)

coords() (GeoIP method)

(GeoIP2 method)

CoordTransform (class in django.contrib.gis.gdal)

copy() (QueryDict method)

Corr (class in django.contrib.postgres.aggregates)

Count (class in django.db.models)

count (Paginator attribute)

count() (in module django.db.models.query.QuerySet)

country() (GeoIP method)

(GeoIP2 method)

country_code() (GeoIP method)

(GeoIP2 method)

country_code_by_addr() (GeoIP method)

country_code_by_name() (GeoIP method)

country_info (GeoIP attribute)

country_name() (GeoIP method)

(GeoIP2 method)

country_name_by_addr() (GeoIP method)

country_name_by_name() (GeoIP method)

coupling

loose

CovarPop (class in django.contrib.postgres.aggregates)

coveredby

field lookup type

covers

field lookup type

covers() (PreparedGeometry method)

create() (in module django.db.models.query.QuerySet)

(RelatedManager method)

create_model() (BaseDatabaseSchemaEditor method)

create_model_instance() (backends.db.SessionStore method)

create_superuser() (models.CustomUserManager method)

(models.UserManager method)

create_test_db() (in module django.db.connection.creation)

create_unknown_user (RemoteUserBackend attribute)

create_user() (models.CustomUserManager method)

(models.UserManager method)

createcachetable

django-admin command

createcachetable command line option

--database DATABASE

--dry-run

created_time() (Storage method)

CreateExtension (class in django.contrib.postgres.operations)

CreateModel (class in django.db.migrations.operations)

createsuperuser

django-admin command

createsuperuser command line option

--database DATABASE

--email EMAIL

--username USERNAME

CreateView (built-in class)

Critical (class in django.core.checks)

crosses

field lookup type

crosses() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

CSRF_COOKIE_AGE

setting

CSRF_COOKIE_DOMAIN

setting

CSRF_COOKIE_HTTPONLY

setting

CSRF_COOKIE_NAME

setting

CSRF_COOKIE_PATH

setting

CSRF_COOKIE_SECURE

setting

csrf_exempt() (in module django.views.decorators.csrf)

CSRF_FAILURE_VIEW

setting

CSRF_HEADER_NAME

setting

csrf_protect() (in module django.views.decorators.csrf)

csrf_token

template tag

CSRF_TRUSTED_ORIGINS

setting

CsrfViewMiddleware (class in django.middleware.csrf)

css_classes() (BoundField method)

ct_field (GenericInlineModelAdmin attribute)

ct_fk_field (GenericInlineModelAdmin attribute)

current_app (HttpRequest attribute)

CurrentSiteMiddleware (class in django.contrib.sites.middleware)

cut

template filter

cycle

template tag

cycle_key() (backends.base.SessionBase method)

D

D (class in django.contrib.gis.measure)

data (BoundField attribute)

data() (GDALBand method)

DATABASE-ATOMIC_REQUESTS

setting

DATABASE-AUTOCOMMIT

setting

DATABASE-ENGINE

setting

DATABASE-TEST

setting

DATABASE-TIME_ZONE

setting

DATABASE_ROUTERS

setting

DatabaseError

DATABASES

setting

DataError

DATAFILE

setting

DATAFILE_MAXSIZE

setting

DATAFILE_TMP

setting

DATAFILE_TMP_MAXSIZE

setting

DataSource (class in django.contrib.gis.gdal)

datatype() (GDALBand method)

date

field lookup type

template filter

date_field (DateMixin attribute)

DATE_FORMAT

setting

date_format (SplitDateTimeWidget attribute)

date_hierarchy (ModelAdmin attribute)

DATE_INPUT_FORMATS

setting

date_joined (models.User attribute)

date_list_period (BaseDateListView attribute)

DateDetailView (built-in class)

(class in django.views.generic.dates)

DateField (class in django.db.models)

(class in django.forms)

DateInput (class in django.forms)

DateMixin (class in django.views.generic.dates)

DateRangeField (class in django.contrib.postgres.fields)

(class in django.contrib.postgres.forms)

dates() (in module django.db.models.query.QuerySet)

DATETIME_FORMAT

setting

DATETIME_INPUT_FORMATS

setting

DateTimeField (class in django.db.models)

(class in django.forms)

DateTimeInput (class in django.forms)

DateTimeRangeField (class in django.contrib.postgres.fields)

(class in django.contrib.postgres.forms)

datetimes() (in module django.db.models.query.QuerySet)

day

field lookup type

day (DayMixin attribute)

day_format (DayMixin attribute)

DayArchiveView (built-in class)

(class in django.views.generic.dates)

DayMixin (class in django.views.generic.dates)

db (QuerySet attribute)

db_column (Field attribute)

db_constraint (ForeignKey attribute)

(ManyToManyField attribute)

db_for_read()

db_for_write()

db_index (Field attribute)

db_table (ManyToManyField attribute)

(Options attribute)

db_tablespace (Field attribute)

(Options attribute)

db_type() (Field method)

dbshell

django-admin command

dbshell command line option

--database DATABASE

deactivate() (in module django.utils.timezone)

(in module django.utils.translation)

deactivate_all() (in module django.utils.translation)

DEBUG

setting

debug

template tag

Debug (class in django.core.checks)

debug() (in module django.template.context_processors)

DEBUG_PROPAGATE_EXCEPTIONS

setting

decimal_places (DecimalField attribute), [1]

DECIMAL_SEPARATOR

setting

DecimalField (class in django.db.models)

(class in django.forms)

DecimalValidator (class in django.core.validators)

decompress() (MultiWidget method)

(RangeWidget method)

deconstruct() (Field method)

decorator_from_middleware() (in module django.utils.decorators)

decorator_from_middleware_with_args() (in module django.utils.decorators)

default

template filter

default (Field attribute)

DEFAULT_CHARSET

setting

DEFAULT_CONTENT_TYPE

setting

DEFAULT_EXCEPTION_REPORTER_FILTER

setting

DEFAULT_FILE_STORAGE

setting

DEFAULT_FROM_EMAIL

setting

default_if_none

template filter

DEFAULT_INDEX_TABLESPACE

setting

default_lat (GeoModelAdmin attribute)

default_lon (GeoModelAdmin attribute)

default_permissions (Options attribute)

default_related_name (Options attribute)

DEFAULT_TABLESPACE

setting

default_zoom (GeoModelAdmin attribute)

defaults.bad_request() (in module django.views)

defaults.page_not_found() (in module django.views)

defaults.permission_denied() (in module django.views)

defaults.server_error() (in module django.views)

DefaultStorage (class in django.core.files.storage)

defer() (in module django.db.models.query.QuerySet)

delete() (Client method)

(FieldFile method)

(File method)

(Model method)

(Storage method)

(in module django.db.models.query.QuerySet)

delete_confirmation_template (ModelAdmin attribute)

delete_cookie() (HttpResponse method)

delete_model() (BaseDatabaseSchemaEditor method)

(ModelAdmin method)

delete_selected_confirmation_template (ModelAdmin attribute)

delete_test_cookie() (backends.base.SessionBase method)

delete_view() (ModelAdmin method)

deleted_objects (models.BaseModelFormSet attribute)

DeleteModel (class in django.db.migrations.operations)

DeleteView (built-in class)

delimiter (SimpleArrayField attribute)

(StringAgg attribute)

desc() (Expression method)

description (Field attribute)

(GDALBand attribute)

destroy_test_db() (in module django.db.connection.creation)

DetailView (built-in class)

dict() (QueryDict method)

dictsort

template filter

dictsortreversed

template filter

Difference (class in django.contrib.gis.db.models.functions)

difference() (GeoQuerySet method)

(GEOSGeometry method)

(OGRGeometry method)

diffsettings

django-admin command

diffsettings command line option

--all

dim (GeometryField attribute)

dimension (OGRGeometry attribute)

dims (GEOSGeometry attribute)

directory_permissions_mode (FileSystemStorage attribute)

disable_action() (AdminSite method)

disabled (Field attribute)

DISALLOWED_USER_AGENTS

setting

disconnect() (Signal method)

DiscoverRunner (class in django.test.runner)

disjoint

field lookup type

disjoint() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

dispatch() (django.views.generic.base.View method)

display_raw (BaseGeometryWidget attribute)

Distance (class in django.contrib.gis.db.models.functions)

(class in django.contrib.gis.measure)

distance() (GeoQuerySet method)

(GEOSGeometry method)

distance_gt

field lookup type

distance_gte

field lookup type

distance_lt

field lookup type

distance_lte

field lookup type

distinct (Count attribute)

distinct() (in module django.db.models.query.QuerySet)

divisibleby

template filter

django (OGRGeomType attribute)

django-admin command

changepassword

check

clearsessions

collectstatic

compilemessages

createcachetable

createsuperuser

dbshell

diffsettings

dumpdata

findstatic

flush

help

inspectdb

loaddata

makemessages

makemigrations

migrate

ogrinspect

ping_google

runserver, [1]

sendtestemail

shell

showmigrations

sqlflush

sqlmigrate

sqlsequencereset

squashmigrations

startapp

startproject

test

testserver

version

django.apps (module)

django.conf.settings.configure() (built-in function)

django.conf.urls (module)

django.conf.urls.i18n (module)

django.contrib.admin (module)

django.contrib.admindocs (module)

django.contrib.auth (module)

django.contrib.auth.backends (module)

django.contrib.auth.forms (module)

django.contrib.auth.hashers (module)

django.contrib.auth.middleware (module)

django.contrib.auth.password_validation (module)

django.contrib.auth.signals (module)

django.contrib.auth.views (module)

django.contrib.contenttypes (module)

django.contrib.contenttypes.admin (module)

django.contrib.contenttypes.fields (module)

django.contrib.contenttypes.forms (module)

django.contrib.flatpages (module)

django.contrib.gis (module)

django.contrib.gis.admin (module)

django.contrib.gis.db.backends (module)

django.contrib.gis.db.models (module), [1]

django.contrib.gis.db.models.functions (module), [1]

django.contrib.gis.feeds (module)

django.contrib.gis.forms (module)

django.contrib.gis.gdal (module)

django.contrib.gis.geoip (module)

django.contrib.gis.geoip2 (module)

django.contrib.gis.geos (module)

django.contrib.gis.measure (module)

django.contrib.gis.serializers.geojson (module)

django.contrib.gis.utils (module)

django.contrib.gis.utils.layermapping (module)

django.contrib.gis.utils.ogrinspect (module)

django.contrib.gis.widgets (module)

django.contrib.humanize (module)

django.contrib.messages (module)

django.contrib.messages.middleware (module)

django.contrib.postgres (module)

django.contrib.postgres.aggregates (module)

django.contrib.postgres.forms.BaseRangeField (class in django.contrib.postgres.fields)

django.contrib.postgres.validators (module)

django.contrib.redirects (module)

django.contrib.sessions (module)

django.contrib.sessions.middleware (module)

django.contrib.sitemaps (module)

django.contrib.sites (module)

django.contrib.sites.middleware (module)

django.contrib.staticfiles (module)

django.contrib.syndication (module)

django.contrib.webdesign (module)

django.core.cache.cache (built-in variable)

django.core.cache.caches (built-in variable)

django.core.cache.utils.make_template_fragment_key() (built-in function)

django.core.checks (module)

django.core.exceptions (module)

django.core.files (module)

django.core.files.storage (module)

django.core.files.uploadedfile (module)

django.core.files.uploadhandler (module)

django.core.mail (module)

django.core.mail.outbox (in module django.core.mail)

django.core.management (module)

django.core.management.call_command() (built-in function)

django.core.paginator (module)

django.core.serializers.get_serializer() (built-in function)

django.core.serializers.json.DjangoJSONEncoder (built-in class)

django.core.signals (module)

django.core.signals.got_request_exception (built-in variable)

django.core.signals.request_finished (built-in variable)

django.core.signals.request_started (built-in variable)

django.core.signing (module)

django.core.urlresolvers (module)

django.core.validators (module)

django.db (module)

django.db.backends (module)

django.db.backends.base.schema (module)

django.db.backends.signals.connection_created (built-in variable)

django.db.migrations (module)

django.db.migrations.operations (module)

django.db.models (module)

django.db.models.fields (module)

django.db.models.fields.related (module)

django.db.models.functions (module)

django.db.models.lookups (module)

django.db.models.options (module)

django.db.models.signals (module)

django.db.models.signals.class_prepared (built-in variable)

django.db.models.signals.m2m_changed (built-in variable)

django.db.models.signals.post_delete (built-in variable)

django.db.models.signals.post_init (built-in variable)

django.db.models.signals.post_migrate (built-in variable)

django.db.models.signals.post_save (built-in variable)

django.db.models.signals.pre_delete (built-in variable)

django.db.models.signals.pre_migrate (built-in variable)

django.db.models.signals.pre_save (built-in variable)

django.db.transaction (module)

django.dispatch (module)

django.forms (module)

django.forms.fields (module)

django.forms.formsets (module), [1]

django.forms.models (module), [1]

django.forms.widgets (module)

django.http (module)

django.http.Http404 (built-in class)

django.middleware (module)

django.middleware.cache (module)

django.middleware.clickjacking (module), [1]

django.middleware.common (module)

django.middleware.csrf (module), [1]

django.middleware.gzip (module)

django.middleware.http (module)

django.middleware.locale (module)

django.middleware.security (module)

django.shortcuts (module)

django.template (module)

django.template.backends (module)

django.template.backends.django (module)

django.template.backends.jinja2 (module)

django.template.loader (module)

django.template.response (module)

django.test (module)

django.test.signals (module)

django.test.signals.setting_changed (built-in variable)

django.test.signals.template_rendered (built-in variable)

django.test.utils (module)

django.utils (module)

django.utils.cache (module)

django.utils.dateparse (module)

django.utils.decorators (module)

django.utils.encoding (module)

django.utils.feedgenerator (module)

django.utils.functional (module)

django.utils.html (module)

django.utils.http (module)

django.utils.log (module)

django.utils.module_loading (module)

django.utils.safestring (module)

django.utils.six (module)

django.utils.text (module)

django.utils.timezone (module)

django.utils.translation (module), [1]

django.views (module)

django.views.decorators.cache (module)

django.views.decorators.cache.cache_page() (built-in function)

django.views.decorators.csrf (module)

django.views.decorators.gzip (module)

django.views.decorators.http (module)

django.views.decorators.vary (module)

django.views.generic.base.ContextMixin (built-in class)

django.views.generic.base.RedirectView (built-in class)

django.views.generic.base.TemplateResponseMixin (built-in class)

django.views.generic.base.TemplateView (built-in class)

django.views.generic.base.View (built-in class)

django.views.generic.dates (module)

django.views.generic.detail.DetailView (built-in class)

django.views.generic.detail.SingleObjectMixin (built-in class)

django.views.generic.detail.SingleObjectTemplateResponseMixin (built-in class)

django.views.generic.edit.CreateView (built-in class)

django.views.generic.edit.DeleteView (built-in class)

django.views.generic.edit.DeletionMixin (built-in class)

django.views.generic.edit.FormMixin (built-in class)

django.views.generic.edit.FormView (built-in class)

django.views.generic.edit.ModelFormMixin (built-in class)

django.views.generic.edit.ProcessFormView (built-in class)

django.views.generic.edit.UpdateView (built-in class)

django.views.generic.list.BaseListView (built-in class)

django.views.generic.list.ListView (built-in class)

django.views.generic.list.MultipleObjectMixin (built-in class)

django.views.generic.list.MultipleObjectTemplateResponseMixin (built-in class)

django.views.i18n (module)

DJANGO_SETTINGS_MODULE, [1], [2], [3], [4], [5], [6]

DjangoTemplates (class in django.template.backends.django)

DO_NOTHING (in module django.db.models)

domain (models.Site attribute)

Don't repeat yourself

Driver (class in django.contrib.gis.gdal)

driver (GDALRaster attribute)

driver_count (Driver attribute)

DRY

dumpdata

django-admin command

dumpdata command line option

--all, -a

--database DATABASE

--exclude EXCLUDE, -e EXCLUDE

--format FORMAT

--indent INDENT

--natural-foreign

--natural-primary

--output OUTPUT, -o OUTPUT

--pks PRIMARY_KEYS

dumps() (in module django.core.signing)

DurationField (class in django.db.models)

(class in django.forms)

dwithin

field lookup type

E

each_context() (AdminSite method)

earliest() (in module django.db.models.query.QuerySet)

editable (Field attribute)

eggs.Loader (class in django.template.loaders)

ellipsoid (SpatialReference attribute)

email (models.User attribute)

EMAIL_BACKEND

setting

EMAIL_FILE_PATH

setting

EMAIL_HOST

setting

EMAIL_HOST_PASSWORD

setting

EMAIL_HOST_USER

setting

EMAIL_PORT

setting

EMAIL_SSL_CERTFILE

setting

EMAIL_SSL_KEYFILE

setting

EMAIL_SUBJECT_PREFIX

setting

EMAIL_TIMEOUT

setting

EMAIL_USE_SSL

setting

EMAIL_USE_TLS

setting

email_user() (models.User method)

EmailField (class in django.db.models)

(class in django.forms)

EmailInput (class in django.forms)

EmailMessage (class in django.core.mail)

EmailValidator (class in django.core.validators)

empty (GEOSGeometry attribute)

empty_label (ModelChoiceField attribute)

(SelectDateWidget attribute)

empty_value (TypedChoiceField attribute)

empty_value_display (AdminSite attribute)

(ModelAdmin attribute)

EmptyPage

Enclosure (class in django.utils.feedgenerator)

encode() (base_session.BaseSessionManager method)

encoding (HttpRequest attribute)

end_index() (Page method)

endswith

field lookup type

Engine (class in django.template)

engines (in module django.template.loader)

ensure_csrf_cookie() (in module django.views.decorators.csrf)

Envelope (class in django.contrib.gis.db.models.functions)

(class in django.contrib.gis.gdal)

envelope (GEOSGeometry attribute)

(OGRGeometry attribute)

envelope() (GeoQuerySet method)

environment variable

DJANGO_SETTINGS_MODULE, [1], [2], [3], [4], [5], [6], [7]

PYTHONHASHSEED

PYTHONPATH

PYTHONSTARTUP

PYTHONWARNINGS

equals

field lookup type

equals() (GEOSGeometry method)

(OGRGeometry method)

equals_exact() (GEOSGeometry method)

Error

(class in django.core.checks)

error_css_class (Form attribute)

error_messages (Field attribute), [1]

errors (BoundField attribute)

(Form attribute)

escape

template filter

escape() (in module django.utils.html)

escape_uri_path() (in module django.utils.encoding)

escapejs

template filter

etag() (in module django.views.decorators.http)

ewkb (GEOSGeometry attribute)

ewkt (GEOSGeometry attribute)

(OGRGeometry attribute)

exact

field lookup type, [1]

exclude (ModelAdmin attribute)

exclude() (in module django.db.models.query.QuerySet)

execute() (BaseCommand method)

(BaseDatabaseSchemaEditor method)

exists() (in module django.db.models.query.QuerySet)

(Storage method)

expand_to_include() (Envelope method)

expire_date (base_session.AbstractBaseSession attribute)

Expression (class in django.db.models)

ExpressionWrapper (class in django.db.models)

extends

template tag

Extent (class in django.contrib.gis.db.models)

extent (GDALRaster attribute)

(GEOSGeometry attribute)

(Layer attribute)

(OGRGeometry attribute)

extent() (GeoQuerySet method)

Extent3D (class in django.contrib.gis.db.models)

extent3d() (GeoQuerySet method)

exterior_ring (Polygon attribute)

extra (InlineModelAdmin attribute)

extra() (in module django.db.models.query.QuerySet)

extra_js (GeoModelAdmin attribute)

F

F (class in django.db.models)

Feature (class in django.contrib.gis.gdal)

Feature release

Feed (class in django.contrib.gis.feeds)

FetchFromCacheMiddleware (class in django.middleware.cache)

fid (Feature attribute)

field

(BoundField attribute)

Field (class in django.contrib.gis.gdal)

(class in django.db.models)

(class in django.forms)

field lookup type

arrayfield.contained_by

arrayfield.contains

arrayfield.index

arrayfield.len

arrayfield.overlap

arrayfield.slice

bbcontains

bboverlaps

contained

contains

contains_properly

coveredby

covers

crosses

date

day

disjoint

distance_gt

distance_gte

distance_lt

distance_lte

dwithin

endswith

equals

exact, [1]

gis-contains

gt

gte

hour

hstorefield.contained_by

hstorefield.contains

hstorefield.has_any_keys

hstorefield.has_key

hstorefield.has_keys

hstorefield.key

hstorefield.keys

hstorefield.values

icontains

iendswith

iexact

in

intersects

iregex

isnull

istartswith

jsonfield.contained_by

jsonfield.contains

jsonfield.has_any_keys

jsonfield.has_key

jsonfield.has_keys

jsonfield.key

left

lt

lte

minute

month

overlaps

overlaps_above

overlaps_below

overlaps_left

overlaps_right

range

rangefield.adjacent_to

rangefield.contained_by

rangefield.contains

rangefield.endswith

rangefield.fully_gt

rangefield.fully_lt

rangefield.isempty

rangefield.not_gt

rangefield.not_lt

rangefield.overlap

rangefield.startswith

regex

relate

right

same_as

search

second

startswith

strictly_above

strictly_below

touches

unaccent

week_day

within

year

field_order (Form attribute)

field_precisions (Layer attribute)

field_widths (Layer attribute)

FieldDoesNotExist

FieldError

FieldFile (class in django.db.models.fields.files)

fields (ComboField attribute)

(Feature attribute)

(Form attribute)

(Layer attribute)

(ModelAdmin attribute)

(MultiValueField attribute)

(django.views.generic.edit.ModelFormMixin attribute)

fieldsets (ModelAdmin attribute)

File (class in django.core.files)

file (File attribute)

FILE_CHARSET

setting

file_complete() (FileUploadHandler method)

file_hash() (storage.ManifestStaticFilesStorage method)

file_permissions_mode (FileSystemStorage attribute)

FILE_UPLOAD_DIRECTORY_PERMISSIONS

setting

FILE_UPLOAD_HANDLERS

setting

FILE_UPLOAD_MAX_MEMORY_SIZE

setting

FILE_UPLOAD_PERMISSIONS

setting

FILE_UPLOAD_TEMP_DIR

setting

FileField (class in django.db.models)

(class in django.forms)

FileInput (class in django.forms)

filepath_to_uri() (in module django.utils.encoding)

FilePathField (class in django.db.models)

(class in django.forms)

FileResponse (class in django.http)

FILES (HttpRequest attribute)

filesizeformat

template filter

filesystem.Loader (class in django.template.loaders)

FileSystemStorage (class in django.core.files.storage)

FileUploadHandler (class in django.core.files.uploadhandler)

filter

template tag

filter() (django.template.Library method)

(in module django.db.models.query.QuerySet)

filter_horizontal (ModelAdmin attribute)

filter_vertical (ModelAdmin attribute)

findstatic

django-admin command

findstatic --first

findstatic command line option

findstatic command line option

findstatic --first

first

template filter

first() (in module django.db.models.query.QuerySet)

FIRST_DAY_OF_WEEK

setting

first_name (models.User attribute)

firstof

template tag

FixedOffset (class in django.utils.timezone)

FIXTURE_DIRS

setting

fixtures (TransactionTestCase attribute)

fk_name (InlineModelAdmin attribute)

flags (RegexValidator attribute)

FlatPage (class in django.contrib.flatpages.models)

FlatpageFallbackMiddleware (class in django.contrib.flatpages.middleware)

FlatPageSitemap (class in django.contrib.flatpages.sitemaps)

flatten() (Context method)

FloatField (class in django.db.models)

(class in django.forms)

floatformat

template filter

FloatRangeField (class in django.contrib.postgres.fields)

(class in django.contrib.postgres.forms)

flush

django-admin command

flush command line option

--database DATABASE

--noinput, --no-input

flush() (backends.base.SessionBase method)

(HttpResponse method)

for

template tag

for_concrete_model (GenericForeignKey attribute)

force_bytes() (in module django.utils.encoding)

force_escape

template filter

force_login() (Client method)

force_rhr() (GeoQuerySet method)

FORCE_SCRIPT_NAME

setting

force_str() (in module django.utils.encoding)

force_text() (in module django.utils.encoding)

force_unicode() (in module django.utils.encoding)

ForceRHR (class in django.contrib.gis.db.models.functions)

ForeignKey (class in django.db.models)

form (BoundField attribute)

Form (class in django.forms)

form (InlineModelAdmin attribute)

(ModelAdmin attribute)

form_class (django.views.generic.edit.FormMixin attribute)

form_field (RangeField attribute)

form_invalid() (django.views.generic.edit.FormMixin method)

(django.views.generic.edit.ModelFormMixin method)

form_valid() (django.views.generic.edit.FormMixin method)

(django.views.generic.edit.ModelFormMixin method)

format (DateInput attribute)

(DateTimeInput attribute)

(TimeInput attribute)

format file

format_html() (in module django.utils.html)

format_html_join() (in module django.utils.html)

FORMAT_MODULE_PATH

setting

format_output() (MultiWidget method)

formfield() (Field method)

formfield_for_choice_field() (ModelAdmin method)

formfield_for_foreignkey() (ModelAdmin method)

formfield_for_manytomany() (ModelAdmin method)

formfield_overrides (ModelAdmin attribute)

formset (InlineModelAdmin attribute)

formset_factory() (in module django.forms.formsets)

FormView (built-in class)

from_bbox() (django.contrib.gis.gdal.OGRGeometry class method)

(django.contrib.gis.geos.Polygon class method)

from_db() (django.db.models.Model class method)

from_db_value() (Field method)

from_esri() (SpatialReference method)

from_queryset() (in module django.db.models)

from_string() (Engine method)

fromfile() (in module django.contrib.gis.geos)

fromstr() (in module django.contrib.gis.geos)

full_clean() (Model method)

Func (class in django.db.models)

func (ResolverMatch attribute)

function (Aggregate attribute)

(Func attribute)

G

GDAL_LIBRARY_PATH

setting

GDALBand (class in django.contrib.gis.gdal)

GDALRaster (class in django.contrib.gis.gdal)

generic view

generic_inlineformset_factory() (in module django.contrib.contenttypes.forms)

GenericForeignKey (class in django.contrib.contenttypes.fields)

GenericInlineModelAdmin (class in django.contrib.contenttypes.admin)

GenericIPAddressField (class in django.db.models)

(class in django.forms)

GenericRelation (class in django.contrib.contenttypes.fields)

GenericSitemap (class in django.contrib.sitemaps)

GenericStackedInline (class in django.contrib.contenttypes.admin)

GenericTabularInline (class in django.contrib.contenttypes.admin)

GeoAtom1Feed (class in django.contrib.gis.feeds)

geographic (SpatialReference attribute)

geography (GeometryField attribute)

GeoHash (class in django.contrib.gis.db.models.functions)

geohash() (GeoQuerySet method)

GeoIP (class in django.contrib.gis.geoip)

GeoIP2 (class in django.contrib.gis.geoip2)

GEOIP_CITY

setting, [1]

GEOIP_COUNTRY

setting, [1]

GEOIP_LIBRARY_PATH

setting

GEOIP_PATH

setting, [1]

geojson (GEOSGeometry attribute)

geojson() (GeoQuerySet method)

geom (Feature attribute)

geom_count (OGRGeometry attribute)

geom_name (OGRGeometry attribute)

geom_type (BaseGeometryWidget attribute)

(Feature attribute)

(Field attribute)

(GEOSGeometry attribute)

(Layer attribute)

(OGRGeometry attribute)

geom_typeid (GEOSGeometry attribute)

GeoManager (class in django.contrib.gis.db.models)

geometry() (Feed method)

GeometryCollection (class in django.contrib.gis.gdal)

(class in django.contrib.gis.geos)

GeometryCollectionField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

GeometryField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

GeoModelAdmin (class in django.contrib.gis.admin)

GeoQuerySet (class in django.contrib.gis.db.models)

GeoRSSFeed (class in django.contrib.gis.feeds)

geos (OGRGeometry attribute)

geos() (GeoIP method)

(GeoIP2 method)

GEOS_LIBRARY_PATH

setting

GEOSException

GEOSGeometry (class in django.contrib.gis.geos)

geotransform (GDALRaster attribute)

get (Feature attribute)

GET (HttpRequest attribute)

get() (backends.base.SessionBase method)

(Client method)

(Context method)

(QueryDict method)

(django.views.generic.edit.ProcessFormView method)

(django.views.generic.list.BaseListView method)

(in module django.db.models.query.QuerySet)

get_absolute_url() (Model method)

get_actions() (ModelAdmin method)

get_all_permissions() (ModelBackend method)

(models.PermissionsMixin method)

(models.User method)

get_allow_empty() (django.views.generic.list.MultipleObjectMixin method)

get_allow_future() (DateMixin method)

get_app_config() (apps method)

get_app_configs() (apps method)

get_autocommit() (in module django.db.transaction)

get_available_languages

template tag

get_available_name() (in module django.core.files.storage)

(Storage method)

get_bound_field() (Field method)

get_by_natural_key() (ContentTypeManager method)

(models.BaseUserManager method)

get_cache_key() (in module django.utils.cache)

get_changeform_initial_data() (ModelAdmin method)

get_changelist() (ModelAdmin method)

get_changelist_form() (ModelAdmin method)

get_changelist_formset() (ModelAdmin method)

get_connection() (in module django.core.mail)

get_contents() (Loader method)

get_context_data() (django.views.generic.base.ContextMixin method)

(Feed method)

(django.views.generic.detail.SingleObjectMixin method)

(django.views.generic.edit.FormMixin method)

(django.views.generic.list.MultipleObjectMixin method)

get_context_object_name() (django.views.generic.detail.SingleObjectMixin method)

(django.views.generic.list.MultipleObjectMixin method)

get_current_language

template tag

get_current_language_bidi

template tag

get_current_timezone

template tag

get_current_timezone() (in module django.utils.timezone)

get_current_timezone_name() (in module django.utils.timezone)

get_date_field() (DateMixin method)

get_date_list() (BaseDateListView method)

get_date_list_period() (BaseDateListView method)

get_dated_items() (BaseDateListView method)

get_dated_queryset() (BaseDateListView method)

get_day() (DayMixin method)

get_day_format() (DayMixin method)

get_db_prep_lookup() (Field method)

get_db_prep_save() (Field method)

get_db_prep_value() (Field method)

get_decoded() (base_session.AbstractBaseSession method)

get_default() (Engine static method)

get_default_timezone() (in module django.utils.timezone)

get_default_timezone_name() (in module django.utils.timezone)

get_deferred_fields() (Model method)

get_digit

template filter

get_edited_object() (LogEntry method)

get_expire_at_browser_close() (backends.base.SessionBase method)

get_expiry_age() (backends.base.SessionBase method)

get_expiry_date() (backends.base.SessionBase method)

get_extra() (InlineModelAdmin method)

get_field() (Options method)

get_fields() (Layer method)

(ModelAdmin method)

(Options method)

get_fieldsets() (ModelAdmin method)

get_fixed_timezone() (in module django.utils.timezone)

get_flatpages

template tag

get_FOO_display() (Model method)

get_for_id() (ContentTypeManager method)

get_for_model() (ContentTypeManager method)

get_for_models() (ContentTypeManager method)

get_form() (django.views.generic.edit.FormMixin method)

(ModelAdmin method)

get_form_class() (django.views.generic.edit.FormMixin method)

(django.views.generic.edit.ModelFormMixin method)

get_form_kwargs() (django.views.generic.edit.FormMixin method)

(django.views.generic.edit.ModelFormMixin method)

get_formset() (InlineModelAdmin method)

get_formsets_with_inlines() (ModelAdmin method)

get_full_name() (models.CustomUser method)

(models.User method)

get_full_path() (HttpRequest method)

get_geoms() (Layer method)

get_group_by_cols() (Expression method)

get_group_permissions() (ModelBackend method)

(models.PermissionsMixin method)

(models.User method)

get_host() (HttpRequest method)

get_initial() (django.views.generic.edit.FormMixin method)

get_inline_instances() (ModelAdmin method)

get_internal_type() (Field method)

get_language() (in module django.utils.translation)

get_language_bidi() (in module django.utils.translation)

get_language_from_request() (in module django.utils.translation)

get_language_info

template tag

get_language_info() (in module django.utils.translation)

get_language_info_list

template tag

get_latest_by (Options attribute)

get_list_display() (ModelAdmin method)

get_list_display_links() (ModelAdmin method)

get_list_filter() (ModelAdmin method)

get_list_or_404() (in module django.shortcuts)

get_list_select_related() (ModelAdmin method)

get_login_url() (AccessMixin method)

get_lookup() (in module django.db.models)

(lookups.RegisterLookupMixin method)

get_make_object_list() (YearArchiveView method)

get_max_age() (in module django.utils.cache)

get_max_num() (InlineModelAdmin method)

get_media_prefix

template tag

get_messages() (in module django.contrib.messages)

get_min_num() (InlineModelAdmin method)

get_model() (AppConfig method)

(apps method)

get_model_class() (django.contrib.sessions.backends.db.SessionStore class method)

get_models() (AppConfig method)

get_month() (MonthMixin method)

get_month_format() (MonthMixin method)

get_next_by_FOO() (Model method)

get_next_day() (DayMixin method)

get_next_month() (MonthMixin method)

get_next_week() (WeekMixin method)

get_next_year() (YearMixin method)

get_object() (django.views.generic.detail.SingleObjectMixin method)

get_object_for_this_type() (ContentType method)

get_object_or_404() (in module django.shortcuts)

get_or_create() (in module django.db.models.query.QuerySet)

get_ordering() (django.views.generic.list.MultipleObjectMixin method)

(ModelAdmin method)

get_paginate_by() (django.views.generic.list.MultipleObjectMixin method)

get_paginate_orphans() (django.views.generic.list.MultipleObjectMixin method)

get_paginator() (django.views.generic.list.MultipleObjectMixin method)

(ModelAdmin method)

get_password_validators() (in module django.contrib.auth.password_validation)

get_permission_denied_message() (AccessMixin method)

get_permission_required() (PermissionRequiredMixin method)

get_port() (HttpRequest method)

get_post_parameters() (SafeExceptionReporterFilter method)

get_prefix() (django.views.generic.edit.FormMixin method)

get_prep_lookup() (Field method)

get_prep_value() (Field method)

get_prepopulated_fields() (ModelAdmin method)

get_prev_week() (WeekMixin method)

get_previous_by_FOO() (Model method)

get_previous_day() (DayMixin method)

get_previous_month() (MonthMixin method)

get_previous_year() (YearMixin method)

get_queryset() (django.views.generic.detail.SingleObjectMixin method)

(ModelAdmin method)

(django.views.generic.list.MultipleObjectMixin method)

get_readonly_fields() (ModelAdmin method)

get_redirect_field_name() (AccessMixin method)

get_redirect_url() (django.views.generic.base.RedirectView method)

get_rollback() (in module django.db.transaction)

get_script_prefix() (in module django.core.urlresolvers)

get_search_fields() (ModelAdmin method)

get_search_results() (ModelAdmin method)

get_session_auth_hash() (models.AbstractBaseUser method)

get_session_store_class() (django.contrib.sessions.base_session.AbstractBaseSession class method)

get_short_name() (models.CustomUser method)

(models.User method)

get_signed_cookie() (HttpRequest method)

get_slug_field() (django.views.generic.detail.SingleObjectMixin method)

get_source_expressions() (Expression method)

get_static_prefix

template tag

get_storage_class() (in module django.core.files.storage)

get_success_message() (views.SuccessMessageMixin method)

get_success_url() (django.views.generic.edit.DeletionMixin method)

(django.views.generic.edit.FormMixin method)

(django.views.generic.edit.ModelFormMixin method)

get_tag_uri() (in module django.utils.feedgenerator)

get_template() (Engine method)

(Loader method)

(in module django.template.loader)

get_template_names() (django.views.generic.base.TemplateResponseMixin method)

(django.views.generic.detail.SingleObjectTemplateResponseMixin method)

(django.views.generic.list.MultipleObjectTemplateResponseMixin method)

get_template_sources() (Loader method)

get_test_func() (UserPassesTestMixin method)

get_traceback_frame_variables() (SafeExceptionReporterFilter method)

get_transform() (in module django.db.models)

(lookups.RegisterLookupMixin method)

get_urls() (ModelAdmin method)

get_user_model() (in module django.contrib.auth)

get_user_permissions() (ModelBackend method)

get_username() (models.AbstractBaseUser method)

(models.User method)

get_valid_name() (in module django.core.files.storage)

(Storage method)

get_version() (BaseCommand method)

get_week() (WeekMixin method)

get_week_format() (WeekMixin method)

get_year() (YearMixin method)

get_year_format() (YearMixin method)

getlist() (QueryDict method)

gettext() (in module django.utils.translation)

gettext_lazy() (in module django.utils.translation)

gettext_noop() (in module django.utils.translation)

getvalue() (HttpResponse method)

gis-contains

field lookup type

gml (OGRGeometry attribute)

gml() (GeoQuerySet method)

Greatest (class in django.db.models.functions)

groups (models.User attribute)

gt

field lookup type

gte

field lookup type

gzip_page() (in module django.views.decorators.gzip)

GZipMiddleware (class in django.middleware.gzip)

H

handle() (BaseCommand method)

handle_app_config() (AppCommand method)

handle_label() (LabelCommand method)

handle_no_permission() (AccessMixin method)

handle_noargs() (NoArgsCommand method)

handle_raw_input() (FileUploadHandler method)

handler400 (in module django.conf.urls)

handler403 (in module django.conf.urls)

handler404 (in module django.conf.urls)

handler500 (in module django.conf.urls)

has_add_permission() (ModelAdmin method)

has_change_permission() (ModelAdmin method)

has_changed() (Field method)

(Form method)

has_delete_permission() (ModelAdmin method)

has_error() (Form method)

has_header() (HttpResponse method)

has_module_permission() (ModelAdmin method)

has_module_perms() (ModelBackend method)

(models.PermissionsMixin method)

(models.User method)

has_next() (Page method)

has_other_pages() (Page method)

has_perm() (ModelBackend method)

(models.PermissionsMixin method)

(models.User method)

has_permission() (AdminSite method)

(PermissionRequiredMixin method)

has_perms() (models.PermissionsMixin method)

(models.User method)

has_previous() (Page method)

has_usable_password() (models.AbstractBaseUser method)

(models.User method)

hasz (GEOSGeometry attribute)

head() (Client method)

height (GDALBand attribute)

(GDALRaster attribute)

(ImageFile attribute)

height_field (ImageField attribute)

help

django-admin command

help (BaseCommand attribute)

help_text (BoundField attribute)

(Field attribute), [1]

hex (GEOSGeometry attribute)

(OGRGeometry attribute)

hexewkb (GEOSGeometry attribute)

hidden (Field attribute)

HiddenInput (class in django.forms)

history_view() (ModelAdmin method)

HOST

setting

hour

field lookup type

HStoreExtension (class in django.contrib.postgres.operations)

HStoreField (class in django.contrib.postgres.fields)

(class in django.contrib.postgres.forms)

hstorefield.contained_by

field lookup type

hstorefield.contains

field lookup type

hstorefield.has_any_keys

field lookup type

hstorefield.has_key

field lookup type

hstorefield.has_keys

field lookup type

hstorefield.key

field lookup type

hstorefield.keys

field lookup type

hstorefield.values

field lookup type

html_name (BoundField attribute)

html_safe() (in module django.utils.html)

http_date() (in module django.utils.http)

http_method_names (django.views.generic.base.View attribute)

http_method_not_allowed() (django.views.generic.base.View method)

HttpRequest (class in django.http)

HttpResponse (class in django.http)

HttpResponseBadRequest (class in django.http)

HttpResponseForbidden (class in django.http)

HttpResponseGone (class in django.http)

HttpResponseNotAllowed (class in django.http)

HttpResponseNotFound (class in django.http)

HttpResponseNotModified (class in django.http)

HttpResponsePermanentRedirect (class in django.http)

HttpResponseRedirect (class in django.http)

HttpResponseServerError (class in django.http)

I

i18n (Sitemap attribute)

i18n_patterns() (in module django.conf.urls.i18n)

icontains

field lookup type

id_for_label (BoundField attribute)

id_for_label() (Widget method)

identify_epsg() (SpatialReference method)

iendswith

field lookup type

iexact

field lookup type

if

template tag

ifchanged

template tag

IGNORABLE_404_URLS

setting

ImageField (class in django.db.models)

(class in django.forms)

ImageFile (class in django.core.files.images)

import_epsg() (SpatialReference method)

import_proj() (SpatialReference method)

import_string() (in module django.utils.module_loading)

import_user_input() (SpatialReference method)

import_wkt() (SpatialReference method)

import_xml() (SpatialReference method)

ImproperlyConfigured

in

field lookup type

in_bulk() (in module django.db.models.query.QuerySet)

include

template tag

include() (in module django.conf.urls)

inclusion_tag() (django.template.Library method)

index (Feature attribute)

index_template (AdminSite attribute)

index_title (AdminSite attribute)

index_together (Options attribute)

Info (class in django.core.checks)

info (GeoIP attribute)

initial (django.views.generic.edit.FormMixin attribute)

(Field attribute)

(Form attribute)

(Migration attribute)

inlineformset_factory() (in module django.forms.models)

InlineModelAdmin (class in django.contrib.admin)

inlines (ModelAdmin attribute)

InMemoryUploadedFile (class in django.core.files.uploadedfile)

input_date_formats (SplitDateTimeField attribute)

input_formats (DateField attribute)

(DateTimeField attribute)

(TimeField attribute)

input_time_formats (SplitDateTimeField attribute)

inspectdb

django-admin command

inspectdb command line option

--database DATABASE

INSTALLED_APPS

setting

instance namespace

int_list_validator() (in module django.core.validators)

int_to_base36() (in module django.utils.http)

intcomma

template filter

IntegerField (class in django.db.models)

(class in django.forms)

IntegerRangeField (class in django.contrib.postgres.fields)

(class in django.contrib.postgres.forms)

IntegrityError

InterfaceError

INTERNAL_IPS

setting

InternalError

internationalization

interpolate() (GEOSGeometry method)

interpolate_normalized() (GEOSGeometry method)

Intersection (class in django.contrib.gis.db.models.functions)

intersection() (GeoQuerySet method)

(GEOSGeometry method)

(OGRGeometry method)

intersects

field lookup type

intersects() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

intword

template filter

InvalidPage

inverse_flattening (SpatialReference attribute)

inverse_match (RegexValidator attribute)

iregex

field lookup type

iri_to_uri() (in module django.utils.encoding)

iriencode

template filter

is_active (in module django.contrib.auth)

(models.CustomUser attribute)

(models.User attribute)

is_active() (SafeExceptionReporterFilter method)

is_ajax() (HttpRequest method)

is_anonymous() (models.AbstractBaseUser method)

(models.User method)

is_authenticated() (models.AbstractBaseUser method)

(models.User method)

is_aware() (in module django.utils.timezone)

is_bound (Form attribute)

is_hidden (BoundField attribute)

is_installed() (apps method)

is_multipart() (Form method)

is_naive() (in module django.utils.timezone)

is_password_usable() (in module django.contrib.auth.hashers)

is_protected_type() (in module django.utils.encoding)

is_relation (Field attribute)

is_rendered (SimpleTemplateResponse attribute)

is_secure() (HttpRequest method)

is_staff (in module django.contrib.auth)

(models.User attribute)

is_superuser (models.PermissionsMixin attribute)

(models.User attribute)

is_valid() (Form method)

isnull

field lookup type

istartswith

field lookup type

item_attributes() (SyndicationFeed method)

item_geometry() (Feed method)

items (Sitemap attribute)

items() (backends.base.SessionBase method)

(QueryDict method)

iterator() (in module django.db.models.query.QuerySet)

iteritems() (QueryDict method)

iterlists() (QueryDict method)

itervalues() (QueryDict method)

J

Java

javascript_catalog() (in module django.views.i18n)

Jinja2 (class in django.template.backends.jinja2)

join

template filter

json (GEOSGeometry attribute)

(OGRGeometry attribute)

json() (Response method)

json_catalog() (in module django.views.i18n)

JSONField (class in django.contrib.postgres.fields)

(class in django.contrib.postgres.forms)

jsonfield.contained_by

field lookup type

jsonfield.contains

field lookup type

jsonfield.has_any_keys

field lookup type

jsonfield.has_key

field lookup type

jsonfield.has_keys

field lookup type

jsonfield.key

field lookup type

JsonResponse (class in django.http)

JVM

Jython

JYTHONPATH

K

keys() (backends.base.SessionBase method)

KeysValidator (class in django.contrib.postgres.validators)

kml (GEOSGeometry attribute)

(OGRGeometry attribute)

kml() (GeoQuerySet method)

kwargs (ResolverMatch attribute)

L

label (AppConfig attribute)

(BoundField attribute)

(Field attribute)

(Options attribute)

label_lower (Options attribute)

label_suffix (Field attribute)

(Form attribute)

label_tag() (BoundField method)

LabelCommand (class in django.core.management)

language

template tag

language code

language_bidi

template filter

LANGUAGE_CODE

setting

LANGUAGE_COOKIE_AGE

setting

LANGUAGE_COOKIE_DOMAIN

setting

LANGUAGE_COOKIE_NAME

setting

LANGUAGE_COOKIE_PATH

setting

language_name

template filter

language_name_local

template filter

language_name_translated

template filter

LANGUAGE_SESSION_KEY (in module django.utils.translation)

LANGUAGES

setting

last

template filter

last() (in module django.db.models.query.QuerySet)

last_login (models.User attribute)

last_modified() (in module django.views.decorators.http)

last_name (models.User attribute)

lastmod (Sitemap attribute)

lat_lon() (GeoIP method)

(GeoIP2 method)

latest() (in module django.db.models.query.QuerySet)

latest_post_date() (SyndicationFeed method)

Layer (class in django.contrib.gis.gdal)

layer_count (DataSource attribute)

layer_name (Feature attribute)

LayerMapping (class in django.contrib.gis.utils)

learn_cache_key() (in module django.utils.cache)

Least (class in django.db.models.functions)

leave_locale_alone (BaseCommand attribute)

left

field lookup type

length

template filter

Length (class in django.contrib.gis.db.models.functions)

(class in django.db.models.functions)

length (GEOSGeometry attribute)

length() (GeoQuerySet method)

length_is

template filter

lhs (Lookup attribute)

(Transform attribute)

limit (Sitemap attribute)

limit_choices_to (ForeignKey attribute)

(ManyToManyField attribute)

linear_name (SpatialReference attribute)

linear_units (SpatialReference attribute)

LinearRing (class in django.contrib.gis.geos)

linebreaks

template filter

linebreaksbr

template filter

linenumbers

template filter

LineString (class in django.contrib.gis.gdal)

(class in django.contrib.gis.geos)

LineStringField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

list_display (ModelAdmin attribute)

list_display_links (ModelAdmin attribute)

list_editable (ModelAdmin attribute)

list_filter (ModelAdmin attribute)

list_max_show_all (ModelAdmin attribute)

list_per_page (ModelAdmin attribute)

list_select_related (ModelAdmin attribute)

listdir() (Storage method)

lists() (QueryDict method)

ListView (built-in class)

LiveServerTestCase (class in django.test)

ljust

template filter

ll (Envelope attribute)

load

template tag

load_template() (Loader method)

load_template_source() (Loader method)

loaddata

django-admin command

loaddata command line option

--app APP_LABEL

--database DATABASE

--ignorenonexistent, -i

Loader (class in django.template.loaders.base)

loads() (in module django.core.signing)

local (SpatialReference attribute)

locale name

LOCALE_PATHS

setting

LocaleMiddleware (class in django.middleware.locale)

localization

localize

template filter

template tag

localize (Field attribute)

localtime

template filter

template tag

localtime() (in module django.utils.timezone)

location (FileSystemStorage attribute)

(Sitemap attribute)

locmem.Loader (class in django.template.loaders)

LOGGING

setting

LOGGING_CONFIG

setting

login() (Client method)

(in module django.contrib.auth)

(in module django.contrib.auth.views)

login_form (AdminSite attribute)

LOGIN_REDIRECT_URL

setting

login_required() (in module django.contrib.auth.decorators)

login_template (AdminSite attribute)

LOGIN_URL

setting

login_url (AccessMixin attribute)

LoginRequiredMixin (class in django.contrib.auth.mixins)

logout() (Client method)

(in module django.contrib.auth)

(in module django.contrib.auth.views)

logout_template (AdminSite attribute)

logout_then_login() (in module django.contrib.auth.views)

lon_lat() (GeoIP method)

(GeoIP2 method)

Long-term support release

Lookup (class in django.db.models)

lookup_name (Lookup attribute)

(Transform attribute)

lookups.RegisterLookupMixin (class in django.db.models)

lorem

template tag

lower

template filter

Lower (class in django.db.models.functions)

lt

field lookup type

lte

field lookup type

M

mail_admins() (in module django.core.mail)

mail_managers() (in module django.core.mail)

make_aware() (in module django.utils.timezone)

make_line() (GeoQuerySet method)

make_list

template filter

make_naive() (in module django.utils.timezone)

make_object_list (YearArchiveView attribute)

make_password() (in module django.contrib.auth.hashers)

make_random_password() (models.BaseUserManager method)

MakeLine (class in django.contrib.gis.db.models)

makemessages

django-admin command

makemessages command line option

--all, -a

--domain DOMAIN, -d DOMAIN

--exclude EXCLUDE, -x EXCLUDE

--extension EXTENSIONS, -e EXTENSIONS

--ignore PATTERN, -i PATTERN

--keep-pot

--locale LOCALE, -l LOCALE

--no-default-ignore

--no-location

--no-wrap

--symlinks, -s

makemigrations

django-admin command

makemigrations command line option

--dry-run

--empty

--exit, -e

--merge

--name NAME, -n NAME

--noinput, --no-input

managed (Options attribute)

Manager (class in django.db.models)

MANAGERS

setting

managers.CurrentSiteManager (class in django.contrib.sites)

many_to_many (Field attribute)

many_to_one (Field attribute)

ManyToManyField (class in django.db.models)

map_height (BaseGeometryWidget attribute)

(GeoModelAdmin attribute)

map_srid (BaseGeometryWidget attribute)

map_template (GeoModelAdmin attribute)

map_width (BaseGeometryWidget attribute)

(GeoModelAdmin attribute)

mapping() (in module django.contrib.gis.utils)

mark_for_escaping() (in module django.utils.safestring)

mark_safe() (in module django.utils.safestring)

match (FilePathField attribute), [1]

Max (class in django.db.models)

max (GDALBand attribute)

max_digits (DecimalField attribute), [1]

max_length (CharField attribute), [1]

(SimpleArrayField attribute)

(URLField attribute)

max_num (InlineModelAdmin attribute)

max_value (DecimalField attribute)

(IntegerField attribute)

max_x (Envelope attribute)

max_y (Envelope attribute)

MaxLengthValidator (class in django.core.validators)

MaxValueValidator (class in django.core.validators)

MEDIA_ROOT

setting

MEDIA_URL

setting

mem_size() (GeoQuerySet method)

MemoryFileUploadHandler (class in django.core.files.uploadhandler)

MemSize (class in django.contrib.gis.db.models.functions)

merged (MultiLineString attribute)

message (EmailValidator attribute)

(RegexValidator attribute)

message file

MESSAGE_LEVEL

setting

MESSAGE_STORAGE

setting

MESSAGE_TAGS

setting

message_user() (ModelAdmin method)

MessageMiddleware (class in django.contrib.messages.middleware)

META (HttpRequest attribute)

method (HttpRequest attribute)

method_decorator() (in module django.utils.decorators)

middleware.RedirectFallbackMiddleware (class in django.contrib.redirects)

MIDDLEWARE_CLASSES

setting

MiddlewareNotUsed

migrate

django-admin command

migrate command line option

--database DATABASE

--fake

--fake-initial

--list, -l

--noinput, --no-input

--run-syncdb

MIGRATION_MODULES

setting

Min (class in django.db.models)

min (GDALBand attribute)

min_length (CharField attribute)

(SimpleArrayField attribute)

(URLField attribute)

min_num (InlineModelAdmin attribute)

min_value (DecimalField attribute)

(IntegerField attribute)

min_x (Envelope attribute)

min_y (Envelope attribute)

MinimumLengthValidator (class in django.contrib.auth.password_validation)

MinLengthValidator (class in django.core.validators)

minute

field lookup type

MinValueValidator (class in django.core.validators)

missing_args_message (BaseCommand attribute)

mode (File attribute)

model

Model (class in django.db.models)

model (ContentType attribute)

(Field attribute)

(InlineModelAdmin attribute)

(django.views.generic.detail.SingleObjectMixin attribute)

(django.views.generic.edit.ModelFormMixin attribute)

(django.views.generic.list.MultipleObjectMixin attribute)

Model.DoesNotExist

model_class() (ContentType method)

ModelAdmin (class in django.contrib.admin)

ModelBackend (class in django.contrib.auth.backends)

ModelChoiceField (class in django.forms)

ModelForm (class in django.forms)

modelform_factory() (in module django.forms.models)

modelformset_factory() (in module django.forms.models)

ModelMultipleChoiceField (class in django.forms)

models.AbstractBaseUser (class in django.contrib.auth)

models.AnonymousUser (class in django.contrib.auth)

models.BaseInlineFormSet (class in django.forms)

models.BaseModelFormSet (class in django.forms)

models.BaseUserManager (class in django.contrib.auth)

models.CustomUser (class in django.contrib.auth), [1]

models.CustomUserManager (class in django.contrib.auth)

models.Group (class in django.contrib.auth), [1]

models.LogEntry (class in django.contrib.admin)

models.Permission (class in django.contrib.auth), [1]

models.PermissionsMixin (class in django.contrib.auth)

models.ProtectedError

models.Redirect (class in django.contrib.redirects)

models.Site (class in django.contrib.sites)

models.User (class in django.contrib.auth), [1]

models.UserManager (class in django.contrib.auth)

models_module (AppConfig attribute)

modifiable (GeoModelAdmin attribute)

modified_time() (Storage method)

modify_settings() (in module django.test)

(SimpleTestCase method)

module (AppConfig attribute)

month

field lookup type

month (MonthMixin attribute)

MONTH_DAY_FORMAT

setting

month_format (MonthMixin attribute)

MonthArchiveView (built-in class)

(class in django.views.generic.dates)

MonthMixin (class in django.views.generic.dates)

months (SelectDateWidget attribute)

MTV

multi_db (TransactionTestCase attribute)

MultiLineString (class in django.contrib.gis.geos)

MultiLineStringField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

multiple_chunks() (File method)

(UploadedFile method)

MultipleChoiceField (class in django.forms)

MultipleHiddenInput (class in django.forms)

MultipleObjectsReturned

MultiPoint (class in django.contrib.gis.geos)

MultiPointField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

MultiPolygon (class in django.contrib.gis.geos)

MultiPolygonField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

MultiValueField (class in django.forms)

MultiWidget (class in django.forms)

MVC

N

NAME

setting

name (AppConfig attribute)

(BoundField attribute)

(ContentType attribute)

(CreateExtension attribute)

(DataSource attribute)

(Field attribute)

(FieldFile attribute)

(File attribute)

(GDALRaster attribute)

(Layer attribute)

(OGRGeomType attribute)

(Origin attribute)

(SpatialReference attribute)

(UploadedFile attribute)

(models.Group attribute)

(models.Permission attribute)

(models.Site attribute)

namespace (ResolverMatch attribute)

namespaces (ResolverMatch attribute)

naturalday

template filter

naturaltime

template filter

never_cache() (in module django.views.decorators.cache)

new_file() (FileUploadHandler method)

new_objects (models.BaseModelFormSet attribute)

next_page_number() (Page method)

ngettext() (in module django.utils.translation)

ngettext_lazy() (in module django.utils.translation)

NoArgsCommand (class in django.core.management)

nodata_value (GDALBand attribute)

non_atomic_requests() (in module django.db.transaction)

NON_FIELD_ERRORS (in module django.core.exceptions)

non_field_errors() (Form method)

none() (in module django.db.models.query.QuerySet)

noop (RunSQL attribute)

noop() (RunPython static method)

NoReverseMatch

normalize_email() (django.contrib.auth.models.BaseUserManager class method)

NotSupportedError

now

template tag

Now (class in django.db.models.functions)

now() (in module django.utils.timezone)

npgettext() (in module django.utils.translation)

npgettext_lazy() (in module django.utils.translation)

null (Field attribute)

NullBooleanField (class in django.db.models)

(class in django.forms)

NullBooleanSelect (class in django.forms)

num (OGRGeomType attribute)

num_coords (GEOSGeometry attribute)

(OGRGeometry attribute)

num_feat (Layer attribute)

num_fields (Feature attribute)

(Layer attribute)

num_geom (GEOSGeometry attribute)

num_geom() (GeoQuerySet method)

num_interior_rings (Polygon attribute)

num_items() (SyndicationFeed method)

num_pages (Paginator attribute)

num_points (OGRGeometry attribute)

num_points() (GeoQuerySet method)

number (Page attribute)

NUMBER_GROUPING

setting

NumberInput (class in django.forms)

NumericPasswordValidator (class in django.contrib.auth.password_validation)

NumGeometries (class in django.contrib.gis.db.models.functions)

NumPoints (class in django.contrib.gis.db.models.functions)

O

object (django.views.generic.edit.CreateView attribute)

(django.views.generic.edit.UpdateView attribute)

object_history_template (ModelAdmin attribute)

object_id (LogEntry attribute)

object_list (Page attribute)

object_repr (LogEntry attribute)

ObjectDoesNotExist

objects (Model attribute)

ogr (GEOSGeometry attribute)

OGRGeometry (class in django.contrib.gis.gdal)

OGRGeomType (class in django.contrib.gis.gdal)

ogrinspect

django-admin command

ogrinspect command line option

--blank BLANK

--decimal DECIMAL

--geom-name GEOM_NAME

--layer LAYER_KEY

--mapping

--multi-geom

--name-field NAME_FIELD

--no-imports

--null NULL

--srid SRID

on_commit() (in module django.db.transaction)

on_delete (ForeignKey attribute)

one_to_many (Field attribute)

one_to_one (Field attribute)

OneToOneField (class in django.db.models)

only() (in module django.db.models.query.QuerySet)

open() (django.contrib.gis.geoip.GeoIP class method)

(FieldFile method)

(File method)

(Storage method)

(django.contrib.gis.geoip2.GeoIP2 class method)

openlayers_url (GeoModelAdmin attribute)

OpenLayersWidget (class in django.contrib.gis.widgets)

OperationalError

option_list (BaseCommand attribute)

(DiscoverRunner attribute)

OPTIONS

setting

Options (class in django.db.models.options)

options() (Client method)

(django.views.generic.base.View method)

order_by() (in module django.db.models.query.QuerySet)

order_fields() (Form method)

order_with_respect_to (Options attribute)

ordered (QuerySet attribute)

ordering (django.views.generic.list.MultipleObjectMixin attribute)

(ModelAdmin attribute)

(Options attribute)

ordinal

template filter

Origin (class in django.template.base)

origin (GDALRaster attribute)

OSMGeoAdmin (class in django.contrib.gis.admin)

OSMWidget (class in django.contrib.gis.widgets)

outdim (WKBWriter attribute)

output_field (in module django.db.models)

(Transform attribute)

output_transaction (BaseCommand attribute)

overlaps

field lookup type

overlaps() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

overlaps_above

field lookup type

overlaps_below

field lookup type

overlaps_left

field lookup type

overlaps_right

field lookup type

override() (in module django.utils.timezone)

(in module django.utils.translation)

override_settings() (in module django.test)

P

Page (class in django.core.paginator)

page() (Paginator method)

page_kwarg (django.views.generic.list.MultipleObjectMixin attribute)

page_range (Paginator attribute)

PageNotAnInteger

paginate_by (django.views.generic.list.MultipleObjectMixin attribute)

paginate_orphans (django.views.generic.list.MultipleObjectMixin attribute)

paginate_queryset() (django.views.generic.list.MultipleObjectMixin method)

Paginator (class in django.core.paginator)

paginator (ModelAdmin attribute)

(Page attribute)

paginator_class (django.views.generic.list.MultipleObjectMixin attribute)

parent_link (OneToOneField attribute)

parse_date() (in module django.utils.dateparse)

parse_datetime() (in module django.utils.dateparse)

parse_duration() (in module django.utils.dateparse)

parse_time() (in module django.utils.dateparse)

PASSWORD

setting

password (models.User attribute)

password_change() (in module django.contrib.auth.views)

password_change_done() (in module django.contrib.auth.views)

password_change_done_template (AdminSite attribute)

password_change_template (AdminSite attribute)

password_changed() (in module django.contrib.auth.password_validation)

PASSWORD_HASHERS

setting

password_reset() (in module django.contrib.auth.views)

password_reset_complete() (in module django.contrib.auth.views)

password_reset_confirm() (in module django.contrib.auth.views)

password_reset_done() (in module django.contrib.auth.views)

PASSWORD_RESET_TIMEOUT_DAYS

setting

password_validators_help_text_html() (in module django.contrib.auth.password_validation)

password_validators_help_texts() (in module django.contrib.auth.password_validation)

PasswordChangeForm (class in django.contrib.auth.forms)

PasswordInput (class in django.forms)

PasswordResetForm (class in django.contrib.auth.forms)

Patch release

patch() (Client method)

patch_cache_control() (in module django.utils.cache)

patch_response_headers() (in module django.utils.cache)

patch_vary_headers() (in module django.utils.cache)

path (AppConfig attribute)

(FilePathField attribute), [1]

(HttpRequest attribute)

path() (Storage method)

path_info (HttpRequest attribute)

pattern_name (django.views.generic.base.RedirectView attribute)

patterns() (in module django.conf.urls)

Perimeter (class in django.contrib.gis.db.models.functions)

perimeter() (GeoQuerySet method)

permanent (django.views.generic.base.RedirectView attribute)

permission_denied_message (AccessMixin attribute)

permission_required() (in module django.contrib.auth.decorators)

PermissionDenied

PermissionRequiredMixin (class in django.contrib.auth.mixins)

permissions (models.Group attribute)

(Options attribute)

PersistentRemoteUserMiddleware (class in django.contrib.auth.middleware)

pgettext() (in module django.utils.translation)

pgettext_lazy() (in module django.utils.translation)

phone2numeric

template filter

ping_google

django-admin command

ping_google() (in module django.contrib.sitemaps)

pixel_count (GDALBand attribute)

pk (Model attribute)

pk_url_kwarg (django.views.generic.detail.SingleObjectMixin attribute)

pluralize

template filter

Point (class in django.contrib.gis.gdal)

(class in django.contrib.gis.geos)

point_count (OGRGeometry attribute)

point_on_surface (GEOSGeometry attribute)

point_on_surface() (GeoQuerySet method)

PointField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

PointOnSurface (class in django.contrib.gis.db.models.functions)

Polygon (class in django.contrib.gis.gdal)

(class in django.contrib.gis.geos)

PolygonField (class in django.contrib.gis.db.models)

(class in django.contrib.gis.forms)

pop() (backends.base.SessionBase method)

(Context method)

(QueryDict method)

popitem() (QueryDict method)

PORT

setting

PositiveIntegerField (class in django.db.models)

PositiveSmallIntegerField (class in django.db.models)

POST (HttpRequest attribute)

post() (Client method)

(django.views.generic.edit.ProcessFormView method)

post_process() (storage.StaticFilesStorage method)

POSTGIS_VERSION

setting

pprint

template filter

pre_init (django.db.models.signals attribute)

pre_save() (Field method)

precision (Field attribute)

Prefetch (class in django.db.models)

prefetch_related() (in module django.db.models.query.QuerySet)

prefix (django.views.generic.edit.FormMixin attribute)

(Form attribute)

prepared (GEOSGeometry attribute)

PreparedGeometry (class in django.contrib.gis.geos)

PREPEND_WWW

setting

prepopulated_fields (ModelAdmin attribute)

preserve_filters (ModelAdmin attribute)

pretty_wkt (SpatialReference attribute)

previous_page_number() (Page method)

primary_key (Field attribute)

priority (Sitemap attribute)

process_exception()

process_lhs() (Lookup method)

process_request()

process_response()

process_rhs() (Lookup method)

process_template_response()

process_view()

ProgrammingError

proj (SpatialReference attribute)

proj4 (SpatialReference attribute)

project

project() (GEOSGeometry method)

project_normalized() (GEOSGeometry method)

projected (SpatialReference attribute)

property

PROTECT (in module django.db.models)

protocol (GenericIPAddressField attribute), [1]

(Sitemap attribute)

proxy (Options attribute)

push() (Context method)

put() (Client method)

(django.views.generic.edit.ProcessFormView method)

Python Enhancement Proposals

PEP 20

PEP 234

PEP 249, [1], [2], [3], [4]

PEP 257

PEP 3134, [1]

PEP 318

PEP 3333, [1], [2], [3]

PEP 343

PEP 386

PEP 414

PEP 420

PEP 8, [1], [2], [3], [4]

python_2_unicode_compatible() (in module django.utils.encoding)

PYTHONHASHSEED

PYTHONPATH

PYTHONSTARTUP

PYTHONWARNINGS

Q

Q (class in django.db.models)

query_pk_and_slug (django.views.generic.detail.SingleObjectMixin attribute)

query_string (django.views.generic.base.RedirectView attribute)

QueryDict (class in django.http)

queryset

QuerySet (class in django.db.models.query)

queryset (django.views.generic.detail.SingleObjectMixin attribute)

(ModelChoiceField attribute)

(ModelMultipleChoiceField attribute)

(django.views.generic.list.MultipleObjectMixin attribute)

R

radio_fields (ModelAdmin attribute)

RadioSelect (class in django.forms)

raise_exception (AccessMixin attribute)

random

template filter

range

field lookup type

range_type (django.contrib.postgres.forms.BaseRangeField attribute)

(RangeField attribute)

RangeField (class in django.contrib.postgres.fields)

rangefield.adjacent_to

field lookup type

rangefield.contained_by

field lookup type

rangefield.contains

field lookup type

rangefield.endswith

field lookup type

rangefield.fully_gt

field lookup type

rangefield.fully_lt

field lookup type

rangefield.isempty

field lookup type

rangefield.not_gt

field lookup type

rangefield.not_lt

field lookup type

rangefield.overlap

field lookup type

rangefield.startswith

field lookup type

RangeMaxValueValidator (class in django.contrib.postgres.validators)

RangeMinValueValidator (class in django.contrib.postgres.validators)

RangeWidget (class in django.contrib.postgres.forms)

RasterField (class in django.contrib.gis.db.models)

raw() (in module django.db.models.query.QuerySet)

(Manager method)

raw_id_fields (InlineModelAdmin attribute)

(ModelAdmin attribute)

RawSQL (class in django.db.models.expressions)

read() (File method)

(HttpRequest method)

(UploadedFile method)

readline() (HttpRequest method)

readlines() (HttpRequest method)

readonly_fields (ModelAdmin attribute)

ready (apps attribute)

ready() (AppConfig method)

reason_phrase (HttpResponse attribute)

(StreamingHttpResponse attribute)

receive_data_chunk() (FileUploadHandler method)

receiver() (in module django.dispatch)

record_by_addr() (GeoIP method)

record_by_name() (GeoIP method)

recursive (FilePathField attribute), [1]

redirect() (in module django.shortcuts)

redirect_field_name (AccessMixin attribute)

redirect_to_login() (in module django.contrib.auth.views)

RedirectView (built-in class)

refresh_from_db() (Model method)

refs_aggregate() (Expression method)

regex

field lookup type

regex (RegexField attribute)

(RegexValidator attribute)

RegexField (class in django.forms)

RegexValidator (class in django.core.validators)

region_by_addr() (GeoIP method)

region_by_name() (GeoIP method)

register() (in module django.contrib.admin)

(in module django.core.checks)

register_lookup() (django.db.models.lookups.RegisterLookupMixin class method)

RegrAvgX (class in django.contrib.postgres.aggregates)

RegrAvgY (class in django.contrib.postgres.aggregates)

RegrCount (class in django.contrib.postgres.aggregates)

RegrIntercept (class in django.contrib.postgres.aggregates)

regroup

template tag

RegrR2 (class in django.contrib.postgres.aggregates)

RegrSlope (class in django.contrib.postgres.aggregates)

RegrSXX (class in django.contrib.postgres.aggregates)

RegrSXY (class in django.contrib.postgres.aggregates)

RegrSYY (class in django.contrib.postgres.aggregates)

relabeled_clone() (Expression method)

relate

field lookup type

relate() (GEOSGeometry method)

relate_pattern() (GEOSGeometry method)

related_model (Field attribute)

related_name (ForeignKey attribute)

(ManyToManyField attribute)

related_query_name (ForeignKey attribute)

(GenericRelation attribute)

(ManyToManyField attribute)

RelatedManager (class in django.db.models.fields.related)

RemoteUserBackend (class in django.contrib.auth.backends)

RemoteUserMiddleware (class in django.contrib.auth.middleware)

remove() (RelatedManager method)

remove_field() (BaseDatabaseSchemaEditor method)

remove_tags() (in module django.utils.html)

remove_trailing_nulls (SplitArrayField attribute)

RemoveField (class in django.db.migrations.operations)

removetags

template filter

RenameField (class in django.db.migrations.operations)

RenameModel (class in django.db.migrations.operations)

render() (in module django.shortcuts)

(MultiWidget method)

(SimpleTemplateResponse method)

(Template method), [1]

(Widget method)

render_to_response() (django.views.generic.base.TemplateResponseMixin method)

(in module django.shortcuts)

render_to_string() (in module django.template.loader)

render_value (PasswordInput attribute)

rendered_content (SimpleTemplateResponse attribute)

request (Response attribute)

RequestContext (class in django.template)

RequestFactory (class in django.test)

requests.RequestSite (class in django.contrib.sites)

require_all_fields (MultiValueField attribute)

require_GET() (in module django.views.decorators.http)

require_http_methods() (in module django.views.decorators.http)

require_POST() (in module django.views.decorators.http)

require_safe() (in module django.views.decorators.http)

required (Field attribute)

required_css_class (Form attribute)

required_db_features (Options attribute)

required_db_vendor (Options attribute)

REQUIRED_FIELDS (models.CustomUser attribute)

RequireDebugFalse (class in django.utils.log)

RequireDebugTrue (class in django.utils.log)

requires_csrf_token() (in module django.views.decorators.csrf)

requires_system_checks (BaseCommand attribute)

reset_sequences (TransactionTestCase attribute)

resolve() (in module django.core.urlresolvers)

resolve_context() (SimpleTemplateResponse method)

resolve_expression() (Expression method)

resolve_template() (SimpleTemplateResponse method)

Resolver404

resolver_match (HttpRequest attribute)

(Response attribute)

ResolverMatch (class in django.core.urlresolvers)

Response (class in django.test)

response_add() (ModelAdmin method)

response_change() (ModelAdmin method)

response_class (django.views.generic.base.TemplateResponseMixin attribute)

response_delete() (ModelAdmin method)

response_gone_class (middleware.RedirectFallbackMiddleware attribute)

response_redirect_class (CommonMiddleware attribute)

(LocaleMiddleware attribute)

(middleware.RedirectFallbackMiddleware attribute)

Reverse (class in django.contrib.gis.db.models.functions)

reverse() (in module django.core.urlresolvers)

(in module django.db.models.query.QuerySet)

reverse_geom() (GeoQuerySet method)

reverse_lazy() (in module django.core.urlresolvers)

reverse_ordering() (Expression method)

RFC

RFC 1034

RFC 1123

RFC 2046#section-5.2.1

RFC 2109, [1], [2]

RFC 2396

RFC 2616, [1]

RFC 2732

RFC 2822

RFC 3987#section-3.1, [1]

RFC 3987#section-3.2, [1]

RFC 4291#section-2.2, [1]

RFC 6265

RFC 7231, [1], [2]

RFC 7231#section-4.2.1, [1]

RFC 7231#section-4.3.8

RFC 7231#section-6, [1], [2]

RFC 7231#section-6.1, [1]

RFC 7231#section-6.5.3

RFC 7231#section-7.1.1.1

RFC 7231#section-7.1.4, [1]

RFC 7234

RFC 7234#section-5.2.2.8

RFC 7239#page-7

rhs (Lookup attribute)

right

field lookup type

ring (GEOSGeometry attribute)

rjust

template filter

rollback() (in module django.db.transaction)

root_attributes() (SyndicationFeed method)

ROOT_URLCONF

setting

Rss201rev2Feed (class in django.utils.feedgenerator)

RssFeed (class in django.utils.feedgenerator)

RssUserland091Feed (class in django.utils.feedgenerator)

run_suite() (DiscoverRunner method)

run_tests() (DiscoverRunner method)

RunPython (class in django.db.migrations.operations)

runserver

django-admin command, [1]

runserver command line option

--insecure

--ipv6, -6

--noreload

--nostatic

--nothreading

RunSQL (class in django.db.migrations.operations)

S

safe

template filter

SafeBytes (class in django.utils.safestring)

SafeExceptionReporterFilter (class in django.views.debug)

safeseq

template filter

SafeString (class in django.utils.safestring)

SafeText (class in django.utils.safestring)

SafeUnicode (class in django.utils.safestring)

same_as

field lookup type

sample (CovarPop attribute)

(StdDev attribute)

(Variance attribute)

save() (base_session.BaseSessionManager method)

(FieldFile method)

(File method)

(LayerMapping method)

(Model method)

(Storage method)

save_as (ModelAdmin attribute)

save_formset() (ModelAdmin method)

save_model() (ModelAdmin method)

save_on_top (ModelAdmin attribute)

save_related() (ModelAdmin method)

savepoint() (in module django.db.transaction)

savepoint_commit() (in module django.db.transaction)

savepoint_rollback() (in module django.db.transaction)

Scale (class in django.contrib.gis.db.models.functions)

scale (GDALRaster attribute)

scale() (GeoQuerySet method)

scheme (HttpRequest attribute)

schemes (URLValidator attribute)

search

field lookup type

search_fields (ModelAdmin attribute)

second

field lookup type

SECRET_KEY

setting

SECURE_BROWSER_XSS_FILTER

setting

SECURE_CONTENT_TYPE_NOSNIFF

setting

SECURE_HSTS_INCLUDE_SUBDOMAINS

setting

SECURE_HSTS_SECONDS

setting

SECURE_PROXY_SSL_HEADER

setting

SECURE_REDIRECT_EXEMPT

setting

SECURE_SSL_HOST

setting

SECURE_SSL_REDIRECT

setting

SecurityMiddleware (class in django.middleware.security)

Select (class in django.forms)

select_for_update() (in module django.db.models.query.QuerySet)

select_on_save (Options attribute)

select_related() (in module django.db.models.query.QuerySet)

select_template() (Engine method)

(in module django.template.loader)

SelectDateWidget (class in django.forms)

SelectMultiple (class in django.forms)

semi_major (SpatialReference attribute)

semi_minor (SpatialReference attribute)

send() (Signal method)

send_email() (PasswordResetForm method)

send_mail() (AdminEmailHandler method)

(in module django.core.mail)

send_mass_mail() (in module django.core.mail)

send_robust() (Signal method)

sendtestemail

django-admin command

sendtestemail command line option

--admins

--managers

sensitive_post_parameters() (in module django.views.decorators.debug)

sensitive_variables() (in module django.views.decorators.debug)

SeparateDatabaseAndState (class in django.db.migrations.operations)

SERIALIZATION_MODULES

setting

serializers.JSONSerializer (class in django.contrib.sessions)

serializers.PickleSerializer (class in django.contrib.sessions)

SERVER_EMAIL

setting

session (Client attribute)

(HttpRequest attribute)

SESSION_CACHE_ALIAS

setting

SESSION_COOKIE_AGE

setting

SESSION_COOKIE_DOMAIN

setting

SESSION_COOKIE_HTTPONLY

setting

SESSION_COOKIE_NAME

setting

SESSION_COOKIE_PATH

setting

SESSION_COOKIE_SECURE

setting

session_data (base_session.AbstractBaseSession attribute)

SESSION_ENGINE

setting

SESSION_EXPIRE_AT_BROWSER_CLOSE

setting

SESSION_FILE_PATH

setting

session_key (base_session.AbstractBaseSession attribute)

SESSION_SAVE_EVERY_REQUEST

setting

SESSION_SERIALIZER

setting

SessionAuthenticationMiddleware (class in django.contrib.auth.middleware)

SessionMiddleware (class in django.contrib.sessions.middleware)

SET() (in module django.db.models)

set() (RelatedManager method)

set_autocommit() (in module django.db.transaction)

set_cookie() (HttpResponse method)

SET_DEFAULT (in module django.db.models)

set_expiry() (backends.base.SessionBase method)

set_language() (in module django.views.i18n)

SET_NULL (in module django.db.models)

set_password() (models.AbstractBaseUser method)

(models.User method)

set_rollback() (in module django.db.transaction)

set_signed_cookie() (HttpResponse method)

set_source_expressions() (Expression method)

set_test_cookie() (backends.base.SessionBase method)

set_unusable_password() (models.AbstractBaseUser method)

(models.User method)

setdefault() (backends.base.SessionBase method)

(Context method)

(HttpResponse method)

(QueryDict method)

setlist() (QueryDict method)

setlistdefault() (QueryDict method)

SetPasswordForm (class in django.contrib.auth.forms)

setting

ABSOLUTE_URL_OVERRIDES

ADMINS

ALLOWED_HOSTS

ALLOWED_INCLUDE_ROOTS

APPEND_SLASH

AUTHENTICATION_BACKENDS

AUTH_PASSWORD_VALIDATORS

AUTH_USER_MODEL

CACHES

CACHES-BACKEND

CACHES-KEY_FUNCTION

CACHES-KEY_PREFIX

CACHES-LOCATION

CACHES-OPTIONS

CACHES-TIMEOUT

CACHES-VERSION

CACHE_MIDDLEWARE_ALIAS

CACHE_MIDDLEWARE_KEY_PREFIX

CACHE_MIDDLEWARE_SECONDS

CONN_MAX_AGE

CSRF_COOKIE_AGE

CSRF_COOKIE_DOMAIN

CSRF_COOKIE_HTTPONLY

CSRF_COOKIE_NAME

CSRF_COOKIE_PATH

CSRF_COOKIE_SECURE

CSRF_FAILURE_VIEW

CSRF_HEADER_NAME

CSRF_TRUSTED_ORIGINS

DATABASE-ATOMIC_REQUESTS

DATABASE-AUTOCOMMIT

DATABASE-ENGINE

DATABASE-TEST

DATABASE-TIME_ZONE

DATABASES

DATABASE_ROUTERS

DATAFILE

DATAFILE_MAXSIZE

DATAFILE_TMP

DATAFILE_TMP_MAXSIZE

DATETIME_FORMAT

DATETIME_INPUT_FORMATS

DATE_FORMAT

DATE_INPUT_FORMATS

DEBUG

DEBUG_PROPAGATE_EXCEPTIONS

DECIMAL_SEPARATOR

DEFAULT_CHARSET

DEFAULT_CONTENT_TYPE

DEFAULT_EXCEPTION_REPORTER_FILTER

DEFAULT_FILE_STORAGE

DEFAULT_FROM_EMAIL

DEFAULT_INDEX_TABLESPACE

DEFAULT_TABLESPACE

DISALLOWED_USER_AGENTS

EMAIL_BACKEND

EMAIL_FILE_PATH

EMAIL_HOST

EMAIL_HOST_PASSWORD

EMAIL_HOST_USER

EMAIL_PORT

EMAIL_SSL_CERTFILE

EMAIL_SSL_KEYFILE

EMAIL_SUBJECT_PREFIX

EMAIL_TIMEOUT

EMAIL_USE_SSL

EMAIL_USE_TLS

FILE_CHARSET

FILE_UPLOAD_DIRECTORY_PERMISSIONS

FILE_UPLOAD_HANDLERS

FILE_UPLOAD_MAX_MEMORY_SIZE

FILE_UPLOAD_PERMISSIONS

FILE_UPLOAD_TEMP_DIR

FIRST_DAY_OF_WEEK

FIXTURE_DIRS

FORCE_SCRIPT_NAME

FORMAT_MODULE_PATH

GDAL_LIBRARY_PATH

GEOIP_CITY, [1]

GEOIP_COUNTRY, [1]

GEOIP_LIBRARY_PATH

GEOIP_PATH, [1]

GEOS_LIBRARY_PATH

HOST

IGNORABLE_404_URLS

INSTALLED_APPS

INTERNAL_IPS

LANGUAGES

LANGUAGE_CODE

LANGUAGE_COOKIE_AGE

LANGUAGE_COOKIE_DOMAIN

LANGUAGE_COOKIE_NAME

LANGUAGE_COOKIE_PATH

LOCALE_PATHS

LOGGING

LOGGING_CONFIG

LOGIN_REDIRECT_URL

LOGIN_URL

MANAGERS

MEDIA_ROOT

MEDIA_URL

MESSAGE_LEVEL

MESSAGE_STORAGE

MESSAGE_TAGS

MIDDLEWARE_CLASSES

MIGRATION_MODULES

MONTH_DAY_FORMAT

NAME

NUMBER_GROUPING

OPTIONS

PASSWORD

PASSWORD_HASHERS

PASSWORD_RESET_TIMEOUT_DAYS

PORT

POSTGIS_VERSION

PREPEND_WWW

ROOT_URLCONF

SECRET_KEY

SECURE_BROWSER_XSS_FILTER

SECURE_CONTENT_TYPE_NOSNIFF

SECURE_HSTS_INCLUDE_SUBDOMAINS

SECURE_HSTS_SECONDS

SECURE_PROXY_SSL_HEADER

SECURE_REDIRECT_EXEMPT

SECURE_SSL_HOST

SECURE_SSL_REDIRECT

SERIALIZATION_MODULES

SERVER_EMAIL

SESSION_CACHE_ALIAS

SESSION_COOKIE_AGE

SESSION_COOKIE_DOMAIN

SESSION_COOKIE_HTTPONLY

SESSION_COOKIE_NAME

SESSION_COOKIE_PATH

SESSION_COOKIE_SECURE

SESSION_ENGINE

SESSION_EXPIRE_AT_BROWSER_CLOSE

SESSION_FILE_PATH

SESSION_SAVE_EVERY_REQUEST

SESSION_SERIALIZER

SHORT_DATETIME_FORMAT

SHORT_DATE_FORMAT

SIGNING_BACKEND

SILENCED_SYSTEM_CHECKS

SITE_ID

STATICFILES_DIRS

STATICFILES_FINDERS

STATICFILES_STORAGE

STATIC_ROOT

STATIC_URL

TEMPLATES

TEMPLATES-APP_DIRS

TEMPLATES-BACKEND

TEMPLATES-DIRS

TEMPLATES-NAME

TEMPLATES-OPTIONS

TEMPLATE_CONTEXT_PROCESSORS

TEMPLATE_DEBUG

TEMPLATE_DIRS

TEMPLATE_LOADERS

TEMPLATE_STRING_IF_INVALID

TEST_CHARSET

TEST_COLLATION

TEST_CREATE

TEST_DEPENDENCIES

TEST_MIRROR

TEST_NAME

TEST_NON_SERIALIZED_APPS

TEST_PASSWD

TEST_RUNNER

TEST_SERIALIZE

TEST_TBLSPACE

TEST_TBLSPACE_TMP

TEST_USER

TEST_USER_CREATE

THOUSAND_SEPARATOR

TIME_FORMAT

TIME_INPUT_FORMATS

TIME_ZONE

USER

USE_ETAGS

USE_I18N

USE_L10N

USE_THOUSAND_SEPARATOR

USE_TZ

USE_X_FORWARDED_HOST

USE_X_FORWARDED_PORT

WSGI_APPLICATION

X_FRAME_OPTIONS

YEAR_MONTH_FORMAT

settings() (SimpleTestCase method)

setup() (in module django)

setup_databases() (DiscoverRunner method)

setup_test_environment() (DiscoverRunner method)

(in module django.test.utils)

setUpTestData() (django.test.TestCase class method)

shell

django-admin command

shell (Polygon attribute)

shell command line option

--interface {ipython,bpython}, -i {ipython,bpython}

--nostartup

--plain

SHORT_DATE_FORMAT

setting

SHORT_DATETIME_FORMAT

setting

shortcuts

shortcuts.get_current_site() (in module django.contrib.sites)

show_change_link (InlineModelAdmin attribute)

show_full_result_count (ModelAdmin attribute)

showmigrations

django-admin command

showmigrations command line option

--database DATABASE

--list, -l

--plan, -p

sign() (TimestampSigner method)

Signal (class in django.dispatch)

Signer (class in django.core.signing)

SIGNING_BACKEND

setting

SILENCED_SYSTEM_CHECKS

setting

simple (GEOSGeometry attribute)

simple_tag() (django.template.Library method)

SimpleArrayField (class in django.contrib.postgres.forms)

SimpleTemplateResponse (class in django.template.response)

SimpleTestCase (class in django.test)

simplify() (GEOSGeometry method)

site (HttpRequest attribute)

site_header (AdminSite attribute)

SITE_ID

setting

site_title (AdminSite attribute)

site_url (AdminSite attribute)

Sitemap (class in django.contrib.sitemaps)

size (ArrayField attribute)

(FieldFile attribute)

(File attribute)

(SplitArrayField attribute)

(UploadedFile attribute)

size() (Storage method)

skew (GDALRaster attribute)

skipIfDBFeature() (in module django.test)

skipUnlessDBFeature() (in module django.test)

slice

template filter

slug

slug_field (django.views.generic.detail.SingleObjectMixin attribute)

slug_url_kwarg (django.views.generic.detail.SingleObjectMixin attribute)

SlugField (class in django.db.models)

(class in django.forms)

slugify

template filter

slugify() (in module django.utils.text)

SmallIntegerField (class in django.db.models)

smart_bytes() (in module django.utils.encoding)

smart_str() (in module django.utils.encoding)

smart_text() (in module django.utils.encoding)

smart_unicode() (in module django.utils.encoding)

snap_to_grid() (GeoQuerySet method)

SnapToGrid (class in django.contrib.gis.db.models.functions)

spaceless

template tag

spatial_filter (Layer attribute)

spatial_index (BaseSpatialField attribute)

SpatialReference (class in django.contrib.gis.gdal)

SplitArrayField (class in django.contrib.postgres.forms)

SplitDateTimeField (class in django.forms)

SplitDateTimeWidget (class in django.forms)

SplitHiddenDateTimeWidget (class in django.forms)

sqlflush

django-admin command

sqlflush command line option

--database DATABASE

sqlmigrate

django-admin command

sqlmigrate command line option

--backwards

--database DATABASE

sqlsequencereset

django-admin command

sqlsequencereset command line option

--database DATABASE

squashmigrations

django-admin command

squashmigrations command line option

--no-optimize

--noinput, --no-input

srid (BaseSpatialField attribute)

(Field attribute)

(GEOSGeometry attribute)

(OGRGeometry attribute)

(SpatialReference attribute)

(WKBWriter attribute)

srs (GDALRaster attribute)

(GEOSGeometry attribute)

(Layer attribute)

(OGRGeometry attribute)

ssi

template tag

StackedInline (class in django.contrib.admin)

staff_member_required() (in module django.contrib.admin.views.decorators)

start_index() (Page method)

startapp

django-admin command

startapp command line option

--extension EXTENSIONS, -e EXTENSIONS

--name FILES, -n FILES

--template TEMPLATE

startproject

django-admin command

startproject command line option

--extension EXTENSIONS, -e EXTENSIONS

--name FILES, -n FILES

--template TEMPLATE

startswith

field lookup type

static

template tag

static() (in module django.template.context_processors)

static.serve() (in module django.views)

static.static() (in module django.conf.urls)

STATIC_ROOT

setting

STATIC_URL

setting

staticfiles-static

template tag

STATICFILES_DIRS

setting

STATICFILES_FINDERS

setting

STATICFILES_STORAGE

setting

status_code (HttpResponse attribute)

(Response attribute)

(StreamingHttpResponse attribute)

StdDev (class in django.db.models)

Storage (class in django.core.files.storage)

storage (FileField attribute)

storage.base.BaseStorage (class in django.contrib.messages)

storage.base.Message (class in django.contrib.messages)

storage.CachedStaticFilesStorage (class in django.contrib.staticfiles)

storage.cookie.CookieStorage (class in django.contrib.messages)

storage.fallback.FallbackStorage (class in django.contrib.messages)

storage.ManifestStaticFilesStorage (class in django.contrib.staticfiles)

storage.session.SessionStorage (class in django.contrib.messages)

storage.StaticFilesStorage (class in django.contrib.staticfiles)

streaming (HttpResponse attribute)

(StreamingHttpResponse attribute)

streaming_content (StreamingHttpResponse attribute)

StreamingHttpResponse (class in django.http)

strictly_above

field lookup type

strictly_below

field lookup type

string_concat() (in module django.utils.translation)

StringAgg (class in django.contrib.postgres.aggregates)

stringfilter() (django.template.defaultfilters method)

stringformat

template filter

strip (CharField attribute)

(RegexField attribute)

strip_tags() (in module django.utils.html)

striptags

template filter

style (BaseCommand attribute)

Substr (class in django.db.models.functions)

success_url (django.views.generic.edit.DeletionMixin attribute)

(django.views.generic.edit.FormMixin attribute)

(django.views.generic.edit.ModelFormMixin attribute)

suite_result() (DiscoverRunner method)

Sum (class in django.db.models)

supports_3d (BaseGeometryWidget attribute)

supports_microseconds (Widget attribute)

SuspiciousOperation

svg() (GeoQuerySet method)

swappable (ForeignKey attribute)

(ManyToManyField attribute)

sym_difference() (GeoQuerySet method)

(GEOSGeometry method)

(OGRGeometry method)

SymDifference (class in django.contrib.gis.db.models.functions)

symmetrical (ManyToManyField attribute)

SyndicationFeed (class in django.utils.feedgenerator)

T

TabularInline (class in django.contrib.admin)

teardown_databases() (DiscoverRunner method)

teardown_test_environment() (DiscoverRunner method)

(in module django.test.utils)

tell() (HttpResponse method)

template

(Aggregate attribute)

Template (class in django.template)

template (Func attribute)

(InlineModelAdmin attribute)

template filter

add

addslashes

apnumber

capfirst

center

cut

date

default

default_if_none

dictsort

dictsortreversed

divisibleby

escape

escapejs

filesizeformat

first

floatformat

force_escape

get_digit

intcomma

intword

iriencode

join

language_bidi

language_name

language_name_local

language_name_translated

last

length

length_is

linebreaks

linebreaksbr

linenumbers

ljust

localize

localtime

lower

make_list

naturalday

naturaltime

ordinal

phone2numeric

pluralize

pprint

random

removetags

rjust

safe

safeseq

slice

slugify

stringformat

striptags

time

timesince

timeuntil

timezone

title

truncatechars

truncatechars_html

truncatewords

truncatewords_html

unlocalize

unordered_list

upper

urlencode

urlize

urlizetrunc

utc

wordcount

wordwrap

yesno

template tag

autoescape

block

blocktrans

cache

comment

csrf_token

cycle

debug

extends

filter

firstof

for

get_available_languages

get_current_language

get_current_language_bidi

get_current_timezone

get_flatpages

get_language_info

get_language_info_list

get_media_prefix

get_static_prefix

if

ifchanged

include

language

load

localize

localtime

lorem

now

regroup

spaceless

ssi

static

staticfiles-static

templatetag

timezone

trans

url

verbatim

widthratio

with

TEMPLATE_CONTEXT_PROCESSORS

setting

TEMPLATE_DEBUG

setting

TEMPLATE_DIRS

setting

template_engine (django.views.generic.base.TemplateResponseMixin attribute)

TEMPLATE_LOADERS

setting

template_name (BaseGeometryWidget attribute)

(Origin attribute)

(SimpleTemplateResponse attribute)

(django.views.generic.base.TemplateResponseMixin attribute)

template_name_field (django.views.generic.detail.SingleObjectTemplateResponseMixin attribute)

template_name_suffix (django.views.generic.detail.SingleObjectTemplateResponseMixin attribute)

(django.views.generic.edit.CreateView attribute)

(django.views.generic.edit.DeleteView attribute)

(django.views.generic.edit.UpdateView attribute)

(django.views.generic.list.MultipleObjectTemplateResponseMixin attribute)

TEMPLATE_STRING_IF_INVALID

setting

TemplateDoesNotExist

TemplateResponse (class in django.template.response)

TEMPLATES

setting

templates (Response attribute)

TEMPLATES-APP_DIRS

setting

TEMPLATES-BACKEND

setting

TEMPLATES-DIRS

setting

TEMPLATES-NAME

setting

TEMPLATES-OPTIONS

setting

TemplateSyntaxError

templatetag

template tag

TemplateView (built-in class)

templatize() (in module django.utils.translation)

temporary_file_path() (TemporaryUploadedFile method)

TemporaryFileUploadHandler (class in django.core.files.uploadhandler)

TemporaryUploadedFile (class in django.core.files.uploadedfile)

test

django-admin command

test command line option

--debug-sql, -d

--failfast

--keepdb, -k

--liveserver LIVESERVER

--noinput, --no-input

--parallel [N]

--reverse, -r

--testrunner TESTRUNNER

test_capability() (Layer method)

TEST_CHARSET

setting

TEST_COLLATION

setting

test_cookie_worked() (backends.base.SessionBase method)

TEST_CREATE

setting

TEST_DEPENDENCIES

setting

test_func() (UserPassesTestMixin method)

test_loader (DiscoverRunner attribute)

TEST_MIRROR

setting

TEST_NAME

setting

TEST_NON_SERIALIZED_APPS

setting

TEST_PASSWD

setting

TEST_RUNNER

setting

test_runner (DiscoverRunner attribute)

TEST_SERIALIZE

setting

test_suite (DiscoverRunner attribute)

TEST_TBLSPACE

setting

TEST_TBLSPACE_TMP

setting

TEST_USER

setting

TEST_USER_CREATE

setting

TestCase (class in django.test)

testing.StaticLiveServerTestCase (class in django.contrib.staticfiles)

testserver

django-admin command

testserver command line option

--addrport ADDRPORT

--noinput, --no-input

Textarea (class in django.forms)

TextField (class in django.db.models)

TextInput (class in django.forms)

THOUSAND_SEPARATOR

setting

through (ManyToManyField attribute)

through_fields (ManyToManyField attribute)

time

template filter

TIME_FORMAT

setting

time_format (SplitDateTimeWidget attribute)

TIME_INPUT_FORMATS

setting

TIME_ZONE

setting

TimeField (class in django.db.models)

(class in django.forms)

TimeInput (class in django.forms)

timesince

template filter

TimestampSigner (class in django.core.signing)

timeuntil

template filter

timezone

template filter

template tag

title

template filter

to_esri() (SpatialReference method)

to_field (ForeignKey attribute)

to_field_name (ModelChoiceField attribute)

(ModelMultipleChoiceField attribute)

to_locale() (in module django.utils.translation)

to_python() (Field method)

TodayArchiveView (built-in class)

(class in django.views.generic.dates)

total_error_count() (BaseFormSet method)

touches

field lookup type

touches() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

trace() (Client method)

trans

template tag

TransactionManagementError

TransactionNow (class in django.contrib.postgres.functions)

TransactionTestCase (class in django.test)

Transform (class in django.contrib.gis.db.models.functions)

(class in django.db.models)

transform() (GDALRaster method)

(GEOSGeometry method)

(GeoQuerySet method)

(OGRGeometry method)

Translate (class in django.contrib.gis.db.models.functions)

translate() (GeoQuerySet method)

translation string

truncatechars

template filter

truncatechars_html

template filter

truncatewords

template filter

truncatewords_html

template filter

tuple (Envelope attribute)

(OGRGeometry attribute)

type (Field attribute)

type_name (Field attribute)

TypedChoiceField (class in django.forms)

TypedMultipleChoiceField (class in django.forms)

tz() (in module django.template.context_processors)

U

ugettext() (in module django.utils.translation)

ugettext_lazy() (in module django.utils.translation)

ugettext_noop() (in module django.utils.translation)

unaccent

field lookup type

UnaccentExtension (class in django.contrib.postgres.operations)

ungettext() (in module django.utils.translation)

ungettext_lazy() (in module django.utils.translation)

Union (class in django.contrib.gis.db.models)

(class in django.contrib.gis.db.models.functions)

union() (GeoQuerySet method)

(GEOSGeometry method)

(OGRGeometry method)

unionagg() (GeoQuerySet method)

unique (Field attribute)

unique_for_date (Field attribute)

unique_for_month (Field attribute)

unique_for_year (Field attribute)

unique_together (Options attribute)

unit_attname() (django.contrib.gis.measure.Area class method)

(django.contrib.gis.measure.Distance class method)

units (SpatialReference attribute)

unlocalize

template filter

unordered_list

template filter

unpack_ipv4 (GenericIPAddressField attribute), [1]

UnreadablePostError

unsign() (TimestampSigner method)

update() (Context method)

(QueryDict method)

(in module django.db.models.query.QuerySet)

update_or_create() (in module django.db.models.query.QuerySet)

update_session_auth_hash() (in module django.contrib.auth.mixins)

UpdateCacheMiddleware (class in django.middleware.cache)

UpdateView (built-in class)

upload_complete() (FileUploadHandler method)

upload_to (FileField attribute)

UploadedFile (class in django.core.files.uploadedfile)

upper

template filter

Upper (class in django.db.models.functions)

ur (Envelope attribute)

uri_to_iri() (in module django.utils.encoding)

url

template tag

url (django.views.generic.base.RedirectView attribute)

(FieldFile attribute)

(HttpResponseRedirect attribute)

url() (in module django.conf.urls)

(Storage method)

url_name (ResolverMatch attribute)

urlconf (HttpRequest attribute)

urlencode

template filter

urlencode() (in module django.utils.http)

(QueryDict method)

URLField (class in django.db.models)

(class in django.forms)

URLInput (class in django.forms)

urlize

template filter

urlizetrunc

template filter

urlquote() (in module django.utils.http)

urlquote_plus() (in module django.utils.http)

urls

definitive

urls (SimpleTestCase attribute)

urls.staticfiles_urlpatterns() (in module django.contrib.staticfiles)

urlsafe_base64_decode() (in module django.utils.http)

urlsafe_base64_encode() (in module django.utils.http)

URLValidator (class in django.core.validators)

USE_ETAGS

setting

USE_I18N

setting

USE_L10N

setting

USE_THOUSAND_SEPARATOR

setting

USE_TZ

setting

USE_X_FORWARDED_HOST

setting

USE_X_FORWARDED_PORT

setting

USER

setting

user (HttpRequest attribute)

(LogEntry attribute)

user_logged_in() (in module django.contrib.auth.signals)

user_logged_out() (in module django.contrib.auth.signals)

user_login_failed() (in module django.contrib.auth.signals)

user_passes_test() (in module django.contrib.auth.decorators)

user_permissions (models.User attribute)

UserAttributeSimilarityValidator (class in django.contrib.auth.password_validation)

UserChangeForm (class in django.contrib.auth.forms)

UserCreationForm (class in django.contrib.auth.forms)

username (models.User attribute)

USERNAME_FIELD (models.CustomUser attribute)

UserPassesTestMixin (class in django.contrib.auth.mixins)

using() (in module django.db.models.query.QuerySet)

utc

template filter

utc (in module django.utils.timezone)

UUIDField (class in django.db.models)

(class in django.forms)

V

valid (GEOSGeometry attribute)

valid_reason (GEOSGeometry attribute)

validate() (SpatialReference method)

validate_comma_separated_integer_list (in module django.core.validators)

validate_email (in module django.core.validators)

validate_ipv46_address (in module django.core.validators)

validate_ipv4_address (in module django.core.validators)

validate_ipv6_address (in module django.core.validators)

validate_password() (in module django.contrib.auth.password_validation)

validate_slug (in module django.core.validators)

validate_unicode_slug (in module django.core.validators)

validate_unique() (Model method)

ValidationError

validators (Field attribute), [1]

Value (class in django.db.models)

value (Field attribute)

value() (BoundField method)

value_from_datadict() (Widget method)

value_to_string() (Field method)

values() (in module django.db.models.query.QuerySet)

(QueryDict method)

values_list() (in module django.db.models.query.QuerySet)

Variance (class in django.db.models)

vary_on_cookie() (in module django.views.decorators.vary)

vary_on_headers() (in module django.views.decorators.vary)

verbatim

template tag

verbose_name (AppConfig attribute)

(Field attribute)

(InlineModelAdmin attribute)

(Options attribute)

verbose_name_plural (InlineModelAdmin attribute)

(Options attribute)

version

django-admin command

view

View (built-in class)

view_name (ResolverMatch attribute)

view_on_site (ModelAdmin attribute)

ViewDoesNotExist

views.Feed (class in django.contrib.syndication)

views.index() (in module django.contrib.sitemaps)

views.serve() (in module django.contrib.staticfiles)

views.sitemap() (in module django.contrib.sitemaps)

views.SuccessMessageMixin (class in django.contrib.messages)

W

W3CGeoFeed (class in django.contrib.gis.feeds)

Warning (class in django.core.checks)

warp() (GDALRaster method)

week (WeekMixin attribute)

week_day

field lookup type

week_format (WeekMixin attribute)

WeekArchiveView (built-in class)

(class in django.views.generic.dates)

WeekMixin (class in django.views.generic.dates)

When (class in django.db.models.expressions)

whitelist (EmailValidator attribute)

Widget (class in django.forms)

widget (Field attribute)

(MultiValueField attribute)

widgets (MultiWidget attribute)

width (Field attribute)

(GDALBand attribute)

(GDALRaster attribute)

(ImageFile attribute)

width_field (ImageField attribute)

widthratio

template tag

with

template tag

within

field lookup type

within() (GEOSGeometry method)

(OGRGeometry method)

(PreparedGeometry method)

wkb (GEOSGeometry attribute)

(OGRGeometry attribute)

wkb_size (OGRGeometry attribute)

WKBReader (class in django.contrib.gis.geos)

WKBWriter (class in django.contrib.gis.geos)

wkt (Envelope attribute)

(GEOSGeometry attribute)

(OGRGeometry attribute)

(SpatialReference attribute)

WKTReader (class in django.contrib.gis.geos)

WKTWriter (class in django.contrib.gis.geos)

wordcount

template filter

wordwrap

template filter

writable() (HttpResponse method)

write() (File method)

(HttpResponse method)

(SyndicationFeed method)

(WKBWriter method)

(WKTWriter method)

write_hex() (WKBWriter method)

writelines() (HttpResponse method)

writeString() (SyndicationFeed method)

WSGI_APPLICATION

setting

wsgi_request (Response attribute)

X

x (LineString attribute)

(Point attribute)

X_FRAME_OPTIONS

setting

XFrameOptionsMiddleware (class in django.middleware.clickjacking)

xml

suckiness of

xml (SpatialReference attribute)

xreadlines() (HttpRequest method)

Y

y (LineString attribute)

(Point attribute)

year

field lookup type

year (YearMixin attribute)

year_format (YearMixin attribute)

YEAR_MONTH_FORMAT

setting

YearArchiveView (built-in class)

(class in django.views.generic.dates)

YearMixin (class in django.views.generic.dates)

years (SelectDateWidget attribute)

yesno

template filter

Z

z (LineString attribute)

(Point attribute)

Search

Please activate JavaScript to enable the search functionality.

From here you can search these documents. Enter your search words into the box below and click "search". Note that the search function will automatically search for all of the words. Pages containing fewer words won't appear in the result list.

Source code for pytz

'''
datetime.tzinfo timezone definitions generated from the
Olson timezone database:

ftp://elsie.nci.nih.gov/pub/tz*.tar.gz

See the datetime section of the Python Library Reference for information
on how to use these modules.
'''

# The IANA (nee Olson) database is updated several times a year.
OLSON_VERSION = '2016f'
VERSION = '2016.6.1'  # Switching to pip compatible version numbering.
__version__ = VERSION

OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling

__all__ = [
'timezone', 'utc', 'country_timezones', 'country_names',
'AmbiguousTimeError', 'InvalidTimeError',
'NonExistentTimeError', 'UnknownTimeZoneError',
'all_timezones', 'all_timezones_set',
'common_timezones', 'common_timezones_set',
]

import sys, datetime, os.path, gettext

from pytz.exceptions import AmbiguousTimeError
from pytz.exceptions import InvalidTimeError
from pytz.exceptions import NonExistentTimeError
from pytz.exceptions import UnknownTimeZoneError
from pytz.lazy import LazyDict, LazyList, LazySet
from pytz.tzinfo import unpickler
from pytz.tzfile import build_tzinfo, _byte_string

try:
unicode

except NameError: # Python 3.x

# Python 3.x doesn't have unicode(), making writing code
# for Python 2.3 and Python 3.x a pain.
unicode = str

def ascii(s):
r"""
>>> ascii('Hello')
'Hello'
>>> ascii('\N{TRADE MARK SIGN}') #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
UnicodeEncodeError: ...
"""
s.encode('ASCII') # Raise an exception if not ASCII
return s # But return the original string - not a byte string.

else: # Python 2.x

def ascii(s):
r"""
>>> ascii('Hello')
'Hello'
>>> ascii(u'Hello')
'Hello'
>>> ascii(u'\N{TRADE MARK SIGN}') #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
UnicodeEncodeError: ...
"""
return s.encode('ASCII')

def open_resource(name):
"""Open a resource from the zoneinfo subdir for reading.

Uses the pkg_resources module if available and no standard file
found at the calculated location.
"""
name_parts = name.lstrip('/').split('/')
for part in name_parts:
if part == os.path.pardir or os.path.sep in part:
raise ValueError('Bad path segment: %r' % part)
filename = os.path.join(os.path.dirname(__file__),
'zoneinfo', *name_parts)
if not os.path.exists(filename):
# http://bugs.launchpad.net/bugs/383171 - we avoid using this
# unless absolutely necessary to help when a broken version of
# pkg_resources is installed.
try:
from pkg_resources import resource_stream
except ImportError:
resource_stream = None

if resource_stream is not None:
return resource_stream(__name__, 'zoneinfo/' + name)
return open(filename, 'rb')

def resource_exists(name):
"""Return true if the given resource exists"""
try:
open_resource(name).close()
return True
except IOError:
return False

# Enable this when we get some translations?
# We want an i18n API that is useful to programs using Python's gettext
# module, as well as the Zope3 i18n package. Perhaps we should just provide
# the POT file and translations, and leave it up to callers to make use
# of them.
#
# t = gettext.translation(
#         'pytz', os.path.join(os.path.dirname(__file__), 'locales'),
#         fallback=True
#         )
# def _(timezone_name):
#     """Translate a timezone name using the current locale, returning Unicode"""
#     return t.ugettext(timezone_name)

_tzinfo_cache = {}

def timezone(zone):
r''' Return a datetime.tzinfo implementation for the given timezone

>>> from datetime import datetime, timedelta
>>> utc = timezone('UTC')
>>> eastern = timezone('US/Eastern')
>>> eastern.zone
'US/Eastern'
>>> timezone(unicode('US/Eastern')) is eastern
True
>>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)
>>> loc_dt = utc_dt.astimezone(eastern)
>>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
>>> loc_dt.strftime(fmt)
'2002-10-27 01:00:00 EST (-0500)'
>>> (loc_dt - timedelta(minutes=10)).strftime(fmt)
'2002-10-27 00:50:00 EST (-0500)'
>>> eastern.normalize(loc_dt - timedelta(minutes=10)).strftime(fmt)
'2002-10-27 01:50:00 EDT (-0400)'
>>> (loc_dt + timedelta(minutes=10)).strftime(fmt)
'2002-10-27 01:10:00 EST (-0500)'

Raises UnknownTimeZoneError if passed an unknown zone.

>>> try:
...     timezone('Asia/Shangri-La')
... except UnknownTimeZoneError:
...     print('Unknown')
Unknown

>>> try:
...     timezone(unicode('\N{TRADE MARK SIGN}'))
... except UnknownTimeZoneError:
...     print('Unknown')
Unknown

'''
if zone.upper() == 'UTC':
return utc

try:
zone = ascii(zone)
except UnicodeEncodeError:
# All valid timezones are ASCII
raise UnknownTimeZoneError(zone)

zone = _unmunge_zone(zone)
if zone not in _tzinfo_cache:
if zone in all_timezones_set:
fp = open_resource(zone)
try:
_tzinfo_cache[zone] = build_tzinfo(zone, fp)
finally:
fp.close()
else:
raise UnknownTimeZoneError(zone)

return _tzinfo_cache[zone]

def _unmunge_zone(zone):
"""Undo the time zone name munging done by older versions of pytz."""
return zone.replace('_plus_', '+').replace('_minus_', '-')

ZERO = datetime.timedelta(0)
HOUR = datetime.timedelta(hours=1)

class UTC(datetime.tzinfo):
"""UTC

Optimized UTC implementation. It unpickles using the single module global
instance defined beneath this class declaration.
"""
zone = "UTC"

_utcoffset = ZERO
_dst = ZERO
_tzname = zone

def fromutc(self, dt):
if dt.tzinfo is None:
return self.localize(dt)
return super(utc.__class__, self).fromutc(dt)

def utcoffset(self, dt):
return ZERO

def tzname(self, dt):
return "UTC"

def dst(self, dt):
return ZERO

def __reduce__(self):
return _UTC, ()

def localize(self, dt, is_dst=False):
'''Convert naive time to local time'''
if dt.tzinfo is not None:
raise ValueError('Not naive datetime (tzinfo is already set)')
return dt.replace(tzinfo=self)

def normalize(self, dt, is_dst=False):
'''Correct the timezone information on the given datetime'''
if dt.tzinfo is self:
return dt
if dt.tzinfo is None:
raise ValueError('Naive time - no tzinfo set')
return dt.astimezone(self)

def __repr__(self):
return "<UTC>"

def __str__(self):
return "UTC"

UTC = utc = UTC()  # UTC is a singleton

def _UTC():
"""Factory function for utc unpickling.

Makes sure that unpickling a utc instance always returns the same
module global.

These examples belong in the UTC class above, but it is obscured; or in
the README.txt, but we are not depending on Python 2.4 so integrating
the README.txt examples with the unit tests is not trivial.

>>> import datetime, pickle
>>> dt = datetime.datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)
>>> naive = dt.replace(tzinfo=None)
>>> p = pickle.dumps(dt, 1)
>>> naive_p = pickle.dumps(naive, 1)
>>> len(p) - len(naive_p)
17
>>> new = pickle.loads(p)
>>> new == dt
True
>>> new is dt
False
>>> new.tzinfo is dt.tzinfo
True
>>> utc is UTC is timezone('UTC')
True
>>> utc is timezone('GMT')
False
"""
return utc
_UTC.__safe_for_unpickling__ = True

def _p(*args):
"""Factory function for unpickling pytz tzinfo instances.

Just a wrapper around tzinfo.unpickler to save a few bytes in each pickle
by shortening the path.
"""
return unpickler(*args)
_p.__safe_for_unpickling__ = True

class _CountryTimezoneDict(LazyDict):
"""Map ISO 3166 country code to a list of timezone names commonly used
in that country.

iso3166_code is the two letter code used to identify the country.

>>> def print_list(list_of_strings):
...     'We use a helper so doctests work under Python 2.3 -> 3.x'
...     for s in list_of_strings:
...         print(s)

>>> print_list(country_timezones['nz'])
Pacific/Auckland
Pacific/Chatham
>>> print_list(country_timezones['ch'])
Europe/Zurich
>>> print_list(country_timezones['CH'])
Europe/Zurich
>>> print_list(country_timezones[unicode('ch')])
Europe/Zurich
>>> print_list(country_timezones['XXX'])
Traceback (most recent call last):
...
KeyError: 'XXX'

Previously, this information was exposed as a function rather than a
dictionary. This is still supported::

>>> print_list(country_timezones('nz'))
Pacific/Auckland
Pacific/Chatham
"""
def __call__(self, iso3166_code):
"""Backwards compatibility."""
return self[iso3166_code]

def _fill(self):
data = {}
zone_tab = open_resource('zone.tab')
try:
for line in zone_tab:
line = line.decode('UTF-8')
if line.startswith('#'):
continue
code, coordinates, zone = line.split(None, 4)[:3]
if zone not in all_timezones_set:
continue
try:
data[code].append(zone)
except KeyError:
data[code] = [zone]
self.data = data
finally:
zone_tab.close()

country_timezones = _CountryTimezoneDict()

class _CountryNameDict(LazyDict):
'''Dictionary proving ISO3166 code -> English name.

>>> print(country_names['au'])
Australia
'''
def _fill(self):
data = {}
zone_tab = open_resource('iso3166.tab')
try:
for line in zone_tab.readlines():
line = line.decode('UTF-8')
if line.startswith('#'):
continue
code, name = line.split(None, 1)
data[code] = name.strip()
self.data = data
finally:
zone_tab.close()

country_names = _CountryNameDict()

# Time-zone info based solely on fixed offsets

class _FixedOffset(datetime.tzinfo):

zone = None # to match the standard pytz API

def __init__(self, minutes):
if abs(minutes) >= 1440:
raise ValueError("absolute offset is too large", minutes)
self._minutes = minutes
self._offset = datetime.timedelta(minutes=minutes)

def utcoffset(self, dt):
return self._offset

def __reduce__(self):
return FixedOffset, (self._minutes, )

def dst(self, dt):
return ZERO

def tzname(self, dt):
return None

def __repr__(self):
return 'pytz.FixedOffset(%d)' % self._minutes

def localize(self, dt, is_dst=False):
'''Convert naive time to local time'''
if dt.tzinfo is not None:
raise ValueError('Not naive datetime (tzinfo is already set)')
return dt.replace(tzinfo=self)

def normalize(self, dt, is_dst=False):
'''Correct the timezone information on the given datetime'''
if dt.tzinfo is self:
return dt
if dt.tzinfo is None:
raise ValueError('Naive time - no tzinfo set')
return dt.astimezone(self)

def FixedOffset(offset, _tzinfos = {}):
"""return a fixed-offset timezone based off a number of minutes.

>>> one = FixedOffset(-330)
>>> one
pytz.FixedOffset(-330)
>>> one.utcoffset(datetime.datetime.now())
datetime.timedelta(-1, 66600)
>>> one.dst(datetime.datetime.now())
datetime.timedelta(0)

>>> two = FixedOffset(1380)
>>> two
pytz.FixedOffset(1380)
>>> two.utcoffset(datetime.datetime.now())
datetime.timedelta(0, 82800)
>>> two.dst(datetime.datetime.now())
datetime.timedelta(0)

The datetime.timedelta must be between the range of -1 and 1 day,
non-inclusive.

>>> FixedOffset(1440)
Traceback (most recent call last):
...
ValueError: ('absolute offset is too large', 1440)

>>> FixedOffset(-1440)
Traceback (most recent call last):
...
ValueError: ('absolute offset is too large', -1440)

An offset of 0 is special-cased to return UTC.

>>> FixedOffset(0) is UTC
True

There should always be only one instance of a FixedOffset per timedelta.
This should be true for multiple creation calls.

>>> FixedOffset(-330) is one
True
>>> FixedOffset(1380) is two
True

It should also be true for pickling.

>>> import pickle
>>> pickle.loads(pickle.dumps(one)) is one
True
>>> pickle.loads(pickle.dumps(two)) is two
True
"""
if offset == 0:
return UTC

info = _tzinfos.get(offset)
if info is None:
# We haven't seen this one before. we need to save it.

# Use setdefault to avoid a race condition and make sure we have
# only one
info = _tzinfos.setdefault(offset, _FixedOffset(offset))

return info

FixedOffset.__safe_for_unpickling__ = True

def _test():
import doctest, os, sys
sys.path.insert(0, os.pardir)
import pytz
return doctest.testmod(pytz)

if __name__ == '__main__':
_test()

all_timezones = \
['Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
'Africa/Algiers',
'Africa/Asmara',
'Africa/Asmera',
'Africa/Bamako',
'Africa/Bangui',
'Africa/Banjul',
'Africa/Bissau',
'Africa/Blantyre',
'Africa/Brazzaville',
'Africa/Bujumbura',
'Africa/Cairo',
'Africa/Casablanca',
'Africa/Ceuta',
'Africa/Conakry',
'Africa/Dakar',
'Africa/Dar_es_Salaam',
'Africa/Djibouti',
'Africa/Douala',
'Africa/El_Aaiun',
'Africa/Freetown',
'Africa/Gaborone',
'Africa/Harare',
'Africa/Johannesburg',
'Africa/Juba',
'Africa/Kampala',
'Africa/Khartoum',
'Africa/Kigali',
'Africa/Kinshasa',
'Africa/Lagos',
'Africa/Libreville',
'Africa/Lome',
'Africa/Luanda',
'Africa/Lubumbashi',
'Africa/Lusaka',
'Africa/Malabo',
'Africa/Maputo',
'Africa/Maseru',
'Africa/Mbabane',
'Africa/Mogadishu',
'Africa/Monrovia',
'Africa/Nairobi',
'Africa/Ndjamena',
'Africa/Niamey',
'Africa/Nouakchott',
'Africa/Ouagadougou',
'Africa/Porto-Novo',
'Africa/Sao_Tome',
'Africa/Timbuktu',
'Africa/Tripoli',
'Africa/Tunis',
'Africa/Windhoek',
'America/Adak',
'America/Anchorage',
'America/Anguilla',
'America/Antigua',
'America/Araguaina',
'America/Argentina/Buenos_Aires',
'America/Argentina/Catamarca',
'America/Argentina/ComodRivadavia',
'America/Argentina/Cordoba',
'America/Argentina/Jujuy',
'America/Argentina/La_Rioja',
'America/Argentina/Mendoza',
'America/Argentina/Rio_Gallegos',
'America/Argentina/Salta',
'America/Argentina/San_Juan',
'America/Argentina/San_Luis',
'America/Argentina/Tucuman',
'America/Argentina/Ushuaia',
'America/Aruba',
'America/Asuncion',
'America/Atikokan',
'America/Atka',
'America/Bahia',
'America/Bahia_Banderas',
'America/Barbados',
'America/Belem',
'America/Belize',
'America/Blanc-Sablon',
'America/Boa_Vista',
'America/Bogota',
'America/Boise',
'America/Buenos_Aires',
'America/Cambridge_Bay',
'America/Campo_Grande',
'America/Cancun',
'America/Caracas',
'America/Catamarca',
'America/Cayenne',
'America/Cayman',
'America/Chicago',
'America/Chihuahua',
'America/Coral_Harbour',
'America/Cordoba',
'America/Costa_Rica',
'America/Creston',
'America/Cuiaba',
'America/Curacao',
'America/Danmarkshavn',
'America/Dawson',
'America/Dawson_Creek',
'America/Denver',
'America/Detroit',
'America/Dominica',
'America/Edmonton',
'America/Eirunepe',
'America/El_Salvador',
'America/Ensenada',
'America/Fort_Nelson',
'America/Fort_Wayne',
'America/Fortaleza',
'America/Glace_Bay',
'America/Godthab',
'America/Goose_Bay',
'America/Grand_Turk',
'America/Grenada',
'America/Guadeloupe',
'America/Guatemala',
'America/Guayaquil',
'America/Guyana',
'America/Halifax',
'America/Havana',
'America/Hermosillo',
'America/Indiana/Indianapolis',
'America/Indiana/Knox',
'America/Indiana/Marengo',
'America/Indiana/Petersburg',
'America/Indiana/Tell_City',
'America/Indiana/Vevay',
'America/Indiana/Vincennes',
'America/Indiana/Winamac',
'America/Indianapolis',
'America/Inuvik',
'America/Iqaluit',
'America/Jamaica',
'America/Jujuy',
'America/Juneau',
'America/Kentucky/Louisville',
'America/Kentucky/Monticello',
'America/Knox_IN',
'America/Kralendijk',
'America/La_Paz',
'America/Lima',
'America/Los_Angeles',
'America/Louisville',
'America/Lower_Princes',
'America/Maceio',
'America/Managua',
'America/Manaus',
'America/Marigot',
'America/Martinique',
'America/Matamoros',
'America/Mazatlan',
'America/Mendoza',
'America/Menominee',
'America/Merida',
'America/Metlakatla',
'America/Mexico_City',
'America/Miquelon',
'America/Moncton',
'America/Monterrey',
'America/Montevideo',
'America/Montreal',
'America/Montserrat',
'America/Nassau',
'America/New_York',
'America/Nipigon',
'America/Nome',
'America/Noronha',
'America/North_Dakota/Beulah',
'America/North_Dakota/Center',
'America/North_Dakota/New_Salem',
'America/Ojinaga',
'America/Panama',
'America/Pangnirtung',
'America/Paramaribo',
'America/Phoenix',
'America/Port-au-Prince',
'America/Port_of_Spain',
'America/Porto_Acre',
'America/Porto_Velho',
'America/Puerto_Rico',
'America/Rainy_River',
'America/Rankin_Inlet',
'America/Recife',
'America/Regina',
'America/Resolute',
'America/Rio_Branco',
'America/Rosario',
'America/Santa_Isabel',
'America/Santarem',
'America/Santiago',
'America/Santo_Domingo',
'America/Sao_Paulo',
'America/Scoresbysund',
'America/Shiprock',
'America/Sitka',
'America/St_Barthelemy',
'America/St_Johns',
'America/St_Kitts',
'America/St_Lucia',
'America/St_Thomas',
'America/St_Vincent',
'America/Swift_Current',
'America/Tegucigalpa',
'America/Thule',
'America/Thunder_Bay',
'America/Tijuana',
'America/Toronto',
'America/Tortola',
'America/Vancouver',
'America/Virgin',
'America/Whitehorse',
'America/Winnipeg',
'America/Yakutat',
'America/Yellowknife',
'Antarctica/Casey',
'Antarctica/Davis',
'Antarctica/DumontDUrville',
'Antarctica/Macquarie',
'Antarctica/Mawson',
'Antarctica/McMurdo',
'Antarctica/Palmer',
'Antarctica/Rothera',
'Antarctica/South_Pole',
'Antarctica/Syowa',
'Antarctica/Troll',
'Antarctica/Vostok',
'Arctic/Longyearbyen',
'Asia/Aden',
'Asia/Almaty',
'Asia/Amman',
'Asia/Anadyr',
'Asia/Aqtau',
'Asia/Aqtobe',
'Asia/Ashgabat',
'Asia/Ashkhabad',
'Asia/Baghdad',
'Asia/Bahrain',
'Asia/Baku',
'Asia/Bangkok',
'Asia/Barnaul',
'Asia/Beirut',
'Asia/Bishkek',
'Asia/Brunei',
'Asia/Calcutta',
'Asia/Chita',
'Asia/Choibalsan',
'Asia/Chongqing',
'Asia/Chungking',
'Asia/Colombo',
'Asia/Dacca',
'Asia/Damascus',
'Asia/Dhaka',
'Asia/Dili',
'Asia/Dubai',
'Asia/Dushanbe',
'Asia/Gaza',
'Asia/Harbin',
'Asia/Hebron',
'Asia/Ho_Chi_Minh',
'Asia/Hong_Kong',
'Asia/Hovd',
'Asia/Irkutsk',
'Asia/Istanbul',
'Asia/Jakarta',
'Asia/Jayapura',
'Asia/Jerusalem',
'Asia/Kabul',
'Asia/Kamchatka',
'Asia/Karachi',
'Asia/Kashgar',
'Asia/Kathmandu',
'Asia/Katmandu',
'Asia/Khandyga',
'Asia/Kolkata',
'Asia/Krasnoyarsk',
'Asia/Kuala_Lumpur',
'Asia/Kuching',
'Asia/Kuwait',
'Asia/Macao',
'Asia/Macau',
'Asia/Magadan',
'Asia/Makassar',
'Asia/Manila',
'Asia/Muscat',
'Asia/Nicosia',
'Asia/Novokuznetsk',
'Asia/Novosibirsk',
'Asia/Omsk',
'Asia/Oral',
'Asia/Phnom_Penh',
'Asia/Pontianak',
'Asia/Pyongyang',
'Asia/Qatar',
'Asia/Qyzylorda',
'Asia/Rangoon',
'Asia/Riyadh',
'Asia/Saigon',
'Asia/Sakhalin',
'Asia/Samarkand',
'Asia/Seoul',
'Asia/Shanghai',
'Asia/Singapore',
'Asia/Srednekolymsk',
'Asia/Taipei',
'Asia/Tashkent',
'Asia/Tbilisi',
'Asia/Tehran',
'Asia/Tel_Aviv',
'Asia/Thimbu',
'Asia/Thimphu',
'Asia/Tokyo',
'Asia/Tomsk',
'Asia/Ujung_Pandang',
'Asia/Ulaanbaatar',
'Asia/Ulan_Bator',
'Asia/Urumqi',
'Asia/Ust-Nera',
'Asia/Vientiane',
'Asia/Vladivostok',
'Asia/Yakutsk',
'Asia/Yekaterinburg',
'Asia/Yerevan',
'Atlantic/Azores',
'Atlantic/Bermuda',
'Atlantic/Canary',
'Atlantic/Cape_Verde',
'Atlantic/Faeroe',
'Atlantic/Faroe',
'Atlantic/Jan_Mayen',
'Atlantic/Madeira',
'Atlantic/Reykjavik',
'Atlantic/South_Georgia',
'Atlantic/St_Helena',
'Atlantic/Stanley',
'Australia/ACT',
'Australia/Adelaide',
'Australia/Brisbane',
'Australia/Broken_Hill',
'Australia/Canberra',
'Australia/Currie',
'Australia/Darwin',
'Australia/Eucla',
'Australia/Hobart',
'Australia/LHI',
'Australia/Lindeman',
'Australia/Lord_Howe',
'Australia/Melbourne',
'Australia/NSW',
'Australia/North',
'Australia/Perth',
'Australia/Queensland',
'Australia/South',
'Australia/Sydney',
'Australia/Tasmania',
'Australia/Victoria',
'Australia/West',
'Australia/Yancowinna',
'Brazil/Acre',
'Brazil/DeNoronha',
'Brazil/East',
'Brazil/West',
'CET',
'CST6CDT',
'Canada/Atlantic',
'Canada/Central',
'Canada/East-Saskatchewan',
'Canada/Eastern',
'Canada/Mountain',
'Canada/Newfoundland',
'Canada/Pacific',
'Canada/Saskatchewan',
'Canada/Yukon',
'Chile/Continental',
'Chile/EasterIsland',
'Cuba',
'EET',
'EST',
'EST5EDT',
'Egypt',
'Eire',
'Etc/GMT',
'Etc/GMT+0',
'Etc/GMT+1',
'Etc/GMT+10',
'Etc/GMT+11',
'Etc/GMT+12',
'Etc/GMT+2',
'Etc/GMT+3',
'Etc/GMT+4',
'Etc/GMT+5',
'Etc/GMT+6',
'Etc/GMT+7',
'Etc/GMT+8',
'Etc/GMT+9',
'Etc/GMT-0',
'Etc/GMT-1',
'Etc/GMT-10',
'Etc/GMT-11',
'Etc/GMT-12',
'Etc/GMT-13',
'Etc/GMT-14',
'Etc/GMT-2',
'Etc/GMT-3',
'Etc/GMT-4',
'Etc/GMT-5',
'Etc/GMT-6',
'Etc/GMT-7',
'Etc/GMT-8',
'Etc/GMT-9',
'Etc/GMT0',
'Etc/Greenwich',
'Etc/UCT',
'Etc/UTC',
'Etc/Universal',
'Etc/Zulu',
'Europe/Amsterdam',
'Europe/Andorra',
'Europe/Astrakhan',
'Europe/Athens',
'Europe/Belfast',
'Europe/Belgrade',
'Europe/Berlin',
'Europe/Bratislava',
'Europe/Brussels',
'Europe/Bucharest',
'Europe/Budapest',
'Europe/Busingen',
'Europe/Chisinau',
'Europe/Copenhagen',
'Europe/Dublin',
'Europe/Gibraltar',
'Europe/Guernsey',
'Europe/Helsinki',
'Europe/Isle_of_Man',
'Europe/Istanbul',
'Europe/Jersey',
'Europe/Kaliningrad',
'Europe/Kiev',
'Europe/Kirov',
'Europe/Lisbon',
'Europe/Ljubljana',
'Europe/London',
'Europe/Luxembourg',
'Europe/Madrid',
'Europe/Malta',
'Europe/Mariehamn',
'Europe/Minsk',
'Europe/Monaco',
'Europe/Moscow',
'Europe/Nicosia',
'Europe/Oslo',
'Europe/Paris',
'Europe/Podgorica',
'Europe/Prague',
'Europe/Riga',
'Europe/Rome',
'Europe/Samara',
'Europe/San_Marino',
'Europe/Sarajevo',
'Europe/Simferopol',
'Europe/Skopje',
'Europe/Sofia',
'Europe/Stockholm',
'Europe/Tallinn',
'Europe/Tirane',
'Europe/Tiraspol',
'Europe/Ulyanovsk',
'Europe/Uzhgorod',
'Europe/Vaduz',
'Europe/Vatican',
'Europe/Vienna',
'Europe/Vilnius',
'Europe/Volgograd',
'Europe/Warsaw',
'Europe/Zagreb',
'Europe/Zaporozhye',
'Europe/Zurich',
'GB',
'GB-Eire',
'GMT',
'GMT+0',
'GMT-0',
'GMT0',
'Greenwich',
'HST',
'Hongkong',
'Iceland',
'Indian/Antananarivo',
'Indian/Chagos',
'Indian/Christmas',
'Indian/Cocos',
'Indian/Comoro',
'Indian/Kerguelen',
'Indian/Mahe',
'Indian/Maldives',
'Indian/Mauritius',
'Indian/Mayotte',
'Indian/Reunion',
'Iran',
'Israel',
'Jamaica',
'Japan',
'Kwajalein',
'Libya',
'MET',
'MST',
'MST7MDT',
'Mexico/BajaNorte',
'Mexico/BajaSur',
'Mexico/General',
'NZ',
'NZ-CHAT',
'Navajo',
'PRC',
'PST8PDT',
'Pacific/Apia',
'Pacific/Auckland',
'Pacific/Bougainville',
'Pacific/Chatham',
'Pacific/Chuuk',
'Pacific/Easter',
'Pacific/Efate',
'Pacific/Enderbury',
'Pacific/Fakaofo',
'Pacific/Fiji',
'Pacific/Funafuti',
'Pacific/Galapagos',
'Pacific/Gambier',
'Pacific/Guadalcanal',
'Pacific/Guam',
'Pacific/Honolulu',
'Pacific/Johnston',
'Pacific/Kiritimati',
'Pacific/Kosrae',
'Pacific/Kwajalein',
'Pacific/Majuro',
'Pacific/Marquesas',
'Pacific/Midway',
'Pacific/Nauru',
'Pacific/Niue',
'Pacific/Norfolk',
'Pacific/Noumea',
'Pacific/Pago_Pago',
'Pacific/Palau',
'Pacific/Pitcairn',
'Pacific/Pohnpei',
'Pacific/Ponape',
'Pacific/Port_Moresby',
'Pacific/Rarotonga',
'Pacific/Saipan',
'Pacific/Samoa',
'Pacific/Tahiti',
'Pacific/Tarawa',
'Pacific/Tongatapu',
'Pacific/Truk',
'Pacific/Wake',
'Pacific/Wallis',
'Pacific/Yap',
'Poland',
'Portugal',
'ROC',
'ROK',
'Singapore',
'Turkey',
'UCT',
'US/Alaska',
'US/Aleutian',
'US/Arizona',
'US/Central',
'US/East-Indiana',
'US/Eastern',
'US/Hawaii',
'US/Indiana-Starke',
'US/Michigan',
'US/Mountain',
'US/Pacific',
'US/Pacific-New',
'US/Samoa',
'UTC',
'Universal',
'W-SU',
'WET',
'Zulu']
all_timezones = LazyList(
tz for tz in all_timezones if resource_exists(tz))

all_timezones_set = LazySet(all_timezones)
common_timezones = \
['Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
'Africa/Algiers',
'Africa/Asmara',
'Africa/Bamako',
'Africa/Bangui',
'Africa/Banjul',
'Africa/Bissau',
'Africa/Blantyre',
'Africa/Brazzaville',
'Africa/Bujumbura',
'Africa/Cairo',
'Africa/Casablanca',
'Africa/Ceuta',
'Africa/Conakry',
'Africa/Dakar',
'Africa/Dar_es_Salaam',
'Africa/Djibouti',
'Africa/Douala',
'Africa/El_Aaiun',
'Africa/Freetown',
'Africa/Gaborone',
'Africa/Harare',
'Africa/Johannesburg',
'Africa/Juba',
'Africa/Kampala',
'Africa/Khartoum',
'Africa/Kigali',
'Africa/Kinshasa',
'Africa/Lagos',
'Africa/Libreville',
'Africa/Lome',
'Africa/Luanda',
'Africa/Lubumbashi',
'Africa/Lusaka',
'Africa/Malabo',
'Africa/Maputo',
'Africa/Maseru',
'Africa/Mbabane',
'Africa/Mogadishu',
'Africa/Monrovia',
'Africa/Nairobi',
'Africa/Ndjamena',
'Africa/Niamey',
'Africa/Nouakchott',
'Africa/Ouagadougou',
'Africa/Porto-Novo',
'Africa/Sao_Tome',
'Africa/Tripoli',
'Africa/Tunis',
'Africa/Windhoek',
'America/Adak',
'America/Anchorage',
'America/Anguilla',
'America/Antigua',
'America/Araguaina',
'America/Argentina/Buenos_Aires',
'America/Argentina/Catamarca',
'America/Argentina/Cordoba',
'America/Argentina/Jujuy',
'America/Argentina/La_Rioja',
'America/Argentina/Mendoza',
'America/Argentina/Rio_Gallegos',
'America/Argentina/Salta',
'America/Argentina/San_Juan',
'America/Argentina/San_Luis',
'America/Argentina/Tucuman',
'America/Argentina/Ushuaia',
'America/Aruba',
'America/Asuncion',
'America/Atikokan',
'America/Bahia',
'America/Bahia_Banderas',
'America/Barbados',
'America/Belem',
'America/Belize',
'America/Blanc-Sablon',
'America/Boa_Vista',
'America/Bogota',
'America/Boise',
'America/Cambridge_Bay',
'America/Campo_Grande',
'America/Cancun',
'America/Caracas',
'America/Cayenne',
'America/Cayman',
'America/Chicago',
'America/Chihuahua',
'America/Costa_Rica',
'America/Creston',
'America/Cuiaba',
'America/Curacao',
'America/Danmarkshavn',
'America/Dawson',
'America/Dawson_Creek',
'America/Denver',
'America/Detroit',
'America/Dominica',
'America/Edmonton',
'America/Eirunepe',
'America/El_Salvador',
'America/Fort_Nelson',
'America/Fortaleza',
'America/Glace_Bay',
'America/Godthab',
'America/Goose_Bay',
'America/Grand_Turk',
'America/Grenada',
'America/Guadeloupe',
'America/Guatemala',
'America/Guayaquil',
'America/Guyana',
'America/Halifax',
'America/Havana',
'America/Hermosillo',
'America/Indiana/Indianapolis',
'America/Indiana/Knox',
'America/Indiana/Marengo',
'America/Indiana/Petersburg',
'America/Indiana/Tell_City',
'America/Indiana/Vevay',
'America/Indiana/Vincennes',
'America/Indiana/Winamac',
'America/Inuvik',
'America/Iqaluit',
'America/Jamaica',
'America/Juneau',
'America/Kentucky/Louisville',
'America/Kentucky/Monticello',
'America/Kralendijk',
'America/La_Paz',
'America/Lima',
'America/Los_Angeles',
'America/Lower_Princes',
'America/Maceio',
'America/Managua',
'America/Manaus',
'America/Marigot',
'America/Martinique',
'America/Matamoros',
'America/Mazatlan',
'America/Menominee',
'America/Merida',
'America/Metlakatla',
'America/Mexico_City',
'America/Miquelon',
'America/Moncton',
'America/Monterrey',
'America/Montevideo',
'America/Montserrat',
'America/Nassau',
'America/New_York',
'America/Nipigon',
'America/Nome',
'America/Noronha',
'America/North_Dakota/Beulah',
'America/North_Dakota/Center',
'America/North_Dakota/New_Salem',
'America/Ojinaga',
'America/Panama',
'America/Pangnirtung',
'America/Paramaribo',
'America/Phoenix',
'America/Port-au-Prince',
'America/Port_of_Spain',
'America/Porto_Velho',
'America/Puerto_Rico',
'America/Rainy_River',
'America/Rankin_Inlet',
'America/Recife',
'America/Regina',
'America/Resolute',
'America/Rio_Branco',
'America/Santarem',
'America/Santiago',
'America/Santo_Domingo',
'America/Sao_Paulo',
'America/Scoresbysund',
'America/Sitka',
'America/St_Barthelemy',
'America/St_Johns',
'America/St_Kitts',
'America/St_Lucia',
'America/St_Thomas',
'America/St_Vincent',
'America/Swift_Current',
'America/Tegucigalpa',
'America/Thule',
'America/Thunder_Bay',
'America/Tijuana',
'America/Toronto',
'America/Tortola',
'America/Vancouver',
'America/Whitehorse',
'America/Winnipeg',
'America/Yakutat',
'America/Yellowknife',
'Antarctica/Casey',
'Antarctica/Davis',
'Antarctica/DumontDUrville',
'Antarctica/Macquarie',
'Antarctica/Mawson',
'Antarctica/McMurdo',
'Antarctica/Palmer',
'Antarctica/Rothera',
'Antarctica/Syowa',
'Antarctica/Troll',
'Antarctica/Vostok',
'Arctic/Longyearbyen',
'Asia/Aden',
'Asia/Almaty',
'Asia/Amman',
'Asia/Anadyr',
'Asia/Aqtau',
'Asia/Aqtobe',
'Asia/Ashgabat',
'Asia/Baghdad',
'Asia/Bahrain',
'Asia/Baku',
'Asia/Bangkok',
'Asia/Barnaul',
'Asia/Beirut',
'Asia/Bishkek',
'Asia/Brunei',
'Asia/Chita',
'Asia/Choibalsan',
'Asia/Colombo',
'Asia/Damascus',
'Asia/Dhaka',
'Asia/Dili',
'Asia/Dubai',
'Asia/Dushanbe',
'Asia/Gaza',
'Asia/Hebron',
'Asia/Ho_Chi_Minh',
'Asia/Hong_Kong',
'Asia/Hovd',
'Asia/Irkutsk',
'Asia/Jakarta',
'Asia/Jayapura',
'Asia/Jerusalem',
'Asia/Kabul',
'Asia/Kamchatka',
'Asia/Karachi',
'Asia/Kathmandu',
'Asia/Khandyga',
'Asia/Kolkata',
'Asia/Krasnoyarsk',
'Asia/Kuala_Lumpur',
'Asia/Kuching',
'Asia/Kuwait',
'Asia/Macau',
'Asia/Magadan',
'Asia/Makassar',
'Asia/Manila',
'Asia/Muscat',
'Asia/Nicosia',
'Asia/Novokuznetsk',
'Asia/Novosibirsk',
'Asia/Omsk',
'Asia/Oral',
'Asia/Phnom_Penh',
'Asia/Pontianak',
'Asia/Pyongyang',
'Asia/Qatar',
'Asia/Qyzylorda',
'Asia/Rangoon',
'Asia/Riyadh',
'Asia/Sakhalin',
'Asia/Samarkand',
'Asia/Seoul',
'Asia/Shanghai',
'Asia/Singapore',
'Asia/Srednekolymsk',
'Asia/Taipei',
'Asia/Tashkent',
'Asia/Tbilisi',
'Asia/Tehran',
'Asia/Thimphu',
'Asia/Tokyo',
'Asia/Tomsk',
'Asia/Ulaanbaatar',
'Asia/Urumqi',
'Asia/Ust-Nera',
'Asia/Vientiane',
'Asia/Vladivostok',
'Asia/Yakutsk',
'Asia/Yekaterinburg',
'Asia/Yerevan',
'Atlantic/Azores',
'Atlantic/Bermuda',
'Atlantic/Canary',
'Atlantic/Cape_Verde',
'Atlantic/Faroe',
'Atlantic/Madeira',
'Atlantic/Reykjavik',
'Atlantic/South_Georgia',
'Atlantic/St_Helena',
'Atlantic/Stanley',
'Australia/Adelaide',
'Australia/Brisbane',
'Australia/Broken_Hill',
'Australia/Currie',
'Australia/Darwin',
'Australia/Eucla',
'Australia/Hobart',
'Australia/Lindeman',
'Australia/Lord_Howe',
'Australia/Melbourne',
'Australia/Perth',
'Australia/Sydney',
'Canada/Atlantic',
'Canada/Central',
'Canada/Eastern',
'Canada/Mountain',
'Canada/Newfoundland',
'Canada/Pacific',
'Europe/Amsterdam',
'Europe/Andorra',
'Europe/Astrakhan',
'Europe/Athens',
'Europe/Belgrade',
'Europe/Berlin',
'Europe/Bratislava',
'Europe/Brussels',
'Europe/Bucharest',
'Europe/Budapest',
'Europe/Busingen',
'Europe/Chisinau',
'Europe/Copenhagen',
'Europe/Dublin',
'Europe/Gibraltar',
'Europe/Guernsey',
'Europe/Helsinki',
'Europe/Isle_of_Man',
'Europe/Istanbul',
'Europe/Jersey',
'Europe/Kaliningrad',
'Europe/Kiev',
'Europe/Kirov',
'Europe/Lisbon',
'Europe/Ljubljana',
'Europe/London',
'Europe/Luxembourg',
'Europe/Madrid',
'Europe/Malta',
'Europe/Mariehamn',
'Europe/Minsk',
'Europe/Monaco',
'Europe/Moscow',
'Europe/Oslo',
'Europe/Paris',
'Europe/Podgorica',
'Europe/Prague',
'Europe/Riga',
'Europe/Rome',
'Europe/Samara',
'Europe/San_Marino',
'Europe/Sarajevo',
'Europe/Simferopol',
'Europe/Skopje',
'Europe/Sofia',
'Europe/Stockholm',
'Europe/Tallinn',
'Europe/Tirane',
'Europe/Ulyanovsk',
'Europe/Uzhgorod',
'Europe/Vaduz',
'Europe/Vatican',
'Europe/Vienna',
'Europe/Vilnius',
'Europe/Volgograd',
'Europe/Warsaw',
'Europe/Zagreb',
'Europe/Zaporozhye',
'Europe/Zurich',
'GMT',
'Indian/Antananarivo',
'Indian/Chagos',
'Indian/Christmas',
'Indian/Cocos',
'Indian/Comoro',
'Indian/Kerguelen',
'Indian/Mahe',
'Indian/Maldives',
'Indian/Mauritius',
'Indian/Mayotte',
'Indian/Reunion',
'Pacific/Apia',
'Pacific/Auckland',
'Pacific/Bougainville',
'Pacific/Chatham',
'Pacific/Chuuk',
'Pacific/Easter',
'Pacific/Efate',
'Pacific/Enderbury',
'Pacific/Fakaofo',
'Pacific/Fiji',
'Pacific/Funafuti',
'Pacific/Galapagos',
'Pacific/Gambier',
'Pacific/Guadalcanal',
'Pacific/Guam',
'Pacific/Honolulu',
'Pacific/Johnston',
'Pacific/Kiritimati',
'Pacific/Kosrae',
'Pacific/Kwajalein',
'Pacific/Majuro',
'Pacific/Marquesas',
'Pacific/Midway',
'Pacific/Nauru',
'Pacific/Niue',
'Pacific/Norfolk',
'Pacific/Noumea',
'Pacific/Pago_Pago',
'Pacific/Palau',
'Pacific/Pitcairn',
'Pacific/Pohnpei',
'Pacific/Port_Moresby',
'Pacific/Rarotonga',
'Pacific/Saipan',
'Pacific/Tahiti',
'Pacific/Tarawa',
'Pacific/Tongatapu',
'Pacific/Wake',
'Pacific/Wallis',
'US/Alaska',
'US/Arizona',
'US/Central',
'US/Eastern',
'US/Hawaii',
'US/Mountain',
'US/Pacific',
'UTC']
common_timezones = LazyList(
tz for tz in common_timezones if tz in all_timezones)

common_timezones_set = LazySet(common_timezones)

All modules for which code is available

- django

- django.apps.config

- django.apps.registry

- django.conf.urls

- django.conf.urls.i18n

- django.contrib.admin

- django.contrib.admin.decorators

- django.contrib.admin.options

- django.contrib.admin.sites

- django.contrib.admin.views.decorators

- django.contrib.auth

- django.contrib.auth.context_processors

- django.contrib.auth.decorators

- django.contrib.auth.hashers

- django.contrib.auth.password_validation

- django.contrib.flatpages.sitemaps

- django.contrib.gis.feeds

- django.contrib.gis.forms.fields

- django.contrib.gis.gdal.envelope

- django.contrib.gis.gdal.geomtype

- django.contrib.gis.geos.collections

- django.contrib.gis.geos.error

- django.contrib.gis.geos.factory

- django.contrib.gis.geos.geometry

- django.contrib.gis.geos.io

- django.contrib.gis.geos.linestring

- django.contrib.gis.geos.point

- django.contrib.gis.geos.polygon

- django.contrib.gis.geos.prototypes.io

- django.contrib.gis.measure

- django.contrib.messages.api

- django.contrib.messages.middleware

- django.contrib.postgres.functions

- django.contrib.postgres.validators

- django.contrib.sessions.middleware

- django.contrib.sitemaps

- django.contrib.sites.middleware

- django.contrib.sites.shortcuts

- django.contrib.syndication.views

- django.core.checks.messages

- django.core.checks.registry

- django.core.exceptions

- django.core.files.base

- django.core.files.images

- django.core.files.storage

- django.core.files.uploadedfile

- django.core.files.uploadhandler

- django.core.mail

- django.core.mail.message

- django.core.management.base

- django.core.paginator

- django.core.signing

- django.core.urlresolvers

- django.core.validators

- django.db.backends.base.schema

- django.db.migrations.operations.fields

- django.db.migrations.operations.models

- django.db.migrations.operations.special

- django.db.models.aggregates

- django.db.models.base

- django.db.models.deletion

- django.db.models.expressions

- django.db.models.fields

- django.db.models.fields.files

- django.db.models.fields.related

- django.db.models.functions

- django.db.models.lookups

- django.db.models.manager

- django.db.models.options

- django.db.models.query

- django.db.models.query_utils

- django.db.transaction

- django.db.utils

- django.dispatch.dispatcher

- django.forms.boundfield

- django.forms.fields

- django.forms.forms

- django.forms.formsets

- django.forms.models

- django.forms.widgets

- django.http.request

- django.http.response

- django.middleware.cache

- django.middleware.clickjacking

- django.middleware.common

- django.middleware.csrf

- django.middleware.gzip

- django.middleware.http

- django.middleware.locale

- django.middleware.security

- django.shortcuts

- django.template.backends.django

- django.template.backends.jinja2

- django.template.base

- django.template.context

- django.template.context_processors

- django.template.engine

- django.template.exceptions

- django.template.loader

- django.template.loaders.base

- django.template.response

- django.template.utils

- django.test.client

- django.test.runner

- django.test.testcases

- django.test.utils

- django.utils.cache

- django.utils.datastructures

- django.utils.dateparse

- django.utils.decorators

- django.utils.encoding

- django.utils.feedgenerator

- django.utils.functional

- django.utils.html

- django.utils.http

- django.utils.log

- django.utils.module_loading

- django.utils.safestring

- django.utils.six

- django.utils.text

- django.utils.timezone

- django.utils.translation

- django.views.debug

- django.views.decorators.cache

- django.views.decorators.csrf

- django.views.decorators.debug

- django.views.decorators.http

- django.views.decorators.vary

- django.views.generic.dates

- django.views.i18n

- django.views.static

- pytz

- unittest.loader

- unittest.runner

- unittest.suite

Source code for django

from django.utils.version import get_version

VERSION = (1, 9, 9, 'alpha', 0)

__version__ = get_version(VERSION)

[docs]def setup():
"""
Configure the settings (this happens as a side effect of accessing the
first setting), configure logging and populate the app registry.
"""
from django.apps import apps
from django.conf import settings
from django.utils.log import configure_logging

configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
apps.populate(settings.INSTALLED_APPS)

Source code for django.shortcuts

"""
This module collects helper functions and classes that "span" multiple levels
of MVC. In other words, these functions/classes introduce controlled coupling
for convenience's sake.
"""

import warnings

from django.core import urlresolvers
from django.db.models.base import ModelBase
from django.db.models.manager import Manager
from django.db.models.query import QuerySet
from django.http import (
Http404, HttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect,
)
from django.template import RequestContext, loader
from django.template.context import _current_app_undefined
from django.template.engine import (
_context_instance_undefined, _dictionary_undefined, _dirs_undefined,
)
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_text
from django.utils.functional import Promise

[docs]def render_to_response(template_name, context=None,
context_instance=_context_instance_undefined,
content_type=None, status=None, dirs=_dirs_undefined,
dictionary=_dictionary_undefined, using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
if (context_instance is _context_instance_undefined
and dirs is _dirs_undefined
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
content = loader.render_to_string(template_name, context, using=using)

else:
# Some deprecated arguments were passed - use the legacy code path
content = loader.render_to_string(
template_name, context, context_instance, dirs, dictionary,
using=using)

return HttpResponse(content, content_type, status)

[docs]def render(request, template_name, context=None,
context_instance=_context_instance_undefined,
content_type=None, status=None, current_app=_current_app_undefined,
dirs=_dirs_undefined, dictionary=_dictionary_undefined,
using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
Uses a RequestContext by default.
"""
if (context_instance is _context_instance_undefined
and current_app is _current_app_undefined
and dirs is _dirs_undefined
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
# In Django 1.10, request should become a positional argument.
content = loader.render_to_string(
template_name, context, request=request, using=using)

else:
# Some deprecated arguments were passed - use the legacy code path
if context_instance is not _context_instance_undefined:
if current_app is not _current_app_undefined:
raise ValueError('If you provide a context_instance you must '
'set its current_app before calling render()')
else:
context_instance = RequestContext(request)
if current_app is not _current_app_undefined:
warnings.warn(
"The current_app argument of render is deprecated. "
"Set the current_app attribute of request instead.",
RemovedInDjango110Warning, stacklevel=2)
request.current_app = current_app
# Directly set the private attribute to avoid triggering the
# warning in RequestContext.__init__.
context_instance._current_app = current_app

content = loader.render_to_string(
template_name, context, context_instance, dirs, dictionary,
using=using)

return HttpResponse(content, content_type, status)

[docs]def redirect(to, *args, **kwargs):
"""
Returns an HttpResponseRedirect to the appropriate URL for the arguments
passed.

The arguments could be:

* A model: the model's `get_absolute_url()` function will be called.

* A view name, possibly with arguments: `urlresolvers.reverse()` will
be used to reverse-resolve the name.

* A URL, which will be used as-is for the redirect location.

By default issues a temporary redirect; pass permanent=True to issue a
permanent redirect
"""
if kwargs.pop('permanent', False):
redirect_class = HttpResponsePermanentRedirect
else:
redirect_class = HttpResponseRedirect

return redirect_class(resolve_url(to, *args, **kwargs))

def _get_queryset(klass):
"""
Returns a QuerySet from a Model, Manager, or QuerySet. Created to make
get_object_or_404 and get_list_or_404 more DRY.

Raises a ValueError if klass is not a Model, Manager, or QuerySet.
"""
if isinstance(klass, QuerySet):
return klass
elif isinstance(klass, Manager):
manager = klass
elif isinstance(klass, ModelBase):
manager = klass._default_manager
else:
if isinstance(klass, type):
klass__name = klass.__name__
else:
klass__name = klass.__class__.__name__
raise ValueError("Object is of type '%s', but must be a Django Model, "
"Manager, or QuerySet" % klass__name)
return manager.all()

[docs]def get_object_or_404(klass, *args, **kwargs):
"""
Uses get() to return an object, or raises a Http404 exception if the object
does not exist.

klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.

Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
object is found.
"""
queryset = _get_queryset(klass)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)

[docs]def get_list_or_404(klass, *args, **kwargs):
"""
Uses filter() to return a list of objects, or raise a Http404 exception if
the list is empty.

klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the filter() query.
"""
queryset = _get_queryset(klass)
obj_list = list(queryset.filter(*args, **kwargs))
if not obj_list:
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
return obj_list

def resolve_url(to, *args, **kwargs):
"""
Return a URL appropriate for the arguments passed.

The arguments could be:

* A model: the model's `get_absolute_url()` function will be called.

* A view name, possibly with arguments: `urlresolvers.reverse()` will
be used to reverse-resolve the name.

* A URL, which will be returned as-is.
"""
# If it's a model, use get_absolute_url()
if hasattr(to, 'get_absolute_url'):
return to.get_absolute_url()

if isinstance(to, Promise):
# Expand the lazy instance, as it can cause issues when it is passed
# further to some Python functions like urlparse.
to = force_text(to)

if isinstance(to, six.string_types):
# Handle relative URLs
if to.startswith(('./', '../')):
return to

# Next try a reverse URL resolution.
try:
return urlresolvers.reverse(to, args=args, kwargs=kwargs)
except urlresolvers.NoReverseMatch:
# If this is a callable, re-raise.
if callable(to):
raise
# If this doesn't "feel" like a URL, re-raise.
if '/' not in to and '.' not in to:
raise

# Finally, fall back and assume it's a URL
return to

Source code for django.middleware.security

import re

from django.conf import settings
from django.http import HttpResponsePermanentRedirect

[docs]class SecurityMiddleware(object):
def __init__(self):
self.sts_seconds = settings.SECURE_HSTS_SECONDS
self.sts_include_subdomains = settings.SECURE_HSTS_INCLUDE_SUBDOMAINS
self.content_type_nosniff = settings.SECURE_CONTENT_TYPE_NOSNIFF
self.xss_filter = settings.SECURE_BROWSER_XSS_FILTER
self.redirect = settings.SECURE_SSL_REDIRECT
self.redirect_host = settings.SECURE_SSL_HOST
self.redirect_exempt = [re.compile(r) for r in settings.SECURE_REDIRECT_EXEMPT]

def process_request(self, request):
path = request.path.lstrip("/")
if (self.redirect and not request.is_secure() and
not any(pattern.search(path)
for pattern in self.redirect_exempt)):
host = self.redirect_host or request.get_host()
return HttpResponsePermanentRedirect(
"https://%s%s" % (host, request.get_full_path())
)

def process_response(self, request, response):
if (self.sts_seconds and request.is_secure() and
'strict-transport-security' not in response):
sts_header = "max-age=%s" % self.sts_seconds

if self.sts_include_subdomains:
sts_header = sts_header + "; includeSubDomains"

response["strict-transport-security"] = sts_header

if self.content_type_nosniff and 'x-content-type-options' not in response:
response["x-content-type-options"] = "nosniff"

if self.xss_filter and 'x-xss-protection' not in response:
response["x-xss-protection"] = "1; mode=block"

return response

Source code for django.middleware.gzip

import re

from django.utils.cache import patch_vary_headers
from django.utils.text import compress_sequence, compress_string

re_accepts_gzip = re.compile(r'\bgzip\b')

[docs]class GZipMiddleware(object):
"""
This middleware compresses content if the browser allows gzip compression.
It sets the Vary header accordingly, so that caches will base their storage
on the Accept-Encoding header.
"""
def process_response(self, request, response):
# It's not worth attempting to compress really short responses.
if not response.streaming and len(response.content) < 200:
return response

# Avoid gzipping if we've already got a content-encoding.
if response.has_header('Content-Encoding'):
return response

patch_vary_headers(response, ('Accept-Encoding',))

ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
if not re_accepts_gzip.search(ae):
return response

if response.streaming:
# Delete the `Content-Length` header for streaming content, because
# we won't know the compressed size until we stream it.
response.streaming_content = compress_sequence(response.streaming_content)
del response['Content-Length']
else:
# Return the compressed content only if it's actually shorter.
compressed_content = compress_string(response.content)
if len(compressed_content) >= len(response.content):
return response
response.content = compressed_content
response['Content-Length'] = str(len(response.content))

if response.has_header('ETag'):
response['ETag'] = re.sub('"$', ';gzip"', response['ETag'])
response['Content-Encoding'] = 'gzip'

return response

Source code for django.middleware.csrf

"""
Cross Site Request Forgery Middleware.

This module provides a middleware that implements protection
against request forgeries from other sites.
"""
from __future__ import unicode_literals

import logging
import re

from django.conf import settings
from django.core.urlresolvers import get_callable
from django.utils.cache import patch_vary_headers
from django.utils.crypto import constant_time_compare, get_random_string
from django.utils.encoding import force_text
from django.utils.http import is_same_domain
from django.utils.six.moves.urllib.parse import urlparse

logger = logging.getLogger('django.request')

REASON_NO_REFERER = "Referer checking failed - no Referer."
REASON_BAD_REFERER = "Referer checking failed - %s does not match any trusted origins."
REASON_NO_CSRF_COOKIE = "CSRF cookie not set."
REASON_BAD_TOKEN = "CSRF token missing or incorrect."
REASON_MALFORMED_REFERER = "Referer checking failed - Referer is malformed."
REASON_INSECURE_REFERER = "Referer checking failed - Referer is insecure while host is secure."

CSRF_KEY_LENGTH = 32

def _get_failure_view():
"""
Returns the view to be used for CSRF rejections
"""
return get_callable(settings.CSRF_FAILURE_VIEW)

def _get_new_csrf_key():
return get_random_string(CSRF_KEY_LENGTH)

def get_token(request):
"""
Returns the CSRF token required for a POST form. The token is an
alphanumeric value. A new token is created if one is not already set.

A side effect of calling this function is to make the csrf_protect
decorator and the CsrfViewMiddleware add a CSRF cookie and a 'Vary: Cookie'
header to the outgoing response.  For this reason, you may need to use this
function lazily, as is done by the csrf context processor.
"""
if "CSRF_COOKIE" not in request.META:
request.META["CSRF_COOKIE"] = _get_new_csrf_key()
request.META["CSRF_COOKIE_USED"] = True
return request.META["CSRF_COOKIE"]

def rotate_token(request):
"""
Changes the CSRF token in use for a request - should be done on login
for security purposes.
"""
request.META.update({
"CSRF_COOKIE_USED": True,
"CSRF_COOKIE": _get_new_csrf_key(),
})

def _sanitize_token(token):
# Allow only alphanum
if len(token) > CSRF_KEY_LENGTH:
return _get_new_csrf_key()
token = re.sub('[^a-zA-Z0-9]+', '', force_text(token))
if token == "":
# In case the cookie has been truncated to nothing at some point.
return _get_new_csrf_key()
return token

[docs]class CsrfViewMiddleware(object):
"""
Middleware that requires a present and correct csrfmiddlewaretoken
for POST requests that have a CSRF cookie, and sets an outgoing
CSRF cookie.

This middleware should be used in conjunction with the csrf_token template
tag.
"""
# The _accept and _reject methods currently only exist for the sake of the
# requires_csrf_token decorator.
def _accept(self, request):
# Avoid checking the request twice by adding a custom attribute to
# request.  This will be relevant when both decorator and middleware
# are used.
request.csrf_processing_done = True
return None

def _reject(self, request, reason):
logger.warning('Forbidden (%s): %s', reason, request.path,
extra={
'status_code': 403,
'request': request,
}
)
return _get_failure_view()(request, reason=reason)

def process_view(self, request, callback, callback_args, callback_kwargs):

if getattr(request, 'csrf_processing_done', False):
return None

try:
csrf_token = _sanitize_token(
request.COOKIES[settings.CSRF_COOKIE_NAME])
# Use same token next time
request.META['CSRF_COOKIE'] = csrf_token
except KeyError:
csrf_token = None

# Wait until request.META["CSRF_COOKIE"] has been manipulated before
# bailing out, so that get_token still works
if getattr(callback, 'csrf_exempt', False):
return None

# Assume that anything not defined as 'safe' by RFC7231 needs protection
if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
if getattr(request, '_dont_enforce_csrf_checks', False):
# Mechanism to turn off CSRF checks for test suite.
# It comes after the creation of CSRF cookies, so that
# everything else continues to work exactly the same
# (e.g. cookies are sent, etc.), but before any
# branches that call reject().
return self._accept(request)

if request.is_secure():
# Suppose user visits http://example.com/
# An active network attacker (man-in-the-middle, MITM) sends a
# POST form that targets https://example.com/detonate-bomb/ and
# submits it via JavaScript.
#
# The attacker will need to provide a CSRF cookie and token, but
# that's no problem for a MITM and the session-independent
# nonce we're using. So the MITM can circumvent the CSRF
# protection. This is true for any HTTP connection, but anyone
# using HTTPS expects better! For this reason, for
# https://example.com/ we need additional protection that treats
# http://example.com/ as completely untrusted. Under HTTPS,
# Barth et al. found that the Referer header is missing for
# same-domain requests in only about 0.2% of cases or less, so
# we can use strict Referer checking.
referer = force_text(
request.META.get('HTTP_REFERER'),
strings_only=True,
errors='replace'
)
if referer is None:
return self._reject(request, REASON_NO_REFERER)

referer = urlparse(referer)

# Make sure we have a valid URL for Referer.
if '' in (referer.scheme, referer.netloc):
return self._reject(request, REASON_MALFORMED_REFERER)

# Ensure that our Referer is also secure.
if referer.scheme != 'https':
return self._reject(request, REASON_INSECURE_REFERER)

# If there isn't a CSRF_COOKIE_DOMAIN, assume we need an exact
# match on host:port. If not, obey the cookie rules.
if settings.CSRF_COOKIE_DOMAIN is None:
# request.get_host() includes the port.
good_referer = request.get_host()
else:
good_referer = settings.CSRF_COOKIE_DOMAIN
server_port = request.get_port()
if server_port not in ('443', '80'):
good_referer = '%s:%s' % (good_referer, server_port)

# Here we generate a list of all acceptable HTTP referers,
# including the current host since that has been validated
# upstream.
good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
good_hosts.append(good_referer)

if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
reason = REASON_BAD_REFERER % referer.geturl()
return self._reject(request, reason)

if csrf_token is None:
# No CSRF cookie. For POST requests, we insist on a CSRF cookie,
# and in this way we can avoid all CSRF attacks, including login
# CSRF.
return self._reject(request, REASON_NO_CSRF_COOKIE)

# Check non-cookie token for match.
request_csrf_token = ""
if request.method == "POST":
try:
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
except IOError:
# Handle a broken connection before we've completed reading
# the POST data. process_view shouldn't raise any
# exceptions, so we'll ignore and serve the user a 403
# (assuming they're still listening, which they probably
# aren't because of the error).
pass

if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX,
# and possible for PUT/DELETE.
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

if not constant_time_compare(request_csrf_token, csrf_token):
return self._reject(request, REASON_BAD_TOKEN)

return self._accept(request)

def process_response(self, request, response):
if getattr(response, 'csrf_processing_done', False):
return response

if not request.META.get("CSRF_COOKIE_USED", False):
return response

# Set the CSRF cookie even if it's already set, so we renew
# the expiry timer.
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"],
max_age=settings.CSRF_COOKIE_AGE,
domain=settings.CSRF_COOKIE_DOMAIN,
path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE,
httponly=settings.CSRF_COOKIE_HTTPONLY
)
# Content varies with the CSRF cookie, so set the Vary header.
patch_vary_headers(response, ('Cookie',))
response.csrf_processing_done = True
return response

Source code for django.middleware.clickjacking

"""
Clickjacking Protection Middleware.

This module provides a middleware that implements protection against a
malicious site loading resources from your site in a hidden frame.
"""

from django.conf import settings

[docs]class XFrameOptionsMiddleware(object):
"""
Middleware that sets the X-Frame-Options HTTP header in HTTP responses.

Does not set the header if it's already set or if the response contains
a xframe_options_exempt value set to True.

By default, sets the X-Frame-Options header to 'SAMEORIGIN', meaning the
response can only be loaded on a frame within the same site. To prevent the
response from being loaded in a frame in any site, set X_FRAME_OPTIONS in
your project's Django settings to 'DENY'.

Note: older browsers will quietly ignore this header, thus other
clickjacking protection techniques should be used if protection in those
browsers is required.

https://en.wikipedia.org/wiki/Clickjacking#Server_and_client
"""
def process_response(self, request, response):
# Don't set it if it's already in the response
if response.get('X-Frame-Options') is not None:
return response

# Don't set it if they used @xframe_options_exempt
if getattr(response, 'xframe_options_exempt', False):
return response

response['X-Frame-Options'] = self.get_xframe_options_value(request,
response)
return response

def get_xframe_options_value(self, request, response):
"""
Gets the value to set for the X_FRAME_OPTIONS header.

By default this uses the value from the X_FRAME_OPTIONS Django
settings. If not found in settings, defaults to 'SAMEORIGIN'.

This method can be overridden if needed, allowing it to vary based on
the request or response.
"""
return getattr(settings, 'X_FRAME_OPTIONS', 'SAMEORIGIN').upper()

Source code for django.middleware.http

from django.utils.cache import get_conditional_response
from django.utils.http import http_date, parse_http_date_safe, unquote_etag

[docs]class ConditionalGetMiddleware(object):
"""
Handles conditional GET operations. If the response has an ETag or
Last-Modified header, and the request has If-None-Match or
If-Modified-Since, the response is replaced by an HttpNotModified.

Also sets the Date and Content-Length response-headers.
"""
def process_response(self, request, response):
response['Date'] = http_date()
if not response.streaming and not response.has_header('Content-Length'):
response['Content-Length'] = str(len(response.content))

etag = response.get('ETag')
last_modified = response.get('Last-Modified')
if last_modified:
last_modified = parse_http_date_safe(last_modified)

if etag or last_modified:
return get_conditional_response(
request,
etag=unquote_etag(etag),
last_modified=last_modified,
response=response,
)

return response

Source code for django.middleware.cache

"""
Cache middleware. If enabled, each Django-powered page will be cached based on
URL. The canonical way to enable cache middleware is to set
``UpdateCacheMiddleware`` as your first piece of middleware, and
``FetchFromCacheMiddleware`` as the last::

MIDDLEWARE_CLASSES = [
'django.middleware.cache.UpdateCacheMiddleware',
...
'django.middleware.cache.FetchFromCacheMiddleware'
]

This is counter-intuitive, but correct: ``UpdateCacheMiddleware`` needs to run
last during the response phase, which processes middleware bottom-up;
``FetchFromCacheMiddleware`` needs to run last during the request phase, which
processes middleware top-down.

The single-class ``CacheMiddleware`` can be used for some simple sites.
However, if any other piece of middleware needs to affect the cache key, you'll
need to use the two-part ``UpdateCacheMiddleware`` and
``FetchFromCacheMiddleware``. This'll most often happen when you're using
Django's ``LocaleMiddleware``.

More details about how the caching works:

* Only GET or HEAD-requests with status code 200 are cached.

* The number of seconds each page is stored for is set by the "max-age" section
of the response's "Cache-Control" header, falling back to the
CACHE_MIDDLEWARE_SECONDS setting if the section was not found.

* This middleware expects that a HEAD request is answered with the same response
headers exactly like the corresponding GET request.

* When a hit occurs, a shallow copy of the original response object is returned
from process_request.

* Pages will be cached based on the contents of the request headers listed in
the response's "Vary" header.

* This middleware also sets ETag, Last-Modified, Expires and Cache-Control
headers on the response object.

"""

from django.conf import settings
from django.core.cache import DEFAULT_CACHE_ALIAS, caches
from django.utils.cache import (
get_cache_key, get_max_age, has_vary_header, learn_cache_key,
patch_response_headers,
)

[docs]class UpdateCacheMiddleware(object):
"""
Response-phase cache middleware that updates the cache if the response is
cacheable.

Must be used as part of the two-part update/fetch cache middleware.
UpdateCacheMiddleware must be the first piece of middleware in
MIDDLEWARE_CLASSES so that it'll get called last during the response phase.
"""
def __init__(self):
self.cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
self.cache_alias = settings.CACHE_MIDDLEWARE_ALIAS
self.cache = caches[self.cache_alias]

def _should_update_cache(self, request, response):
return hasattr(request, '_cache_update_cache') and request._cache_update_cache

def process_response(self, request, response):
"""Sets the cache, if needed."""
if not self._should_update_cache(request, response):
# We don't need to update the cache, just return.
return response

if response.streaming or response.status_code != 200:
return response

# Don't cache responses that set a user-specific (and maybe security
# sensitive) cookie in response to a cookie-less request.
if not request.COOKIES and response.cookies and has_vary_header(response, 'Cookie'):
return response

# Try to get the timeout from the "max-age" section of the "Cache-
# Control" header before reverting to using the default cache_timeout
# length.
timeout = get_max_age(response)
if timeout is None:
timeout = self.cache_timeout
elif timeout == 0:
# max-age was set to 0, don't bother caching.
return response
patch_response_headers(response, timeout)
if timeout:
cache_key = learn_cache_key(request, response, timeout, self.key_prefix, cache=self.cache)
if hasattr(response, 'render') and callable(response.render):
response.add_post_render_callback(
lambda r: self.cache.set(cache_key, r, timeout)
)
else:
self.cache.set(cache_key, response, timeout)
return response

[docs]class FetchFromCacheMiddleware(object):
"""
Request-phase cache middleware that fetches a page from the cache.

Must be used as part of the two-part update/fetch cache middleware.
FetchFromCacheMiddleware must be the last piece of middleware in
MIDDLEWARE_CLASSES so that it'll get called last during the request phase.
"""
def __init__(self):
self.key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
self.cache_alias = settings.CACHE_MIDDLEWARE_ALIAS
self.cache = caches[self.cache_alias]

def process_request(self, request):
"""
Checks whether the page is already cached and returns the cached
version if available.
"""
if request.method not in ('GET', 'HEAD'):
request._cache_update_cache = False
return None  # Don't bother checking the cache.

# try and get the cached GET response
cache_key = get_cache_key(request, self.key_prefix, 'GET', cache=self.cache)
if cache_key is None:
request._cache_update_cache = True
return None  # No cache information available, need to rebuild.
response = self.cache.get(cache_key)
# if it wasn't found and we are looking for a HEAD, try looking just for that
if response is None and request.method == 'HEAD':
cache_key = get_cache_key(request, self.key_prefix, 'HEAD', cache=self.cache)
response = self.cache.get(cache_key)

if response is None:
request._cache_update_cache = True
return None  # No cache information available, need to rebuild.

# hit, return cached response
request._cache_update_cache = False
return response

class CacheMiddleware(UpdateCacheMiddleware, FetchFromCacheMiddleware):
"""
Cache middleware that provides basic behavior for many simple sites.

Also used as the hook point for the cache decorator, which is generated
using the decorator-from-middleware utility.
"""
def __init__(self, cache_timeout=None, **kwargs):
# We need to differentiate between "provided, but using default value",
# and "not provided". If the value is provided using a default, then
# we fall back to system defaults. If it is not provided at all,
# we need to use middleware defaults.

try:
key_prefix = kwargs['key_prefix']
if key_prefix is None:
key_prefix = ''
except KeyError:
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
self.key_prefix = key_prefix

try:
cache_alias = kwargs['cache_alias']
if cache_alias is None:
cache_alias = DEFAULT_CACHE_ALIAS
except KeyError:
cache_alias = settings.CACHE_MIDDLEWARE_ALIAS
self.cache_alias = cache_alias

if cache_timeout is None:
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
self.cache_timeout = cache_timeout
self.cache = caches[self.cache_alias]

Source code for django.middleware.locale

"This is the locale selecting middleware that will look at accept headers"

from django.conf import settings
from django.core.urlresolvers import (
LocaleRegexURLResolver, get_resolver, get_script_prefix, is_valid_path,
)
from django.http import HttpResponseRedirect
from django.utils import translation
from django.utils.cache import patch_vary_headers
from django.utils.functional import cached_property

[docs]class LocaleMiddleware(object):
"""
This is a very simple middleware that parses a request
and decides what translation object to install in the current
thread context. This allows pages to be dynamically
translated to the language the user desires (if the language
is available, of course).
"""
response_redirect_class = HttpResponseRedirect

def process_request(self, request):
language = translation.get_language_from_request(
request, check_path=self.is_language_prefix_patterns_used)
translation.activate(language)
request.LANGUAGE_CODE = translation.get_language()

def process_response(self, request, response):
language = translation.get_language()
language_from_path = translation.get_language_from_path(request.path_info)
if (response.status_code == 404 and not language_from_path
and self.is_language_prefix_patterns_used):
urlconf = getattr(request, 'urlconf', None)
language_path = '/%s%s' % (language, request.path_info)
path_valid = is_valid_path(language_path, urlconf)
path_needs_slash = (
not path_valid and (
settings.APPEND_SLASH and not language_path.endswith('/')
and is_valid_path('%s/' % language_path, urlconf)
)
)

if path_valid or path_needs_slash:
script_prefix = get_script_prefix()
# Insert language after the script prefix and before the
# rest of the URL
language_url = request.get_full_path(force_append_slash=path_needs_slash).replace(
script_prefix,
'%s%s/' % (script_prefix, language),
1
)
return self.response_redirect_class(language_url)

if not (self.is_language_prefix_patterns_used
and language_from_path):
patch_vary_headers(response, ('Accept-Language',))
if 'Content-Language' not in response:
response['Content-Language'] = language
return response

@cached_property
def is_language_prefix_patterns_used(self):
"""
Returns `True` if the `LocaleRegexURLResolver` is used
at root level of the urlpatterns, else it returns `False`.
"""
for url_pattern in get_resolver(None).url_patterns:
if isinstance(url_pattern, LocaleRegexURLResolver):
return True
return False

Source code for django.middleware.common

import logging
import re

from django import http
from django.conf import settings
from django.core import urlresolvers
from django.core.exceptions import PermissionDenied
from django.core.mail import mail_managers
from django.utils.cache import get_conditional_response, set_response_etag
from django.utils.encoding import force_text
from django.utils.http import unquote_etag
from django.utils.six.moves.urllib.parse import urlparse

logger = logging.getLogger('django.request')

[docs]class CommonMiddleware(object):
"""
"Common" middleware for taking care of some basic operations:

- Forbids access to User-Agents in settings.DISALLOWED_USER_AGENTS

- URL rewriting: Based on the APPEND_SLASH and PREPEND_WWW settings,
this middleware appends missing slashes and/or prepends missing
"www."s.

- If APPEND_SLASH is set and the initial URL doesn't end with a
slash, and it is not found in urlpatterns, a new URL is formed by
appending a slash at the end. If this new URL is found in
urlpatterns, then an HTTP-redirect is returned to this new URL;
otherwise the initial URL is processed as usual.

This behavior can be customized by subclassing CommonMiddleware and
overriding the response_redirect_class attribute.

- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
the entire page content and Not Modified responses will be returned
appropriately.
"""

response_redirect_class = http.HttpResponsePermanentRedirect

def process_request(self, request):
"""
Check for denied User-Agents and rewrite the URL based on
settings.APPEND_SLASH and settings.PREPEND_WWW
"""

# Check for denied User-Agents
if 'HTTP_USER_AGENT' in request.META:
for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
raise PermissionDenied('Forbidden user agent')

# Check for a redirect based on settings.PREPEND_WWW
host = request.get_host()
must_prepend = settings.PREPEND_WWW and host and not host.startswith('www.')
redirect_url = ('%s://www.%s' % (request.scheme, host)) if must_prepend else ''

# Check if a slash should be appended
if self.should_redirect_with_slash(request):
path = self.get_full_path_with_slash(request)
else:
path = request.get_full_path()

# Return a redirect if necessary
if redirect_url or path != request.get_full_path():
redirect_url += path
return self.response_redirect_class(redirect_url)

def should_redirect_with_slash(self, request):
"""
Return True if settings.APPEND_SLASH is True and appending a slash to
the request path turns an invalid path into a valid one.
"""
if settings.APPEND_SLASH and not request.get_full_path().endswith('/'):
urlconf = getattr(request, 'urlconf', None)
return (
not urlresolvers.is_valid_path(request.path_info, urlconf)
and urlresolvers.is_valid_path('%s/' % request.path_info, urlconf)
)
return False

def get_full_path_with_slash(self, request):
"""
Return the full path of the request with a trailing slash appended.

Raise a RuntimeError if settings.DEBUG is True and request.method is
POST, PUT, or PATCH.
"""
new_path = request.get_full_path(force_append_slash=True)
if settings.DEBUG and request.method in ('POST', 'PUT', 'PATCH'):
raise RuntimeError(
"You called this URL via %(method)s, but the URL doesn't end "
"in a slash and you have APPEND_SLASH set. Django can't "
"redirect to the slash URL while maintaining %(method)s data. "
"Change your form to point to %(url)s (note the trailing "
"slash), or set APPEND_SLASH=False in your Django settings." % {
'method': request.method,
'url': request.get_host() + new_path,
}
)
return new_path

def process_response(self, request, response):
"""
Calculate the ETag, if needed.

When the status code of the response is 404, it may redirect to a path
with an appended slash if should_redirect_with_slash() returns True.
"""
# If the given URL is "Not Found", then check if we should redirect to
# a path with a slash appended.
if response.status_code == 404:
if self.should_redirect_with_slash(request):
return self.response_redirect_class(self.get_full_path_with_slash(request))

if settings.USE_ETAGS:
if not response.has_header('ETag'):
set_response_etag(response)

if response.has_header('ETag'):
return get_conditional_response(
request,
etag=unquote_etag(response['ETag']),
response=response,
)

return response

[docs]class BrokenLinkEmailsMiddleware(object):

def process_response(self, request, response):
"""
Send broken link emails for relevant 404 NOT FOUND responses.
"""
if response.status_code == 404 and not settings.DEBUG:
domain = request.get_host()
path = request.get_full_path()
referer = force_text(request.META.get('HTTP_REFERER', ''), errors='replace')

if not self.is_ignorable_request(request, path, domain, referer):
ua = force_text(request.META.get('HTTP_USER_AGENT', '<none>'), errors='replace')
ip = request.META.get('REMOTE_ADDR', '<none>')
mail_managers(
"Broken %slink on %s" % (
('INTERNAL ' if self.is_internal_request(domain, referer) else ''),
domain
),
"Referrer: %s\nRequested URL: %s\nUser agent: %s\n"
"IP address: %s\n" % (referer, path, ua, ip),
fail_silently=True)
return response

def is_internal_request(self, domain, referer):
"""
Returns True if the referring URL is the same domain as the current request.
"""
# Different subdomains are treated as different domains.
return bool(re.match("^https?://%s/" % re.escape(domain), referer))

def is_ignorable_request(self, request, uri, domain, referer):
"""
Return True if the given request *shouldn't* notify the site managers
according to project settings or in three specific situations:
- If the referer is empty.
- If a '?' in referer is identified as a search engine source.
- If the referer is equal to the current URL, ignoring the scheme
(assumed to be a poorly implemented bot).
"""
if not referer:
return True

if not self.is_internal_request(domain, referer) and '?' in referer:
return True

parsed_referer = urlparse(referer)
if parsed_referer.netloc in ['', domain] and parsed_referer.path == uri:
return True

return any(pattern.search(uri) for pattern in settings.IGNORABLE_404_URLS)

Source code for django.contrib.admin

# ACTION_CHECKBOX_NAME is unused, but should stay since its import from here
# has been referenced in documentation.
from django.contrib.admin.decorators import register
from django.contrib.admin.filters import (
AllValuesFieldListFilter, BooleanFieldListFilter, ChoicesFieldListFilter,
DateFieldListFilter, FieldListFilter, ListFilter, RelatedFieldListFilter,
RelatedOnlyFieldListFilter, SimpleListFilter,
)
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
from django.contrib.admin.options import (
HORIZONTAL, VERTICAL, ModelAdmin, StackedInline, TabularInline,
)
from django.contrib.admin.sites import AdminSite, site
from django.utils.module_loading import autodiscover_modules

__all__ = [
"register", "ACTION_CHECKBOX_NAME", "ModelAdmin", "HORIZONTAL", "VERTICAL",
"StackedInline", "TabularInline", "AdminSite", "site", "ListFilter",
"SimpleListFilter", "FieldListFilter", "BooleanFieldListFilter",
"RelatedFieldListFilter", "ChoicesFieldListFilter", "DateFieldListFilter",
"AllValuesFieldListFilter", "RelatedOnlyFieldListFilter", "autodiscover",
]

[docs]def autodiscover():
autodiscover_modules('admin', register_to=site)

default_app_config = 'django.contrib.admin.apps.AdminConfig'

Source code for django.contrib.sitemaps

from django.apps import apps as django_apps
from django.conf import settings
from django.core import paginator, urlresolvers
from django.core.exceptions import ImproperlyConfigured
from django.utils import translation
from django.utils.six.moves.urllib.parse import urlencode
from django.utils.six.moves.urllib.request import urlopen

PING_URL = "http://www.google.com/webmasters/tools/ping"

class SitemapNotFound(Exception):
pass

[docs]def ping_google(sitemap_url=None, ping_url=PING_URL):
"""
Alerts Google that the sitemap for the current site has been updated.
If sitemap_url is provided, it should be an absolute path to the sitemap
for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
function will attempt to deduce it by using urlresolvers.reverse().
"""
if sitemap_url is None:
try:
# First, try to get the "index" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.index')
except urlresolvers.NoReverseMatch:
try:
# Next, try for the "global" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap')
except urlresolvers.NoReverseMatch:
pass

if sitemap_url is None:
raise SitemapNotFound("You didn't provide a sitemap_url, and the sitemap URL couldn't be auto-detected.")

if not django_apps.is_installed('django.contrib.sites'):
raise ImproperlyConfigured("ping_google requires django.contrib.sites, which isn't installed.")
Site = django_apps.get_model('sites.Site')
current_site = Site.objects.get_current()
url = "http://%s%s" % (current_site.domain, sitemap_url)
params = urlencode({'sitemap': url})
urlopen("%s?%s" % (ping_url, params))

[docs]class Sitemap(object):
# This limit is defined by Google. See the index documentation at
# http://www.sitemaps.org/protocol.html#index.
limit = 50000

# If protocol is None, the URLs in the sitemap will use the protocol
# with which the sitemap was requested.
protocol = None

def __get(self, name, obj, default=None):
try:
attr = getattr(self, name)
except AttributeError:
return default
if callable(attr):
return attr(obj)
return attr

[docs]    def items(self):
return []

[docs]    def location(self, obj):
return obj.get_absolute_url()

def _get_paginator(self):
return paginator.Paginator(self.items(), self.limit)
paginator = property(_get_paginator)

def get_urls(self, page=1, site=None, protocol=None):
# Determine protocol
if self.protocol is not None:
protocol = self.protocol
if protocol is None:
protocol = 'http'

# Determine domain
if site is None:
if django_apps.is_installed('django.contrib.sites'):
Site = django_apps.get_model('sites.Site')
try:
site = Site.objects.get_current()
except Site.DoesNotExist:
pass
if site is None:
raise ImproperlyConfigured(
"To use sitemaps, either enable the sites framework or pass "
"a Site/RequestSite object in your view."
)
domain = site.domain

if getattr(self, 'i18n', False):
urls = []
current_lang_code = translation.get_language()
for lang_code, lang_name in settings.LANGUAGES:
translation.activate(lang_code)
urls += self._urls(page, protocol, domain)
translation.activate(current_lang_code)
else:
urls = self._urls(page, protocol, domain)

return urls

def _urls(self, page, protocol, domain):
urls = []
latest_lastmod = None
all_items_lastmod = True  # track if all items have a lastmod
for item in self.paginator.page(page).object_list:
loc = "%s://%s%s" % (protocol, domain, self.__get('location', item))
priority = self.__get('priority', item)
lastmod = self.__get('lastmod', item)
if all_items_lastmod:
all_items_lastmod = lastmod is not None
if (all_items_lastmod and
(latest_lastmod is None or lastmod > latest_lastmod)):
latest_lastmod = lastmod
url_info = {
'item': item,
'location': loc,
'lastmod': lastmod,
'changefreq': self.__get('changefreq', item),
'priority': str(priority if priority is not None else ''),
}
urls.append(url_info)
if all_items_lastmod and latest_lastmod:
self.latest_lastmod = latest_lastmod
return urls

[docs]class GenericSitemap(Sitemap):
priority = None
changefreq = None

def __init__(self, info_dict, priority=None, changefreq=None):
self.queryset = info_dict['queryset']
self.date_field = info_dict.get('date_field')
self.priority = priority
self.changefreq = changefreq

def items(self):
# Make sure to return a clone; we don't want premature evaluation.
return self.queryset.filter()

def lastmod(self, item):
if self.date_field is not None:
return getattr(item, self.date_field)
return None

default_app_config = 'django.contrib.sitemaps.apps.SiteMapsConfig'

Source code for django.contrib.auth

import inspect
import re

from django.apps import apps as django_apps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.middleware.csrf import rotate_token
from django.utils.crypto import constant_time_compare
from django.utils.module_loading import import_string
from django.utils.translation import LANGUAGE_SESSION_KEY

from .signals import user_logged_in, user_logged_out, user_login_failed

SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
HASH_SESSION_KEY = '_auth_user_hash'
REDIRECT_FIELD_NAME = 'next'

def load_backend(path):
return import_string(path)()

def _get_backends(return_tuples=False):
backends = []
for backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
backends.append((backend, backend_path) if return_tuples else backend)
if not backends:
raise ImproperlyConfigured(
'No authentication backends have been defined. Does '
'AUTHENTICATION_BACKENDS contain anything?'
)
return backends

def get_backends():
return _get_backends(return_tuples=False)

def _clean_credentials(credentials):
"""
Cleans a dictionary of credentials of potentially sensitive info before
sending to less secure functions.

Not comprehensive - intended for user_login_failed signal
"""
SENSITIVE_CREDENTIALS = re.compile('api|token|key|secret|password|signature', re.I)
CLEANSED_SUBSTITUTE = '********************'
for key in credentials:
if SENSITIVE_CREDENTIALS.search(key):
credentials[key] = CLEANSED_SUBSTITUTE
return credentials

def _get_user_session_key(request):
# This value in the session is always serialized to a string, so we need
# to convert it back to Python whenever we access it.
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])

[docs]def authenticate(**credentials):
"""
If the given credentials are valid, return a User object.
"""
for backend, backend_path in _get_backends(return_tuples=True):
try:
inspect.getcallargs(backend.authenticate, **credentials)
except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one.
continue

try:
user = backend.authenticate(**credentials)
except PermissionDenied:
# This backend says to stop in our tracks - this user should not be allowed in at all.
return None
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = backend_path
return user

# The credentials supplied are invalid to all backends, fire signal
user_login_failed.send(sender=__name__,
credentials=_clean_credentials(credentials))

[docs]def login(request, user):
"""
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
"""
session_auth_hash = ''
if user is None:
user = request.user
if hasattr(user, 'get_session_auth_hash'):
session_auth_hash = user.get_session_auth_hash()

if SESSION_KEY in request.session:
if _get_user_session_key(request) != user.pk or (
session_auth_hash and
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
# To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different
# authenticated user.
request.session.flush()
else:
request.session.cycle_key()
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = user.backend
request.session[HASH_SESSION_KEY] = session_auth_hash
if hasattr(request, 'user'):
request.user = user
rotate_token(request)
user_logged_in.send(sender=user.__class__, request=request, user=user)

[docs]def logout(request):
"""
Removes the authenticated user's ID from the request and flushes their
session data.
"""
# Dispatch the signal before the user is logged out so the receivers have a
# chance to find out *who* logged out.
user = getattr(request, 'user', None)
if hasattr(user, 'is_authenticated') and not user.is_authenticated():
user = None
user_logged_out.send(sender=user.__class__, request=request, user=user)

# remember language choice saved to session
language = request.session.get(LANGUAGE_SESSION_KEY)

request.session.flush()

if language is not None:
request.session[LANGUAGE_SESSION_KEY] = language

if hasattr(request, 'user'):
from django.contrib.auth.models import AnonymousUser
request.user = AnonymousUser()

[docs]def get_user_model():
"""
Returns the User model that is active in this project.
"""
try:
return django_apps.get_model(settings.AUTH_USER_MODEL)
except ValueError:
raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
except LookupError:
raise ImproperlyConfigured(
"AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
)

def get_user(request):
"""
Returns the user model instance associated with the given request session.
If no user is retrieved an instance of `AnonymousUser` is returned.
"""
from .models import AnonymousUser
user = None
try:
user_id = _get_user_session_key(request)
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
else:
if backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
user = backend.get_user(user_id)
# Verify the session
if ('django.contrib.auth.middleware.SessionAuthenticationMiddleware'
in settings.MIDDLEWARE_CLASSES and hasattr(user, 'get_session_auth_hash')):
session_hash = request.session.get(HASH_SESSION_KEY)
session_hash_verified = session_hash and constant_time_compare(
session_hash,
user.get_session_auth_hash()
)
if not session_hash_verified:
request.session.flush()
user = None

return user or AnonymousUser()

def get_permission_codename(action, opts):
"""
Returns the codename of the permission for the specified action.
"""
return '%s_%s' % (action, opts.model_name)

def update_session_auth_hash(request, user):
"""
Updating a user's password logs out all sessions for the user if
django.contrib.auth.middleware.SessionAuthenticationMiddleware is enabled.

This function takes the current request and the updated user object from
which the new session hash will be derived and updates the session hash
appropriately to prevent a password change from logging out the session
from which the password was changed.
"""
if hasattr(user, 'get_session_auth_hash') and request.user == user:
request.session[HASH_SESSION_KEY] = user.get_session_auth_hash()

default_app_config = 'django.contrib.auth.apps.AuthConfig'

Source code for django.contrib.admin.decorators

[docs]def register(*models, **kwargs):
"""
Registers the given model(s) classes and wrapped ModelAdmin class with
admin site:

@register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass

A kwarg of `site` can be passed as the admin site, otherwise the default
admin site will be used.
"""
from django.contrib.admin import ModelAdmin
from django.contrib.admin.sites import site, AdminSite

def _model_admin_wrapper(admin_class):
admin_site = kwargs.pop('site', site)

if not isinstance(admin_site, AdminSite):
raise ValueError('site must subclass AdminSite')

if not issubclass(admin_class, ModelAdmin):
raise ValueError('Wrapped class must subclass ModelAdmin.')

admin_site.register(models, admin_class=admin_class)

return admin_class
return _model_admin_wrapper

Source code for django.contrib.admin.sites

from functools import update_wrapper

from django.apps import apps
from django.conf import settings
from django.contrib.admin import ModelAdmin, actions
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db.models.base import ModelBase
from django.http import Http404, HttpResponseRedirect
from django.template.engine import Engine
from django.template.response import TemplateResponse
from django.utils import six
from django.utils.text import capfirst
from django.utils.translation import ugettext as _, ugettext_lazy
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect

system_check_errors = []

class AlreadyRegistered(Exception):
pass

class NotRegistered(Exception):
pass

[docs]class AdminSite(object):
"""
An AdminSite object encapsulates an instance of the Django admin application, ready
to be hooked in to your URLconf. Models are registered with the AdminSite using the
register() method, and the get_urls() method can then be used to access Django view
functions that present a full admin interface for the collection of registered
models.
"""

# Text to put at the end of each page's <title>.
site_title = ugettext_lazy('Django site admin')

# Text to put in each page's <h1>.
site_header = ugettext_lazy('Django administration')

# Text to put at the top of the admin index page.
index_title = ugettext_lazy('Site administration')

# URL for the "View site" link at the top of each admin page.
site_url = '/'

_empty_value_display = '-'

login_form = None
index_template = None
app_index_template = None
login_template = None
logout_template = None
password_change_template = None
password_change_done_template = None

def __init__(self, name='admin'):
self._registry = {}  # model_class class -> admin_class instance
self.name = name
self._actions = {'delete_selected': actions.delete_selected}
self._global_actions = self._actions.copy()

def register(self, model_or_iterable, admin_class=None, **options):
"""
Registers the given model(s) with the given admin class.

The model(s) should be Model classes, not instances.

If an admin class isn't given, it will use ModelAdmin (the default
admin options). If keyword arguments are given -- e.g., list_display --
they'll be applied as options to the admin class.

If a model is already registered, this will raise AlreadyRegistered.

If a model is abstract, this will raise ImproperlyConfigured.
"""
if not admin_class:
admin_class = ModelAdmin

if isinstance(model_or_iterable, ModelBase):
model_or_iterable = [model_or_iterable]
for model in model_or_iterable:
if model._meta.abstract:
raise ImproperlyConfigured('The model %s is abstract, so it '
'cannot be registered with admin.' % model.__name__)

if model in self._registry:
raise AlreadyRegistered('The model %s is already registered' % model.__name__)

# Ignore the registration if the model has been
# swapped out.
if not model._meta.swapped:
# If we got **options then dynamically construct a subclass of
# admin_class with those **options.
if options:
# For reasons I don't quite understand, without a __module__
# the created class appears to "live" in the wrong place,
# which causes issues later on.
options['__module__'] = __name__
admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)

# Instantiate the admin class to save in the registry
admin_obj = admin_class(model, self)
if admin_class is not ModelAdmin and settings.DEBUG:
system_check_errors.extend(admin_obj.check())

self._registry[model] = admin_obj

def unregister(self, model_or_iterable):
"""
Unregisters the given model(s).

If a model isn't already registered, this will raise NotRegistered.
"""
if isinstance(model_or_iterable, ModelBase):
model_or_iterable = [model_or_iterable]
for model in model_or_iterable:
if model not in self._registry:
raise NotRegistered('The model %s is not registered' % model.__name__)
del self._registry[model]

def is_registered(self, model):
"""
Check if a model class is registered with this `AdminSite`.
"""
return model in self._registry

[docs]    def add_action(self, action, name=None):
"""
Register an action to be available globally.
"""
name = name or action.__name__
self._actions[name] = action
self._global_actions[name] = action

[docs]    def disable_action(self, name):
"""
Disable a globally-registered action. Raises KeyError for invalid names.
"""
del self._actions[name]

def get_action(self, name):
"""
Explicitly get a registered global action whether it's enabled or
not. Raises KeyError for invalid names.
"""
return self._global_actions[name]

@property
def actions(self):
"""
Get all the enabled actions as an iterable of (name, func).
"""
return six.iteritems(self._actions)

@property
def empty_value_display(self):
return self._empty_value_display

@empty_value_display.setter
def empty_value_display(self, empty_value_display):
self._empty_value_display = empty_value_display

[docs]    def has_permission(self, request):
"""
Returns True if the given HttpRequest has permission to view
*at least one* page in the admin site.
"""
return request.user.is_active and request.user.is_staff

def check_dependencies(self):
"""
Check that all things needed to run the admin have been correctly installed.

The default implementation checks that admin and contenttypes apps are
installed, as well as the auth context processor.
"""
if not apps.is_installed('django.contrib.admin'):
raise ImproperlyConfigured(
"Put 'django.contrib.admin' in your INSTALLED_APPS "
"setting in order to use the admin application.")
if not apps.is_installed('django.contrib.contenttypes'):
raise ImproperlyConfigured(
"Put 'django.contrib.contenttypes' in your INSTALLED_APPS "
"setting in order to use the admin application.")
try:
default_template_engine = Engine.get_default()
except Exception:
# Skip this non-critical check:
# 1. if the user has a non-trivial TEMPLATES setting and Django
#    can't find a default template engine
# 2. if anything goes wrong while loading template engines, in
#    order to avoid raising an exception from a confusing location
# Catching ImproperlyConfigured suffices for 1. but 2. requires
# catching all exceptions.
pass
else:
if ('django.contrib.auth.context_processors.auth'
not in default_template_engine.context_processors):
raise ImproperlyConfigured(
"Enable 'django.contrib.auth.context_processors.auth' "
"in your TEMPLATES setting in order to use the admin "
"application.")

def admin_view(self, view, cacheable=False):
"""
Decorator to create an admin view attached to this ``AdminSite``. This
wraps the view and provides permission checking by calling
``self.has_permission``.

You'll want to use this from within ``AdminSite.get_urls()``:

class MyAdminSite(AdminSite):

def get_urls(self):
from django.conf.urls import url

urls = super(MyAdminSite, self).get_urls()
urls += [
url(r'^my_view/$', self.admin_view(some_view))
]
return urls

By default, admin_views are marked non-cacheable using the
``never_cache`` decorator. If the view can be safely cached, set
cacheable=True.
"""
def inner(request, *args, **kwargs):
if not self.has_permission(request):
if request.path == reverse('admin:logout', current_app=self.name):
index_path = reverse('admin:index', current_app=self.name)
return HttpResponseRedirect(index_path)
# Inner import to prevent django.contrib.admin (app) from
# importing django.contrib.auth.models.User (unrelated model).
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
request.get_full_path(),
reverse('admin:login', current_app=self.name)
)
return view(request, *args, **kwargs)
if not cacheable:
inner = never_cache(inner)
# We add csrf_protect here so this function can be used as a utility
# function for any view, without having to repeat 'csrf_protect'.
if not getattr(view, 'csrf_exempt', False):
inner = csrf_protect(inner)
return update_wrapper(inner, view)

def get_urls(self):
from django.conf.urls import url, include
# Since this module gets imported in the application's root package,
# it cannot import models from other applications at the module level,
# and django.contrib.contenttypes.views imports ContentType.
from django.contrib.contenttypes import views as contenttype_views

if settings.DEBUG:
self.check_dependencies()

def wrap(view, cacheable=False):
def wrapper(*args, **kwargs):
return self.admin_view(view, cacheable)(*args, **kwargs)
wrapper.admin_site = self
return update_wrapper(wrapper, view)

# Admin-site-wide views.
urlpatterns = [
url(r'^$', wrap(self.index), name='index'),
url(r'^login/$', self.login, name='login'),
url(r'^logout/$', wrap(self.logout), name='logout'),
url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
name='password_change_done'),
url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
name='view_on_site'),
]

# Add in each model's views, and create a list of valid URLS for the
# app_index
valid_app_labels = []
for model, model_admin in self._registry.items():
urlpatterns += [
url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
]
if model._meta.app_label not in valid_app_labels:
valid_app_labels.append(model._meta.app_label)

# If there were ModelAdmins registered, we should have a list of app
# labels for which we need to allow access to the app_index view,
if valid_app_labels:
regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
urlpatterns += [
url(regex, wrap(self.app_index), name='app_list'),
]
return urlpatterns

@property
def urls(self):
return self.get_urls(), 'admin', self.name

[docs]    def each_context(self, request):
"""
Returns a dictionary of variables to put in the template context for
*every* page in the admin site.
"""
return {
'site_title': self.site_title,
'site_header': self.site_header,
'site_url': self.site_url,
'has_permission': self.has_permission(request),
'available_apps': self.get_app_list(request),
}

def password_change(self, request, extra_context=None):
"""
Handles the "change password" task -- both form display and validation.
"""
from django.contrib.admin.forms import AdminPasswordChangeForm
from django.contrib.auth.views import password_change
url = reverse('admin:password_change_done', current_app=self.name)
defaults = {
'password_change_form': AdminPasswordChangeForm,
'post_change_redirect': url,
'extra_context': dict(self.each_context(request), **(extra_context or {})),
}
if self.password_change_template is not None:
defaults['template_name'] = self.password_change_template
request.current_app = self.name
return password_change(request, **defaults)

def password_change_done(self, request, extra_context=None):
"""
Displays the "success" page after a password change.
"""
from django.contrib.auth.views import password_change_done
defaults = {
'extra_context': dict(self.each_context(request), **(extra_context or {})),
}
if self.password_change_done_template is not None:
defaults['template_name'] = self.password_change_done_template
request.current_app = self.name
return password_change_done(request, **defaults)

def i18n_javascript(self, request):
"""
Displays the i18n JavaScript that the Django admin requires.

This takes into account the USE_I18N setting. If it's set to False, the
generated JavaScript will be leaner and faster.
"""
if settings.USE_I18N:
from django.views.i18n import javascript_catalog
else:
from django.views.i18n import null_javascript_catalog as javascript_catalog
return javascript_catalog(request, packages=['django.conf', 'django.contrib.admin'])

@never_cache
def logout(self, request, extra_context=None):
"""
Logs out the user for the given HttpRequest.

This should *not* assume the user is already logged in.
"""
from django.contrib.auth.views import logout
defaults = {
'extra_context': dict(
self.each_context(request),
# Since the user isn't logged out at this point, the value of
# has_permission must be overridden.
has_permission=False,
**(extra_context or {})
),
}
if self.logout_template is not None:
defaults['template_name'] = self.logout_template
request.current_app = self.name
return logout(request, **defaults)

@never_cache
def login(self, request, extra_context=None):
"""
Displays the login form for the given HttpRequest.
"""
if request.method == 'GET' and self.has_permission(request):
# Already logged-in, redirect to admin index
index_path = reverse('admin:index', current_app=self.name)
return HttpResponseRedirect(index_path)

from django.contrib.auth.views import login
# Since this module gets imported in the application's root package,
# it cannot import models from other applications at the module level,
# and django.contrib.admin.forms eventually imports User.
from django.contrib.admin.forms import AdminAuthenticationForm
context = dict(self.each_context(request),
title=_('Log in'),
app_path=request.get_full_path(),
username=request.user.get_username(),
)
if (REDIRECT_FIELD_NAME not in request.GET and
REDIRECT_FIELD_NAME not in request.POST):
context[REDIRECT_FIELD_NAME] = reverse('admin:index', current_app=self.name)
context.update(extra_context or {})

defaults = {
'extra_context': context,
'authentication_form': self.login_form or AdminAuthenticationForm,
'template_name': self.login_template or 'admin/login.html',
}
request.current_app = self.name
return login(request, **defaults)

def _build_app_dict(self, request, label=None):
"""
Builds the app dictionary. Takes an optional label parameters to filter
models of a specific app.
"""
app_dict = {}

if label:
models = {
m: m_a for m, m_a in self._registry.items()
if m._meta.app_label == label
}
else:
models = self._registry

for model, model_admin in models.items():
app_label = model._meta.app_label

has_module_perms = model_admin.has_module_permission(request)
if not has_module_perms:
if label:
raise PermissionDenied
continue

perms = model_admin.get_model_perms(request)

# Check whether user has any perm for this module.
# If so, add the module to the model_list.
if True not in perms.values():
continue

info = (app_label, model._meta.model_name)
model_dict = {
'name': capfirst(model._meta.verbose_name_plural),
'object_name': model._meta.object_name,
'perms': perms,
}
if perms.get('change'):
try:
model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name)
except NoReverseMatch:
pass
if perms.get('add'):
try:
model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=self.name)
except NoReverseMatch:
pass

if app_label in app_dict:
app_dict[app_label]['models'].append(model_dict)
else:
app_dict[app_label] = {
'name': apps.get_app_config(app_label).verbose_name,
'app_label': app_label,
'app_url': reverse(
'admin:app_list',
kwargs={'app_label': app_label},
current_app=self.name,
),
'has_module_perms': has_module_perms,
'models': [model_dict],
}

if label:
return app_dict.get(label)
return app_dict

def get_app_list(self, request):
"""
Returns a sorted list of all the installed apps that have been
registered in this site.
"""
app_dict = self._build_app_dict(request)

# Sort the apps alphabetically.
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())

# Sort the models alphabetically within each app.
for app in app_list:
app['models'].sort(key=lambda x: x['name'])

return app_list

@never_cache
def index(self, request, extra_context=None):
"""
Displays the main admin index page, which lists all of the installed
apps that have been registered in this site.
"""
app_list = self.get_app_list(request)

context = dict(
self.each_context(request),
title=self.index_title,
app_list=app_list,
)
context.update(extra_context or {})

request.current_app = self.name

return TemplateResponse(request, self.index_template or
'admin/index.html', context)

def app_index(self, request, app_label, extra_context=None):
app_dict = self._build_app_dict(request, app_label)
if not app_dict:
raise Http404('The requested admin page does not exist.')
# Sort the models alphabetically within each app.
app_dict['models'].sort(key=lambda x: x['name'])
app_name = apps.get_app_config(app_label).verbose_name
context = dict(self.each_context(request),
title=_('%(app)s administration') % {'app': app_name},
app_list=[app_dict],
app_label=app_label,
)
context.update(extra_context or {})

request.current_app = self.name

return TemplateResponse(request, self.app_index_template or [
'admin/%s/app_index.html' % app_label,
'admin/app_index.html'
], context)

# This global object represents the default admin site, for the common case.
# You can instantiate AdminSite in your own code to create a custom admin site.
site = AdminSite()

Source code for django.contrib.admin.options

import copy
import operator
from collections import OrderedDict
from functools import partial, reduce, update_wrapper

from django import forms
from django.conf import settings
from django.contrib import messages
from django.contrib.admin import helpers, widgets
from django.contrib.admin.checks import (
BaseModelAdminChecks, InlineModelAdminChecks, ModelAdminChecks,
)
from django.contrib.admin.exceptions import DisallowedModelAdminToField
from django.contrib.admin.templatetags.admin_static import static
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib.admin.utils import (
NestedObjects, flatten_fieldsets, get_deleted_objects,
lookup_needs_distinct, model_format_dict, quote, unquote,
)
from django.contrib.auth import get_permission_codename
from django.core.exceptions import (
FieldDoesNotExist, FieldError, PermissionDenied, ValidationError,
)
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse
from django.db import models, router, transaction
from django.db.models.constants import LOOKUP_SEP
from django.db.models.fields import BLANK_CHOICE_DASH
from django.forms.formsets import DELETION_FIELD_NAME, all_valid
from django.forms.models import (
BaseInlineFormSet, inlineformset_factory, modelform_defines_fields,
modelform_factory, modelformset_factory,
)
from django.forms.widgets import CheckboxSelectMultiple, SelectMultiple
from django.http import Http404, HttpResponseRedirect
from django.http.response import HttpResponseBase
from django.template.response import SimpleTemplateResponse, TemplateResponse
from django.utils import six
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.html import escape
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
from django.utils.text import capfirst, get_text_list
from django.utils.translation import string_concat, ugettext as _, ungettext
from django.views.decorators.csrf import csrf_protect
from django.views.generic import RedirectView

IS_POPUP_VAR = '_popup'
TO_FIELD_VAR = '_to_field'

HORIZONTAL, VERTICAL = 1, 2

def get_content_type_for_model(obj):
# Since this module gets imported in the application's root package,
# it cannot import models from other applications at the module level.
from django.contrib.contenttypes.models import ContentType
return ContentType.objects.get_for_model(obj, for_concrete_model=False)

def get_ul_class(radio_style):
return 'radiolist' if radio_style == VERTICAL else 'radiolist inline'

class IncorrectLookupParameters(Exception):
pass

# Defaults for formfield_overrides. ModelAdmin subclasses can change this
# by adding to ModelAdmin.formfield_overrides.

FORMFIELD_FOR_DBFIELD_DEFAULTS = {
models.DateTimeField: {
'form_class': forms.SplitDateTimeField,
'widget': widgets.AdminSplitDateTime
},
models.DateField: {'widget': widgets.AdminDateWidget},
models.TimeField: {'widget': widgets.AdminTimeWidget},
models.TextField: {'widget': widgets.AdminTextareaWidget},
models.URLField: {'widget': widgets.AdminURLFieldWidget},
models.IntegerField: {'widget': widgets.AdminIntegerFieldWidget},
models.BigIntegerField: {'widget': widgets.AdminBigIntegerFieldWidget},
models.CharField: {'widget': widgets.AdminTextInputWidget},
models.ImageField: {'widget': widgets.AdminFileWidget},
models.FileField: {'widget': widgets.AdminFileWidget},
models.EmailField: {'widget': widgets.AdminEmailInputWidget},
}

csrf_protect_m = method_decorator(csrf_protect)

class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
"""Functionality common to both ModelAdmin and InlineAdmin."""

raw_id_fields = ()
fields = None
exclude = None
fieldsets = None
form = forms.ModelForm
filter_vertical = ()
filter_horizontal = ()
radio_fields = {}
prepopulated_fields = {}
formfield_overrides = {}
readonly_fields = ()
ordering = None
view_on_site = True
show_full_result_count = True
checks_class = BaseModelAdminChecks

def check(self, **kwargs):
return self.checks_class().check(self, **kwargs)

def __init__(self):
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
overrides.update(self.formfield_overrides)
self.formfield_overrides = overrides

def formfield_for_dbfield(self, db_field, **kwargs):
"""
Hook for specifying the form Field instance for a given database Field
instance.

If kwargs are given, they're passed to the form Field's constructor.
"""
request = kwargs.pop("request", None)

# If the field specifies choices, we don't need to look for special
# admin widgets - we just need to use a select widget of some kind.
if db_field.choices:
return self.formfield_for_choice_field(db_field, request, **kwargs)

# ForeignKey or ManyToManyFields
if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
# Combine the field kwargs with any options for formfield_overrides.
# Make sure the passed in **kwargs override anything in
# formfield_overrides because **kwargs is more specific, and should
# always win.
if db_field.__class__ in self.formfield_overrides:
kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs)

# Get the correct formfield.
if isinstance(db_field, models.ForeignKey):
formfield = self.formfield_for_foreignkey(db_field, request, **kwargs)
elif isinstance(db_field, models.ManyToManyField):
formfield = self.formfield_for_manytomany(db_field, request, **kwargs)

# For non-raw_id fields, wrap the widget with a wrapper that adds
# extra HTML -- the "add other" interface -- to the end of the
# rendered output. formfield can be None if it came from a
# OneToOneField with parent_link=True or a M2M intermediary.
if formfield and db_field.name not in self.raw_id_fields:
related_modeladmin = self.admin_site._registry.get(db_field.remote_field.model)
wrapper_kwargs = {}
if related_modeladmin:
wrapper_kwargs.update(
can_add_related=related_modeladmin.has_add_permission(request),
can_change_related=related_modeladmin.has_change_permission(request),
can_delete_related=related_modeladmin.has_delete_permission(request),
)
formfield.widget = widgets.RelatedFieldWidgetWrapper(
formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs
)

return formfield

# If we've got overrides for the formfield defined, use 'em. **kwargs
# passed to formfield_for_dbfield override the defaults.
for klass in db_field.__class__.mro():
if klass in self.formfield_overrides:
kwargs = dict(copy.deepcopy(self.formfield_overrides[klass]), **kwargs)
return db_field.formfield(**kwargs)

# For any other type of field, just call its formfield() method.
return db_field.formfield(**kwargs)

def formfield_for_choice_field(self, db_field, request=None, **kwargs):
"""
Get a form Field for a database Field that has declared choices.
"""
# If the field is named as a radio_field, use a RadioSelect
if db_field.name in self.radio_fields:
# Avoid stomping on custom widget/choices arguments.
if 'widget' not in kwargs:
kwargs['widget'] = widgets.AdminRadioSelect(attrs={
'class': get_ul_class(self.radio_fields[db_field.name]),
})
if 'choices' not in kwargs:
kwargs['choices'] = db_field.get_choices(
include_blank=db_field.blank,
blank_choice=[('', _('None'))]
)
return db_field.formfield(**kwargs)

def get_field_queryset(self, db, db_field, request):
"""
If the ModelAdmin specifies ordering, the queryset should respect that
ordering.  Otherwise don't specify the queryset, let the field decide
(returns None in that case).
"""
related_admin = self.admin_site._registry.get(db_field.remote_field.model)
if related_admin is not None:
ordering = related_admin.get_ordering(request)
if ordering is not None and ordering != ():
return db_field.remote_field.model._default_manager.using(db).order_by(*ordering)
return None

def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
"""
Get a form Field for a ForeignKey.
"""
db = kwargs.get('using')
if db_field.name in self.raw_id_fields:
kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field,
self.admin_site, using=db)
elif db_field.name in self.radio_fields:
kwargs['widget'] = widgets.AdminRadioSelect(attrs={
'class': get_ul_class(self.radio_fields[db_field.name]),
})
kwargs['empty_label'] = _('None') if db_field.blank else None

if 'queryset' not in kwargs:
queryset = self.get_field_queryset(db, db_field, request)
if queryset is not None:
kwargs['queryset'] = queryset

return db_field.formfield(**kwargs)

def formfield_for_manytomany(self, db_field, request=None, **kwargs):
"""
Get a form Field for a ManyToManyField.
"""
# If it uses an intermediary model that isn't auto created, don't show
# a field in admin.
if not db_field.remote_field.through._meta.auto_created:
return None
db = kwargs.get('using')

if db_field.name in self.raw_id_fields:
kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.remote_field,
self.admin_site, using=db)
kwargs['help_text'] = ''
elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
kwargs['widget'] = widgets.FilteredSelectMultiple(
db_field.verbose_name,
db_field.name in self.filter_vertical
)

if 'queryset' not in kwargs:
queryset = self.get_field_queryset(db, db_field, request)
if queryset is not None:
kwargs['queryset'] = queryset

form_field = db_field.formfield(**kwargs)
if isinstance(form_field.widget, SelectMultiple) and not isinstance(form_field.widget, CheckboxSelectMultiple):
msg = _('Hold down "Control", or "Command" on a Mac, to select more than one.')
help_text = form_field.help_text
form_field.help_text = string_concat(help_text, ' ', msg) if help_text else msg
return form_field

def get_view_on_site_url(self, obj=None):
if obj is None or not self.view_on_site:
return None

if callable(self.view_on_site):
return self.view_on_site(obj)
elif self.view_on_site and hasattr(obj, 'get_absolute_url'):
# use the ContentType lookup if view_on_site is True
return reverse('admin:view_on_site', kwargs={
'content_type_id': get_content_type_for_model(obj).pk,
'object_id': obj.pk
})

def get_empty_value_display(self):
"""
Return the empty_value_display set on ModelAdmin or AdminSite.
"""
try:
return mark_safe(self.empty_value_display)
except AttributeError:
return mark_safe(self.admin_site.empty_value_display)

def get_fields(self, request, obj=None):
"""
Hook for specifying fields.
"""
return self.fields

def get_fieldsets(self, request, obj=None):
"""
Hook for specifying fieldsets.
"""
if self.fieldsets:
return self.fieldsets
return [(None, {'fields': self.get_fields(request, obj)})]

def get_ordering(self, request):
"""
Hook for specifying field ordering.
"""
return self.ordering or ()  # otherwise we might try to *None, which is bad ;)

def get_readonly_fields(self, request, obj=None):
"""
Hook for specifying custom readonly fields.
"""
return self.readonly_fields

def get_prepopulated_fields(self, request, obj=None):
"""
Hook for specifying custom prepopulated fields.
"""
return self.prepopulated_fields

def get_queryset(self, request):
"""
Returns a QuerySet of all model instances that can be edited by the
admin site. This is used by changelist_view.
"""
qs = self.model._default_manager.get_queryset()
# TODO: this should be handled by some parameter to the ChangeList.
ordering = self.get_ordering(request)
if ordering:
qs = qs.order_by(*ordering)
return qs

def lookup_allowed(self, lookup, value):
from django.contrib.admin.filters import SimpleListFilter

model = self.model
# Check FKey lookups that are allowed, so that popups produced by
# ForeignKeyRawIdWidget, on the basis of ForeignKey.limit_choices_to,
# are allowed to work.
for l in model._meta.related_fkey_lookups:
# As ``limit_choices_to`` can be a callable, invoke it here.
if callable(l):
l = l()
for k, v in widgets.url_params_from_lookup_dict(l).items():
if k == lookup and v == value:
return True

relation_parts = []
prev_field = None
for part in lookup.split(LOOKUP_SEP):
try:
field = model._meta.get_field(part)
except FieldDoesNotExist:
# Lookups on non-existent fields are ok, since they're ignored
# later.
break
# It is allowed to filter on values that would be found from local
# model anyways. For example, if you filter on employee__department__id,
# then the id value would be found already from employee__department_id.
if not prev_field or (prev_field.concrete and
field not in prev_field.get_path_info()[-1].target_fields):
relation_parts.append(part)
if not getattr(field, 'get_path_info', None):
# This is not a relational field, so further parts
# must be transforms.
break
prev_field = field
model = field.get_path_info()[-1].to_opts.model

if len(relation_parts) <= 1:
# Either a local field filter, or no fields at all.
return True
clean_lookup = LOOKUP_SEP.join(relation_parts)
valid_lookups = [self.date_hierarchy]
for filter_item in self.list_filter:
if isinstance(filter_item, type) and issubclass(filter_item, SimpleListFilter):
valid_lookups.append(filter_item.parameter_name)
elif isinstance(filter_item, (list, tuple)):
valid_lookups.append(filter_item[0])
else:
valid_lookups.append(filter_item)
return clean_lookup in valid_lookups

def to_field_allowed(self, request, to_field):
"""
Returns True if the model associated with this admin should be
allowed to be referenced by the specified field.
"""
opts = self.model._meta

try:
field = opts.get_field(to_field)
except FieldDoesNotExist:
return False

# Always allow referencing the primary key since it's already possible
# to get this information from the change view URL.
if field.primary_key:
return True

# Allow reverse relationships to models defining m2m fields if they
# target the specified field.
for many_to_many in opts.many_to_many:
if many_to_many.m2m_target_field_name() == to_field:
return True

# Make sure at least one of the models registered for this site
# references this field through a FK or a M2M relationship.
registered_models = set()
for model, admin in self.admin_site._registry.items():
registered_models.add(model)
for inline in admin.inlines:
registered_models.add(inline.model)

related_objects = (
f for f in opts.get_fields(include_hidden=True)
if (f.auto_created and not f.concrete)
)
for related_object in related_objects:
related_model = related_object.related_model
remote_field = related_object.field.remote_field
if (any(issubclass(model, related_model) for model in registered_models) and
hasattr(remote_field, 'get_related_field') and
remote_field.get_related_field() == field):
return True

return False

def has_add_permission(self, request):
"""
Returns True if the given request has permission to add an object.
Can be overridden by the user in subclasses.
"""
opts = self.opts
codename = get_permission_codename('add', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_change_permission(self, request, obj=None):
"""
Returns True if the given request has permission to change the given
Django model instance, the default implementation doesn't examine the
`obj` parameter.

Can be overridden by the user in subclasses. In such case it should
return True if the given request has permission to change the `obj`
model instance. If `obj` is None, this should return True if the given
request has permission to change *any* object of the given type.
"""
opts = self.opts
codename = get_permission_codename('change', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_delete_permission(self, request, obj=None):
"""
Returns True if the given request has permission to change the given
Django model instance, the default implementation doesn't examine the
`obj` parameter.

Can be overridden by the user in subclasses. In such case it should
return True if the given request has permission to delete the `obj`
model instance. If `obj` is None, this should return True if the given
request has permission to delete *any* object of the given type.
"""
opts = self.opts
codename = get_permission_codename('delete', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_module_permission(self, request):
"""
Returns True if the given request has any permission in the given
app label.

Can be overridden by the user in subclasses. In such case it should
return True if the given request has permission to view the module on
the admin index page and access the module's index page. Overriding it
does not restrict access to the add, change or delete views. Use
`ModelAdmin.has_(add|change|delete)_permission` for that.
"""
return request.user.has_module_perms(self.opts.app_label)

@python_2_unicode_compatible

[docs]class ModelAdmin(BaseModelAdmin):
"Encapsulates all admin options and functionality for a given model."

list_display = ('__str__',)
list_display_links = ()
list_filter = ()
list_select_related = False
list_per_page = 100
list_max_show_all = 200
list_editable = ()
search_fields = ()
date_hierarchy = None
save_as = False
save_on_top = False
paginator = Paginator
preserve_filters = True
inlines = []

# Custom templates (designed to be over-ridden in subclasses)
add_form_template = None
change_form_template = None
change_list_template = None
delete_confirmation_template = None
delete_selected_confirmation_template = None
object_history_template = None

# Actions
actions = []
action_form = helpers.ActionForm
actions_on_top = True
actions_on_bottom = False
actions_selection_counter = True
checks_class = ModelAdminChecks

def __init__(self, model, admin_site):
self.model = model
self.opts = model._meta
self.admin_site = admin_site
super(ModelAdmin, self).__init__()

def __str__(self):
return "%s.%s" % (self.model._meta.app_label, self.__class__.__name__)

[docs]    def get_inline_instances(self, request, obj=None):
inline_instances = []
for inline_class in self.inlines:
inline = inline_class(self.model, self.admin_site)
if request:
if not (inline.has_add_permission(request) or
inline.has_change_permission(request, obj) or
inline.has_delete_permission(request, obj)):
continue
if not inline.has_add_permission(request):
inline.max_num = 0
inline_instances.append(inline)

return inline_instances

[docs]    def get_urls(self):
from django.conf.urls import url

def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
wrapper.model_admin = self
return update_wrapper(wrapper, view)

info = self.model._meta.app_label, self.model._meta.model_name

urlpatterns = [
url(r'^$', wrap(self.changelist_view), name='%s_%s_changelist' % info),
url(r'^add/$', wrap(self.add_view), name='%s_%s_add' % info),
url(r'^(.+)/history/$', wrap(self.history_view), name='%s_%s_history' % info),
url(r'^(.+)/delete/$', wrap(self.delete_view), name='%s_%s_delete' % info),
url(r'^(.+)/change/$', wrap(self.change_view), name='%s_%s_change' % info),
# For backwards compatibility (was the change url before 1.9)
url(r'^(.+)/$', wrap(RedirectView.as_view(
pattern_name='%s:%s_%s_change' % ((self.admin_site.name,) + info)
))),
]
return urlpatterns

def urls(self):
return self.get_urls()
urls = property(urls)

@property
def media(self):
extra = '' if settings.DEBUG else '.min'
js = [
'core.js',
'vendor/jquery/jquery%s.js' % extra,
'jquery.init.js',
'admin/RelatedObjectLookups.js',
'actions%s.js' % extra,
'urlify.js',
'prepopulate%s.js' % extra,
'vendor/xregexp/xregexp%s.js' % extra,
]
return forms.Media(js=[static('admin/js/%s' % url) for url in js])

def get_model_perms(self, request):
"""
Returns a dict of all perms for this model. This dict has the keys
``add``, ``change``, and ``delete`` mapping to the True/False for each
of those actions.
"""
return {
'add': self.has_add_permission(request),
'change': self.has_change_permission(request),
'delete': self.has_delete_permission(request),
}

[docs]    def get_fields(self, request, obj=None):
if self.fields:
return self.fields
form = self.get_form(request, obj, fields=None)
return list(form.base_fields) + list(self.get_readonly_fields(request, obj))

[docs]    def get_form(self, request, obj=None, **kwargs):
"""
Returns a Form class for use in the admin add view. This is used by
add_view and change_view.
"""
if 'fields' in kwargs:
fields = kwargs.pop('fields')
else:
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
if self.exclude is None:
exclude = []
else:
exclude = list(self.exclude)
readonly_fields = self.get_readonly_fields(request, obj)
exclude.extend(readonly_fields)
if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
# Take the custom ModelForm's Meta.exclude into account only if the
# ModelAdmin doesn't define its own.
exclude.extend(self.form._meta.exclude)
# if exclude is an empty list we pass None to be consistent with the
# default on modelform_factory
exclude = exclude or None

# Remove declared form fields which are in readonly_fields.
new_attrs = OrderedDict(
(f, None) for f in readonly_fields
if f in self.form.declared_fields
)
form = type(self.form.__name__, (self.form,), new_attrs)

defaults = {
"form": form,
"fields": fields,
"exclude": exclude,
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
}
defaults.update(kwargs)

if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
defaults['fields'] = forms.ALL_FIELDS

try:
return modelform_factory(self.model, **defaults)
except FieldError as e:
raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.'
% (e, self.__class__.__name__))

[docs]    def get_changelist(self, request, **kwargs):
"""
Returns the ChangeList class for use on the changelist page.
"""
from django.contrib.admin.views.main import ChangeList
return ChangeList

def get_object(self, request, object_id, from_field=None):
"""
Returns an instance matching the field and value provided, the primary
key is used if no field is provided. Returns ``None`` if no match is
found or the object_id fails validation.
"""
queryset = self.get_queryset(request)
model = queryset.model
field = model._meta.pk if from_field is None else model._meta.get_field(from_field)
try:
object_id = field.to_python(object_id)
return queryset.get(**{field.name: object_id})
except (model.DoesNotExist, ValidationError, ValueError):
return None

[docs]    def get_changelist_form(self, request, **kwargs):
"""
Returns a Form class for use in the Formset on the changelist page.
"""
defaults = {
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
}
defaults.update(kwargs)
if (defaults.get('fields') is None
and not modelform_defines_fields(defaults.get('form'))):
defaults['fields'] = forms.ALL_FIELDS

return modelform_factory(self.model, **defaults)

[docs]    def get_changelist_formset(self, request, **kwargs):
"""
Returns a FormSet class for use on the changelist page if list_editable
is used.
"""
defaults = {
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
}
defaults.update(kwargs)
return modelformset_factory(self.model,
self.get_changelist_form(request), extra=0,
fields=self.list_editable, **defaults)

[docs]    def get_formsets_with_inlines(self, request, obj=None):
"""
Yields formsets and the corresponding inlines.
"""
for inline in self.get_inline_instances(request, obj):
yield inline.get_formset(request, obj), inline

[docs]    def get_paginator(self, request, queryset, per_page, orphans=0, allow_empty_first_page=True):
return self.paginator(queryset, per_page, orphans, allow_empty_first_page)

def log_addition(self, request, object, message):
"""
Log that an object has been successfully added.

The default implementation creates an admin LogEntry object.
"""
from django.contrib.admin.models import LogEntry, ADDITION
LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=get_content_type_for_model(object).pk,
object_id=object.pk,
object_repr=force_text(object),
action_flag=ADDITION,
change_message=message,
)

def log_change(self, request, object, message):
"""
Log that an object has been successfully changed.

The default implementation creates an admin LogEntry object.
"""
from django.contrib.admin.models import LogEntry, CHANGE
LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=get_content_type_for_model(object).pk,
object_id=object.pk,
object_repr=force_text(object),
action_flag=CHANGE,
change_message=message,
)

def log_deletion(self, request, object, object_repr):
"""
Log that an object will be deleted. Note that this method must be
called before the deletion.

The default implementation creates an admin LogEntry object.
"""
from django.contrib.admin.models import LogEntry, DELETION
LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=get_content_type_for_model(object).pk,
object_id=object.pk,
object_repr=object_repr,
action_flag=DELETION,
)

def action_checkbox(self, obj):
"""
A list_display column containing a checkbox widget.
"""
return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME, force_text(obj.pk))
action_checkbox.short_description = mark_safe('<input type="checkbox" id="action-toggle" />')

[docs]    def get_actions(self, request):
"""
Return a dictionary mapping the names of all actions for this
ModelAdmin to a tuple of (callable, name, description) for each action.
"""
# If self.actions is explicitly set to None that means that we don't
# want *any* actions enabled on this page.
if self.actions is None or IS_POPUP_VAR in request.GET:
return OrderedDict()

actions = []

# Gather actions from the admin site first
for (name, func) in self.admin_site.actions:
description = getattr(func, 'short_description', name.replace('_', ' '))
actions.append((func, name, description))

# Then gather them from the model admin and all parent classes,
# starting with self and working back up.
for klass in self.__class__.mro()[::-1]:
class_actions = getattr(klass, 'actions', [])
# Avoid trying to iterate over None
if not class_actions:
continue
actions.extend(self.get_action(action) for action in class_actions)

# get_action might have returned None, so filter any of those out.
actions = filter(None, actions)

# Convert the actions into an OrderedDict keyed by name.
actions = OrderedDict(
(name, (func, name, desc))
for func, name, desc in actions
)

return actions

def get_action_choices(self, request, default_choices=BLANK_CHOICE_DASH):
"""
Return a list of choices for use in a form object.  Each choice is a
tuple (name, description).
"""
choices = [] + default_choices
for func, name, description in six.itervalues(self.get_actions(request)):
choice = (name, description % model_format_dict(self.opts))
choices.append(choice)
return choices

def get_action(self, action):
"""
Return a given action from a parameter, which can either be a callable,
or the name of a method on the ModelAdmin.  Return is a tuple of
(callable, name, description).
"""
# If the action is a callable, just use it.
if callable(action):
func = action
action = action.__name__

# Next, look for a method. Grab it off self.__class__ to get an unbound
# method instead of a bound one; this ensures that the calling
# conventions are the same for functions and methods.
elif hasattr(self.__class__, action):
func = getattr(self.__class__, action)

# Finally, look for a named method on the admin site
else:
try:
func = self.admin_site.get_action(action)
except KeyError:
return None

if hasattr(func, 'short_description'):
description = func.short_description
else:
description = capfirst(action.replace('_', ' '))
return func, action, description

[docs]    def get_list_display(self, request):
"""
Return a sequence containing the fields to be displayed on the
changelist.
"""
return self.list_display

[docs]    def get_list_display_links(self, request, list_display):
"""
Return a sequence containing the fields to be displayed as links
on the changelist. The list_display parameter is the list of fields
returned by get_list_display().
"""
if self.list_display_links or self.list_display_links is None or not list_display:
return self.list_display_links
else:
# Use only the first item in list_display as link
return list(list_display)[:1]

[docs]    def get_list_filter(self, request):
"""
Returns a sequence containing the fields to be displayed as filters in
the right sidebar of the changelist page.
"""
return self.list_filter

[docs]    def get_list_select_related(self, request):
"""
Returns a list of fields to add to the select_related() part of the
changelist items query.
"""
return self.list_select_related

[docs]    def get_search_fields(self, request):
"""
Returns a sequence containing the fields to be searched whenever
somebody submits a search query.
"""
return self.search_fields

[docs]    def get_search_results(self, request, queryset, search_term):
"""
Returns a tuple containing a queryset to implement the search,
and a boolean indicating if the results may contain duplicates.
"""
# Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name

use_distinct = False
search_fields = self.get_search_fields(request)
if search_fields and search_term:
orm_lookups = [construct_search(str(search_field))
for search_field in search_fields]
for bit in search_term.split():
or_queries = [models.Q(**{orm_lookup: bit})
for orm_lookup in orm_lookups]
queryset = queryset.filter(reduce(operator.or_, or_queries))
if not use_distinct:
for search_spec in orm_lookups:
if lookup_needs_distinct(self.opts, search_spec):
use_distinct = True
break

return queryset, use_distinct

def get_preserved_filters(self, request):
"""
Returns the preserved filters querystring.
"""
match = request.resolver_match
if self.preserve_filters and match:
opts = self.model._meta
current_url = '%s:%s' % (match.app_name, match.url_name)
changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
if current_url == changelist_url:
preserved_filters = request.GET.urlencode()
else:
preserved_filters = request.GET.get('_changelist_filters')

if preserved_filters:
return urlencode({'_changelist_filters': preserved_filters})
return ''

def construct_change_message(self, request, form, formsets, add=False):
"""
Construct a change message from a changed object.
"""
change_message = []
if add:
change_message.append(_('Added.'))
elif form.changed_data:
change_message.append(_('Changed %s.') % get_text_list(form.changed_data, _('and')))

if formsets:
for formset in formsets:
for added_object in formset.new_objects:
change_message.append(_('Added %(name)s "%(object)s".')
% {'name': force_text(added_object._meta.verbose_name),
'object': force_text(added_object)})
for changed_object, changed_fields in formset.changed_objects:
change_message.append(_('Changed %(list)s for %(name)s "%(object)s".')
% {'list': get_text_list(changed_fields, _('and')),
'name': force_text(changed_object._meta.verbose_name),
'object': force_text(changed_object)})
for deleted_object in formset.deleted_objects:
change_message.append(_('Deleted %(name)s "%(object)s".')
% {'name': force_text(deleted_object._meta.verbose_name),
'object': force_text(deleted_object)})
change_message = ' '.join(change_message)
return change_message or _('No fields changed.')

[docs]    def message_user(self, request, message, level=messages.INFO, extra_tags='',
fail_silently=False):
"""
Send a message to the user. The default implementation
posts a message using the django.contrib.messages backend.

Exposes almost the same API as messages.add_message(), but accepts the
positional arguments in a different order to maintain backwards
compatibility. For convenience, it accepts the `level` argument as
a string rather than the usual level number.
"""

if not isinstance(level, int):
# attempt to get the level if passed a string
try:
level = getattr(messages.constants, level.upper())
except AttributeError:
levels = messages.constants.DEFAULT_TAGS.values()
levels_repr = ', '.join('`%s`' % l for l in levels)
raise ValueError('Bad message level string: `%s`. '
'Possible values are: %s' % (level, levels_repr))

messages.add_message(request, level, message, extra_tags=extra_tags,
fail_silently=fail_silently)

def save_form(self, request, form, change):
"""
Given a ModelForm return an unsaved instance. ``change`` is True if
the object is being changed, and False if it's being added.
"""
return form.save(commit=False)

[docs]    def save_model(self, request, obj, form, change):
"""
Given a model instance save it to the database.
"""
obj.save()

[docs]    def delete_model(self, request, obj):
"""
Given a model instance delete it from the database.
"""
obj.delete()

[docs]    def save_formset(self, request, form, formset, change):
"""
Given an inline formset save it to the database.
"""
formset.save()

[docs]    def save_related(self, request, form, formsets, change):
"""
Given the ``HttpRequest``, the parent ``ModelForm`` instance, the
list of inline formsets and a boolean value based on whether the
parent is being added or changed, save the related objects to the
database. Note that at this point save_form() and save_model() have
already been called.
"""
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=change)

def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
opts = self.model._meta
app_label = opts.app_label
preserved_filters = self.get_preserved_filters(request)
form_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, form_url)
view_on_site_url = self.get_view_on_site_url(obj)
context.update({
'add': add,
'change': change,
'has_add_permission': self.has_add_permission(request),
'has_change_permission': self.has_change_permission(request, obj),
'has_delete_permission': self.has_delete_permission(request, obj),
'has_file_field': True,  # FIXME - this should check if form or formsets have a FileField,
'has_absolute_url': view_on_site_url is not None,
'absolute_url': view_on_site_url,
'form_url': form_url,
'opts': opts,
'content_type_id': get_content_type_for_model(self.model).pk,
'save_as': self.save_as,
'save_on_top': self.save_on_top,
'to_field_var': TO_FIELD_VAR,
'is_popup_var': IS_POPUP_VAR,
'app_label': app_label,
})
if add and self.add_form_template is not None:
form_template = self.add_form_template
else:
form_template = self.change_form_template

request.current_app = self.admin_site.name

return TemplateResponse(request, form_template or [
"admin/%s/%s/change_form.html" % (app_label, opts.model_name),
"admin/%s/change_form.html" % app_label,
"admin/change_form.html"
], context)

[docs]    def response_add(self, request, obj, post_url_continue=None):
"""
Determines the HttpResponse for the add_view stage.
"""
opts = obj._meta
pk_value = obj._get_pk_val()
preserved_filters = self.get_preserved_filters(request)
msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)}
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.

if IS_POPUP_VAR in request.POST:
to_field = request.POST.get(TO_FIELD_VAR)
if to_field:
attr = str(to_field)
else:
attr = obj._meta.pk.attname
value = obj.serializable_value(attr)
return SimpleTemplateResponse('admin/popup_response.html', {
'value': value,
'obj': obj,
})

elif "_continue" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
if post_url_continue is None:
post_url_continue = reverse('admin:%s_%s_change' %
(opts.app_label, opts.model_name),
args=(quote(pk_value),),
current_app=self.admin_site.name)
post_url_continue = add_preserved_filters(
{'preserved_filters': preserved_filters, 'opts': opts},
post_url_continue
)
return HttpResponseRedirect(post_url_continue)

elif "_addanother" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may add another %(name)s below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
redirect_url = request.path
redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
return HttpResponseRedirect(redirect_url)

else:
msg = _('The %(name)s "%(obj)s" was added successfully.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
return self.response_post_save_add(request, obj)

[docs]    def response_change(self, request, obj):
"""
Determines the HttpResponse for the change_view stage.
"""

if IS_POPUP_VAR in request.POST:
to_field = request.POST.get(TO_FIELD_VAR)
attr = str(to_field) if to_field else obj._meta.pk.attname
# Retrieve the `object_id` from the resolved pattern arguments.
value = request.resolver_match.args[0]
new_value = obj.serializable_value(attr)
return SimpleTemplateResponse('admin/popup_response.html', {
'action': 'change',
'value': value,
'obj': obj,
'new_value': new_value,
})

opts = self.model._meta
pk_value = obj._get_pk_val()
preserved_filters = self.get_preserved_filters(request)

msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)}
if "_continue" in request.POST:
msg = _('The %(name)s "%(obj)s" was changed successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
redirect_url = request.path
redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
return HttpResponseRedirect(redirect_url)

elif "_saveasnew" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
redirect_url = reverse('admin:%s_%s_change' %
(opts.app_label, opts.model_name),
args=(pk_value,),
current_app=self.admin_site.name)
redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
return HttpResponseRedirect(redirect_url)

elif "_addanother" in request.POST:
msg = _('The %(name)s "%(obj)s" was changed successfully. You may add another %(name)s below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
redirect_url = reverse('admin:%s_%s_add' %
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
return HttpResponseRedirect(redirect_url)

else:
msg = _('The %(name)s "%(obj)s" was changed successfully.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
return self.response_post_save_change(request, obj)

def response_post_save_add(self, request, obj):
"""
Figure out where to redirect after the 'Save' button has been pressed
when adding a new object.
"""
opts = self.model._meta
if self.has_change_permission(request, None):
post_url = reverse('admin:%s_%s_changelist' %
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
preserved_filters = self.get_preserved_filters(request)
post_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
return HttpResponseRedirect(post_url)

def response_post_save_change(self, request, obj):
"""
Figure out where to redirect after the 'Save' button has been pressed
when editing an existing object.
"""
opts = self.model._meta

if self.has_change_permission(request, None):
post_url = reverse('admin:%s_%s_changelist' %
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
preserved_filters = self.get_preserved_filters(request)
post_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
return HttpResponseRedirect(post_url)

def response_action(self, request, queryset):
"""
Handle an admin action. This is called if a request is POSTed to the
changelist; it returns an HttpResponse if the action was handled, and
None otherwise.
"""

# There can be multiple action forms on the page (at the top
# and bottom of the change list, for example). Get the action
# whose button was pushed.
try:
action_index = int(request.POST.get('index', 0))
except ValueError:
action_index = 0

# Construct the action form.
data = request.POST.copy()
data.pop(helpers.ACTION_CHECKBOX_NAME, None)
data.pop("index", None)

# Use the action whose button was pushed
try:
data.update({'action': data.getlist('action')[action_index]})
except IndexError:
# If we didn't get an action from the chosen form that's invalid
# POST data, so by deleting action it'll fail the validation check
# below. So no need to do anything here
pass

action_form = self.action_form(data, auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)

# If the form's valid we can handle the action.
if action_form.is_valid():
action = action_form.cleaned_data['action']
select_across = action_form.cleaned_data['select_across']
func = self.get_actions(request)[action][0]

# Get the list of selected PKs. If nothing's selected, we can't
# perform an action on it, so bail. Except we want to perform
# the action explicitly on all objects.
selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)
if not selected and not select_across:
# Reminder that something needs to be selected or nothing will happen
msg = _("Items must be selected in order to perform "
"actions on them. No items have been changed.")
self.message_user(request, msg, messages.WARNING)
return None

if not select_across:
# Perform the action only on the selected objects
queryset = queryset.filter(pk__in=selected)

response = func(self, request, queryset)

# Actions may return an HttpResponse-like object, which will be
# used as the response from the POST. If not, we'll be a good
# little HTTP citizen and redirect back to the changelist page.
if isinstance(response, HttpResponseBase):
return response
else:
return HttpResponseRedirect(request.get_full_path())
else:
msg = _("No action selected.")
self.message_user(request, msg, messages.WARNING)
return None

[docs]    def response_delete(self, request, obj_display, obj_id):
"""
Determines the HttpResponse for the delete_view stage.
"""

opts = self.model._meta

if IS_POPUP_VAR in request.POST:
return SimpleTemplateResponse('admin/popup_response.html', {
'action': 'delete',
'value': escape(obj_id),
})

self.message_user(request,
_('The %(name)s "%(obj)s" was deleted successfully.') % {
'name': force_text(opts.verbose_name),
'obj': force_text(obj_display),
}, messages.SUCCESS)

if self.has_change_permission(request, None):
post_url = reverse('admin:%s_%s_changelist' %
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
preserved_filters = self.get_preserved_filters(request)
post_url = add_preserved_filters(
{'preserved_filters': preserved_filters, 'opts': opts}, post_url
)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
return HttpResponseRedirect(post_url)

def render_delete_form(self, request, context):
opts = self.model._meta
app_label = opts.app_label

request.current_app = self.admin_site.name
context.update(
to_field_var=TO_FIELD_VAR,
is_popup_var=IS_POPUP_VAR,
)

return TemplateResponse(request,
self.delete_confirmation_template or [
"admin/{}/{}/delete_confirmation.html".format(app_label, opts.model_name),
"admin/{}/delete_confirmation.html".format(app_label),
"admin/delete_confirmation.html"
], context)

def get_inline_formsets(self, request, formsets, inline_instances,
obj=None):
inline_admin_formsets = []
for inline, formset in zip(inline_instances, formsets):
fieldsets = list(inline.get_fieldsets(request, obj))
readonly = list(inline.get_readonly_fields(request, obj))
prepopulated = dict(inline.get_prepopulated_fields(request, obj))
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
fieldsets, prepopulated, readonly, model_admin=self)
inline_admin_formsets.append(inline_admin_formset)
return inline_admin_formsets

[docs]    def get_changeform_initial_data(self, request):
"""
Get the initial form data.
Unless overridden, this populates from the GET params.
"""
initial = dict(request.GET.items())
for k in initial:
try:
f = self.model._meta.get_field(k)
except FieldDoesNotExist:
continue
# We have to special-case M2Ms as a list of comma-separated PKs.
if isinstance(f, models.ManyToManyField):
initial[k] = initial[k].split(",")
return initial

@csrf_protect_m
@transaction.atomic
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):

to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
if to_field and not self.to_field_allowed(request, to_field):
raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

model = self.model
opts = model._meta

if request.method == 'POST' and '_saveasnew' in request.POST:
object_id = None

add = object_id is None

if add:
if not self.has_add_permission(request):
raise PermissionDenied
obj = None

else:
obj = self.get_object(request, unquote(object_id), to_field)

if not self.has_change_permission(request, obj):
raise PermissionDenied

if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {
'name': force_text(opts.verbose_name), 'key': escape(object_id)})

ModelForm = self.get_form(request, obj)
if request.method == 'POST':
form = ModelForm(request.POST, request.FILES, instance=obj)
if form.is_valid():
form_validated = True
new_object = self.save_form(request, form, change=not add)
else:
form_validated = False
new_object = form.instance
formsets, inline_instances = self._create_formsets(request, new_object, change=not add)
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, not add)
self.save_related(request, form, formsets, not add)
change_message = self.construct_change_message(request, form, formsets, add)
if add:
self.log_addition(request, new_object, change_message)
return self.response_add(request, new_object)
else:
self.log_change(request, new_object, change_message)
return self.response_change(request, new_object)
else:
form_validated = False
else:
if add:
initial = self.get_changeform_initial_data(request)
form = ModelForm(initial=initial)
formsets, inline_instances = self._create_formsets(request, form.instance, change=False)
else:
form = ModelForm(instance=obj)
formsets, inline_instances = self._create_formsets(request, obj, change=True)

adminForm = helpers.AdminForm(
form,
list(self.get_fieldsets(request, obj)),
self.get_prepopulated_fields(request, obj),
self.get_readonly_fields(request, obj),
model_admin=self)
media = self.media + adminForm.media

inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj)
for inline_formset in inline_formsets:
media = media + inline_formset.media

context = dict(self.admin_site.each_context(request),
title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name),
adminform=adminForm,
object_id=object_id,
original=obj,
is_popup=(IS_POPUP_VAR in request.POST or
IS_POPUP_VAR in request.GET),
to_field=to_field,
media=media,
inline_admin_formsets=inline_formsets,
errors=helpers.AdminErrorList(form, formsets),
preserved_filters=self.get_preserved_filters(request),
)

# Hide the "Save" and "Save and continue" buttons if "Save as New" was
# previously chosen to prevent the interface from getting confusing.
if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST:
context['show_save'] = False
context['show_save_and_continue'] = False
# Use the change template instead of the add template.
add = False

context.update(extra_context or {})

return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)

[docs]    def add_view(self, request, form_url='', extra_context=None):
return self.changeform_view(request, None, form_url, extra_context)

[docs]    def change_view(self, request, object_id, form_url='', extra_context=None):
return self.changeform_view(request, object_id, form_url, extra_context)

@csrf_protect_m

[docs]    def changelist_view(self, request, extra_context=None):
"""
The 'change list' admin view for this model.
"""
from django.contrib.admin.views.main import ERROR_FLAG
opts = self.model._meta
app_label = opts.app_label
if not self.has_change_permission(request, None):
raise PermissionDenied

list_display = self.get_list_display(request)
list_display_links = self.get_list_display_links(request, list_display)
list_filter = self.get_list_filter(request)
search_fields = self.get_search_fields(request)
list_select_related = self.get_list_select_related(request)

# Check actions to see if any are available on this changelist
actions = self.get_actions(request)
if actions:
# Add the action checkboxes if there are any actions available.
list_display = ['action_checkbox'] + list(list_display)

ChangeList = self.get_changelist(request)
try:
cl = ChangeList(request, self.model, list_display,
list_display_links, list_filter, self.date_hierarchy,
search_fields, list_select_related, self.list_per_page,
self.list_max_show_all, self.list_editable, self)

except IncorrectLookupParameters:
# Wacky lookup parameters were given, so redirect to the main
# changelist page, without parameters, and pass an 'invalid=1'
# parameter via the query string. If wacky parameters were given
# and the 'invalid=1' parameter was already in the query string,
# something is screwed up with the database, so display an error
# page.
if ERROR_FLAG in request.GET.keys():
return SimpleTemplateResponse('admin/invalid_setup.html', {
'title': _('Database error'),
})
return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')

# If the request was POSTed, this might be a bulk action or a bulk
# edit. Try to look up an action or confirmation first, but if this
# isn't an action the POST will fall through to the bulk edit check,
# below.
action_failed = False
selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)

# Actions with no confirmation
if (actions and request.method == 'POST' and
'index' in request.POST and '_save' not in request.POST):
if selected:
response = self.response_action(request, queryset=cl.get_queryset(request))
if response:
return response
else:
action_failed = True
else:
msg = _("Items must be selected in order to perform "
"actions on them. No items have been changed.")
self.message_user(request, msg, messages.WARNING)
action_failed = True

# Actions with confirmation
if (actions and request.method == 'POST' and
helpers.ACTION_CHECKBOX_NAME in request.POST and
'index' not in request.POST and '_save' not in request.POST):
if selected:
response = self.response_action(request, queryset=cl.get_queryset(request))
if response:
return response
else:
action_failed = True

# If we're allowing changelist editing, we need to construct a formset
# for the changelist given all the fields to be edited. Then we'll
# use the formset to validate/process POSTed data.
formset = cl.formset = None

# Handle POSTed bulk-edit data.
if (request.method == "POST" and cl.list_editable and
'_save' in request.POST and not action_failed):
FormSet = self.get_changelist_formset(request)
formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list)
if formset.is_valid():
changecount = 0
for form in formset.forms:
if form.has_changed():
obj = self.save_form(request, form, change=True)
self.save_model(request, obj, form, change=True)
self.save_related(request, form, formsets=[], change=True)
change_msg = self.construct_change_message(request, form, None)
self.log_change(request, obj, change_msg)
changecount += 1

if changecount:
if changecount == 1:
name = force_text(opts.verbose_name)
else:
name = force_text(opts.verbose_name_plural)
msg = ungettext("%(count)s %(name)s was changed successfully.",
"%(count)s %(name)s were changed successfully.",
changecount) % {'count': changecount,
'name': name,
'obj': force_text(obj)}
self.message_user(request, msg, messages.SUCCESS)

return HttpResponseRedirect(request.get_full_path())

# Handle GET -- construct a formset for display.
elif cl.list_editable:
FormSet = self.get_changelist_formset(request)
formset = cl.formset = FormSet(queryset=cl.result_list)

# Build the list of media to be used by the formset.
if formset:
media = self.media + formset.media
else:
media = self.media

# Build the action form and populate it with available actions.
if actions:
action_form = self.action_form(auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)
else:
action_form = None

selection_note_all = ungettext('%(total_count)s selected',
'All %(total_count)s selected', cl.result_count)

context = dict(
self.admin_site.each_context(request),
module_name=force_text(opts.verbose_name_plural),
selection_note=_('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
selection_note_all=selection_note_all % {'total_count': cl.result_count},
title=cl.title,
is_popup=cl.is_popup,
to_field=cl.to_field,
cl=cl,
media=media,
has_add_permission=self.has_add_permission(request),
opts=cl.opts,
action_form=action_form,
actions_on_top=self.actions_on_top,
actions_on_bottom=self.actions_on_bottom,
actions_selection_counter=self.actions_selection_counter,
preserved_filters=self.get_preserved_filters(request),
)
context.update(extra_context or {})

request.current_app = self.admin_site.name

return TemplateResponse(request, self.change_list_template or [
'admin/%s/%s/change_list.html' % (app_label, opts.model_name),
'admin/%s/change_list.html' % app_label,
'admin/change_list.html'
], context)

@csrf_protect_m
@transaction.atomic

[docs]    def delete_view(self, request, object_id, extra_context=None):
"The 'delete' admin view for this model."
opts = self.model._meta
app_label = opts.app_label

to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
if to_field and not self.to_field_allowed(request, to_field):
raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

obj = self.get_object(request, unquote(object_id), to_field)

if not self.has_delete_permission(request, obj):
raise PermissionDenied

if obj is None:
raise Http404(
_('%(name)s object with primary key %(key)r does not exist.') %
{'name': force_text(opts.verbose_name), 'key': escape(object_id)}
)

using = router.db_for_write(self.model)

# Populate deleted_objects, a data structure of all related objects that
# will also be deleted.
(deleted_objects, model_count, perms_needed, protected) = get_deleted_objects(
[obj], opts, request.user, self.admin_site, using)

if request.POST:  # The user has already confirmed the deletion.
if perms_needed:
raise PermissionDenied
obj_display = force_text(obj)
attr = str(to_field) if to_field else opts.pk.attname
obj_id = obj.serializable_value(attr)
self.log_deletion(request, obj, obj_display)
self.delete_model(request, obj)

return self.response_delete(request, obj_display, obj_id)

object_name = force_text(opts.verbose_name)

if perms_needed or protected:
title = _("Cannot delete %(name)s") % {"name": object_name}
else:
title = _("Are you sure?")

context = dict(
self.admin_site.each_context(request),
title=title,
object_name=object_name,
object=obj,
deleted_objects=deleted_objects,
model_count=dict(model_count).items(),
perms_lacking=perms_needed,
protected=protected,
opts=opts,
app_label=app_label,
preserved_filters=self.get_preserved_filters(request),
is_popup=(IS_POPUP_VAR in request.POST or
IS_POPUP_VAR in request.GET),
to_field=to_field,
)
context.update(extra_context or {})

return self.render_delete_form(request, context)

[docs]    def history_view(self, request, object_id, extra_context=None):
"The 'history' admin view for this model."
from django.contrib.admin.models import LogEntry
# First check if the user can see this history.
model = self.model
obj = self.get_object(request, unquote(object_id))
if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {
'name': force_text(model._meta.verbose_name),
'key': escape(object_id),
})

if not self.has_change_permission(request, obj):
raise PermissionDenied

# Then get the history for this object.
opts = model._meta
app_label = opts.app_label
action_list = LogEntry.objects.filter(
object_id=unquote(object_id),
content_type=get_content_type_for_model(model)
).select_related().order_by('action_time')

context = dict(self.admin_site.each_context(request),
title=_('Change history: %s') % force_text(obj),
action_list=action_list,
module_name=capfirst(force_text(opts.verbose_name_plural)),
object=obj,
opts=opts,
preserved_filters=self.get_preserved_filters(request),
)
context.update(extra_context or {})

request.current_app = self.admin_site.name

return TemplateResponse(request, self.object_history_template or [
"admin/%s/%s/object_history.html" % (app_label, opts.model_name),
"admin/%s/object_history.html" % app_label,
"admin/object_history.html"
], context)

def _create_formsets(self, request, obj, change):
"Helper function to generate formsets for add/change_view."
formsets = []
inline_instances = []
prefixes = {}
get_formsets_args = [request]
if change:
get_formsets_args.append(obj)
for FormSet, inline in self.get_formsets_with_inlines(*get_formsets_args):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1 or not prefix:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset_params = {
'instance': obj,
'prefix': prefix,
'queryset': inline.get_queryset(request),
}
if request.method == 'POST':
formset_params.update({
'data': request.POST,
'files': request.FILES,
'save_as_new': '_saveasnew' in request.POST
})
formsets.append(FormSet(**formset_params))
inline_instances.append(inline)
return formsets, inline_instances

class InlineModelAdmin(BaseModelAdmin):
"""
Options for inline editing of ``model`` instances.

Provide ``fk_name`` to specify the attribute name of the ``ForeignKey``
from ``model`` to its parent. This is required if ``model`` has more than
one ``ForeignKey`` to its parent.
"""
model = None
fk_name = None
formset = BaseInlineFormSet
extra = 3
min_num = None
max_num = None
template = None
verbose_name = None
verbose_name_plural = None
can_delete = True
show_change_link = False
checks_class = InlineModelAdminChecks

def __init__(self, parent_model, admin_site):
self.admin_site = admin_site
self.parent_model = parent_model
self.opts = self.model._meta
self.has_registered_model = admin_site.is_registered(self.model)
super(InlineModelAdmin, self).__init__()
if self.verbose_name is None:
self.verbose_name = self.model._meta.verbose_name
if self.verbose_name_plural is None:
self.verbose_name_plural = self.model._meta.verbose_name_plural

@property
def media(self):
extra = '' if settings.DEBUG else '.min'
js = ['vendor/jquery/jquery%s.js' % extra, 'jquery.init.js',
'inlines%s.js' % extra]
if self.filter_vertical or self.filter_horizontal:
js.extend(['SelectBox.js', 'SelectFilter2.js'])
return forms.Media(js=[static('admin/js/%s' % url) for url in js])

def get_extra(self, request, obj=None, **kwargs):
"""Hook for customizing the number of extra inline forms."""
return self.extra

def get_min_num(self, request, obj=None, **kwargs):
"""Hook for customizing the min number of inline forms."""
return self.min_num

def get_max_num(self, request, obj=None, **kwargs):
"""Hook for customizing the max number of extra inline forms."""
return self.max_num

def get_formset(self, request, obj=None, **kwargs):
"""Returns a BaseInlineFormSet class for use in admin add/change views."""
if 'fields' in kwargs:
fields = kwargs.pop('fields')
else:
fields = flatten_fieldsets(self.get_fieldsets(request, obj))
if self.exclude is None:
exclude = []
else:
exclude = list(self.exclude)
exclude.extend(self.get_readonly_fields(request, obj))
if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude:
# Take the custom ModelForm's Meta.exclude into account only if the
# InlineModelAdmin doesn't define its own.
exclude.extend(self.form._meta.exclude)
# If exclude is an empty list we use None, since that's the actual
# default.
exclude = exclude or None
can_delete = self.can_delete and self.has_delete_permission(request, obj)
defaults = {
"form": self.form,
"formset": self.formset,
"fk_name": self.fk_name,
"fields": fields,
"exclude": exclude,
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
"extra": self.get_extra(request, obj, **kwargs),
"min_num": self.get_min_num(request, obj, **kwargs),
"max_num": self.get_max_num(request, obj, **kwargs),
"can_delete": can_delete,
}

defaults.update(kwargs)
base_model_form = defaults['form']

class DeleteProtectedModelForm(base_model_form):
def hand_clean_DELETE(self):
"""
We don't validate the 'DELETE' field itself because on
templates it's not rendered using the field information, but
just using a generic "deletion_field" of the InlineModelAdmin.
"""
if self.cleaned_data.get(DELETION_FIELD_NAME, False):
using = router.db_for_write(self._meta.model)
collector = NestedObjects(using=using)
if self.instance.pk is None:
return
collector.collect([self.instance])
if collector.protected:
objs = []
for p in collector.protected:
objs.append(
# Translators: Model verbose name and instance representation,
# suitable to be an item in a list.
_('%(class_name)s %(instance)s') % {
'class_name': p._meta.verbose_name,
'instance': p}
)
params = {'class_name': self._meta.model._meta.verbose_name,
'instance': self.instance,
'related_objects': get_text_list(objs, _('and'))}
msg = _("Deleting %(class_name)s %(instance)s would require "
"deleting the following protected related objects: "
"%(related_objects)s")
raise ValidationError(msg, code='deleting_protected', params=params)

def is_valid(self):
result = super(DeleteProtectedModelForm, self).is_valid()
self.hand_clean_DELETE()
return result

defaults['form'] = DeleteProtectedModelForm

if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
defaults['fields'] = forms.ALL_FIELDS

return inlineformset_factory(self.parent_model, self.model, **defaults)

def get_fields(self, request, obj=None):
if self.fields:
return self.fields
form = self.get_formset(request, obj, fields=None).form
return list(form.base_fields) + list(self.get_readonly_fields(request, obj))

def get_queryset(self, request):
queryset = super(InlineModelAdmin, self).get_queryset(request)
if not self.has_change_permission(request):
queryset = queryset.none()
return queryset

def has_add_permission(self, request):
if self.opts.auto_created:
# We're checking the rights to an auto-created intermediate model,
# which doesn't have its own individual permissions. The user needs
# to have the change permission for the related model in order to
# be able to do anything with the intermediate model.
return self.has_change_permission(request)
return super(InlineModelAdmin, self).has_add_permission(request)

def has_change_permission(self, request, obj=None):
opts = self.opts
if opts.auto_created:
# The model was auto-created as intermediary for a
# ManyToMany-relationship, find the target model
for field in opts.fields:
if field.remote_field and field.remote_field.model != self.parent_model:
opts = field.remote_field.model._meta
break
codename = get_permission_codename('change', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_delete_permission(self, request, obj=None):
if self.opts.auto_created:
# We're checking the rights to an auto-created intermediate model,
# which doesn't have its own individual permissions. The user needs
# to have the change permission for the related model in order to
# be able to do anything with the intermediate model.
return self.has_change_permission(request, obj)
return super(InlineModelAdmin, self).has_delete_permission(request, obj)

[docs]class StackedInline(InlineModelAdmin):
template = 'admin/edit_inline/stacked.html'

[docs]class TabularInline(InlineModelAdmin):
template = 'admin/edit_inline/tabular.html'

Source code for django.contrib.admin.views.decorators

from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test

[docs]def staff_member_required(view_func=None, redirect_field_name=REDIRECT_FIELD_NAME,
login_url='admin:login'):
"""
Decorator for views that checks that the user is logged in and is a staff
member, redirecting to the login page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_active and u.is_staff,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if view_func:
return actual_decorator(view_func)
return actual_decorator

Source code for django.contrib.postgres.functions

from django.db.models import DateTimeField
from django.db.models.functions import Func

[docs]class TransactionNow(Func):
template = 'CURRENT_TIMESTAMP'

def __init__(self, output_field=None, **extra):
if output_field is None:
output_field = DateTimeField()
super(TransactionNow, self).__init__(output_field=output_field, **extra)

Source code for django.contrib.postgres.validators

import copy

from django.core.exceptions import ValidationError
from django.core.validators import (
MaxLengthValidator, MaxValueValidator, MinLengthValidator,
MinValueValidator,
)
from django.utils.deconstruct import deconstructible
from django.utils.translation import ugettext_lazy as _, ungettext_lazy

class ArrayMaxLengthValidator(MaxLengthValidator):
message = ungettext_lazy(
'List contains %(show_value)d item, it should contain no more than %(limit_value)d.',
'List contains %(show_value)d items, it should contain no more than %(limit_value)d.',
'limit_value')

class ArrayMinLengthValidator(MinLengthValidator):
message = ungettext_lazy(
'List contains %(show_value)d item, it should contain no fewer than %(limit_value)d.',
'List contains %(show_value)d items, it should contain no fewer than %(limit_value)d.',
'limit_value')

@deconstructible

[docs]class KeysValidator(object):
"""A validator designed for HStore to require/restrict keys."""

messages = {
'missing_keys': _('Some keys were missing: %(keys)s'),
'extra_keys': _('Some unknown keys were provided: %(keys)s'),
}
strict = False

def __init__(self, keys, strict=False, messages=None):
self.keys = set(keys)
self.strict = strict
if messages is not None:
self.messages = copy.copy(self.messages)
self.messages.update(messages)

def __call__(self, value):
keys = set(value.keys())
missing_keys = self.keys - keys
if missing_keys:
raise ValidationError(self.messages['missing_keys'],
code='missing_keys',
params={'keys': ', '.join(missing_keys)},
)
if self.strict:
extra_keys = keys - self.keys
if extra_keys:
raise ValidationError(self.messages['extra_keys'],
code='extra_keys',
params={'keys': ', '.join(extra_keys)},
)

def __eq__(self, other):
return (
isinstance(other, self.__class__)
and (self.keys == other.keys)
and (self.messages == other.messages)
and (self.strict == other.strict)
)

def __ne__(self, other):
return not (self == other)

[docs]class RangeMaxValueValidator(MaxValueValidator):
compare = lambda self, a, b: a.upper > b
message = _('Ensure that this range is completely less than or equal to %(limit_value)s.')

[docs]class RangeMinValueValidator(MinValueValidator):
compare = lambda self, a, b: a.lower < b
message = _('Ensure that this range is completely greater than or equal to %(limit_value)s.')

Source code for django.contrib.messages.api

from django.contrib.messages import constants
from django.contrib.messages.storage import default_storage
from django.http import HttpRequest

__all__ = (
'add_message', 'get_messages',
'get_level', 'set_level',
'debug', 'info', 'success', 'warning', 'error',
'MessageFailure',
)

class MessageFailure(Exception):
pass

[docs]def add_message(request, level, message, extra_tags='', fail_silently=False):
"""
Attempts to add a message to the request using the 'messages' app.
"""
if not isinstance(request, HttpRequest):
raise TypeError("add_message() argument must be an HttpRequest object, "
"not '%s'." % request.__class__.__name__)
if hasattr(request, '_messages'):
return request._messages.add(level, message, extra_tags)
if not fail_silently:
raise MessageFailure('You cannot add messages without installing '
'django.contrib.messages.middleware.MessageMiddleware')

[docs]def get_messages(request):
"""
Returns the message storage on the request if it exists, otherwise returns
an empty list.
"""
if hasattr(request, '_messages'):
return request._messages
else:
return []

def get_level(request):
"""
Returns the minimum level of messages to be recorded.

The default level is the ``MESSAGE_LEVEL`` setting. If this is not found,
the ``INFO`` level is used.
"""
if hasattr(request, '_messages'):
storage = request._messages
else:
storage = default_storage(request)
return storage.level

def set_level(request, level):
"""
Sets the minimum level of messages to be recorded, returning ``True`` if
the level was recorded successfully.

If set to ``None``, the default level will be used (see the ``get_level``
method).
"""
if not hasattr(request, '_messages'):
return False
request._messages.level = level
return True

def debug(request, message, extra_tags='', fail_silently=False):
"""
Adds a message with the ``DEBUG`` level.
"""
add_message(request, constants.DEBUG, message, extra_tags=extra_tags,
fail_silently=fail_silently)

def info(request, message, extra_tags='', fail_silently=False):
"""
Adds a message with the ``INFO`` level.
"""
add_message(request, constants.INFO, message, extra_tags=extra_tags,
fail_silently=fail_silently)

def success(request, message, extra_tags='', fail_silently=False):
"""
Adds a message with the ``SUCCESS`` level.
"""
add_message(request, constants.SUCCESS, message, extra_tags=extra_tags,
fail_silently=fail_silently)

def warning(request, message, extra_tags='', fail_silently=False):
"""
Adds a message with the ``WARNING`` level.
"""
add_message(request, constants.WARNING, message, extra_tags=extra_tags,
fail_silently=fail_silently)

def error(request, message, extra_tags='', fail_silently=False):
"""
Adds a message with the ``ERROR`` level.
"""
add_message(request, constants.ERROR, message, extra_tags=extra_tags,
fail_silently=fail_silently)

Source code for django.contrib.messages.middleware

from django.conf import settings
from django.contrib.messages.storage import default_storage

[docs]class MessageMiddleware(object):
"""
Middleware that handles temporary messages.
"""

def process_request(self, request):
request._messages = default_storage(request)

def process_response(self, request, response):
"""
Updates the storage backend (i.e., saves the messages).

If not all messages could not be stored and ``DEBUG`` is ``True``, a
``ValueError`` is raised.
"""
# A higher middleware layer may return a request which does not contain
# messages storage, so make no assumption that it will be there.
if hasattr(request, '_messages'):
unstored_messages = request._messages.update(response)
if unstored_messages and settings.DEBUG:
raise ValueError('Not all temporary messages could be stored.')
return response

Source code for django.contrib.sites.middleware

from .shortcuts import get_current_site

[docs]class CurrentSiteMiddleware(object):
"""
Middleware that sets `site` attribute to request object.
"""

def process_request(self, request):
request.site = get_current_site(request)

Source code for django.contrib.sites.shortcuts

from __future__ import unicode_literals

from django.apps import apps

def get_current_site(request):
"""
Checks if contrib.sites is installed and returns either the current
``Site`` object or a ``RequestSite`` object based on the request.
"""
# Imports are inside the function because its point is to avoid importing
# the Site models when django.contrib.sites isn't installed.
if apps.is_installed('django.contrib.sites'):
from .models import Site
return Site.objects.get_current(request)
else:
from .requests import RequestSite
return RequestSite(request)

Source code for django.contrib.syndication.views

from __future__ import unicode_literals

from calendar import timegm

from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.http import Http404, HttpResponse
from django.template import TemplateDoesNotExist, loader
from django.utils import feedgenerator, six
from django.utils.encoding import force_text, iri_to_uri, smart_text
from django.utils.html import escape
from django.utils.http import http_date
from django.utils.timezone import get_default_timezone, is_naive, make_aware

def add_domain(domain, url, secure=False):
protocol = 'https' if secure else 'http'
if url.startswith('//'):
# Support network-path reference (see #16753) - RSS requires a protocol
url = '%s:%s' % (protocol, url)
elif not url.startswith(('http://', 'https://', 'mailto:')):
url = iri_to_uri('%s://%s%s' % (protocol, domain, url))
return url

class FeedDoesNotExist(ObjectDoesNotExist):
pass

class Feed(object):
feed_type = feedgenerator.DefaultFeed
title_template = None
description_template = None

def __call__(self, request, *args, **kwargs):
try:
obj = self.get_object(request, *args, **kwargs)
except ObjectDoesNotExist:
raise Http404('Feed object does not exist.')
feedgen = self.get_feed(obj, request)
response = HttpResponse(content_type=feedgen.content_type)
if hasattr(self, 'item_pubdate') or hasattr(self, 'item_updateddate'):
# if item_pubdate or item_updateddate is defined for the feed, set
# header so as ConditionalGetMiddleware is able to send 304 NOT MODIFIED
response['Last-Modified'] = http_date(
timegm(feedgen.latest_post_date().utctimetuple()))
feedgen.write(response, 'utf-8')
return response

def item_title(self, item):
# Titles should be double escaped by default (see #6533)
return escape(force_text(item))

def item_description(self, item):
return force_text(item)

def item_link(self, item):
try:
return item.get_absolute_url()
except AttributeError:
raise ImproperlyConfigured(
'Give your %s class a get_absolute_url() method, or define an '
'item_link() method in your Feed class.' % item.__class__.__name__
)

def item_enclosures(self, item):
enc_url = self.__get_dynamic_attr('item_enclosure_url', item)
if enc_url:
enc = feedgenerator.Enclosure(
url=smart_text(enc_url),
length=smart_text(self.__get_dynamic_attr('item_enclosure_length', item)),
mime_type=smart_text(self.__get_dynamic_attr('item_enclosure_mime_type', item)),
)
return [enc]
return []

def __get_dynamic_attr(self, attname, obj, default=None):
try:
attr = getattr(self, attname)
except AttributeError:
return default
if callable(attr):
# Check co_argcount rather than try/excepting the function and
# catching the TypeError, because something inside the function
# may raise the TypeError. This technique is more accurate.
try:
code = six.get_function_code(attr)
except AttributeError:
code = six.get_function_code(attr.__call__)
if code.co_argcount == 2:       # one argument is 'self'
return attr(obj)
else:
return attr()
return attr

def feed_extra_kwargs(self, obj):
"""
Returns an extra keyword arguments dictionary that is used when
initializing the feed generator.
"""
return {}

def item_extra_kwargs(self, item):
"""
Returns an extra keyword arguments dictionary that is used with
the `add_item` call of the feed generator.
"""
return {}

def get_object(self, request, *args, **kwargs):
return None

def get_context_data(self, **kwargs):
"""
Returns a dictionary to use as extra context if either
``self.description_template`` or ``self.item_template`` are used.

Default implementation preserves the old behavior
of using {'obj': item, 'site': current_site} as the context.
"""
return {'obj': kwargs.get('item'), 'site': kwargs.get('site')}

def get_feed(self, obj, request):
"""
Returns a feedgenerator.DefaultFeed object, fully populated, for
this feed. Raises FeedDoesNotExist for invalid parameters.
"""
current_site = get_current_site(request)

link = self.__get_dynamic_attr('link', obj)
link = add_domain(current_site.domain, link, request.is_secure())

feed = self.feed_type(
title=self.__get_dynamic_attr('title', obj),
subtitle=self.__get_dynamic_attr('subtitle', obj),
link=link,
description=self.__get_dynamic_attr('description', obj),
language=settings.LANGUAGE_CODE,
feed_url=add_domain(
current_site.domain,
self.__get_dynamic_attr('feed_url', obj) or request.path,
request.is_secure(),
),
author_name=self.__get_dynamic_attr('author_name', obj),
author_link=self.__get_dynamic_attr('author_link', obj),
author_email=self.__get_dynamic_attr('author_email', obj),
categories=self.__get_dynamic_attr('categories', obj),
feed_copyright=self.__get_dynamic_attr('feed_copyright', obj),
feed_guid=self.__get_dynamic_attr('feed_guid', obj),
ttl=self.__get_dynamic_attr('ttl', obj),
**self.feed_extra_kwargs(obj)
)

title_tmp = None
if self.title_template is not None:
try:
title_tmp = loader.get_template(self.title_template)
except TemplateDoesNotExist:
pass

description_tmp = None
if self.description_template is not None:
try:
description_tmp = loader.get_template(self.description_template)
except TemplateDoesNotExist:
pass

for item in self.__get_dynamic_attr('items', obj):
context = self.get_context_data(item=item, site=current_site,
obj=obj, request=request)
if title_tmp is not None:
title = title_tmp.render(context, request)
else:
title = self.__get_dynamic_attr('item_title', item)
if description_tmp is not None:
description = description_tmp.render(context, request)
else:
description = self.__get_dynamic_attr('item_description', item)
link = add_domain(
current_site.domain,
self.__get_dynamic_attr('item_link', item),
request.is_secure(),
)
enclosures = self.__get_dynamic_attr('item_enclosures', item)
author_name = self.__get_dynamic_attr('item_author_name', item)
if author_name is not None:
author_email = self.__get_dynamic_attr('item_author_email', item)
author_link = self.__get_dynamic_attr('item_author_link', item)
else:
author_email = author_link = None

tz = get_default_timezone()

pubdate = self.__get_dynamic_attr('item_pubdate', item)
if pubdate and is_naive(pubdate):
pubdate = make_aware(pubdate, tz)

updateddate = self.__get_dynamic_attr('item_updateddate', item)
if updateddate and is_naive(updateddate):
updateddate = make_aware(updateddate, tz)

feed.add_item(
title=title,
link=link,
description=description,
unique_id=self.__get_dynamic_attr('item_guid', item, link),
unique_id_is_permalink=self.__get_dynamic_attr(
'item_guid_is_permalink', item),
enclosures=enclosures,
pubdate=pubdate,
updateddate=updateddate,
author_name=author_name,
author_email=author_email,
author_link=author_link,
categories=self.__get_dynamic_attr('item_categories', item),
item_copyright=self.__get_dynamic_attr('item_copyright', item),
**self.item_extra_kwargs(item)
)
return feed

Source code for django.contrib.auth.password_validation

from __future__ import unicode_literals

import gzip
import os
import re
from difflib import SequenceMatcher

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.utils import lru_cache
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.functional import lazy
from django.utils.html import format_html
from django.utils.module_loading import import_string
from django.utils.six import string_types, text_type
from django.utils.translation import ugettext as _, ungettext

@lru_cache.lru_cache(maxsize=None)
def get_default_password_validators():
return get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)

[docs]def get_password_validators(validator_config):
validators = []
for validator in validator_config:
try:
klass = import_string(validator['NAME'])
except ImportError:
msg = "The module in NAME could not be imported: %s. Check your AUTH_PASSWORD_VALIDATORS setting."
raise ImproperlyConfigured(msg % validator['NAME'])
validators.append(klass(**validator.get('OPTIONS', {})))

return validators

[docs]def validate_password(password, user=None, password_validators=None):
"""
Validate whether the password meets all validator requirements.

If the password is valid, return ``None``.
If the password is invalid, raise ValidationError with all error messages.
"""
errors = []
if password_validators is None:
password_validators = get_default_password_validators()
for validator in password_validators:
try:
validator.validate(password, user)
except ValidationError as error:
errors.append(error)
if errors:
raise ValidationError(errors)

[docs]def password_changed(password, user=None, password_validators=None):
"""
Inform all validators that have implemented a password_changed() method
that the password has been changed.
"""
if password_validators is None:
password_validators = get_default_password_validators()
for validator in password_validators:
password_changed = getattr(validator, 'password_changed', lambda *a: None)
password_changed(password, user)

[docs]def password_validators_help_texts(password_validators=None):
"""
Return a list of all help texts of all configured validators.
"""
help_texts = []
if password_validators is None:
password_validators = get_default_password_validators()
for validator in password_validators:
help_texts.append(validator.get_help_text())
return help_texts

def _password_validators_help_text_html(password_validators=None):
"""
Return an HTML string with all help texts of all configured validators
in an <ul>.
"""
help_texts = password_validators_help_texts(password_validators)
help_items = [format_html('<li>{}</li>', help_text) for help_text in help_texts]
return '<ul>%s</ul>' % ''.join(help_items) if help_items else ''
password_validators_help_text_html = lazy(_password_validators_help_text_html, text_type)

[docs]class MinimumLengthValidator(object):
"""
Validate whether the password is of a minimum length.
"""
def __init__(self, min_length=8):
self.min_length = min_length

def validate(self, password, user=None):
if len(password) < self.min_length:
raise ValidationError(
ungettext(
"This password is too short. It must contain at least %(min_length)d character.",
"This password is too short. It must contain at least %(min_length)d characters.",
self.min_length
),
code='password_too_short',
params={'min_length': self.min_length},
)

def get_help_text(self):
return ungettext(
"Your password must contain at least %(min_length)d character.",
"Your password must contain at least %(min_length)d characters.",
self.min_length
) % {'min_length': self.min_length}

[docs]class UserAttributeSimilarityValidator(object):
"""
Validate whether the password is sufficiently different from the user's
attributes.

If no specific attributes are provided, look at a sensible list of
defaults. Attributes that don't exist are ignored. Comparison is made to
not only the full attribute value, but also its components, so that, for
example, a password is validated against either part of an email address,
as well as the full address.
"""
DEFAULT_USER_ATTRIBUTES = ('username', 'first_name', 'last_name', 'email')

def __init__(self, user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7):
self.user_attributes = user_attributes
self.max_similarity = max_similarity

def validate(self, password, user=None):
if not user:
return

for attribute_name in self.user_attributes:
value = getattr(user, attribute_name, None)
if not value or not isinstance(value, string_types):
continue
value_parts = re.split('\W+', value) + [value]
for value_part in value_parts:
if SequenceMatcher(a=password.lower(), b=value_part.lower()).quick_ratio() > self.max_similarity:
verbose_name = force_text(user._meta.get_field(attribute_name).verbose_name)
raise ValidationError(
_("The password is too similar to the %(verbose_name)s."),
code='password_too_similar',
params={'verbose_name': verbose_name},
)

def get_help_text(self):
return _("Your password can't be too similar to your other personal information.")

[docs]class CommonPasswordValidator(object):
"""
Validate whether the password is a common password.

The password is rejected if it occurs in a provided list, which may be gzipped.
The list Django ships with contains 1000 common passwords, created by Mark Burnett:
https://xato.net/passwords/more-top-worst-passwords/
"""
DEFAULT_PASSWORD_LIST_PATH = os.path.join(
os.path.dirname(os.path.realpath(upath(__file__))), 'common-passwords.txt.gz'
)

def __init__(self, password_list_path=DEFAULT_PASSWORD_LIST_PATH):
try:
common_passwords_lines = gzip.open(password_list_path).read().decode('utf-8').splitlines()
except IOError:
with open(password_list_path) as f:
common_passwords_lines = f.readlines()

self.passwords = {p.strip() for p in common_passwords_lines}

def validate(self, password, user=None):
if password.lower().strip() in self.passwords:
raise ValidationError(
_("This password is too common."),
code='password_too_common',
)

def get_help_text(self):
return _("Your password can't be a commonly used password.")

[docs]class NumericPasswordValidator(object):
"""
Validate whether the password is alphanumeric.
"""
def validate(self, password, user=None):
if password.isdigit():
raise ValidationError(
_("This password is entirely numeric."),
code='password_entirely_numeric',
)

def get_help_text(self):
return _("Your password can't be entirely numeric.")

Source code for django.contrib.auth.decorators

from functools import wraps

from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import PermissionDenied
from django.shortcuts import resolve_url
from django.utils import six
from django.utils.decorators import available_attrs
from django.utils.six.moves.urllib.parse import urlparse

[docs]def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""

def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
path = request.build_absolute_uri()
resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
path, resolved_login_url, redirect_field_name)
return _wrapped_view
return decorator

[docs]def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated(),
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator

[docs]def permission_required(perm, login_url=None, raise_exception=False):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.
If the raise_exception parameter is given the PermissionDenied exception
is raised.
"""
def check_perms(user):
if isinstance(perm, six.string_types):
perms = (perm, )
else:
perms = perm
# First check if the user has the permission (even anon users)
if user.has_perms(perms):
return True
# In case the 403 handler should be called raise the exception
if raise_exception:
raise PermissionDenied
# As the last resort, show the login form
return False
return user_passes_test(check_perms, login_url=login_url)

Source code for django.contrib.auth.context_processors

# PermWrapper and PermLookupDict proxy the permissions system into objects that
# the template system can understand.

class PermLookupDict(object):
def __init__(self, user, app_label):
self.user, self.app_label = user, app_label

def __repr__(self):
return str(self.user.get_all_permissions())

def __getitem__(self, perm_name):
return self.user.has_perm("%s.%s" % (self.app_label, perm_name))

def __iter__(self):
# To fix 'item in perms.someapp' and __getitem__ interaction we need to
# define __iter__. See #18979 for details.
raise TypeError("PermLookupDict is not iterable.")

def __bool__(self):
return self.user.has_module_perms(self.app_label)

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

class PermWrapper(object):
def __init__(self, user):
self.user = user

def __getitem__(self, app_label):
return PermLookupDict(self.user, app_label)

def __iter__(self):
# I am large, I contain multitudes.
raise TypeError("PermWrapper is not iterable.")

def __contains__(self, perm_name):
"""
Lookup by "someapp" or "someapp.someperm" in perms.
"""
if '.' not in perm_name:
# The name refers to module.
return bool(self[perm_name])
app_label, perm_name = perm_name.split('.', 1)
return self[app_label][perm_name]

[docs]def auth(request):
"""
Returns context variables required by apps that use Django's authentication
system.

If there is no 'user' attribute in the request, uses AnonymousUser (from
django.contrib.auth).
"""
if hasattr(request, 'user'):
user = request.user
else:
from django.contrib.auth.models import AnonymousUser
user = AnonymousUser()

return {
'user': user,
'perms': PermWrapper(user),
}

Source code for django.contrib.auth.hashers

from __future__ import unicode_literals

import base64
import binascii
import hashlib
import importlib
import warnings
from collections import OrderedDict

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.signals import setting_changed
from django.dispatch import receiver
from django.utils import lru_cache
from django.utils.crypto import (
constant_time_compare, get_random_string, pbkdf2,
)
from django.utils.encoding import force_bytes, force_str, force_text
from django.utils.module_loading import import_string
from django.utils.translation import ugettext_noop as _

UNUSABLE_PASSWORD_PREFIX = '!'  # This will never be a valid encoded hash
UNUSABLE_PASSWORD_SUFFIX_LENGTH = 40  # number of random chars to add after UNUSABLE_PASSWORD_PREFIX

[docs]def is_password_usable(encoded):
if encoded is None or encoded.startswith(UNUSABLE_PASSWORD_PREFIX):
return False
try:
identify_hasher(encoded)
except ValueError:
return False
return True

[docs]def check_password(password, encoded, setter=None, preferred='default'):
"""
Returns a boolean of whether the raw password matches the three
part encoded digest.

If setter is specified, it'll be called when you need to
regenerate the password.
"""
if password is None or not is_password_usable(encoded):
return False

preferred = get_hasher(preferred)
hasher = identify_hasher(encoded)

hasher_changed = hasher.algorithm != preferred.algorithm
must_update = hasher_changed or preferred.must_update(encoded)
is_correct = hasher.verify(password, encoded)

# If the hasher didn't change (we don't protect against enumeration if it
# does) and the password should get updated, try to close the timing gap
# between the work factor of the current encoded password and the default
# work factor.
if not is_correct and not hasher_changed and must_update:
hasher.harden_runtime(password, encoded)

if setter and is_correct and must_update:
setter(password)
return is_correct

[docs]def make_password(password, salt=None, hasher='default'):
"""
Turn a plain-text password into a hash for database storage

Same as encode() but generates a new random salt.
If password is None then a concatenation of
UNUSABLE_PASSWORD_PREFIX and a random string will be returned
which disallows logins. Additional random string reduces chances
of gaining access to staff or superuser accounts.
See ticket #20079 for more info.
"""
if password is None:
return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
hasher = get_hasher(hasher)

if not salt:
salt = hasher.salt()

return hasher.encode(password, salt)

@lru_cache.lru_cache()
def get_hashers():
hashers = []
for hasher_path in settings.PASSWORD_HASHERS:
hasher_cls = import_string(hasher_path)
hasher = hasher_cls()
if not getattr(hasher, 'algorithm'):
raise ImproperlyConfigured("hasher doesn't specify an "
"algorithm name: %s" % hasher_path)
hashers.append(hasher)
return hashers

@lru_cache.lru_cache()
def get_hashers_by_algorithm():
return {hasher.algorithm: hasher for hasher in get_hashers()}

@receiver(setting_changed)
def reset_hashers(**kwargs):
if kwargs['setting'] == 'PASSWORD_HASHERS':
get_hashers.cache_clear()
get_hashers_by_algorithm.cache_clear()

def get_hasher(algorithm='default'):
"""
Returns an instance of a loaded password hasher.

If algorithm is 'default', the default hasher will be returned.
This function will also lazy import hashers specified in your
settings file if needed.
"""
if hasattr(algorithm, 'algorithm'):
return algorithm

elif algorithm == 'default':
return get_hashers()[0]

else:
hashers = get_hashers_by_algorithm()
try:
return hashers[algorithm]
except KeyError:
raise ValueError("Unknown password hashing algorithm '%s'. "
"Did you specify it in the PASSWORD_HASHERS "
"setting?" % algorithm)

def identify_hasher(encoded):
"""
Returns an instance of a loaded password hasher.

Identifies hasher algorithm by examining encoded hash, and calls
get_hasher() to return hasher. Raises ValueError if
algorithm cannot be identified, or if hasher is not loaded.
"""
# Ancient versions of Django created plain MD5 passwords and accepted
# MD5 passwords with an empty salt.
if ((len(encoded) == 32 and '$' not in encoded) or
(len(encoded) == 37 and encoded.startswith('md5$$'))):
algorithm = 'unsalted_md5'
# Ancient versions of Django accepted SHA1 passwords with an empty salt.
elif len(encoded) == 46 and encoded.startswith('sha1$$'):
algorithm = 'unsalted_sha1'
else:
algorithm = encoded.split('$', 1)[0]
return get_hasher(algorithm)

def mask_hash(hash, show=6, char="*"):
"""
Returns the given hash, with only the first ``show`` number shown. The
rest are masked with ``char`` for security reasons.
"""
masked = hash[:show]
masked += char * len(hash[show:])
return masked

class BasePasswordHasher(object):
"""
Abstract base class for password hashers

When creating your own hasher, you need to override algorithm,
verify(), encode() and safe_summary().

PasswordHasher objects are immutable.
"""
algorithm = None
library = None

def _load_library(self):
if self.library is not None:
if isinstance(self.library, (tuple, list)):
name, mod_path = self.library
else:
mod_path = self.library
try:
module = importlib.import_module(mod_path)
except ImportError as e:
raise ValueError("Couldn't load %r algorithm library: %s" %
(self.__class__.__name__, e))
return module
raise ValueError("Hasher %r doesn't specify a library attribute" %
self.__class__.__name__)

def salt(self):
"""
Generates a cryptographically secure nonce salt in ASCII
"""
return get_random_string()

def verify(self, password, encoded):
"""
Checks if the given password is correct
"""
raise NotImplementedError('subclasses of BasePasswordHasher must provide a verify() method')

def encode(self, password, salt):
"""
Creates an encoded database value

The result is normally formatted as "algorithm$salt$hash" and
must be fewer than 128 characters.
"""
raise NotImplementedError('subclasses of BasePasswordHasher must provide an encode() method')

def safe_summary(self, encoded):
"""
Returns a summary of safe values

The result is a dictionary and will be used where the password field
must be displayed to construct a safe representation of the password.
"""
raise NotImplementedError('subclasses of BasePasswordHasher must provide a safe_summary() method')

def must_update(self, encoded):
return False

def harden_runtime(self, password, encoded):
"""
Bridge the runtime gap between the work factor supplied in `encoded`
and the work factor suggested by this hasher.

Taking PBKDF2 as an example, if `encoded` contains 20000 iterations and
`self.iterations` is 30000, this method should run password through
another 10000 iterations of PBKDF2. Similar approaches should exist
for any hasher that has a work factor. If not, this method should be
defined as a no-op to silence the warning.
"""
warnings.warn('subclasses of BasePasswordHasher should provide a harden_runtime() method')

class PBKDF2PasswordHasher(BasePasswordHasher):
"""
Secure password hashing using the PBKDF2 algorithm (recommended)

Configured to use PBKDF2 + HMAC + SHA256.
The result is a 64 byte binary string.  Iterations may be changed
safely but you must rename the algorithm if you change SHA256.
"""
algorithm = "pbkdf2_sha256"
iterations = 24000
digest = hashlib.sha256

def encode(self, password, salt, iterations=None):
assert password is not None
assert salt and '$' not in salt
if not iterations:
iterations = self.iterations
hash = pbkdf2(password, salt, iterations, digest=self.digest)
hash = base64.b64encode(hash).decode('ascii').strip()
return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)

def verify(self, password, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, salt, int(iterations))
return constant_time_compare(encoded, encoded_2)

def safe_summary(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
assert algorithm == self.algorithm
return OrderedDict([
(_('algorithm'), algorithm),
(_('iterations'), iterations),
(_('salt'), mask_hash(salt)),
(_('hash'), mask_hash(hash)),
])

def must_update(self, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
return int(iterations) != self.iterations

def harden_runtime(self, password, encoded):
algorithm, iterations, salt, hash = encoded.split('$', 3)
extra_iterations = self.iterations - int(iterations)
if extra_iterations > 0:
self.encode(password, salt, extra_iterations)

class PBKDF2SHA1PasswordHasher(PBKDF2PasswordHasher):
"""
Alternate PBKDF2 hasher which uses SHA1, the default PRF
recommended by PKCS #5. This is compatible with other
implementations of PBKDF2, such as openssl's
PKCS5_PBKDF2_HMAC_SHA1().
"""
algorithm = "pbkdf2_sha1"
digest = hashlib.sha1

class BCryptSHA256PasswordHasher(BasePasswordHasher):
"""
Secure password hashing using the bcrypt algorithm (recommended)

This is considered by many to be the most secure algorithm but you
must first install the bcrypt library.  Please be warned that
this library depends on native C code and might cause portability
issues.
"""
algorithm = "bcrypt_sha256"
digest = hashlib.sha256
library = ("bcrypt", "bcrypt")
rounds = 12

def salt(self):
bcrypt = self._load_library()
return bcrypt.gensalt(self.rounds)

def encode(self, password, salt):
bcrypt = self._load_library()
# Need to reevaluate the force_bytes call once bcrypt is supported on
# Python 3

# Hash the password prior to using bcrypt to prevent password truncation
#   See: https://code.djangoproject.com/ticket/20138
if self.digest is not None:
# We use binascii.hexlify here because Python3 decided that a hex encoded
#   bytestring is somehow a unicode.
password = binascii.hexlify(self.digest(force_bytes(password)).digest())
else:
password = force_bytes(password)

data = bcrypt.hashpw(password, salt)
return "%s$%s" % (self.algorithm, force_text(data))

def verify(self, password, encoded):
algorithm, data = encoded.split('$', 1)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, force_bytes(data))
return constant_time_compare(encoded, encoded_2)

def safe_summary(self, encoded):
algorithm, empty, algostr, work_factor, data = encoded.split('$', 4)
assert algorithm == self.algorithm
salt, checksum = data[:22], data[22:]
return OrderedDict([
(_('algorithm'), algorithm),
(_('work factor'), work_factor),
(_('salt'), mask_hash(salt)),
(_('checksum'), mask_hash(checksum)),
])

def must_update(self, encoded):
algorithm, empty, algostr, rounds, data = encoded.split('$', 4)
return int(rounds) != self.rounds

def harden_runtime(self, password, encoded):
_, data = encoded.split('$', 1)
salt = data[:29]  # Length of the salt in bcrypt.
rounds = data.split('$')[2]
# work factor is logarithmic, adding one doubles the load.
diff = 2**(self.rounds - int(rounds)) - 1
while diff > 0:
self.encode(password, force_bytes(salt))
diff -= 1

class BCryptPasswordHasher(BCryptSHA256PasswordHasher):
"""
Secure password hashing using the bcrypt algorithm

This is considered by many to be the most secure algorithm but you
must first install the bcrypt library.  Please be warned that
this library depends on native C code and might cause portability
issues.

This hasher does not first hash the password which means it is subject to
the 72 character bcrypt password truncation, most use cases should prefer
the BCryptSHA256PasswordHasher.

See: https://code.djangoproject.com/ticket/20138
"""
algorithm = "bcrypt"
digest = None

class SHA1PasswordHasher(BasePasswordHasher):
"""
The SHA1 password hashing algorithm (not recommended)
"""
algorithm = "sha1"

def encode(self, password, salt):
assert password is not None
assert salt and '$' not in salt
hash = hashlib.sha1(force_bytes(salt + password)).hexdigest()
return "%s$%s$%s" % (self.algorithm, salt, hash)

def verify(self, password, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, salt)
return constant_time_compare(encoded, encoded_2)

def safe_summary(self, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), mask_hash(salt, show=2)),
(_('hash'), mask_hash(hash)),
])

def harden_runtime(self, password, encoded):
pass

class MD5PasswordHasher(BasePasswordHasher):
"""
The Salted MD5 password hashing algorithm (not recommended)
"""
algorithm = "md5"

def encode(self, password, salt):
assert password is not None
assert salt and '$' not in salt
hash = hashlib.md5(force_bytes(salt + password)).hexdigest()
return "%s$%s$%s" % (self.algorithm, salt, hash)

def verify(self, password, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, salt)
return constant_time_compare(encoded, encoded_2)

def safe_summary(self, encoded):
algorithm, salt, hash = encoded.split('$', 2)
assert algorithm == self.algorithm
return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), mask_hash(salt, show=2)),
(_('hash'), mask_hash(hash)),
])

def harden_runtime(self, password, encoded):
pass

class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
"""
Very insecure algorithm that you should *never* use; stores SHA1 hashes
with an empty salt.

This class is implemented because Django used to accept such password
hashes. Some older Django installs still have these values lingering
around so we need to handle and upgrade them properly.
"""
algorithm = "unsalted_sha1"

def salt(self):
return ''

def encode(self, password, salt):
assert salt == ''
hash = hashlib.sha1(force_bytes(password)).hexdigest()
return 'sha1$$%s' % hash

def verify(self, password, encoded):
encoded_2 = self.encode(password, '')
return constant_time_compare(encoded, encoded_2)

def safe_summary(self, encoded):
assert encoded.startswith('sha1$$')
hash = encoded[6:]
return OrderedDict([
(_('algorithm'), self.algorithm),
(_('hash'), mask_hash(hash)),
])

def harden_runtime(self, password, encoded):
pass

class UnsaltedMD5PasswordHasher(BasePasswordHasher):
"""
Incredibly insecure algorithm that you should *never* use; stores unsalted
MD5 hashes without the algorithm prefix, also accepts MD5 hashes with an
empty salt.

This class is implemented because Django used to store passwords this way
and to accept such password hashes. Some older Django installs still have
these values lingering around so we need to handle and upgrade them
properly.
"""
algorithm = "unsalted_md5"

def salt(self):
return ''

def encode(self, password, salt):
assert salt == ''
return hashlib.md5(force_bytes(password)).hexdigest()

def verify(self, password, encoded):
if len(encoded) == 37 and encoded.startswith('md5$$'):
encoded = encoded[5:]
encoded_2 = self.encode(password, '')
return constant_time_compare(encoded, encoded_2)

def safe_summary(self, encoded):
return OrderedDict([
(_('algorithm'), self.algorithm),
(_('hash'), mask_hash(encoded, show=3)),
])

def harden_runtime(self, password, encoded):
pass

class CryptPasswordHasher(BasePasswordHasher):
"""
Password hashing using UNIX crypt (not recommended)

The crypt module is not supported on all platforms.
"""
algorithm = "crypt"
library = "crypt"

def salt(self):
return get_random_string(2)

def encode(self, password, salt):
crypt = self._load_library()
assert len(salt) == 2
data = crypt.crypt(force_str(password), salt)
# we don't need to store the salt, but Django used to do this
return "%s$%s$%s" % (self.algorithm, '', data)

def verify(self, password, encoded):
crypt = self._load_library()
algorithm, salt, data = encoded.split('$', 2)
assert algorithm == self.algorithm
return constant_time_compare(data, crypt.crypt(force_str(password), data))

def safe_summary(self, encoded):
algorithm, salt, data = encoded.split('$', 2)
assert algorithm == self.algorithm
return OrderedDict([
(_('algorithm'), algorithm),
(_('salt'), salt),
(_('hash'), mask_hash(data, show=3)),
])

def harden_runtime(self, password, encoded):
pass

Source code for django.contrib.sessions.middleware

import time
from importlib import import_module

from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date

[docs]class SessionMiddleware(object):
def __init__(self):
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore

def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)

def process_response(self, request, response):
"""
If request.session was modified, or if the configuration is to save the
session every time, save the changes and set a session cookie or delete
the session cookie if the session has been emptied.
"""
try:
accessed = request.session.accessed
modified = request.session.modified
empty = request.session.is_empty()
except AttributeError:
pass
else:
# First check if we need to delete this cookie.
# The session should be deleted only if the session is entirely empty
if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
response.delete_cookie(settings.SESSION_COOKIE_NAME,
domain=settings.SESSION_COOKIE_DOMAIN)
else:
if accessed:
patch_vary_headers(response, ('Cookie',))
if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
if request.session.get_expire_at_browser_close():
max_age = None
expires = None
else:
max_age = request.session.get_expiry_age()
expires_time = time.time() + max_age
expires = cookie_date(expires_time)
# Save the session data and refresh the client cookie.
# Skip session save for 500 responses, refs #3881.
if response.status_code != 500:
request.session.save()
response.set_cookie(settings.SESSION_COOKIE_NAME,
request.session.session_key, max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None)
return response

Source code for django.contrib.gis.measure

# Copyright (c) 2007, Robert Coup <robert.coup@onetrackmind.co.nz>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
#   1. Redistributions of source code must retain the above copyright notice,
#      this list of conditions and the following disclaimer.
#
#   2. Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#
#   3. Neither the name of Distance nor the names of its contributors may be used
#      to endorse or promote products derived from this software without
#      specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
Distance and Area objects to allow for sensible and convenient calculation
and conversions.

Authors: Robert Coup, Justin Bronn, Riccardo Di Virgilio

Inspired by GeoPy (https://github.com/geopy/geopy)
and Geoff Biggs' PhD work on dimensioned units for robotics.
"""
__all__ = ['A', 'Area', 'D', 'Distance']
from decimal import Decimal
from functools import total_ordering

from django.utils import six

NUMERIC_TYPES = six.integer_types + (float, Decimal)
AREA_PREFIX = "sq_"

def pretty_name(obj):
return obj.__name__ if obj.__class__ == type else obj.__class__.__name__

@total_ordering
class MeasureBase(object):
STANDARD_UNIT = None
ALIAS = {}
UNITS = {}
LALIAS = {}

def __init__(self, default_unit=None, **kwargs):
value, self._default_unit = self.default_units(kwargs)
setattr(self, self.STANDARD_UNIT, value)
if default_unit and isinstance(default_unit, six.string_types):
self._default_unit = default_unit

def _get_standard(self):
return getattr(self, self.STANDARD_UNIT)

def _set_standard(self, value):
setattr(self, self.STANDARD_UNIT, value)

standard = property(_get_standard, _set_standard)

def __getattr__(self, name):
if name in self.UNITS:
return self.standard / self.UNITS[name]
else:
raise AttributeError('Unknown unit type: %s' % name)

def __repr__(self):
return '%s(%s=%s)' % (pretty_name(self), self._default_unit,
getattr(self, self._default_unit))

def __str__(self):
return '%s %s' % (getattr(self, self._default_unit), self._default_unit)

# **** Comparison methods ****

def __eq__(self, other):
if isinstance(other, self.__class__):
return self.standard == other.standard
else:
return NotImplemented

def __lt__(self, other):
if isinstance(other, self.__class__):
return self.standard < other.standard
else:
return NotImplemented

# **** Operators methods ****

def __add__(self, other):
if isinstance(other, self.__class__):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard + other.standard)})
else:
raise TypeError('%(class)s must be added with %(class)s' % {"class": pretty_name(self)})

def __iadd__(self, other):
if isinstance(other, self.__class__):
self.standard += other.standard
return self
else:
raise TypeError('%(class)s must be added with %(class)s' % {"class": pretty_name(self)})

def __sub__(self, other):
if isinstance(other, self.__class__):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard - other.standard)})
else:
raise TypeError('%(class)s must be subtracted from %(class)s' % {"class": pretty_name(self)})

def __isub__(self, other):
if isinstance(other, self.__class__):
self.standard -= other.standard
return self
else:
raise TypeError('%(class)s must be subtracted from %(class)s' % {"class": pretty_name(self)})

def __mul__(self, other):
if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard * other)})
else:
raise TypeError('%(class)s must be multiplied with number' % {"class": pretty_name(self)})

def __imul__(self, other):
if isinstance(other, NUMERIC_TYPES):
self.standard *= float(other)
return self
else:
raise TypeError('%(class)s must be multiplied with number' % {"class": pretty_name(self)})

def __rmul__(self, other):
return self * other

def __truediv__(self, other):
if isinstance(other, self.__class__):
return self.standard / other.standard
if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard / other)})
else:
raise TypeError('%(class)s must be divided with number or %(class)s' % {"class": pretty_name(self)})

def __div__(self, other):   # Python 2 compatibility
return type(self).__truediv__(self, other)

def __itruediv__(self, other):
if isinstance(other, NUMERIC_TYPES):
self.standard /= float(other)
return self
else:
raise TypeError('%(class)s must be divided with number' % {"class": pretty_name(self)})

def __idiv__(self, other):  # Python 2 compatibility
return type(self).__itruediv__(self, other)

def __bool__(self):
return bool(self.standard)

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

def default_units(self, kwargs):
"""
Return the unit value and the default units specified
from the given keyword arguments dictionary.
"""
val = 0.0
default_unit = self.STANDARD_UNIT
for unit, value in six.iteritems(kwargs):
if not isinstance(value, float):
value = float(value)
if unit in self.UNITS:
val += self.UNITS[unit] * value
default_unit = unit
elif unit in self.ALIAS:
u = self.ALIAS[unit]
val += self.UNITS[u] * value
default_unit = u
else:
lower = unit.lower()
if lower in self.UNITS:
val += self.UNITS[lower] * value
default_unit = lower
elif lower in self.LALIAS:
u = self.LALIAS[lower]
val += self.UNITS[u] * value
default_unit = u
else:
raise AttributeError('Unknown unit type: %s' % unit)
return val, default_unit

@classmethod
def unit_attname(cls, unit_str):
"""
Retrieves the unit attribute name for the given unit string.
For example, if the given unit string is 'metre', 'm' would be returned.
An exception is raised if an attribute cannot be found.
"""
lower = unit_str.lower()
if unit_str in cls.UNITS:
return unit_str
elif lower in cls.UNITS:
return lower
elif lower in cls.LALIAS:
return cls.LALIAS[lower]
else:
raise Exception('Could not find a unit keyword associated with "%s"' % unit_str)

[docs]class Distance(MeasureBase):
STANDARD_UNIT = "m"
UNITS = {
'chain': 20.1168,
'chain_benoit': 20.116782,
'chain_sears': 20.1167645,
'british_chain_benoit': 20.1167824944,
'british_chain_sears': 20.1167651216,
'british_chain_sears_truncated': 20.116756,
'cm': 0.01,
'british_ft': 0.304799471539,
'british_yd': 0.914398414616,
'clarke_ft': 0.3047972654,
'clarke_link': 0.201166195164,
'fathom': 1.8288,
'ft': 0.3048,
'german_m': 1.0000135965,
'gold_coast_ft': 0.304799710181508,
'indian_yd': 0.914398530744,
'inch': 0.0254,
'km': 1000.0,
'link': 0.201168,
'link_benoit': 0.20116782,
'link_sears': 0.20116765,
'm': 1.0,
'mi': 1609.344,
'mm': 0.001,
'nm': 1852.0,
'nm_uk': 1853.184,
'rod': 5.0292,
'sears_yd': 0.91439841,
'survey_ft': 0.304800609601,
'um': 0.000001,
'yd': 0.9144,
}

# Unit aliases for `UNIT` terms encountered in Spatial Reference WKT.
ALIAS = {
'centimeter': 'cm',
'foot': 'ft',
'inches': 'inch',
'kilometer': 'km',
'kilometre': 'km',
'meter': 'm',
'metre': 'm',
'micrometer': 'um',
'micrometre': 'um',
'millimeter': 'mm',
'millimetre': 'mm',
'mile': 'mi',
'yard': 'yd',
'British chain (Benoit 1895 B)': 'british_chain_benoit',
'British chain (Sears 1922)': 'british_chain_sears',
'British chain (Sears 1922 truncated)': 'british_chain_sears_truncated',
'British foot (Sears 1922)': 'british_ft',
'British foot': 'british_ft',
'British yard (Sears 1922)': 'british_yd',
'British yard': 'british_yd',
"Clarke's Foot": 'clarke_ft',
"Clarke's link": 'clarke_link',
'Chain (Benoit)': 'chain_benoit',
'Chain (Sears)': 'chain_sears',
'Foot (International)': 'ft',
'German legal metre': 'german_m',
'Gold Coast foot': 'gold_coast_ft',
'Indian yard': 'indian_yd',
'Link (Benoit)': 'link_benoit',
'Link (Sears)': 'link_sears',
'Nautical Mile': 'nm',
'Nautical Mile (UK)': 'nm_uk',
'US survey foot': 'survey_ft',
'U.S. Foot': 'survey_ft',
'Yard (Indian)': 'indian_yd',
'Yard (Sears)': 'sears_yd'
}
LALIAS = {k.lower(): v for k, v in ALIAS.items()}

def __mul__(self, other):
if isinstance(other, self.__class__):
return Area(default_unit=AREA_PREFIX + self._default_unit,
**{AREA_PREFIX + self.STANDARD_UNIT: (self.standard * other.standard)})
elif isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard * other)})
else:
raise TypeError('%(distance)s must be multiplied with number or %(distance)s' % {
"distance": pretty_name(self.__class__),
})

[docs]class Area(MeasureBase):
STANDARD_UNIT = AREA_PREFIX + Distance.STANDARD_UNIT
# Getting the square units values and the alias dictionary.
UNITS = {'%s%s' % (AREA_PREFIX, k): v ** 2 for k, v in Distance.UNITS.items()}
ALIAS = {k: '%s%s' % (AREA_PREFIX, v) for k, v in Distance.ALIAS.items()}
LALIAS = {k.lower(): v for k, v in ALIAS.items()}

def __truediv__(self, other):
if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard / other)})
else:
raise TypeError('%(class)s must be divided by a number' % {"class": pretty_name(self)})

def __div__(self, other):  # Python 2 compatibility
return type(self).__truediv__(self, other)

# Shortcuts
D = Distance
A = Area

Source code for django.contrib.gis.feeds

from __future__ import unicode_literals

from django.contrib.syndication.views import Feed as BaseFeed
from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed

class GeoFeedMixin(object):
"""
This mixin provides the necessary routines for SyndicationFeed subclasses
to produce simple GeoRSS or W3C Geo elements.
"""

def georss_coords(self, coords):
"""
In GeoRSS coordinate pairs are ordered by lat/lon and separated by
a single white space.  Given a tuple of coordinates, this will return
a unicode GeoRSS representation.
"""
return ' '.join('%f %f' % (coord[1], coord[0]) for coord in coords)

def add_georss_point(self, handler, coords, w3c_geo=False):
"""
Adds a GeoRSS point with the given coords using the given handler.
Handles the differences between simple GeoRSS and the more popular
W3C Geo specification.
"""
if w3c_geo:
lon, lat = coords[:2]
handler.addQuickElement('geo:lat', '%f' % lat)
handler.addQuickElement('geo:lon', '%f' % lon)
else:
handler.addQuickElement('georss:point', self.georss_coords((coords,)))

def add_georss_element(self, handler, item, w3c_geo=False):
"""
This routine adds a GeoRSS XML element using the given item and handler.
"""
# Getting the Geometry object.
geom = item.get('geometry')
if geom is not None:
if isinstance(geom, (list, tuple)):
# Special case if a tuple/list was passed in.  The tuple may be
# a point or a box
box_coords = None
if isinstance(geom[0], (list, tuple)):
# Box: ( (X0, Y0), (X1, Y1) )
if len(geom) == 2:
box_coords = geom
else:
raise ValueError('Only should be two sets of coordinates.')
else:
if len(geom) == 2:
# Point: (X, Y)
self.add_georss_point(handler, geom, w3c_geo=w3c_geo)
elif len(geom) == 4:
# Box: (X0, Y0, X1, Y1)
box_coords = (geom[:2], geom[2:])
else:
raise ValueError('Only should be 2 or 4 numeric elements.')
# If a GeoRSS box was given via tuple.
if box_coords is not None:
if w3c_geo:
raise ValueError('Cannot use simple GeoRSS box in W3C Geo feeds.')
handler.addQuickElement('georss:box', self.georss_coords(box_coords))
else:
# Getting the lower-case geometry type.
gtype = str(geom.geom_type).lower()
if gtype == 'point':
self.add_georss_point(handler, geom.coords, w3c_geo=w3c_geo)
else:
if w3c_geo:
raise ValueError('W3C Geo only supports Point geometries.')
# For formatting consistent w/the GeoRSS simple standard:
# http://georss.org/1.0#simple
if gtype in ('linestring', 'linearring'):
handler.addQuickElement('georss:line', self.georss_coords(geom.coords))
elif gtype in ('polygon',):
# Only support the exterior ring.
handler.addQuickElement('georss:polygon', self.georss_coords(geom[0].coords))
else:
raise ValueError('Geometry type "%s" not supported.' % geom.geom_type)

# ### SyndicationFeed subclasses ###

[docs]class GeoRSSFeed(Rss201rev2Feed, GeoFeedMixin):
def rss_attributes(self):
attrs = super(GeoRSSFeed, self).rss_attributes()
attrs['xmlns:georss'] = 'http://www.georss.org/georss'
return attrs

def add_item_elements(self, handler, item):
super(GeoRSSFeed, self).add_item_elements(handler, item)
self.add_georss_element(handler, item)

def add_root_elements(self, handler):
super(GeoRSSFeed, self).add_root_elements(handler)
self.add_georss_element(handler, self.feed)

[docs]class GeoAtom1Feed(Atom1Feed, GeoFeedMixin):
def root_attributes(self):
attrs = super(GeoAtom1Feed, self).root_attributes()
attrs['xmlns:georss'] = 'http://www.georss.org/georss'
return attrs

def add_item_elements(self, handler, item):
super(GeoAtom1Feed, self).add_item_elements(handler, item)
self.add_georss_element(handler, item)

def add_root_elements(self, handler):
super(GeoAtom1Feed, self).add_root_elements(handler)
self.add_georss_element(handler, self.feed)

[docs]class W3CGeoFeed(Rss201rev2Feed, GeoFeedMixin):
def rss_attributes(self):
attrs = super(W3CGeoFeed, self).rss_attributes()
attrs['xmlns:geo'] = 'http://www.w3.org/2003/01/geo/wgs84_pos#'
return attrs

def add_item_elements(self, handler, item):
super(W3CGeoFeed, self).add_item_elements(handler, item)
self.add_georss_element(handler, item, w3c_geo=True)

def add_root_elements(self, handler):
super(W3CGeoFeed, self).add_root_elements(handler)
self.add_georss_element(handler, self.feed, w3c_geo=True)

# ### Feed subclass ###

[docs]class Feed(BaseFeed):
"""
This is a subclass of the `Feed` from `django.contrib.syndication`.
This allows users to define a `geometry(obj)` and/or `item_geometry(item)`
methods on their own subclasses so that geo-referenced information may
placed in the feed.
"""
feed_type = GeoRSSFeed

def feed_extra_kwargs(self, obj):
return {'geometry': self.__get_dynamic_attr('geometry', obj)}

def item_extra_kwargs(self, item):
return {'geometry': self.__get_dynamic_attr('item_geometry', item)}

Source code for django.contrib.gis.gdal.geomtype

from django.contrib.gis.gdal.error import GDALException
from django.utils import six

[docs]class OGRGeomType(object):
"Encapsulates OGR Geometry Types."

wkb25bit = -2147483648

# Dictionary of acceptable OGRwkbGeometryType s and their string names.
_types = {0: 'Unknown',
1: 'Point',
2: 'LineString',
3: 'Polygon',
4: 'MultiPoint',
5: 'MultiLineString',
6: 'MultiPolygon',
7: 'GeometryCollection',
100: 'None',
101: 'LinearRing',
1 + wkb25bit: 'Point25D',
2 + wkb25bit: 'LineString25D',
3 + wkb25bit: 'Polygon25D',
4 + wkb25bit: 'MultiPoint25D',
5 + wkb25bit: 'MultiLineString25D',
6 + wkb25bit: 'MultiPolygon25D',
7 + wkb25bit: 'GeometryCollection25D',
}
# Reverse type dictionary, keyed by lower-case of the name.
_str_types = {v.lower(): k for k, v in _types.items()}

def __init__(self, type_input):
"Figures out the correct OGR Type based upon the input."
if isinstance(type_input, OGRGeomType):
num = type_input.num
elif isinstance(type_input, six.string_types):
type_input = type_input.lower()
if type_input == 'geometry':
type_input = 'unknown'
num = self._str_types.get(type_input)
if num is None:
raise GDALException('Invalid OGR String Type "%s"' % type_input)
elif isinstance(type_input, int):
if type_input not in self._types:
raise GDALException('Invalid OGR Integer Type: %d' % type_input)
num = type_input
else:
raise TypeError('Invalid OGR input type given.')

# Setting the OGR geometry type number.
self.num = num

def __str__(self):
"Returns the value of the name property."
return self.name

def __eq__(self, other):
"""
Does an equivalence test on the OGR type with the given
other OGRGeomType, the short-hand string, or the integer.
"""
if isinstance(other, OGRGeomType):
return self.num == other.num
elif isinstance(other, six.string_types):
return self.name.lower() == other.lower()
elif isinstance(other, int):
return self.num == other
else:
return False

def __ne__(self, other):
return not (self == other)

@property
def name(self):
"Returns a short-hand string form of the OGR Geometry type."
return self._types[self.num]

@property
def django(self):
"Returns the Django GeometryField for this OGR Type."
s = self.name.replace('25D', '')
if s in ('LinearRing', 'None'):
return None
elif s == 'Unknown':
s = 'Geometry'
return s + 'Field'

def to_multi(self):
"""
Transform Point, LineString, Polygon, and their 25D equivalents
to their Multi... counterpart.
"""
if self.name.startswith(('Point', 'LineString', 'Polygon')):
self.num += 3

Source code for django.contrib.gis.gdal.envelope

"""
The GDAL/OGR library uses an Envelope structure to hold the bounding
box information for a geometry.  The envelope (bounding box) contains
two pairs of coordinates, one for the lower left coordinate and one
for the upper right coordinate:

+----------o Upper right; (max_x, max_y)
|          |
|          |
|          |
Lower left (min_x, min_y) o----------+
"""
from ctypes import Structure, c_double

from django.contrib.gis.gdal.error import GDALException

# The OGR definition of an Envelope is a C structure containing four doubles.
#  See the 'ogr_core.h' source file for more information:
#   http://www.gdal.org/ogr__core_8h_source.html
class OGREnvelope(Structure):
"Represents the OGREnvelope C Structure."
_fields_ = [("MinX", c_double),
("MaxX", c_double),
("MinY", c_double),
("MaxY", c_double),
]

[docs]class Envelope(object):
"""
The Envelope object is a C structure that contains the minimum and
maximum X, Y coordinates for a rectangle bounding box.  The naming
of the variables is compatible with the OGR Envelope structure.
"""

def __init__(self, *args):
"""
The initialization function may take an OGREnvelope structure, 4-element
tuple or list, or 4 individual arguments.
"""

if len(args) == 1:
if isinstance(args[0], OGREnvelope):
# OGREnvelope (a ctypes Structure) was passed in.
self._envelope = args[0]
elif isinstance(args[0], (tuple, list)):
# A tuple was passed in.
if len(args[0]) != 4:
raise GDALException('Incorrect number of tuple elements (%d).' % len(args[0]))
else:
self._from_sequence(args[0])
else:
raise TypeError('Incorrect type of argument: %s' % str(type(args[0])))
elif len(args) == 4:
# Individual parameters passed in.
#  Thanks to ww for the help
self._from_sequence([float(a) for a in args])
else:
raise GDALException('Incorrect number (%d) of arguments.' % len(args))

# Checking the x,y coordinates
if self.min_x > self.max_x:
raise GDALException('Envelope minimum X > maximum X.')
if self.min_y > self.max_y:
raise GDALException('Envelope minimum Y > maximum Y.')

def __eq__(self, other):
"""
Returns True if the envelopes are equivalent; can compare against
other Envelopes and 4-tuples.
"""
if isinstance(other, Envelope):
return (self.min_x == other.min_x) and (self.min_y == other.min_y) and \
(self.max_x == other.max_x) and (self.max_y == other.max_y)
elif isinstance(other, tuple) and len(other) == 4:
return (self.min_x == other[0]) and (self.min_y == other[1]) and \
(self.max_x == other[2]) and (self.max_y == other[3])
else:
raise GDALException('Equivalence testing only works with other Envelopes.')

def __str__(self):
"Returns a string representation of the tuple."
return str(self.tuple)

def _from_sequence(self, seq):
"Initializes the C OGR Envelope structure from the given sequence."
self._envelope = OGREnvelope()
self._envelope.MinX = seq[0]
self._envelope.MinY = seq[1]
self._envelope.MaxX = seq[2]
self._envelope.MaxY = seq[3]

[docs]    def expand_to_include(self, *args):
"""
Modifies the envelope to expand to include the boundaries of
the passed-in 2-tuple (a point), 4-tuple (an extent) or
envelope.
"""
# We provide a number of different signatures for this method,
# and the logic here is all about converting them into a
# 4-tuple single parameter which does the actual work of
# expanding the envelope.
if len(args) == 1:
if isinstance(args[0], Envelope):
return self.expand_to_include(args[0].tuple)
elif hasattr(args[0], 'x') and hasattr(args[0], 'y'):
return self.expand_to_include(args[0].x, args[0].y, args[0].x, args[0].y)
elif isinstance(args[0], (tuple, list)):
# A tuple was passed in.
if len(args[0]) == 2:
return self.expand_to_include((args[0][0], args[0][1], args[0][0], args[0][1]))
elif len(args[0]) == 4:
(minx, miny, maxx, maxy) = args[0]
if minx < self._envelope.MinX:
self._envelope.MinX = minx
if miny < self._envelope.MinY:
self._envelope.MinY = miny
if maxx > self._envelope.MaxX:
self._envelope.MaxX = maxx
if maxy > self._envelope.MaxY:
self._envelope.MaxY = maxy
else:
raise GDALException('Incorrect number of tuple elements (%d).' % len(args[0]))
else:
raise TypeError('Incorrect type of argument: %s' % str(type(args[0])))
elif len(args) == 2:
# An x and an y parameter were passed in
return self.expand_to_include((args[0], args[1], args[0], args[1]))
elif len(args) == 4:
# Individual parameters passed in.
return self.expand_to_include(args)
else:
raise GDALException('Incorrect number (%d) of arguments.' % len(args[0]))

@property
def min_x(self):
"Returns the value of the minimum X coordinate."
return self._envelope.MinX

@property
def min_y(self):
"Returns the value of the minimum Y coordinate."
return self._envelope.MinY

@property
def max_x(self):
"Returns the value of the maximum X coordinate."
return self._envelope.MaxX

@property
def max_y(self):
"Returns the value of the maximum Y coordinate."
return self._envelope.MaxY

@property
def ur(self):
"Returns the upper-right coordinate."
return (self.max_x, self.max_y)

@property
def ll(self):
"Returns the lower-left coordinate."
return (self.min_x, self.min_y)

@property
def tuple(self):
"Returns a tuple representing the envelope."
return (self.min_x, self.min_y, self.max_x, self.max_y)

@property
def wkt(self):
"Returns WKT representing a Polygon for this envelope."
# TODO: Fix significant figures.
return 'POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))' % \
(self.min_x, self.min_y, self.min_x, self.max_y,
self.max_x, self.max_y, self.max_x, self.min_y,
self.min_x, self.min_y)

Source code for django.contrib.gis.geos.geometry

"""
This module contains the 'base' GEOSGeometry object -- all GEOS Geometries
inherit from this object.
"""
from __future__ import unicode_literals

import json
from ctypes import addressof, byref, c_double

from django.contrib.gis import gdal
from django.contrib.gis.geometry.regex import hex_regex, json_regex, wkt_regex
from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.geos.coordseq import GEOSCoordSeq
from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.libgeos import GEOM_PTR
from django.contrib.gis.geos.mutable_list import ListMixin
from django.contrib.gis.geos.prepared import PreparedGeometry
from django.contrib.gis.geos.prototypes.io import (
ewkb_w, wkb_r, wkb_w, wkt_r, wkt_w,
)
from django.utils import six
from django.utils.encoding import force_bytes, force_text

[docs]class GEOSGeometry(GEOSBase, ListMixin):
"A class that, generally, encapsulates a GEOS geometry."

_GEOS_CLASSES = None

ptr_type = GEOM_PTR
has_cs = False  # Only Point, LineString, LinearRing have coordinate sequences

def __init__(self, geo_input, srid=None):
"""
The base constructor for GEOS geometry objects, and may take the
following inputs:

* strings:
- WKT
- HEXEWKB (a PostGIS-specific canonical form)
- GeoJSON (requires GDAL)
* buffer:
- WKB

The `srid` keyword is used to specify the Source Reference Identifier
(SRID) number for this Geometry.  If not set, the SRID will be None.
"""
if isinstance(geo_input, bytes):
geo_input = force_text(geo_input)
if isinstance(geo_input, six.string_types):
wkt_m = wkt_regex.match(geo_input)
if wkt_m:
# Handling WKT input.
if wkt_m.group('srid'):
srid = int(wkt_m.group('srid'))
g = wkt_r().read(force_bytes(wkt_m.group('wkt')))
elif hex_regex.match(geo_input):
# Handling HEXEWKB input.
g = wkb_r().read(force_bytes(geo_input))
elif json_regex.match(geo_input):
# Handling GeoJSON input.
if not gdal.HAS_GDAL:
raise ValueError('Initializing geometry from JSON input requires GDAL.')
g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb)
else:
raise ValueError('String or unicode input unrecognized as WKT EWKT, and HEXEWKB.')
elif isinstance(geo_input, GEOM_PTR):
# When the input is a pointer to a geometry (GEOM_PTR).
g = geo_input
elif isinstance(geo_input, six.memoryview):
# When the input is a buffer (WKB).
g = wkb_r().read(geo_input)
elif isinstance(geo_input, GEOSGeometry):
g = capi.geom_clone(geo_input.ptr)
else:
# Invalid geometry type.
raise TypeError('Improper geometry input type: %s' % str(type(geo_input)))

if g:
# Setting the pointer object with a valid pointer.
self.ptr = g
else:
raise GEOSException('Could not initialize GEOS Geometry with given input.')

# Post-initialization setup.
self._post_init(srid)

def _post_init(self, srid):
"Helper routine for performing post-initialization setup."
# Setting the SRID, if given.
if srid and isinstance(srid, int):
self.srid = srid

# Setting the class type (e.g., Point, Polygon, etc.)
if GEOSGeometry._GEOS_CLASSES is None:
# Lazy-loaded variable to avoid import conflicts with GEOSGeometry.
from .linestring import LineString, LinearRing
from .point import Point
from .polygon import Polygon
from .collections import (
GeometryCollection, MultiPoint, MultiLineString, MultiPolygon)
GEOSGeometry._GEOS_CLASSES = {
0: Point,
1: LineString,
2: LinearRing,
3: Polygon,
4: MultiPoint,
5: MultiLineString,
6: MultiPolygon,
7: GeometryCollection,
}
self.__class__ = GEOSGeometry._GEOS_CLASSES[self.geom_typeid]

# Setting the coordinate sequence for the geometry (will be None on
# geometries that do not have coordinate sequences)
self._set_cs()

def __del__(self):
"""
Destroys this Geometry; in other words, frees the memory used by the
GEOS C++ object.
"""
if self._ptr and capi:
capi.destroy_geom(self._ptr)

def __copy__(self):
"""
Returns a clone because the copy of a GEOSGeometry may contain an
invalid pointer location if the original is garbage collected.
"""
return self.clone()

def __deepcopy__(self, memodict):
"""
The `deepcopy` routine is used by the `Node` class of django.utils.tree;
thus, the protocol routine needs to be implemented to return correct
copies (clones) of these GEOS objects, which use C pointers.
"""
return self.clone()

def __str__(self):
"EWKT is used for the string representation."
return self.ewkt

def __repr__(self):
"Short-hand representation because WKT may be very large."
return '<%s object at %s>' % (self.geom_type, hex(addressof(self.ptr)))

# Pickling support
def __getstate__(self):
# The pickled state is simply a tuple of the WKB (in string form)
# and the SRID.
return bytes(self.wkb), self.srid

def __setstate__(self, state):
# Instantiating from the tuple state that was pickled.
wkb, srid = state
ptr = wkb_r().read(six.memoryview(wkb))
if not ptr:
raise GEOSException('Invalid Geometry loaded from pickled state.')
self.ptr = ptr
self._post_init(srid)

# Comparison operators
def __eq__(self, other):
"""
Equivalence testing, a Geometry may be compared with another Geometry
or a WKT representation.
"""
if isinstance(other, six.string_types):
return self.wkt == other
elif isinstance(other, GEOSGeometry):
return self.equals_exact(other)
else:
return False

def __ne__(self, other):
"The not equals operator."
return not (self == other)

# ### Geometry set-like operations ###
# Thanks to Sean Gillies for inspiration:
#  http://lists.gispython.org/pipermail/community/2007-July/001034.html
# g = g1 | g2
def __or__(self, other):
"Returns the union of this Geometry and the other."
return self.union(other)

# g = g1 & g2
def __and__(self, other):
"Returns the intersection of this Geometry and the other."
return self.intersection(other)

# g = g1 - g2
def __sub__(self, other):
"Return the difference this Geometry and the other."
return self.difference(other)

# g = g1 ^ g2
def __xor__(self, other):
"Return the symmetric difference of this Geometry and the other."
return self.sym_difference(other)

# #### Coordinate Sequence Routines ####
def _set_cs(self):
"Sets the coordinate sequence for this Geometry."
if self.has_cs:
self._cs = GEOSCoordSeq(capi.get_cs(self.ptr), self.hasz)
else:
self._cs = None

@property
def coord_seq(self):
"Returns a clone of the coordinate sequence for this Geometry."
if self.has_cs:
return self._cs.clone()

# #### Geometry Info ####
@property
def geom_type(self):
"Returns a string representing the Geometry type, e.g. 'Polygon'"
return capi.geos_type(self.ptr).decode()

@property
def geom_typeid(self):
"Returns an integer representing the Geometry type."
return capi.geos_typeid(self.ptr)

@property
def num_geom(self):
"Returns the number of geometries in the Geometry."
return capi.get_num_geoms(self.ptr)

@property
def num_coords(self):
"Returns the number of coordinates in the Geometry."
return capi.get_num_coords(self.ptr)

@property
def num_points(self):
"Returns the number points, or coordinates, in the Geometry."
return self.num_coords

@property
def dims(self):
"Returns the dimension of this Geometry (0=point, 1=line, 2=surface)."
return capi.get_dims(self.ptr)

def normalize(self):
"Converts this Geometry to normal form (or canonical form)."
return capi.geos_normalize(self.ptr)

# #### Unary predicates ####
@property
def empty(self):
"""
Returns a boolean indicating whether the set of points in this Geometry
are empty.
"""
return capi.geos_isempty(self.ptr)

@property
def hasz(self):
"Returns whether the geometry has a 3D dimension."
return capi.geos_hasz(self.ptr)

@property
def ring(self):
"Returns whether or not the geometry is a ring."
return capi.geos_isring(self.ptr)

@property
def simple(self):
"Returns false if the Geometry not simple."
return capi.geos_issimple(self.ptr)

@property
def valid(self):
"This property tests the validity of this Geometry."
return capi.geos_isvalid(self.ptr)

@property
def valid_reason(self):
"""
Returns a string containing the reason for any invalidity.
"""
return capi.geos_isvalidreason(self.ptr).decode()

# #### Binary predicates. ####

[docs]    def contains(self, other):
"Returns true if other.within(this) returns true."
return capi.geos_contains(self.ptr, other.ptr)

[docs]    def crosses(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
is T*T****** (for a point and a curve,a point and an area or a line and
an area) 0******** (for two curves).
"""
return capi.geos_crosses(self.ptr, other.ptr)

[docs]    def disjoint(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
is FF*FF****.
"""
return capi.geos_disjoint(self.ptr, other.ptr)

[docs]    def equals(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
is T*F**FFF*.
"""
return capi.geos_equals(self.ptr, other.ptr)

[docs]    def equals_exact(self, other, tolerance=0):
"""
Returns true if the two Geometries are exactly equal, up to a
specified tolerance.
"""
return capi.geos_equalsexact(self.ptr, other.ptr, float(tolerance))

[docs]    def intersects(self, other):
"Returns true if disjoint returns false."
return capi.geos_intersects(self.ptr, other.ptr)

[docs]    def overlaps(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
is T*T***T** (for two points or two surfaces) 1*T***T** (for two curves).
"""
return capi.geos_overlaps(self.ptr, other.ptr)

[docs]    def relate_pattern(self, other, pattern):
"""
Returns true if the elements in the DE-9IM intersection matrix for the
two Geometries match the elements in pattern.
"""
if not isinstance(pattern, six.string_types) or len(pattern) > 9:
raise GEOSException('invalid intersection matrix pattern')
return capi.geos_relatepattern(self.ptr, other.ptr, force_bytes(pattern))

[docs]    def touches(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
is FT*******, F**T***** or F***T****.
"""
return capi.geos_touches(self.ptr, other.ptr)

[docs]    def within(self, other):
"""
Returns true if the DE-9IM intersection matrix for the two Geometries
is T*F**F***.
"""
return capi.geos_within(self.ptr, other.ptr)

# #### SRID Routines ####
def get_srid(self):
"Gets the SRID for the geometry, returns None if no SRID is set."
s = capi.geos_get_srid(self.ptr)
if s == 0:
return None
else:
return s

def set_srid(self, srid):
"Sets the SRID for the geometry."
capi.geos_set_srid(self.ptr, srid)
srid = property(get_srid, set_srid)

# #### Output Routines ####
@property
def ewkt(self):
"""
Returns the EWKT (SRID + WKT) of the Geometry. Note that Z values
are only included in this representation if GEOS >= 3.3.0.
"""
if self.get_srid():
return 'SRID=%s;%s' % (self.srid, self.wkt)
else:
return self.wkt

@property
def wkt(self):
"Returns the WKT (Well-Known Text) representation of this Geometry."
return wkt_w(3 if self.hasz else 2).write(self).decode()

@property
def hex(self):
"""
Returns the WKB of this Geometry in hexadecimal form.  Please note
that the SRID is not included in this representation because it is not
a part of the OGC specification (use the `hexewkb` property instead).
"""
# A possible faster, all-python, implementation:
#  str(self.wkb).encode('hex')
return wkb_w(3 if self.hasz else 2).write_hex(self)

@property
def hexewkb(self):
"""
Returns the EWKB of this Geometry in hexadecimal form.  This is an
extension of the WKB specification that includes SRID value that are
a part of this geometry.
"""
return ewkb_w(3 if self.hasz else 2).write_hex(self)

@property
def json(self):
"""
Returns GeoJSON representation of this Geometry.
"""
return json.dumps({'type': self.__class__.__name__, 'coordinates': self.coords})
geojson = json

@property
def wkb(self):
"""
Returns the WKB (Well-Known Binary) representation of this Geometry
as a Python buffer.  SRID and Z values are not included, use the
`ewkb` property instead.
"""
return wkb_w(3 if self.hasz else 2).write(self)

@property
def ewkb(self):
"""
Return the EWKB representation of this Geometry as a Python buffer.
This is an extension of the WKB specification that includes any SRID
value that are a part of this geometry.
"""
return ewkb_w(3 if self.hasz else 2).write(self)

@property
def kml(self):
"Returns the KML representation of this Geometry."
gtype = self.geom_type
return '<%s>%s</%s>' % (gtype, self.coord_seq.kml, gtype)

@property
def prepared(self):
"""
Returns a PreparedGeometry corresponding to this geometry -- it is
optimized for the contains, intersects, and covers operations.
"""
return PreparedGeometry(self)

# #### GDAL-specific output routines ####
@property
def ogr(self):
"Returns the OGR Geometry for this Geometry."
if not gdal.HAS_GDAL:
raise GEOSException('GDAL required to convert to an OGRGeometry.')
if self.srid:
try:
return gdal.OGRGeometry(self.wkb, self.srid)
except gdal.SRSException:
pass
return gdal.OGRGeometry(self.wkb)

@property
def srs(self):
"Returns the OSR SpatialReference for SRID of this Geometry."
if not gdal.HAS_GDAL:
raise GEOSException('GDAL required to return a SpatialReference object.')
if self.srid:
try:
return gdal.SpatialReference(self.srid)
except gdal.SRSException:
pass
return None

@property
def crs(self):
"Alias for `srs` property."
return self.srs

[docs]    def transform(self, ct, clone=False):
"""
Requires GDAL. Transforms the geometry according to the given
transformation object, which may be an integer SRID, and WKT or
PROJ.4 string. By default, the geometry is transformed in-place and
nothing is returned. However if the `clone` keyword is set, then this
geometry will not be modified and a transformed clone will be returned
instead.
"""
srid = self.srid

if ct == srid:
# short-circuit where source & dest SRIDs match
if clone:
return self.clone()
else:
return

if (srid is None) or (srid < 0):
raise GEOSException("Calling transform() with no SRID set is not supported")

if not gdal.HAS_GDAL:
raise GEOSException("GDAL library is not available to transform() geometry.")

# Creating an OGR Geometry, which is then transformed.
g = self.ogr
g.transform(ct)
# Getting a new GEOS pointer
ptr = wkb_r().read(g.wkb)
if clone:
# User wants a cloned transformed geometry returned.
return GEOSGeometry(ptr, srid=g.srid)
if ptr:
# Reassigning pointer, and performing post-initialization setup
# again due to the reassignment.
capi.destroy_geom(self.ptr)
self.ptr = ptr
self._post_init(g.srid)
else:
raise GEOSException('Transformed WKB was invalid.')

# #### Topology Routines ####
def _topology(self, gptr):
"Helper routine to return Geometry from the given pointer."
return GEOSGeometry(gptr, srid=self.srid)

@property
def boundary(self):
"Returns the boundary as a newly allocated Geometry object."
return self._topology(capi.geos_boundary(self.ptr))

[docs]    def buffer(self, width, quadsegs=8):
"""
Returns a geometry that represents all points whose distance from this
Geometry is less than or equal to distance. Calculations are in the
Spatial Reference System of this Geometry. The optional third parameter sets
the number of segment used to approximate a quarter circle (defaults to 8).
(Text from PostGIS documentation at ch. 6.1.3)
"""
return self._topology(capi.geos_buffer(self.ptr, width, quadsegs))

@property
def centroid(self):
"""
The centroid is equal to the centroid of the set of component Geometries
of highest dimension (since the lower-dimension geometries contribute zero
"weight" to the centroid).
"""
return self._topology(capi.geos_centroid(self.ptr))

@property
def convex_hull(self):
"""
Returns the smallest convex Polygon that contains all the points
in the Geometry.
"""
return self._topology(capi.geos_convexhull(self.ptr))

[docs]    def difference(self, other):
"""
Returns a Geometry representing the points making up this Geometry
that do not make up other.
"""
return self._topology(capi.geos_difference(self.ptr, other.ptr))

@property
def envelope(self):
"Return the envelope for this geometry (a polygon)."
return self._topology(capi.geos_envelope(self.ptr))

[docs]    def intersection(self, other):
"Returns a Geometry representing the points shared by this Geometry and other."
return self._topology(capi.geos_intersection(self.ptr, other.ptr))

@property
def point_on_surface(self):
"Computes an interior point of this Geometry."
return self._topology(capi.geos_pointonsurface(self.ptr))

[docs]    def relate(self, other):
"Returns the DE-9IM intersection matrix for this Geometry and the other."
return capi.geos_relate(self.ptr, other.ptr).decode()

[docs]    def simplify(self, tolerance=0.0, preserve_topology=False):
"""
Returns the Geometry, simplified using the Douglas-Peucker algorithm
to the specified tolerance (higher tolerance => less points).  If no
tolerance provided, defaults to 0.

By default, this function does not preserve topology - e.g. polygons can
be split, collapse to lines or disappear holes can be created or
disappear, and lines can cross. By specifying preserve_topology=True,
the result will have the same dimension and number of components as the
input. This is significantly slower.
"""
if preserve_topology:
return self._topology(capi.geos_preservesimplify(self.ptr, tolerance))
else:
return self._topology(capi.geos_simplify(self.ptr, tolerance))

[docs]    def sym_difference(self, other):
"""
Returns a set combining the points in this Geometry not in other,
and the points in other not in this Geometry.
"""
return self._topology(capi.geos_symdifference(self.ptr, other.ptr))

[docs]    def union(self, other):
"Returns a Geometry representing all the points in this Geometry and other."
return self._topology(capi.geos_union(self.ptr, other.ptr))

# #### Other Routines ####
@property
def area(self):
"Returns the area of the Geometry."
return capi.geos_area(self.ptr, byref(c_double()))

[docs]    def distance(self, other):
"""
Returns the distance between the closest points on this Geometry
and the other. Units will be in those of the coordinate system of
the Geometry.
"""
if not isinstance(other, GEOSGeometry):
raise TypeError('distance() works only on other GEOS Geometries.')
return capi.geos_distance(self.ptr, other.ptr, byref(c_double()))

@property
def extent(self):
"""
Returns the extent of this geometry as a 4-tuple, consisting of
(xmin, ymin, xmax, ymax).
"""
from .point import Point
env = self.envelope
if isinstance(env, Point):
xmin, ymin = env.tuple
xmax, ymax = xmin, ymin
else:
xmin, ymin = env[0][0]
xmax, ymax = env[0][2]
return (xmin, ymin, xmax, ymax)

@property
def length(self):
"""
Returns the length of this Geometry (e.g., 0 for point, or the
circumference of a Polygon).
"""
return capi.geos_length(self.ptr, byref(c_double()))

[docs]    def clone(self):
"Clones this Geometry."
return GEOSGeometry(capi.geom_clone(self.ptr), srid=self.srid)

class ProjectInterpolateMixin(object):
"""
Used for LineString and MultiLineString.
"""
def interpolate(self, distance):
return self._topology(capi.geos_interpolate(self.ptr, distance))

def interpolate_normalized(self, distance):
return self._topology(capi.geos_interpolate_normalized(self.ptr, distance))

def project(self, point):
from .point import Point
if not isinstance(point, Point):
raise TypeError('locate_point argument must be a Point')
return capi.geos_project(self.ptr, point.ptr)

def project_normalized(self, point):
from .point import Point
if not isinstance(point, Point):
raise TypeError('locate_point argument must be a Point')
return capi.geos_project_normalized(self.ptr, point.ptr)

Source code for django.contrib.gis.geos.linestring

from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.coordseq import GEOSCoordSeq
from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.geometry import (
GEOSGeometry, ProjectInterpolateMixin,
)
from django.contrib.gis.geos.point import Point
from django.contrib.gis.shortcuts import numpy
from django.utils.six.moves import range

[docs]class LineString(ProjectInterpolateMixin, GEOSGeometry):
_init_func = capi.create_linestring
_minlength = 2
has_cs = True

def __init__(self, *args, **kwargs):
"""
Initializes on the given sequence -- may take lists, tuples, NumPy arrays
of X,Y pairs, or Point objects.  If Point objects are used, ownership is
_not_ transferred to the LineString object.

Examples:
ls = LineString((1, 1), (2, 2))
ls = LineString([(1, 1), (2, 2)])
ls = LineString(array([(1, 1), (2, 2)]))
ls = LineString(Point(1, 1), Point(2, 2))
"""
# If only one argument provided, set the coords array appropriately
if len(args) == 1:
coords = args[0]
else:
coords = args

if isinstance(coords, (tuple, list)):
# Getting the number of coords and the number of dimensions -- which
#  must stay the same, e.g., no LineString((1, 2), (1, 2, 3)).
ncoords = len(coords)
if coords:
ndim = len(coords[0])
else:
raise TypeError('Cannot initialize on empty sequence.')
self._checkdim(ndim)
# Incrementing through each of the coordinates and verifying
for i in range(1, ncoords):
if not isinstance(coords[i], (tuple, list, Point)):
raise TypeError('each coordinate should be a sequence (list or tuple)')
if len(coords[i]) != ndim:
raise TypeError('Dimension mismatch.')
numpy_coords = False
elif numpy and isinstance(coords, numpy.ndarray):
shape = coords.shape  # Using numpy's shape.
if len(shape) != 2:
raise TypeError('Too many dimensions.')
self._checkdim(shape[1])
ncoords = shape[0]
ndim = shape[1]
numpy_coords = True
else:
raise TypeError('Invalid initialization input for LineStrings.')

# Creating a coordinate sequence object because it is easier to
# set the points using GEOSCoordSeq.__setitem__().
cs = GEOSCoordSeq(capi.create_cs(ncoords, ndim), z=bool(ndim == 3))

for i in range(ncoords):
if numpy_coords:
cs[i] = coords[i, :]
elif isinstance(coords[i], Point):
cs[i] = coords[i].tuple
else:
cs[i] = coords[i]

# If SRID was passed in with the keyword arguments
srid = kwargs.get('srid')

# Calling the base geometry initialization with the returned pointer
#  from the function.
super(LineString, self).__init__(self._init_func(cs.ptr), srid=srid)

def __iter__(self):
"Allows iteration over this LineString."
for i in range(len(self)):
yield self[i]

def __len__(self):
"Returns the number of points in this LineString."
return len(self._cs)

def _get_single_external(self, index):
return self._cs[index]

_get_single_internal = _get_single_external

def _set_list(self, length, items):
ndim = self._cs.dims
hasz = self._cs.hasz  # I don't understand why these are different

# create a new coordinate sequence and populate accordingly
cs = GEOSCoordSeq(capi.create_cs(length, ndim), z=hasz)
for i, c in enumerate(items):
cs[i] = c

ptr = self._init_func(cs.ptr)
if ptr:
capi.destroy_geom(self.ptr)
self.ptr = ptr
self._post_init(self.srid)
else:
# can this happen?
raise GEOSException('Geometry resulting from slice deletion was invalid.')

def _set_single(self, index, value):
self._checkindex(index)
self._cs[index] = value

def _checkdim(self, dim):
if dim not in (2, 3):
raise TypeError('Dimension mismatch.')

# #### Sequence Properties ####
@property
def tuple(self):
"Returns a tuple version of the geometry from the coordinate sequence."
return self._cs.tuple
coords = tuple

def _listarr(self, func):
"""
Internal routine that returns a sequence (list) corresponding with
the given function.  Will return a numpy array if possible.
"""
lst = [func(i) for i in range(len(self))]
if numpy:
return numpy.array(lst)  # ARRRR!
else:
return lst

@property
def array(self):
"Returns a numpy array for the LineString."
return self._listarr(self._cs.__getitem__)

@property
def merged(self):
"Returns the line merge of this LineString."
return self._topology(capi.geos_linemerge(self.ptr))

@property
def x(self):
"Returns a list or numpy array of the X variable."
return self._listarr(self._cs.getX)

@property
def y(self):
"Returns a list or numpy array of the Y variable."
return self._listarr(self._cs.getY)

@property
def z(self):
"Returns a list or numpy array of the Z variable."
if not self.hasz:
return None
else:
return self._listarr(self._cs.getZ)

# LinearRings are LineStrings used within Polygons.

[docs]class LinearRing(LineString):
_minlength = 4
_init_func = capi.create_linearring

Source code for django.contrib.gis.geos.collections

"""
This module houses the Geometry Collection objects:
GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
"""
import json
from ctypes import byref, c_int, c_uint

from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.geometry import (
GEOSGeometry, ProjectInterpolateMixin,
)
from django.contrib.gis.geos.libgeos import get_pointer_arr
from django.contrib.gis.geos.linestring import LinearRing, LineString
from django.contrib.gis.geos.point import Point
from django.contrib.gis.geos.polygon import Polygon
from django.utils.six.moves import range

[docs]class GeometryCollection(GEOSGeometry):
_typeid = 7

def __init__(self, *args, **kwargs):
"Initializes a Geometry Collection from a sequence of Geometry objects."

# Checking the arguments
if not args:
raise TypeError('Must provide at least one Geometry to initialize %s.' % self.__class__.__name__)

if len(args) == 1:
# If only one geometry provided or a list of geometries is provided
#  in the first argument.
if isinstance(args[0], (tuple, list)):
init_geoms = args[0]
else:
init_geoms = args
else:
init_geoms = args

# Ensuring that only the permitted geometries are allowed in this collection
# this is moved to list mixin super class
self._check_allowed(init_geoms)

# Creating the geometry pointer array.
collection = self._create_collection(len(init_geoms), iter(init_geoms))
super(GeometryCollection, self).__init__(collection, **kwargs)

def __iter__(self):
"Iterates over each Geometry in the Collection."
for i in range(len(self)):
yield self[i]

def __len__(self):
"Returns the number of geometries in this Collection."
return self.num_geom

# ### Methods for compatibility with ListMixin ###
def _create_collection(self, length, items):
# Creating the geometry pointer array.
geoms = get_pointer_arr(length)
for i, g in enumerate(items):
# this is a little sloppy, but makes life easier
# allow GEOSGeometry types (python wrappers) or pointer types
geoms[i] = capi.geom_clone(getattr(g, 'ptr', g))

return capi.create_collection(c_int(self._typeid), byref(geoms), c_uint(length))

def _get_single_internal(self, index):
return capi.get_geomn(self.ptr, index)

def _get_single_external(self, index):
"Returns the Geometry from this Collection at the given index (0-based)."
# Checking the index and returning the corresponding GEOS geometry.
return GEOSGeometry(capi.geom_clone(self._get_single_internal(index)), srid=self.srid)

def _set_list(self, length, items):
"Create a new collection, and destroy the contents of the previous pointer."
prev_ptr = self.ptr
srid = self.srid
self.ptr = self._create_collection(length, items)
if srid:
self.srid = srid
capi.destroy_geom(prev_ptr)

_set_single = GEOSGeometry._set_single_rebuild
_assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild

@property
def json(self):
if self.__class__.__name__ == 'GeometryCollection':
return json.dumps({
'type': self.__class__.__name__,
'geometries': [
{'type': geom.__class__.__name__, 'coordinates': geom.coords}
for geom in self
],
})
return super(GeometryCollection, self).json
geojson = json

@property
def kml(self):
"Returns the KML for this Geometry Collection."
return '<MultiGeometry>%s</MultiGeometry>' % ''.join(g.kml for g in self)

@property
def tuple(self):
"Returns a tuple of all the coordinates in this Geometry Collection"
return tuple(g.tuple for g in self)
coords = tuple

# MultiPoint, MultiLineString, and MultiPolygon class definitions.

[docs]class MultiPoint(GeometryCollection):
_allowed = Point
_typeid = 4

[docs]class MultiLineString(ProjectInterpolateMixin, GeometryCollection):
_allowed = (LineString, LinearRing)
_typeid = 5

@property
def merged(self):
"""
Returns a LineString representing the line merge of this
MultiLineString.
"""
return self._topology(capi.geos_linemerge(self.ptr))

[docs]class MultiPolygon(GeometryCollection):
_allowed = Polygon
_typeid = 6

@property
def cascaded_union(self):
"Returns a cascaded union of this MultiPolygon."
return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid)

# Setting the allowed types here since GeometryCollection is defined before
# its subclasses.
GeometryCollection._allowed = (Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon)

Source code for django.contrib.gis.geos.factory

from django.contrib.gis.geos.geometry import GEOSGeometry, hex_regex, wkt_regex
from django.utils import six

[docs]def fromfile(file_h):
"""
Given a string file name, returns a GEOSGeometry. The file may contain WKB,
WKT, or HEX.
"""
# If given a file name, get a real handle.
if isinstance(file_h, six.string_types):
with open(file_h, 'rb') as file_h:
buf = file_h.read()
else:
buf = file_h.read()

# If we get WKB need to wrap in memoryview(), so run through regexes.
if isinstance(buf, bytes):
try:
decoded = buf.decode()
if wkt_regex.match(decoded) or hex_regex.match(decoded):
return GEOSGeometry(decoded)
except UnicodeDecodeError:
pass
else:
return GEOSGeometry(buf)

return GEOSGeometry(six.memoryview(buf))

[docs]def fromstr(string, **kwargs):
"Given a string value, returns a GEOSGeometry object."
return GEOSGeometry(string, **kwargs)

Source code for django.contrib.gis.geos.io

"""
Module that holds classes for performing I/O operations on GEOS geometry
objects.  Specifically, this has Python implementations of WKB/WKT
reader and writer classes.
"""
from django.contrib.gis.geos.geometry import GEOSGeometry
from django.contrib.gis.geos.prototypes.io import (
WKBWriter, WKTWriter, _WKBReader, _WKTReader,
)

__all__ = ['WKBWriter', 'WKTWriter', 'WKBReader', 'WKTReader']

# Public classes for (WKB|WKT)Reader, which return GEOSGeometry

[docs]class WKBReader(_WKBReader):
def read(self, wkb):
"Returns a GEOSGeometry for the given WKB buffer."
return GEOSGeometry(super(WKBReader, self).read(wkb))

[docs]class WKTReader(_WKTReader):
def read(self, wkt):
"Returns a GEOSGeometry for the given WKT string."
return GEOSGeometry(super(WKTReader, self).read(wkt))

Source code for django.contrib.gis.geos.polygon

from ctypes import byref, c_uint

from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.geometry import GEOSGeometry
from django.contrib.gis.geos.libgeos import GEOM_PTR, get_pointer_arr
from django.contrib.gis.geos.linestring import LinearRing
from django.utils import six
from django.utils.six.moves import range

[docs]class Polygon(GEOSGeometry):
_minlength = 1

def __init__(self, *args, **kwargs):
"""
Initializes on an exterior ring and a sequence of holes (both
instances may be either LinearRing instances, or a tuple/list
that may be constructed into a LinearRing).

Examples of initialization, where shell, hole1, and hole2 are
valid LinearRing geometries:
>>> from django.contrib.gis.geos import LinearRing, Polygon
>>> shell = hole1 = hole2 = LinearRing()
>>> poly = Polygon(shell, hole1, hole2)
>>> poly = Polygon(shell, (hole1, hole2))

>>> # Example where a tuple parameters are used:
>>> poly = Polygon(((0, 0), (0, 10), (10, 10), (0, 10), (0, 0)),
...                ((4, 4), (4, 6), (6, 6), (6, 4), (4, 4)))
"""
if not args:
raise TypeError('Must provide at least one LinearRing, or a tuple, to initialize a Polygon.')

# Getting the ext_ring and init_holes parameters from the argument list
ext_ring = args[0]
init_holes = args[1:]
n_holes = len(init_holes)

# If initialized as Polygon(shell, (LinearRing, LinearRing)) [for backward-compatibility]
if n_holes == 1 and isinstance(init_holes[0], (tuple, list)):
if len(init_holes[0]) == 0:
init_holes = ()
n_holes = 0
elif isinstance(init_holes[0][0], LinearRing):
init_holes = init_holes[0]
n_holes = len(init_holes)

polygon = self._create_polygon(n_holes + 1, (ext_ring,) + init_holes)
super(Polygon, self).__init__(polygon, **kwargs)

def __iter__(self):
"Iterates over each ring in the polygon."
for i in range(len(self)):
yield self[i]

def __len__(self):
"Returns the number of rings in this Polygon."
return self.num_interior_rings + 1

@classmethod

[docs]    def from_bbox(cls, bbox):
"Constructs a Polygon from a bounding box (4-tuple)."
x0, y0, x1, y1 = bbox
for z in bbox:
if not isinstance(z, six.integer_types + (float,)):
return GEOSGeometry('POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' %
(x0, y0, x0, y1, x1, y1, x1, y0, x0, y0))
return Polygon(((x0, y0), (x0, y1), (x1, y1), (x1, y0), (x0, y0)))

# ### These routines are needed for list-like operation w/ListMixin ###
def _create_polygon(self, length, items):
# Instantiate LinearRing objects if necessary, but don't clone them yet
# _construct_ring will throw a TypeError if a parameter isn't a valid ring
# If we cloned the pointers here, we wouldn't be able to clean up
# in case of error.
rings = []
for r in items:
if isinstance(r, GEOM_PTR):
rings.append(r)
else:
rings.append(self._construct_ring(r))

shell = self._clone(rings.pop(0))

n_holes = length - 1
if n_holes:
holes = get_pointer_arr(n_holes)
for i, r in enumerate(rings):
holes[i] = self._clone(r)
holes_param = byref(holes)
else:
holes_param = None

return capi.create_polygon(shell, holes_param, c_uint(n_holes))

def _clone(self, g):
if isinstance(g, GEOM_PTR):
return capi.geom_clone(g)
else:
return capi.geom_clone(g.ptr)

def _construct_ring(self, param, msg=(
'Parameter must be a sequence of LinearRings or objects that can initialize to LinearRings')):
"Helper routine for trying to construct a ring from the given parameter."
if isinstance(param, LinearRing):
return param
try:
ring = LinearRing(param)
return ring
except TypeError:
raise TypeError(msg)

def _set_list(self, length, items):
# Getting the current pointer, replacing with the newly constructed
# geometry, and destroying the old geometry.
prev_ptr = self.ptr
srid = self.srid
self.ptr = self._create_polygon(length, items)
if srid:
self.srid = srid
capi.destroy_geom(prev_ptr)

def _get_single_internal(self, index):
"""
Returns the ring at the specified index.  The first index, 0, will
always return the exterior ring.  Indices > 0 will return the
interior ring at the given index (e.g., poly[1] and poly[2] would
return the first and second interior ring, respectively).

CAREFUL: Internal/External are not the same as Interior/Exterior!
_get_single_internal returns a pointer from the existing geometries for use
internally by the object's methods.  _get_single_external returns a clone
of the same geometry for use by external code.
"""
if index == 0:
return capi.get_extring(self.ptr)
else:
# Getting the interior ring, have to subtract 1 from the index.
return capi.get_intring(self.ptr, index - 1)

def _get_single_external(self, index):
return GEOSGeometry(capi.geom_clone(self._get_single_internal(index)), srid=self.srid)

_set_single = GEOSGeometry._set_single_rebuild
_assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild

# #### Polygon Properties ####
@property
def num_interior_rings(self):
"Returns the number of interior rings."
# Getting the number of rings
return capi.get_nrings(self.ptr)

def _get_ext_ring(self):
"Gets the exterior ring of the Polygon."
return self[0]

def _set_ext_ring(self, ring):
"Sets the exterior ring of the Polygon."
self[0] = ring

# Properties for the exterior ring/shell.
exterior_ring = property(_get_ext_ring, _set_ext_ring)
shell = exterior_ring

@property
def tuple(self):
"Gets the tuple for each ring in this Polygon."
return tuple(self[i].tuple for i in range(len(self)))
coords = tuple

@property
def kml(self):
"Returns the KML representation of this Polygon."
inner_kml = ''.join("<innerBoundaryIs>%s</innerBoundaryIs>" % self[i + 1].kml
for i in range(self.num_interior_rings))
return "<Polygon><outerBoundaryIs>%s</outerBoundaryIs>%s</Polygon>" % (self[0].kml, inner_kml)

Source code for django.contrib.gis.geos.error

[docs]class GEOSException(Exception):
"The base GEOS exception, indicates a GEOS-related error."
pass

Source code for django.contrib.gis.geos.point

from ctypes import c_uint

from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.geometry import GEOSGeometry
from django.utils import six
from django.utils.six.moves import range

[docs]class Point(GEOSGeometry):
_minlength = 2
_maxlength = 3
has_cs = True

def __init__(self, x, y=None, z=None, srid=None):
"""
The Point object may be initialized with either a tuple, or individual
parameters.

For Example:
>>> p = Point((5, 23)) # 2D point, passed in as a tuple
>>> p = Point(5, 23, 8) # 3D point, passed in with individual parameters
"""
if isinstance(x, (tuple, list)):
# Here a tuple or list was passed in under the `x` parameter.
ndim = len(x)
coords = x
elif isinstance(x, six.integer_types + (float,)) and isinstance(y, six.integer_types + (float,)):
# Here X, Y, and (optionally) Z were passed in individually, as parameters.
if isinstance(z, six.integer_types + (float,)):
ndim = 3
coords = [x, y, z]
else:
ndim = 2
coords = [x, y]
else:
raise TypeError('Invalid parameters given for Point initialization.')

point = self._create_point(ndim, coords)

# Initializing using the address returned from the GEOS
#  createPoint factory.
super(Point, self).__init__(point, srid=srid)

def _create_point(self, ndim, coords):
"""
Create a coordinate sequence, set X, Y, [Z], and create point
"""
if ndim < 2 or ndim > 3:
raise TypeError('Invalid point dimension: %s' % str(ndim))

cs = capi.create_cs(c_uint(1), c_uint(ndim))
i = iter(coords)
capi.cs_setx(cs, 0, next(i))
capi.cs_sety(cs, 0, next(i))
if ndim == 3:
capi.cs_setz(cs, 0, next(i))

return capi.create_point(cs)

def _set_list(self, length, items):
ptr = self._create_point(length, items)
if ptr:
capi.destroy_geom(self.ptr)
self._ptr = ptr
self._set_cs()
else:
# can this happen?
raise GEOSException('Geometry resulting from slice deletion was invalid.')

def _set_single(self, index, value):
self._cs.setOrdinate(index, 0, value)

def __iter__(self):
"Allows iteration over coordinates of this Point."
for i in range(len(self)):
yield self[i]

def __len__(self):
"Returns the number of dimensions for this Point (either 0, 2 or 3)."
if self.empty:
return 0
if self.hasz:
return 3
else:
return 2

def _get_single_external(self, index):
if index == 0:
return self.x
elif index == 1:
return self.y
elif index == 2:
return self.z

_get_single_internal = _get_single_external

def get_x(self):
"Returns the X component of the Point."
return self._cs.getOrdinate(0, 0)

def set_x(self, value):
"Sets the X component of the Point."
self._cs.setOrdinate(0, 0, value)

def get_y(self):
"Returns the Y component of the Point."
return self._cs.getOrdinate(1, 0)

def set_y(self, value):
"Sets the Y component of the Point."
self._cs.setOrdinate(1, 0, value)

def get_z(self):
"Returns the Z component of the Point."
if self.hasz:
return self._cs.getOrdinate(2, 0)
else:
return None

def set_z(self, value):
"Sets the Z component of the Point."
if self.hasz:
self._cs.setOrdinate(2, 0, value)
else:
raise GEOSException('Cannot set Z on 2D Point.')

# X, Y, Z properties
x = property(get_x, set_x)
y = property(get_y, set_y)
z = property(get_z, set_z)

# ### Tuple setting and retrieval routines. ###
def get_coords(self):
"Returns a tuple of the point."
return self._cs.tuple

def set_coords(self, tup):
"Sets the coordinates of the point with the given tuple."
self._cs[0] = tup

# The tuple and coords properties
tuple = property(get_coords, set_coords)
coords = tuple

Source code for django.contrib.gis.geos.prototypes.io

import threading
from ctypes import POINTER, Structure, byref, c_char, c_char_p, c_int, c_size_t

from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory
from django.contrib.gis.geos.prototypes.errcheck import (
check_geom, check_sized_string, check_string,
)
from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p
from django.utils import six
from django.utils.encoding import force_bytes

# ### The WKB/WKT Reader/Writer structures and pointers ###
class WKTReader_st(Structure):
pass

class WKTWriter_st(Structure):
pass

class WKBReader_st(Structure):
pass

class WKBWriter_st(Structure):
pass

WKT_READ_PTR = POINTER(WKTReader_st)
WKT_WRITE_PTR = POINTER(WKTWriter_st)
WKB_READ_PTR = POINTER(WKBReader_st)
WKB_WRITE_PTR = POINTER(WKBReader_st)

# WKTReader routines
wkt_reader_create = GEOSFuncFactory('GEOSWKTReader_create', restype=WKT_READ_PTR)
wkt_reader_destroy = GEOSFuncFactory('GEOSWKTReader_destroy', argtypes=[WKT_READ_PTR])

wkt_reader_read = GEOSFuncFactory(
'GEOSWKTReader_read', argtypes=[WKT_READ_PTR, c_char_p], restype=GEOM_PTR, errcheck=check_geom
)
# WKTWriter routines
wkt_writer_create = GEOSFuncFactory('GEOSWKTWriter_create', restype=WKT_WRITE_PTR)
wkt_writer_destroy = GEOSFuncFactory('GEOSWKTWriter_destroy', argtypes=[WKT_WRITE_PTR])

wkt_writer_write = GEOSFuncFactory(
'GEOSWKTWriter_write', argtypes=[WKT_WRITE_PTR, GEOM_PTR], restype=geos_char_p, errcheck=check_string
)

class WKTOutputDim(GEOSFuncFactory):
def get_func(self, *args, **kwargs):
try:
return super(WKTOutputDim, self).get_func(*args, **kwargs)
except AttributeError:
# GEOSWKTWriter_get/setOutputDimension has been introduced in GEOS 3.3.0
# Always return 2 if not available
return {
'GEOSWKTWriter_getOutputDimension': lambda ptr: 2,
'GEOSWKTWriter_setOutputDimension': lambda ptr, dim: None,
}.get(self.func_name)

wkt_writer_get_outdim = WKTOutputDim(
'GEOSWKTWriter_getOutputDimension', argtypes=[WKT_WRITE_PTR], restype=c_int
)
wkt_writer_set_outdim = WKTOutputDim(
'GEOSWKTWriter_setOutputDimension', argtypes=[WKT_WRITE_PTR, c_int]
)

# WKBReader routines
wkb_reader_create = GEOSFuncFactory('GEOSWKBReader_create', restype=WKB_READ_PTR)
wkb_reader_destroy = GEOSFuncFactory('GEOSWKBReader_destroy', argtypes=[WKB_READ_PTR])

class WKBReadFunc(GEOSFuncFactory):
# Although the function definitions take `const unsigned char *`
# as their parameter, we use c_char_p here so the function may
# take Python strings directly as parameters.  Inside Python there
# is not a difference between signed and unsigned characters, so
# it is not a problem.
argtypes = [WKB_READ_PTR, c_char_p, c_size_t]
restype = GEOM_PTR
errcheck = staticmethod(check_geom)

wkb_reader_read = WKBReadFunc('GEOSWKBReader_read')
wkb_reader_read_hex = WKBReadFunc('GEOSWKBReader_readHEX')

# WKBWriter routines
wkb_writer_create = GEOSFuncFactory('GEOSWKBWriter_create', restype=WKB_WRITE_PTR)
wkb_writer_destroy = GEOSFuncFactory('GEOSWKBWriter_destroy', argtypes=[WKB_WRITE_PTR])

# WKB Writing prototypes.
class WKBWriteFunc(GEOSFuncFactory):
argtypes = [WKB_WRITE_PTR, GEOM_PTR, POINTER(c_size_t)]
restype = c_uchar_p
errcheck = staticmethod(check_sized_string)

wkb_writer_write = WKBWriteFunc('GEOSWKBWriter_write')
wkb_writer_write_hex = WKBWriteFunc('GEOSWKBWriter_writeHEX')

# WKBWriter property getter/setter prototypes.
class WKBWriterGet(GEOSFuncFactory):
argtypes = [WKB_WRITE_PTR]
restype = c_int

class WKBWriterSet(GEOSFuncFactory):
argtypes = [WKB_WRITE_PTR, c_int]

wkb_writer_get_byteorder = WKBWriterGet('GEOSWKBWriter_getByteOrder')
wkb_writer_set_byteorder = WKBWriterSet('GEOSWKBWriter_setByteOrder')
wkb_writer_get_outdim = WKBWriterGet('GEOSWKBWriter_getOutputDimension')
wkb_writer_set_outdim = WKBWriterSet('GEOSWKBWriter_setOutputDimension')
wkb_writer_get_include_srid = WKBWriterGet('GEOSWKBWriter_getIncludeSRID', restype=c_char)
wkb_writer_set_include_srid = WKBWriterSet('GEOSWKBWriter_setIncludeSRID', argtypes=[WKB_WRITE_PTR, c_char])

# ### Base I/O Class ###
class IOBase(GEOSBase):
"Base class for GEOS I/O objects."
def __init__(self):
# Getting the pointer with the constructor.
self.ptr = self._constructor()
# Loading the real destructor function at this point as doing it in
# __del__ is too late (import error).
self._destructor.func = self._destructor.get_func(
*self._destructor.args, **self._destructor.kwargs
)

def __del__(self):
# Cleaning up with the appropriate destructor.
if self._ptr:
self._destructor(self._ptr)

# ### Base WKB/WKT Reading and Writing objects ###

# Non-public WKB/WKT reader classes for internal use because
# their `read` methods return _pointers_ instead of GEOSGeometry
# objects.
class _WKTReader(IOBase):
_constructor = wkt_reader_create
_destructor = wkt_reader_destroy
ptr_type = WKT_READ_PTR

def read(self, wkt):
if not isinstance(wkt, (bytes, six.string_types)):
raise TypeError
return wkt_reader_read(self.ptr, force_bytes(wkt))

class _WKBReader(IOBase):
_constructor = wkb_reader_create
_destructor = wkb_reader_destroy
ptr_type = WKB_READ_PTR

def read(self, wkb):
"Returns a _pointer_ to C GEOS Geometry object from the given WKB."
if isinstance(wkb, six.memoryview):
wkb_s = bytes(wkb)
return wkb_reader_read(self.ptr, wkb_s, len(wkb_s))
elif isinstance(wkb, (bytes, six.string_types)):
return wkb_reader_read_hex(self.ptr, wkb, len(wkb))
else:
raise TypeError

# ### WKB/WKT Writer Classes ###

[docs]class WKTWriter(IOBase):
_constructor = wkt_writer_create
_destructor = wkt_writer_destroy
ptr_type = WKT_WRITE_PTR

[docs]    def write(self, geom):
"Returns the WKT representation of the given geometry."
return wkt_writer_write(self.ptr, geom.ptr)

@property
def outdim(self):
return wkt_writer_get_outdim(self.ptr)

@outdim.setter
def outdim(self, new_dim):
if new_dim not in (2, 3):
raise ValueError('WKT output dimension must be 2 or 3')
wkt_writer_set_outdim(self.ptr, new_dim)

[docs]class WKBWriter(IOBase):
_constructor = wkb_writer_create
_destructor = wkb_writer_destroy
ptr_type = WKB_WRITE_PTR

[docs]    def write(self, geom):
"Returns the WKB representation of the given geometry."
return six.memoryview(wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t())))

[docs]    def write_hex(self, geom):
"Returns the HEXEWKB representation of the given geometry."
return wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t()))

# ### WKBWriter Properties ###

# Property for getting/setting the byteorder.
def _get_byteorder(self):
return wkb_writer_get_byteorder(self.ptr)

def _set_byteorder(self, order):
if order not in (0, 1):
raise ValueError('Byte order parameter must be 0 (Big Endian) or 1 (Little Endian).')
wkb_writer_set_byteorder(self.ptr, order)

byteorder = property(_get_byteorder, _set_byteorder)

# Property for getting/setting the output dimension.
def _get_outdim(self):
return wkb_writer_get_outdim(self.ptr)

def _set_outdim(self, new_dim):
if new_dim not in (2, 3):
raise ValueError('WKB output dimension must be 2 or 3')
wkb_writer_set_outdim(self.ptr, new_dim)

outdim = property(_get_outdim, _set_outdim)

# Property for getting/setting the include srid flag.
def _get_include_srid(self):
return bool(ord(wkb_writer_get_include_srid(self.ptr)))

def _set_include_srid(self, include):
if include:
flag = b'\x01'
else:
flag = b'\x00'
wkb_writer_set_include_srid(self.ptr, flag)

srid = property(_get_include_srid, _set_include_srid)

# `ThreadLocalIO` object holds instances of the WKT and WKB reader/writer
# objects that are local to the thread.  The `GEOSGeometry` internals
# access these instances by calling the module-level functions, defined
# below.
class ThreadLocalIO(threading.local):
wkt_r = None
wkt_w = None
wkb_r = None
wkb_w = None
ewkb_w = None

thread_context = ThreadLocalIO()

# These module-level routines return the I/O object that is local to the
# thread. If the I/O object does not exist yet it will be initialized.
def wkt_r():
if not thread_context.wkt_r:
thread_context.wkt_r = _WKTReader()
return thread_context.wkt_r

def wkt_w(dim=2):
if not thread_context.wkt_w:
thread_context.wkt_w = WKTWriter()
thread_context.wkt_w.outdim = dim
return thread_context.wkt_w

def wkb_r():
if not thread_context.wkb_r:
thread_context.wkb_r = _WKBReader()
return thread_context.wkb_r

def wkb_w(dim=2):
if not thread_context.wkb_w:
thread_context.wkb_w = WKBWriter()
thread_context.wkb_w.outdim = dim
return thread_context.wkb_w

def ewkb_w(dim=2):
if not thread_context.ewkb_w:
thread_context.ewkb_w = WKBWriter()
thread_context.ewkb_w.srid = True
thread_context.ewkb_w.outdim = dim
return thread_context.ewkb_w

Source code for django.contrib.gis.forms.fields

from __future__ import unicode_literals

from django import forms
from django.contrib.gis.geos import GEOSException, GEOSGeometry
from django.utils.translation import ugettext_lazy as _

from .widgets import OpenLayersWidget

[docs]class GeometryField(forms.Field):
"""
This is the basic form field for a Geometry.  Any textual input that is
accepted by GEOSGeometry is accepted by this form.  By default,
this includes WKT, HEXEWKB, WKB (in a buffer), and GeoJSON.
"""
widget = OpenLayersWidget
geom_type = 'GEOMETRY'

default_error_messages = {
'required': _('No geometry value provided.'),
'invalid_geom': _('Invalid geometry value.'),
'invalid_geom_type': _('Invalid geometry type.'),
'transform_error': _('An error occurred when transforming the geometry '
'to the SRID of the geometry form field.'),
}

def __init__(self, **kwargs):
# Pop out attributes from the database field, or use sensible
# defaults (e.g., allow None).
self.srid = kwargs.pop('srid', None)
self.geom_type = kwargs.pop('geom_type', self.geom_type)
super(GeometryField, self).__init__(**kwargs)
self.widget.attrs['geom_type'] = self.geom_type

def to_python(self, value):
"""
Transforms the value to a Geometry object.
"""
if value in self.empty_values:
return None

if not isinstance(value, GEOSGeometry):
try:
value = GEOSGeometry(value)
except (GEOSException, ValueError, TypeError):
raise forms.ValidationError(self.error_messages['invalid_geom'], code='invalid_geom')

# Try to set the srid
if not value.srid:
try:
value.srid = self.widget.map_srid
except AttributeError:
if self.srid:
value.srid = self.srid
return value

def clean(self, value):
"""
Validates that the input value can be converted to a Geometry
object (which is returned).  A ValidationError is raised if
the value cannot be instantiated as a Geometry.
"""
geom = super(GeometryField, self).clean(value)
if geom is None:
return geom

# Ensuring that the geometry is of the correct type (indicated
# using the OGC string label).
if str(geom.geom_type).upper() != self.geom_type and not self.geom_type == 'GEOMETRY':
raise forms.ValidationError(self.error_messages['invalid_geom_type'], code='invalid_geom_type')

# Transforming the geometry if the SRID was set.
if self.srid and self.srid != -1 and self.srid != geom.srid:
try:
geom.transform(self.srid)
except GEOSException:
raise forms.ValidationError(
self.error_messages['transform_error'], code='transform_error')

return geom

def has_changed(self, initial, data):
""" Compare geographic value of data with its initial value. """

try:
data = self.to_python(data)
initial = self.to_python(initial)
except forms.ValidationError:
return True

# Only do a geographic comparison if both values are available
if initial and data:
data.transform(initial.srid)
# If the initial value was not added by the browser, the geometry
# provided may be slightly different, the first time it is saved.
# The comparison is done with a very low tolerance.
return not initial.equals_exact(data, tolerance=0.000001)
else:
# Check for change of state of existence
return bool(initial) != bool(data)

[docs]class GeometryCollectionField(GeometryField):
geom_type = 'GEOMETRYCOLLECTION'

[docs]class PointField(GeometryField):
geom_type = 'POINT'

[docs]class MultiPointField(GeometryField):
geom_type = 'MULTIPOINT'

[docs]class LineStringField(GeometryField):
geom_type = 'LINESTRING'

[docs]class MultiLineStringField(GeometryField):
geom_type = 'MULTILINESTRING'

[docs]class PolygonField(GeometryField):
geom_type = 'POLYGON'

[docs]class MultiPolygonField(GeometryField):
geom_type = 'MULTIPOLYGON'

Source code for django.contrib.flatpages.sitemaps

from django.apps import apps as django_apps
from django.contrib.sitemaps import Sitemap
from django.core.exceptions import ImproperlyConfigured

[docs]class FlatPageSitemap(Sitemap):
def items(self):
if not django_apps.is_installed('django.contrib.sites'):
raise ImproperlyConfigured("FlatPageSitemap requires django.contrib.sites, which isn't installed.")
Site = django_apps.get_model('sites.Site')
current_site = Site.objects.get_current()
return current_site.flatpage_set.filter(registration_required=False)

Source code for django.utils.feedgenerator

"""
Syndication feed generation library -- used for generating RSS, etc.

Sample usage:

>>> from django.utils import feedgenerator
>>> feed = feedgenerator.Rss201rev2Feed(
...     title="Poynter E-Media Tidbits",
...     link="http://www.poynter.org/column.asp?id=31",
...     description="A group Weblog by the sharpest minds in online media/journalism/publishing.",
...     language="en",
... )
>>> feed.add_item(
...     title="Hello",
...     link="http://www.holovaty.com/test/",
...     description="Testing."
... )
>>> with open('test.rss', 'w') as fp:
...     feed.write(fp, 'utf-8')

For definitions of the different versions of RSS, see:
http://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/02/04/incompatible-rss
"""
from __future__ import unicode_literals

import datetime
import warnings

from django.utils import datetime_safe, six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text, iri_to_uri
from django.utils.six import StringIO
from django.utils.six.moves.urllib.parse import urlparse
from django.utils.xmlutils import SimplerXMLGenerator

def rfc2822_date(date):
# We can't use strftime() because it produces locale-dependent results, so
# we have to map english month and day names manually
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',)
days = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
# Support datetime objects older than 1900
date = datetime_safe.new_datetime(date)
# We do this ourselves to be timezone aware, email.Utils is not tz aware.
dow = days[date.weekday()]
month = months[date.month - 1]
time_str = date.strftime('%s, %%d %s %%Y %%H:%%M:%%S ' % (dow, month))
if six.PY2:             # strftime returns a byte string in Python 2
time_str = time_str.decode('utf-8')
offset = date.utcoffset()
# Historically, this function assumes that naive datetimes are in UTC.
if offset is None:
return time_str + '-0000'
else:
timezone = (offset.days * 24 * 60) + (offset.seconds // 60)
hour, minute = divmod(timezone, 60)
return time_str + '%+03d%02d' % (hour, minute)

def rfc3339_date(date):
# Support datetime objects older than 1900
date = datetime_safe.new_datetime(date)
time_str = date.strftime('%Y-%m-%dT%H:%M:%S')
if six.PY2:             # strftime returns a byte string in Python 2
time_str = time_str.decode('utf-8')
offset = date.utcoffset()
# Historically, this function assumes that naive datetimes are in UTC.
if offset is None:
return time_str + 'Z'
else:
timezone = (offset.days * 24 * 60) + (offset.seconds // 60)
hour, minute = divmod(timezone, 60)
return time_str + '%+03d:%02d' % (hour, minute)

[docs]def get_tag_uri(url, date):
"""
Creates a TagURI.

See http://web.archive.org/web/20110514113830/http://diveintomark.org/archives/2004/05/28/howto-atom-id
"""
bits = urlparse(url)
d = ''
if date is not None:
d = ',%s' % datetime_safe.new_datetime(date).strftime('%Y-%m-%d')
return 'tag:%s%s:%s/%s' % (bits.hostname, d, bits.path, bits.fragment)

[docs]class SyndicationFeed(object):
"Base class for all syndication feeds. Subclasses should provide write()"

[docs]    def __init__(self, title, link, description, language=None, author_email=None,
author_name=None, author_link=None, subtitle=None, categories=None,
feed_url=None, feed_copyright=None, feed_guid=None, ttl=None, **kwargs):
to_unicode = lambda s: force_text(s, strings_only=True)
if categories:
categories = [force_text(c) for c in categories]
if ttl is not None:
# Force ints to unicode
ttl = force_text(ttl)
self.feed = {
'title': to_unicode(title),
'link': iri_to_uri(link),
'description': to_unicode(description),
'language': to_unicode(language),
'author_email': to_unicode(author_email),
'author_name': to_unicode(author_name),
'author_link': iri_to_uri(author_link),
'subtitle': to_unicode(subtitle),
'categories': categories or (),
'feed_url': iri_to_uri(feed_url),
'feed_copyright': to_unicode(feed_copyright),
'id': feed_guid or link,
'ttl': ttl,
}
self.feed.update(kwargs)
self.items = []

[docs]    def add_item(self, title, link, description, author_email=None,
author_name=None, author_link=None, pubdate=None, comments=None,
unique_id=None, unique_id_is_permalink=None, enclosure=None,
categories=(), item_copyright=None, ttl=None, updateddate=None,
enclosures=None, **kwargs):
"""
Adds an item to the feed. All args are expected to be Python Unicode
objects except pubdate and updateddate, which are datetime.datetime
objects, and enclosures, which is an iterable of instances of the
Enclosure class.
"""
to_unicode = lambda s: force_text(s, strings_only=True)
if categories:
categories = [to_unicode(c) for c in categories]
if ttl is not None:
# Force ints to unicode
ttl = force_text(ttl)
if enclosure is None:
enclosures = [] if enclosures is None else enclosures
else:
warnings.warn(
"The enclosure keyword argument is deprecated, "
"use enclosures instead.",
RemovedInDjango20Warning,
stacklevel=2,
)
enclosures = [enclosure]
item = {
'title': to_unicode(title),
'link': iri_to_uri(link),
'description': to_unicode(description),
'author_email': to_unicode(author_email),
'author_name': to_unicode(author_name),
'author_link': iri_to_uri(author_link),
'pubdate': pubdate,
'updateddate': updateddate,
'comments': to_unicode(comments),
'unique_id': to_unicode(unique_id),
'unique_id_is_permalink': unique_id_is_permalink,
'enclosures': enclosures,
'categories': categories or (),
'item_copyright': to_unicode(item_copyright),
'ttl': ttl,
}
item.update(kwargs)
self.items.append(item)

[docs]    def num_items(self):
return len(self.items)

[docs]    def root_attributes(self):
"""
Return extra attributes to place on the root (i.e. feed/channel) element.
Called from write().
"""
return {}

[docs]    def add_root_elements(self, handler):
"""
Add elements in the root (i.e. feed/channel) element. Called
from write().
"""
pass

[docs]    def item_attributes(self, item):
"""
Return extra attributes to place on each item (i.e. item/entry) element.
"""
return {}

[docs]    def add_item_elements(self, handler, item):
"""
Add elements on each item (i.e. item/entry) element.
"""
pass

[docs]    def write(self, outfile, encoding):
"""
Outputs the feed in the given encoding to outfile, which is a file-like
object. Subclasses should override this.
"""
raise NotImplementedError('subclasses of SyndicationFeed must provide a write() method')

[docs]    def writeString(self, encoding):
"""
Returns the feed in the given encoding as a string.
"""
s = StringIO()
self.write(s, encoding)
return s.getvalue()

[docs]    def latest_post_date(self):
"""
Returns the latest item's pubdate or updateddate. If no items
have either of these attributes this returns the current date/time.
"""
latest_date = None
date_keys = ('updateddate', 'pubdate')

for item in self.items:
for date_key in date_keys:
item_date = item.get(date_key)
if item_date:
if latest_date is None or item_date > latest_date:
latest_date = item_date

return latest_date or datetime.datetime.now()

[docs]class Enclosure(object):
"Represents an RSS enclosure"
def __init__(self, url, length, mime_type):
"All args are expected to be Python Unicode objects"
self.length, self.mime_type = length, mime_type
self.url = iri_to_uri(url)

[docs]class RssFeed(SyndicationFeed):
content_type = 'application/rss+xml; charset=utf-8'

def write(self, outfile, encoding):
handler = SimplerXMLGenerator(outfile, encoding)
handler.startDocument()
handler.startElement("rss", self.rss_attributes())
handler.startElement("channel", self.root_attributes())
self.add_root_elements(handler)
self.write_items(handler)
self.endChannelElement(handler)
handler.endElement("rss")

def rss_attributes(self):
return {"version": self._version,
"xmlns:atom": "http://www.w3.org/2005/Atom"}

def write_items(self, handler):
for item in self.items:
handler.startElement('item', self.item_attributes(item))
self.add_item_elements(handler, item)
handler.endElement("item")

def add_root_elements(self, handler):
handler.addQuickElement("title", self.feed['title'])
handler.addQuickElement("link", self.feed['link'])
handler.addQuickElement("description", self.feed['description'])
if self.feed['feed_url'] is not None:
handler.addQuickElement("atom:link", None,
{"rel": "self", "href": self.feed['feed_url']})
if self.feed['language'] is not None:
handler.addQuickElement("language", self.feed['language'])
for cat in self.feed['categories']:
handler.addQuickElement("category", cat)
if self.feed['feed_copyright'] is not None:
handler.addQuickElement("copyright", self.feed['feed_copyright'])
handler.addQuickElement("lastBuildDate", rfc2822_date(self.latest_post_date()))
if self.feed['ttl'] is not None:
handler.addQuickElement("ttl", self.feed['ttl'])

def endChannelElement(self, handler):
handler.endElement("channel")

@property
def mime_type(self):
warnings.warn(
'The mime_type attribute of RssFeed is deprecated. '
'Use content_type instead.',
RemovedInDjango20Warning, stacklevel=2
)
return self.content_type

[docs]class RssUserland091Feed(RssFeed):
_version = "0.91"

def add_item_elements(self, handler, item):
handler.addQuickElement("title", item['title'])
handler.addQuickElement("link", item['link'])
if item['description'] is not None:
handler.addQuickElement("description", item['description'])

[docs]class Rss201rev2Feed(RssFeed):
# Spec: http://blogs.law.harvard.edu/tech/rss
_version = "2.0"

def add_item_elements(self, handler, item):
handler.addQuickElement("title", item['title'])
handler.addQuickElement("link", item['link'])
if item['description'] is not None:
handler.addQuickElement("description", item['description'])

# Author information.
if item["author_name"] and item["author_email"]:
handler.addQuickElement("author", "%s (%s)" %
(item['author_email'], item['author_name']))
elif item["author_email"]:
handler.addQuickElement("author", item["author_email"])
elif item["author_name"]:
handler.addQuickElement("dc:creator", item["author_name"],
{"xmlns:dc": "http://purl.org/dc/elements/1.1/"})

if item['pubdate'] is not None:
handler.addQuickElement("pubDate", rfc2822_date(item['pubdate']))
if item['comments'] is not None:
handler.addQuickElement("comments", item['comments'])
if item['unique_id'] is not None:
guid_attrs = {}
if isinstance(item.get('unique_id_is_permalink'), bool):
guid_attrs['isPermaLink'] = str(
item['unique_id_is_permalink']).lower()
handler.addQuickElement("guid", item['unique_id'], guid_attrs)
if item['ttl'] is not None:
handler.addQuickElement("ttl", item['ttl'])

# Enclosure.
if item['enclosures']:
enclosures = list(item['enclosures'])
if len(enclosures) > 1:
raise ValueError(
"RSS feed items may only have one enclosure, see "
"http://www.rssboard.org/rss-profile#element-channel-item-enclosure"
)
enclosure = enclosures[0]
handler.addQuickElement('enclosure', '', {
'url': enclosure.url,
'length': enclosure.length,
'type': enclosure.mime_type,
})

# Categories.
for cat in item['categories']:
handler.addQuickElement("category", cat)

[docs]class Atom1Feed(SyndicationFeed):
# Spec: https://tools.ietf.org/html/rfc4287
content_type = 'application/atom+xml; charset=utf-8'
ns = "http://www.w3.org/2005/Atom"

def write(self, outfile, encoding):
handler = SimplerXMLGenerator(outfile, encoding)
handler.startDocument()
handler.startElement('feed', self.root_attributes())
self.add_root_elements(handler)
self.write_items(handler)
handler.endElement("feed")

def root_attributes(self):
if self.feed['language'] is not None:
return {"xmlns": self.ns, "xml:lang": self.feed['language']}
else:
return {"xmlns": self.ns}

def add_root_elements(self, handler):
handler.addQuickElement("title", self.feed['title'])
handler.addQuickElement("link", "", {"rel": "alternate", "href": self.feed['link']})
if self.feed['feed_url'] is not None:
handler.addQuickElement("link", "", {"rel": "self", "href": self.feed['feed_url']})
handler.addQuickElement("id", self.feed['id'])
handler.addQuickElement("updated", rfc3339_date(self.latest_post_date()))
if self.feed['author_name'] is not None:
handler.startElement("author", {})
handler.addQuickElement("name", self.feed['author_name'])
if self.feed['author_email'] is not None:
handler.addQuickElement("email", self.feed['author_email'])
if self.feed['author_link'] is not None:
handler.addQuickElement("uri", self.feed['author_link'])
handler.endElement("author")
if self.feed['subtitle'] is not None:
handler.addQuickElement("subtitle", self.feed['subtitle'])
for cat in self.feed['categories']:
handler.addQuickElement("category", "", {"term": cat})
if self.feed['feed_copyright'] is not None:
handler.addQuickElement("rights", self.feed['feed_copyright'])

def write_items(self, handler):
for item in self.items:
handler.startElement("entry", self.item_attributes(item))
self.add_item_elements(handler, item)
handler.endElement("entry")

def add_item_elements(self, handler, item):
handler.addQuickElement("title", item['title'])
handler.addQuickElement("link", "", {"href": item['link'], "rel": "alternate"})

if item['pubdate'] is not None:
handler.addQuickElement('published', rfc3339_date(item['pubdate']))

if item['updateddate'] is not None:
handler.addQuickElement('updated', rfc3339_date(item['updateddate']))

# Author information.
if item['author_name'] is not None:
handler.startElement("author", {})
handler.addQuickElement("name", item['author_name'])
if item['author_email'] is not None:
handler.addQuickElement("email", item['author_email'])
if item['author_link'] is not None:
handler.addQuickElement("uri", item['author_link'])
handler.endElement("author")

# Unique ID.
if item['unique_id'] is not None:
unique_id = item['unique_id']
else:
unique_id = get_tag_uri(item['link'], item['pubdate'])
handler.addQuickElement("id", unique_id)

# Summary.
if item['description'] is not None:
handler.addQuickElement("summary", item['description'], {"type": "html"})

# Enclosures.
for enclosure in item['enclosures']:
handler.addQuickElement('link', '', {
'rel': 'enclosure',
'href': enclosure.url,
'length': enclosure.length,
'type': enclosure.mime_type,
})

# Categories.
for cat in item['categories']:
handler.addQuickElement("category", "", {"term": cat})

# Rights.
if item['item_copyright'] is not None:
handler.addQuickElement("rights", item['item_copyright'])

@property
def mime_type(self):
warnings.warn(
'The mime_type attribute of Atom1Feed is deprecated. '
'Use content_type instead.',
RemovedInDjango20Warning, stacklevel=2
)
return self.content_type

# This isolates the decision of what the system default is, so calling code can
# do "feedgenerator.DefaultFeed" instead of "feedgenerator.Rss201rev2Feed".
DefaultFeed = Rss201rev2Feed

Source code for django.utils.safestring

"""
Functions for working with "safe strings": strings that can be displayed safely
without further escaping in HTML. Marking something as a "safe string" means
that the producer of the string has already turned characters that should not
be interpreted by the HTML engine (e.g. '<') into the appropriate entities.
"""
from django.utils import six
from django.utils.functional import Promise, curry

class EscapeData(object):
pass

class EscapeBytes(bytes, EscapeData):
"""
A byte string that should be HTML-escaped when output.
"""
pass

class EscapeText(six.text_type, EscapeData):
"""
A unicode string object that should be HTML-escaped when output.
"""
pass

if six.PY3:
EscapeString = EscapeText
else:
EscapeString = EscapeBytes
# backwards compatibility for Python 2
EscapeUnicode = EscapeText

class SafeData(object):
def __html__(self):
"""
Returns the html representation of a string for interoperability.

This allows other template engines to understand Django's SafeData.
"""
return self

[docs]class SafeBytes(bytes, SafeData):
"""
A bytes subclass that has been specifically marked as "safe" (requires no
further escaping) for HTML output purposes.
"""
def __add__(self, rhs):
"""
Concatenating a safe byte string with another safe byte string or safe
unicode string is safe. Otherwise, the result is no longer safe.
"""
t = super(SafeBytes, self).__add__(rhs)
if isinstance(rhs, SafeText):
return SafeText(t)
elif isinstance(rhs, SafeBytes):
return SafeBytes(t)
return t

def _proxy_method(self, *args, **kwargs):
"""
Wrap a call to a normal unicode method up so that we return safe
results. The method that is being wrapped is passed in the 'method'
argument.
"""
method = kwargs.pop('method')
data = method(self, *args, **kwargs)
if isinstance(data, bytes):
return SafeBytes(data)
else:
return SafeText(data)

decode = curry(_proxy_method, method=bytes.decode)

[docs]class SafeText(six.text_type, SafeData):
"""
A unicode (Python 2) / str (Python 3) subclass that has been specifically
marked as "safe" for HTML output purposes.
"""
def __add__(self, rhs):
"""
Concatenating a safe unicode string with another safe byte string or
safe unicode string is safe. Otherwise, the result is no longer safe.
"""
t = super(SafeText, self).__add__(rhs)
if isinstance(rhs, SafeData):
return SafeText(t)
return t

def _proxy_method(self, *args, **kwargs):
"""
Wrap a call to a normal unicode method up so that we return safe
results. The method that is being wrapped is passed in the 'method'
argument.
"""
method = kwargs.pop('method')
data = method(self, *args, **kwargs)
if isinstance(data, bytes):
return SafeBytes(data)
else:
return SafeText(data)

encode = curry(_proxy_method, method=six.text_type.encode)

if six.PY3:
SafeString = SafeText
else:
SafeString = SafeBytes
# backwards compatibility for Python 2
SafeUnicode = SafeText

[docs]def mark_safe(s):
"""
Explicitly mark a string as safe for (HTML) output purposes. The returned
object can be used everywhere a string or unicode object is appropriate.

Can be called multiple times on a single string.
"""
if hasattr(s, '__html__'):
return s
if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
return SafeBytes(s)
if isinstance(s, (six.text_type, Promise)):
return SafeText(s)
return SafeString(str(s))

[docs]def mark_for_escaping(s):
"""
Explicitly mark a string as requiring HTML escaping upon output. Has no
effect on SafeData subclasses.

Can be called multiple times on a single string (the resulting escaping is
only applied once).
"""
if hasattr(s, '__html__') or isinstance(s, EscapeData):
return s
if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
return EscapeBytes(s)
if isinstance(s, (six.text_type, Promise)):
return EscapeText(s)
return EscapeString(str(s))

Source code for django.utils.module_loading

import copy
import os
import sys
from importlib import import_module

from django.utils import six

[docs]def import_string(dotted_path):
"""
Import a dotted module path and return the attribute/class designated by the
last name in the path. Raise ImportError if the import failed.
"""
try:
module_path, class_name = dotted_path.rsplit('.', 1)
except ValueError:
msg = "%s doesn't look like a module path" % dotted_path
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])

module = import_module(module_path)

try:
return getattr(module, class_name)
except AttributeError:
msg = 'Module "%s" does not define a "%s" attribute/class' % (
module_path, class_name)
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])

def autodiscover_modules(*args, **kwargs):
"""
Auto-discover INSTALLED_APPS modules and fail silently when
not present. This forces an import on them to register any admin bits they
may want.

You may provide a register_to keyword parameter as a way to access a
registry. This register_to object must have a _registry instance variable
to access it.
"""
from django.apps import apps

register_to = kwargs.get('register_to')
for app_config in apps.get_app_configs():
for module_to_search in args:
# Attempt to import the app's module.
try:
if register_to:
before_import_registry = copy.copy(register_to._registry)

import_module('%s.%s' % (app_config.name, module_to_search))
except:
# Reset the registry to the state before the last import
# as this import will have to reoccur on the next request and
# this could raise NotRegistered and AlreadyRegistered
# exceptions (see #8245).
if register_to:
register_to._registry = before_import_registry

# Decide whether to bubble up this error. If the app just
# doesn't have the module in question, we can ignore the error
# attempting to import it, otherwise we want it to bubble up.
if module_has_submodule(app_config.module, module_to_search):
raise

if six.PY3:
from importlib.util import find_spec as importlib_find

def module_has_submodule(package, module_name):
"""See if 'module' is in 'package'."""
try:
package_name = package.__name__
package_path = package.__path__
except AttributeError:
# package isn't a package.
return False

full_module_name = package_name + '.' + module_name
return importlib_find(full_module_name, package_path) is not None

else:
import imp

def module_has_submodule(package, module_name):
"""See if 'module' is in 'package'."""
name = ".".join([package.__name__, module_name])
try:
# None indicates a cached miss; see mark_miss() in Python/import.c.
return sys.modules[name] is not None
except KeyError:
pass
try:
package_path = package.__path__   # No __path__, then not a package.
except AttributeError:
# Since the remainder of this function assumes that we're dealing with
# a package (module with a __path__), so if it's not, then bail here.
return False
for finder in sys.meta_path:
if finder.find_module(name, package_path):
return True
for entry in package_path:
try:
# Try the cached finder.
finder = sys.path_importer_cache[entry]
if finder is None:
# Implicit import machinery should be used.
try:
file_, _, _ = imp.find_module(module_name, [entry])
if file_:
file_.close()
return True
except ImportError:
continue
# Else see if the finder knows of a loader.
elif finder.find_module(name):
return True
else:
continue
except KeyError:
# No cached finder, so try and make one.
for hook in sys.path_hooks:
try:
finder = hook(entry)
# XXX Could cache in sys.path_importer_cache
if finder.find_module(name):
return True
else:
# Once a finder is found, stop the search.
break
except ImportError:
# Continue the search for a finder.
continue
else:
# No finder found.
# Try the implicit import machinery if searching a directory.
if os.path.isdir(entry):
try:
file_, _, _ = imp.find_module(module_name, [entry])
if file_:
file_.close()
return True
except ImportError:
pass
# XXX Could insert None or NullImporter
else:
# Exhausted the search, so the module cannot be found.
return False

def module_dir(module):
"""
Find the name of the directory that contains a module, if possible.

Raise ValueError otherwise, e.g. for namespace packages that are split
over several directories.
"""
# Convert to list because _NamespacePath does not support indexing on 3.3.
paths = list(getattr(module, '__path__', []))
if len(paths) == 1:
return paths[0]
else:
filename = getattr(module, '__file__', None)
if filename is not None:
return os.path.dirname(filename)
raise ValueError("Cannot determine directory containing %s" % module)

Source code for django.utils.text

from __future__ import unicode_literals

import re
import unicodedata
from gzip import GzipFile
from io import BytesIO

from django.utils import six
from django.utils.encoding import force_text
from django.utils.functional import SimpleLazyObject, allow_lazy
from django.utils.safestring import SafeText, mark_safe
from django.utils.six.moves import html_entities
from django.utils.translation import pgettext, ugettext as _, ugettext_lazy

if six.PY2:
# Import force_unicode even though this module doesn't use it, because some
# people rely on it being here.
from django.utils.encoding import force_unicode  # NOQA

# Capitalizes the first letter of a string.
capfirst = lambda x: x and force_text(x)[0].upper() + force_text(x)[1:]
capfirst = allow_lazy(capfirst, six.text_type)

# Set up regular expressions
re_words = re.compile(r'<.*?>|((?:\w[-\w]*|&.*?;)+)', re.U | re.S)
re_chars = re.compile(r'<.*?>|(.)', re.U | re.S)
re_tag = re.compile(r'<(/)?([^ ]+?)(?:(\s*/)| .*?)?>', re.S)
re_newlines = re.compile(r'\r\n|\r')  # Used in normalize_newlines
re_camel_case = re.compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')

def wrap(text, width):
"""
A word-wrap function that preserves existing line breaks. Expects that
existing line breaks are posix newlines.

All white space is preserved except added line breaks consume the space on
which they break the line.

Long words are not wrapped, so the output text may have lines longer than
``width``.
"""
text = force_text(text)

def _generator():
for line in text.splitlines(True):  # True keeps trailing linebreaks
max_width = min((line.endswith('\n') and width + 1 or width), width)
while len(line) > max_width:
space = line[:max_width + 1].rfind(' ') + 1
if space == 0:
space = line.find(' ') + 1
if space == 0:
yield line
line = ''
break
yield '%s\n' % line[:space - 1]
line = line[space:]
max_width = min((line.endswith('\n') and width + 1 or width), width)
if line:
yield line
return ''.join(_generator())
wrap = allow_lazy(wrap, six.text_type)

class Truncator(SimpleLazyObject):
"""
An object used to truncate text, either by characters or words.
"""
def __init__(self, text):
super(Truncator, self).__init__(lambda: force_text(text))

def add_truncation_text(self, text, truncate=None):
if truncate is None:
truncate = pgettext(
'String to return when truncating text',
'%(truncated_text)s...')
truncate = force_text(truncate)
if '%(truncated_text)s' in truncate:
return truncate % {'truncated_text': text}
# The truncation text didn't contain the %(truncated_text)s string
# replacement argument so just append it to the text.
if text.endswith(truncate):
# But don't append the truncation text if the current text already
# ends in this.
return text
return '%s%s' % (text, truncate)

def chars(self, num, truncate=None, html=False):
"""
Returns the text truncated to be no longer than the specified number
of characters.

Takes an optional argument of what should be used to notify that the
string has been truncated, defaulting to a translatable string of an
ellipsis (...).
"""
length = int(num)
text = unicodedata.normalize('NFC', self._wrapped)

# Calculate the length to truncate to (max length - end_text length)
truncate_len = length
for char in self.add_truncation_text('', truncate):
if not unicodedata.combining(char):
truncate_len -= 1
if truncate_len == 0:
break
if html:
return self._truncate_html(length, truncate, text, truncate_len, False)
return self._text_chars(length, truncate, text, truncate_len)
chars = allow_lazy(chars)

def _text_chars(self, length, truncate, text, truncate_len):
"""
Truncates a string after a certain number of chars.
"""
s_len = 0
end_index = None
for i, char in enumerate(text):
if unicodedata.combining(char):
# Don't consider combining characters
# as adding to the string length
continue
s_len += 1
if end_index is None and s_len > truncate_len:
end_index = i
if s_len > length:
# Return the truncated string
return self.add_truncation_text(text[:end_index or 0],
truncate)

# Return the original string since no truncation was necessary
return text

def words(self, num, truncate=None, html=False):
"""
Truncates a string after a certain number of words. Takes an optional
argument of what should be used to notify that the string has been
truncated, defaulting to ellipsis (...).
"""
length = int(num)
if html:
return self._truncate_html(length, truncate, self._wrapped, length, True)
return self._text_words(length, truncate)
words = allow_lazy(words)

def _text_words(self, length, truncate):
"""
Truncates a string after a certain number of words.

Newlines in the string will be stripped.
"""
words = self._wrapped.split()
if len(words) > length:
words = words[:length]
return self.add_truncation_text(' '.join(words), truncate)
return ' '.join(words)

def _truncate_html(self, length, truncate, text, truncate_len, words):
"""
Truncates HTML to a certain number of chars (not counting tags and
comments), or, if words is True, then to a certain number of words.
Closes opened tags if they were correctly closed in the given HTML.

Newlines in the HTML are preserved.
"""
if words and length <= 0:
return ''

html4_singlets = (
'br', 'col', 'link', 'base', 'img',
'param', 'area', 'hr', 'input'
)

# Count non-HTML chars/words and keep note of open tags
pos = 0
end_text_pos = 0
current_len = 0
open_tags = []

regex = re_words if words else re_chars

while current_len <= length:
m = regex.search(text, pos)
if not m:
# Checked through whole string
break
pos = m.end(0)
if m.group(1):
# It's an actual non-HTML word or char
current_len += 1
if current_len == truncate_len:
end_text_pos = pos
continue
# Check for tag
tag = re_tag.match(m.group(0))
if not tag or current_len >= truncate_len:
# Don't worry about non tags or tags after our truncate point
continue
closing_tag, tagname, self_closing = tag.groups()
# Element names are always case-insensitive
tagname = tagname.lower()
if self_closing or tagname in html4_singlets:
pass
elif closing_tag:
# Check for match in open tags list
try:
i = open_tags.index(tagname)
except ValueError:
pass
else:
# SGML: An end tag closes, back to the matching start tag,
# all unclosed intervening start tags with omitted end tags
open_tags = open_tags[i + 1:]
else:
# Add it to the start of the open tags list
open_tags.insert(0, tagname)

if current_len <= length:
return text
out = text[:end_text_pos]
truncate_text = self.add_truncation_text('', truncate)
if truncate_text:
out += truncate_text
# Close any tags still open
for tag in open_tags:
out += '</%s>' % tag
# Return string
return out

def get_valid_filename(s):
"""
Returns the given string converted to a string that can be used for a clean
filename. Specifically, leading and trailing spaces are removed; other
spaces are converted to underscores; and anything that is not a unicode
alphanumeric, dash, underscore, or dot, is removed.
>>> get_valid_filename("john's portrait in 2004.jpg")
'johns_portrait_in_2004.jpg'
"""
s = force_text(s).strip().replace(' ', '_')
return re.sub(r'(?u)[^-\w.]', '', s)
get_valid_filename = allow_lazy(get_valid_filename, six.text_type)

def get_text_list(list_, last_word=ugettext_lazy('or')):
"""
>>> get_text_list(['a', 'b', 'c', 'd'])
'a, b, c or d'
>>> get_text_list(['a', 'b', 'c'], 'and')
'a, b and c'
>>> get_text_list(['a', 'b'], 'and')
'a and b'
>>> get_text_list(['a'])
'a'
>>> get_text_list([])
''
"""
if len(list_) == 0:
return ''
if len(list_) == 1:
return force_text(list_[0])
return '%s %s %s' % (
# Translators: This string is used as a separator between list elements
_(', ').join(force_text(i) for i in list_[:-1]),
force_text(last_word), force_text(list_[-1]))
get_text_list = allow_lazy(get_text_list, six.text_type)

def normalize_newlines(text):
"""Normalizes CRLF and CR newlines to just LF."""
text = force_text(text)
return re_newlines.sub('\n', text)
normalize_newlines = allow_lazy(normalize_newlines, six.text_type)

def phone2numeric(phone):
"""Converts a phone number with letters into its numeric equivalent."""
char2number = {'a': '2', 'b': '2', 'c': '2', 'd': '3', 'e': '3', 'f': '3',
'g': '4', 'h': '4', 'i': '4', 'j': '5', 'k': '5', 'l': '5', 'm': '6',
'n': '6', 'o': '6', 'p': '7', 'q': '7', 'r': '7', 's': '7', 't': '8',
'u': '8', 'v': '8', 'w': '9', 'x': '9', 'y': '9', 'z': '9'}
return ''.join(char2number.get(c, c) for c in phone.lower())
phone2numeric = allow_lazy(phone2numeric)

# From http://www.xhaus.com/alan/python/httpcomp.html#gzip
# Used with permission.
def compress_string(s):
zbuf = BytesIO()
zfile = GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
zfile.write(s)
zfile.close()
return zbuf.getvalue()

class StreamingBuffer(object):
def __init__(self):
self.vals = []

def write(self, val):
self.vals.append(val)

def read(self):
if not self.vals:
return b''
ret = b''.join(self.vals)
self.vals = []
return ret

def flush(self):
return

def close(self):
return

# Like compress_string, but for iterators of strings.
def compress_sequence(sequence):
buf = StreamingBuffer()
zfile = GzipFile(mode='wb', compresslevel=6, fileobj=buf)
# Output headers...
yield buf.read()
for item in sequence:
zfile.write(item)
data = buf.read()
if data:
yield data
zfile.close()
yield buf.read()

# Expression to match some_token and some_token="with spaces" (and similarly
# for single-quoted strings).
smart_split_re = re.compile(r"""
((?:
[^\s'"]*
(?:
(?:"(?:[^"\\]|\\.)*" | '(?:[^'\\]|\\.)*')
[^\s'"]*
)+
) | \S+)
""", re.VERBOSE)

def smart_split(text):
r"""
Generator that splits a string by spaces, leaving quoted phrases together.
Supports both single and double quotes, and supports escaping quotes with
backslashes. In the output, strings will keep their initial and trailing
quote marks and escaped quotes will remain escaped (the results can then
be further processed with unescape_string_literal()).

>>> list(smart_split(r'This is "a person\'s" test.'))
['This', 'is', '"a person\\\'s"', 'test.']
>>> list(smart_split(r"Another 'person\'s' test."))
['Another', "'person\\'s'", 'test.']
>>> list(smart_split(r'A "\"funky\" style" test.'))
['A', '"\\"funky\\" style"', 'test.']
"""
text = force_text(text)
for bit in smart_split_re.finditer(text):
yield bit.group(0)

def _replace_entity(match):
text = match.group(1)
if text[0] == '#':
text = text[1:]
try:
if text[0] in 'xX':
c = int(text[1:], 16)
else:
c = int(text)
return six.unichr(c)
except ValueError:
return match.group(0)
else:
try:
return six.unichr(html_entities.name2codepoint[text])
except (ValueError, KeyError):
return match.group(0)

_entity_re = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));")

def unescape_entities(text):
return _entity_re.sub(_replace_entity, text)
unescape_entities = allow_lazy(unescape_entities, six.text_type)

def unescape_string_literal(s):
r"""
Convert quoted string literals to unquoted strings with escaped quotes and
backslashes unquoted::

>>> unescape_string_literal('"abc"')
'abc'
>>> unescape_string_literal("'abc'")
'abc'
>>> unescape_string_literal('"a \"bc\""')
'a "bc"'
>>> unescape_string_literal("'\'ab\' c'")
"'ab' c"
"""
if s[0] not in "\"'" or s[-1] != s[0]:
raise ValueError("Not a string literal: %r" % s)
quote = s[0]
return s[1:-1].replace(r'\%s' % quote, quote).replace(r'\\', '\\')
unescape_string_literal = allow_lazy(unescape_string_literal)

[docs]def slugify(value, allow_unicode=False):
"""
Convert to ASCII if 'allow_unicode' is False. Convert spaces to hyphens.
Remove characters that aren't alphanumerics, underscores, or hyphens.
Convert to lowercase. Also strip leading and trailing whitespace.
"""
value = force_text(value)
if allow_unicode:
value = unicodedata.normalize('NFKC', value)
value = re.sub('[^\w\s-]', '', value, flags=re.U).strip().lower()
return mark_safe(re.sub('[-\s]+', '-', value, flags=re.U))
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
value = re.sub('[^\w\s-]', '', value).strip().lower()
return mark_safe(re.sub('[-\s]+', '-', value))

slugify = allow_lazy(slugify, six.text_type, SafeText)

def camel_case_to_spaces(value):
"""
Splits CamelCase and converts to lower case. Also strips leading and
trailing whitespace.
"""
return re_camel_case.sub(r' \1', value).strip().lower()

Source code for django.utils.decorators

"Functions that help with dynamically creating decorators for views."

try:
from contextlib import ContextDecorator
except ImportError:
ContextDecorator = None

from functools import WRAPPER_ASSIGNMENTS, update_wrapper, wraps

from django.utils import six

class classonlymethod(classmethod):
def __get__(self, instance, owner):
if instance is not None:
raise AttributeError("This method is available only on the class, not on instances.")
return super(classonlymethod, self).__get__(instance, owner)

[docs]def method_decorator(decorator, name=''):
"""
Converts a function decorator into a method decorator
"""
# 'obj' can be a class or a function. If 'obj' is a function at the time it
# is passed to _dec,  it will eventually be a method of the class it is
# defined on. If 'obj' is a class, the 'name' is required to be the name
# of the method that will be decorated.
def _dec(obj):
is_class = isinstance(obj, type)
if is_class:
if name and hasattr(obj, name):
func = getattr(obj, name)
if not callable(func):
raise TypeError(
"Cannot decorate '{0}' as it isn't a callable "
"attribute of {1} ({2})".format(name, obj, func)
)
else:
raise ValueError(
"The keyword argument `name` must be the name of a method "
"of the decorated class: {0}. Got '{1}' instead".format(
obj, name,
)
)
else:
func = obj

def decorate(function):
"""
Apply a list/tuple of decorators if decorator is one. Decorator
functions are applied so that the call order is the same as the
order in which they appear in the iterable.
"""
if hasattr(decorator, '__iter__'):
for dec in decorator[::-1]:
function = dec(function)
return function
return decorator(function)

def _wrapper(self, *args, **kwargs):
@decorate
def bound_func(*args2, **kwargs2):
return func.__get__(self, type(self))(*args2, **kwargs2)
# bound_func has the signature that 'decorator' expects i.e.  no
# 'self' argument, but it is a closure over self so it can call
# 'func' correctly.
return bound_func(*args, **kwargs)
# In case 'decorator' adds attributes to the function it decorates, we
# want to copy those. We don't have access to bound_func in this scope,
# but we can cheat by using it on a dummy function.

@decorate
def dummy(*args, **kwargs):
pass
update_wrapper(_wrapper, dummy)
# Need to preserve any existing attributes of 'func', including the name.
update_wrapper(_wrapper, func)

if is_class:
setattr(obj, name, _wrapper)
return obj

return _wrapper
# Don't worry about making _dec look similar to a list/tuple as it's rather
# meaningless.
if not hasattr(decorator, '__iter__'):
update_wrapper(_dec, decorator, assigned=available_attrs(decorator))
# Change the name to aid debugging.
if hasattr(decorator, '__name__'):
_dec.__name__ = 'method_decorator(%s)' % decorator.__name__
else:
_dec.__name__ = 'method_decorator(%s)' % decorator.__class__.__name__
return _dec

[docs]def decorator_from_middleware_with_args(middleware_class):
"""
Like decorator_from_middleware, but returns a function
that accepts the arguments to be passed to the middleware_class.
Use like::

cache_page = decorator_from_middleware_with_args(CacheMiddleware)
# ...

@cache_page(3600)
def my_view(request):
# ...
"""
return make_middleware_decorator(middleware_class)

[docs]def decorator_from_middleware(middleware_class):
"""
Given a middleware class (not an instance), returns a view decorator. This
lets you use middleware functionality on a per-view basis. The middleware
is created with no params passed.
"""
return make_middleware_decorator(middleware_class)()

def available_attrs(fn):
"""
Return the list of functools-wrappable attributes on a callable.
This is required as a workaround for http://bugs.python.org/issue3445
under Python 2.
"""
if six.PY3:
return WRAPPER_ASSIGNMENTS
else:
return tuple(a for a in WRAPPER_ASSIGNMENTS if hasattr(fn, a))

def make_middleware_decorator(middleware_class):
def _make_decorator(*m_args, **m_kwargs):
middleware = middleware_class(*m_args, **m_kwargs)

def _decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if hasattr(middleware, 'process_request'):
result = middleware.process_request(request)
if result is not None:
return result
if hasattr(middleware, 'process_view'):
result = middleware.process_view(request, view_func, args, kwargs)
if result is not None:
return result
try:
response = view_func(request, *args, **kwargs)
except Exception as e:
if hasattr(middleware, 'process_exception'):
result = middleware.process_exception(request, e)
if result is not None:
return result
raise
if hasattr(response, 'render') and callable(response.render):
if hasattr(middleware, 'process_template_response'):
response = middleware.process_template_response(request, response)
# Defer running of process_response until after the template
# has been rendered:
if hasattr(middleware, 'process_response'):
callback = lambda response: middleware.process_response(request, response)
response.add_post_render_callback(callback)
else:
if hasattr(middleware, 'process_response'):
return middleware.process_response(request, response)
return response
return _wrapped_view
return _decorator
return _make_decorator

if ContextDecorator is None:
# ContextDecorator was introduced in Python 3.2
# See https://docs.python.org/3/library/contextlib.html#contextlib.ContextDecorator
class ContextDecorator(object):
"""
A base class that enables a context manager to also be used as a decorator.
"""
def __call__(self, func):
@wraps(func, assigned=available_attrs(func))
def inner(*args, **kwargs):
with self:
return func(*args, **kwargs)
return inner

class classproperty(object):
def __init__(self, method=None):
self.fget = method

def __get__(self, instance, owner):
return self.fget(owner)

def getter(self, method):
self.fget = method
return self

Source code for django.utils.html

"""HTML utilities suitable for global use."""

from __future__ import unicode_literals

import re
import warnings

from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_str, force_text
from django.utils.functional import allow_lazy
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS
from django.utils.safestring import SafeData, SafeText, mark_safe
from django.utils.six.moves.urllib.parse import (
parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit,
)
from django.utils.text import normalize_newlines

from .html_parser import HTMLParseError, HTMLParser

# Configuration for urlize() function.
TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)', '"', '\'', '!']
WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('[', ']'), ('&lt;', '&gt;'), ('"', '"'), ('\'', '\'')]

# List of possible strings used for bullets in bulleted lists.
DOTS = ['&middot;', '*', '\u2022', '&#149;', '&bull;', '&#8226;']

unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
word_split_re = re.compile(r'''([\s<>"']+)''')
simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE)
simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$', re.IGNORECASE)
simple_email_re = re.compile(r'^\S+@\S+\.\S+$')
link_target_attribute_re = re.compile(r'(<a [^>]*?)target=[^\s>]+')
html_gunk_re = re.compile(
r'(?:<br clear="all">|<i><\/i>|<b><\/b>|<em><\/em>|<strong><\/strong>|'
'<\/?smallcaps>|<\/?uppercase>)', re.IGNORECASE)
hard_coded_bullets_re = re.compile(
r'((?:<p>(?:%s).*?[a-zA-Z].*?</p>\s*)+)' % '|'.join(re.escape(x)
for x in DOTS), re.DOTALL)
trailing_empty_content_re = re.compile(r'(?:<p>(?:&nbsp;|\s|<br \/>)*?</p>\s*)+\Z')

[docs]def escape(text):
"""
Returns the given text with ampersands, quotes and angle brackets encoded
for use in HTML.

This function always escapes its input, even if it's already escaped and
marked as such. This may result in double-escaping. If this is a concern,
use conditional_escape() instead.
"""
return mark_safe(force_text(text).replace('&', '&amp;').replace('<', '&lt;')
.replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;'))

escape = allow_lazy(escape, six.text_type, SafeText)

_js_escapes = {
ord('\\'): '\\u005C',
ord('\''): '\\u0027',
ord('"'): '\\u0022',
ord('>'): '\\u003E',
ord('<'): '\\u003C',
ord('&'): '\\u0026',
ord('='): '\\u003D',
ord('-'): '\\u002D',
ord(';'): '\\u003B',
ord('\u2028'): '\\u2028',
ord('\u2029'): '\\u2029'
}

# Escape every ASCII character with a value less than 32.
_js_escapes.update((ord('%c' % z), '\\u%04X' % z) for z in range(32))

def escapejs(value):
"""Hex encodes characters for use in JavaScript strings."""
return mark_safe(force_text(value).translate(_js_escapes))
escapejs = allow_lazy(escapejs, six.text_type, SafeText)

[docs]def conditional_escape(text):
"""
Similar to escape(), except that it doesn't operate on pre-escaped strings.

This function relies on the __html__ convention used both by Django's
SafeData class and by third-party libraries like markupsafe.
"""
if hasattr(text, '__html__'):
return text.__html__()
else:
return escape(text)

[docs]def format_html(format_string, *args, **kwargs):
"""
Similar to str.format, but passes all arguments through conditional_escape,
and calls 'mark_safe' on the result. This function should be used instead
of str.format or % interpolation to build up small HTML fragments.
"""
args_safe = map(conditional_escape, args)
kwargs_safe = {k: conditional_escape(v) for (k, v) in six.iteritems(kwargs)}
return mark_safe(format_string.format(*args_safe, **kwargs_safe))

[docs]def format_html_join(sep, format_string, args_generator):
"""
A wrapper of format_html, for the common case of a group of arguments that
need to be formatted using the same format string, and then joined using
'sep'. 'sep' is also passed through conditional_escape.

'args_generator' should be an iterator that returns the sequence of 'args'
that will be passed to format_html.

Example:

format_html_join('\n', "<li>{} {}</li>", ((u.first_name, u.last_name)
for u in users))
"""
return mark_safe(conditional_escape(sep).join(
format_html(format_string, *tuple(args))
for args in args_generator))

def linebreaks(value, autoescape=False):
"""Converts newlines into <p> and <br />s."""
value = normalize_newlines(value)
paras = re.split('\n{2,}', value)
if autoescape:
paras = ['<p>%s</p>' % escape(p).replace('\n', '<br />') for p in paras]
else:
paras = ['<p>%s</p>' % p.replace('\n', '<br />') for p in paras]
return '\n\n'.join(paras)
linebreaks = allow_lazy(linebreaks, six.text_type)

class MLStripper(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.reset()
self.fed = []

def handle_data(self, d):
self.fed.append(d)

def handle_entityref(self, name):
self.fed.append('&%s;' % name)

def handle_charref(self, name):
self.fed.append('&#%s;' % name)

def get_data(self):
return ''.join(self.fed)

def _strip_once(value):
"""
Internal tag stripping utility used by strip_tags.
"""
s = MLStripper()
try:
s.feed(value)
except HTMLParseError:
return value
try:
s.close()
except HTMLParseError:
return s.get_data() + s.rawdata
else:
return s.get_data()

[docs]def strip_tags(value):
"""Returns the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once.
while '<' in value and '>' in value:
new_value = _strip_once(value)
if len(new_value) >= len(value):
# _strip_once was not able to detect more tags or length increased
# due to http://bugs.python.org/issue20288
# (affects Python 2 < 2.7.7 and Python 3 < 3.3.5)
break
value = new_value
return value

strip_tags = allow_lazy(strip_tags)

[docs]def remove_tags(html, tags):
"""Returns the given HTML with given tags removed."""
warnings.warn(
"django.utils.html.remove_tags() and the removetags template filter "
"are deprecated. Consider using the bleach library instead.",
RemovedInDjango110Warning, stacklevel=3
)
tags = [re.escape(tag) for tag in tags.split()]
tags_re = '(%s)' % '|'.join(tags)
starttag_re = re.compile(r'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
endtag_re = re.compile('</%s>' % tags_re)
html = starttag_re.sub('', html)
html = endtag_re.sub('', html)
return html

remove_tags = allow_lazy(remove_tags, six.text_type)

def strip_spaces_between_tags(value):
"""Returns the given HTML with spaces between tags removed."""
return re.sub(r'>\s+<', '><', force_text(value))
strip_spaces_between_tags = allow_lazy(strip_spaces_between_tags, six.text_type)

def strip_entities(value):
"""Returns the given HTML with all entities (&something;) stripped."""
warnings.warn(
"django.utils.html.strip_entities() is deprecated.",
RemovedInDjango110Warning, stacklevel=2
)
return re.sub(r'&(?:\w+|#\d+);', '', force_text(value))
strip_entities = allow_lazy(strip_entities, six.text_type)

def smart_urlquote(url):
"Quotes a URL if it isn't already quoted."
def unquote_quote(segment):
segment = unquote(force_str(segment))
# Tilde is part of RFC3986 Unreserved Characters
# http://tools.ietf.org/html/rfc3986#section-2.3
# See also http://bugs.python.org/issue16285
segment = quote(segment, safe=RFC3986_SUBDELIMS + RFC3986_GENDELIMS + str('~'))
return force_text(segment)

# Handle IDN before quoting.
try:
scheme, netloc, path, query, fragment = urlsplit(url)
except ValueError:
# invalid IPv6 URL (normally square brackets in hostname part).
return unquote_quote(url)

try:
netloc = netloc.encode('idna').decode('ascii')  # IDN -> ACE
except UnicodeError:  # invalid domain part
return unquote_quote(url)

if query:
# Separately unquoting key/value, so as to not mix querystring separators
# included in query values. See #22267.
query_parts = [(unquote(force_str(q[0])), unquote(force_str(q[1])))
for q in parse_qsl(query, keep_blank_values=True)]
# urlencode will take care of quoting
query = urlencode(query_parts)

path = unquote_quote(path)
fragment = unquote_quote(fragment)

return urlunsplit((scheme, netloc, path, query, fragment))

def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
"""
Converts any URLs in text into clickable links.

Works on http://, https://, www. links, and also on links ending in one of
the original seven gTLDs (.com, .edu, .gov, .int, .mil, .net, and .org).
Links can have trailing punctuation (periods, commas, close-parens) and
leading punctuation (opening parens) and it'll still do the right thing.

If trim_url_limit is not None, the URLs in the link text longer than this
limit will be truncated to trim_url_limit-3 characters and appended with
an ellipsis.

If nofollow is True, the links will get a rel="nofollow" attribute.

If autoescape is True, the link text and URLs will be autoescaped.
"""
safe_input = isinstance(text, SafeData)

def trim_url(x, limit=trim_url_limit):
if limit is None or len(x) <= limit:
return x
return '%s...' % x[:max(0, limit - 3)]

def unescape(text, trail):
"""
If input URL is HTML-escaped, unescape it so as we can safely feed it to
smart_urlquote. For example:
http://example.com?x=1&amp;y=&lt;2&gt; => http://example.com?x=1&y=<2>
"""
unescaped = (text + trail).replace(
'&amp;', '&').replace('&lt;', '<').replace(
'&gt;', '>').replace('&quot;', '"').replace('&#39;', "'")
if trail and unescaped.endswith(trail):
# Remove trail for unescaped if it was not consumed by unescape
unescaped = unescaped[:-len(trail)]
elif trail == ';':
# Trail was consumed by unescape (as end-of-entity marker), move it to text
text += trail
trail = ''
return text, unescaped, trail

words = word_split_re.split(force_text(text))
for i, word in enumerate(words):
if '.' in word or '@' in word or ':' in word:
# Deal with punctuation.
lead, middle, trail = '', word, ''
for punctuation in TRAILING_PUNCTUATION:
if middle.endswith(punctuation):
middle = middle[:-len(punctuation)]
trail = punctuation + trail
for opening, closing in WRAPPING_PUNCTUATION:
if middle.startswith(opening):
middle = middle[len(opening):]
lead = lead + opening
# Keep parentheses at the end only if they're balanced.
if (middle.endswith(closing)
and middle.count(closing) == middle.count(opening) + 1):
middle = middle[:-len(closing)]
trail = closing + trail

# Make URL we want to point to.
url = None
nofollow_attr = ' rel="nofollow"' if nofollow else ''
if simple_url_re.match(middle):
middle, middle_unescaped, trail = unescape(middle, trail)
url = smart_urlquote(middle_unescaped)
elif simple_url_2_re.match(middle):
middle, middle_unescaped, trail = unescape(middle, trail)
url = smart_urlquote('http://%s' % middle_unescaped)
elif ':' not in middle and simple_email_re.match(middle):
local, domain = middle.rsplit('@', 1)
try:
domain = domain.encode('idna').decode('ascii')
except UnicodeError:
continue
url = 'mailto:%s@%s' % (local, domain)
nofollow_attr = ''

# Make link.
if url:
trimmed = trim_url(middle)
if autoescape and not safe_input:
lead, trail = escape(lead), escape(trail)
trimmed = escape(trimmed)
middle = '<a href="%s"%s>%s</a>' % (escape(url), nofollow_attr, trimmed)
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
else:
if safe_input:
words[i] = mark_safe(word)
elif autoescape:
words[i] = escape(word)
elif safe_input:
words[i] = mark_safe(word)
elif autoescape:
words[i] = escape(word)
return ''.join(words)
urlize = allow_lazy(urlize, six.text_type)

def avoid_wrapping(value):
"""
Avoid text wrapping in the middle of a phrase by adding non-breaking
spaces where there previously were normal spaces.
"""
return value.replace(" ", "\xa0")

[docs]def html_safe(klass):
"""
A decorator that defines the __html__ method. This helps non-Django
templates to detect classes whose __str__ methods return SafeText.
"""
if '__html__' in klass.__dict__:
raise ValueError(
"can't apply @html_safe to %s because it defines "
"__html__()." % klass.__name__
)
if six.PY2:
if '__unicode__' not in klass.__dict__:
raise ValueError(
"can't apply @html_safe to %s because it doesn't "
"define __unicode__()." % klass.__name__
)
klass_unicode = klass.__unicode__
klass.__unicode__ = lambda self: mark_safe(klass_unicode(self))
klass.__html__ = lambda self: unicode(self)  # NOQA: unicode undefined on PY3
else:
if '__str__' not in klass.__dict__:
raise ValueError(
"can't apply @html_safe to %s because it doesn't "
"define __str__()." % klass.__name__
)
klass_str = klass.__str__
klass.__str__ = lambda self: mark_safe(klass_str(self))
klass.__html__ = lambda self: str(self)
return klass

Source code for django.utils.datastructures

import copy
from collections import OrderedDict

from django.utils import six

class OrderedSet(object):
"""
A set which keeps the ordering of the inserted items.
Currently backs onto OrderedDict.
"""

def __init__(self, iterable=None):
self.dict = OrderedDict(((x, None) for x in iterable) if iterable else [])

def add(self, item):
self.dict[item] = None

def remove(self, item):
del self.dict[item]

def discard(self, item):
try:
self.remove(item)
except KeyError:
pass

def __iter__(self):
return iter(self.dict.keys())

def __contains__(self, item):
return item in self.dict

def __bool__(self):
return bool(self.dict)

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

def __len__(self):
return len(self.dict)

class MultiValueDictKeyError(KeyError):
pass

class MultiValueDict(dict):
"""
A subclass of dictionary customized to handle multiple values for the
same key.

>>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})
>>> d['name']
'Simon'
>>> d.getlist('name')
['Adrian', 'Simon']
>>> d.getlist('doesnotexist')
[]
>>> d.getlist('doesnotexist', ['Adrian', 'Simon'])
['Adrian', 'Simon']
>>> d.get('lastname', 'nonexistent')
'nonexistent'
>>> d.setlist('lastname', ['Holovaty', 'Willison'])

This class exists to solve the irritating problem raised by cgi.parse_qs,
which returns a list for every key, even though most Web forms submit
single name-value pairs.
"""
def __init__(self, key_to_list_mapping=()):
super(MultiValueDict, self).__init__(key_to_list_mapping)

def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__,
super(MultiValueDict, self).__repr__())

def __getitem__(self, key):
"""
Returns the last data value for this key, or [] if it's an empty list;
raises KeyError if not found.
"""
try:
list_ = super(MultiValueDict, self).__getitem__(key)
except KeyError:
raise MultiValueDictKeyError(repr(key))
try:
return list_[-1]
except IndexError:
return []

def __setitem__(self, key, value):
super(MultiValueDict, self).__setitem__(key, [value])

def __copy__(self):
return self.__class__([
(k, v[:])
for k, v in self.lists()
])

def __deepcopy__(self, memo=None):
if memo is None:
memo = {}
result = self.__class__()
memo[id(self)] = result
for key, value in dict.items(self):
dict.__setitem__(result, copy.deepcopy(key, memo),
copy.deepcopy(value, memo))
return result

def __getstate__(self):
obj_dict = self.__dict__.copy()
obj_dict['_data'] = {k: self.getlist(k) for k in self}
return obj_dict

def __setstate__(self, obj_dict):
data = obj_dict.pop('_data', {})
for k, v in data.items():
self.setlist(k, v)
self.__dict__.update(obj_dict)

def get(self, key, default=None):
"""
Returns the last data value for the passed key. If key doesn't exist
or value is an empty list, then default is returned.
"""
try:
val = self[key]
except KeyError:
return default
if val == []:
return default
return val

def getlist(self, key, default=None):
"""
Returns the list of values for the passed key. If key doesn't exist,
then a default value is returned.
"""
try:
return super(MultiValueDict, self).__getitem__(key)
except KeyError:
if default is None:
return []
return default

def setlist(self, key, list_):
super(MultiValueDict, self).__setitem__(key, list_)

def setdefault(self, key, default=None):
if key not in self:
self[key] = default
# Do not return default here because __setitem__() may store
# another value -- QueryDict.__setitem__() does. Look it up.
return self[key]

def setlistdefault(self, key, default_list=None):
if key not in self:
if default_list is None:
default_list = []
self.setlist(key, default_list)
# Do not return default_list here because setlist() may store
# another value -- QueryDict.setlist() does. Look it up.
return self.getlist(key)

def appendlist(self, key, value):
"""Appends an item to the internal list associated with key."""
self.setlistdefault(key).append(value)

def _iteritems(self):
"""
Yields (key, value) pairs, where value is the last item in the list
associated with the key.
"""
for key in self:
yield key, self[key]

def _iterlists(self):
"""Yields (key, list) pairs."""
return six.iteritems(super(MultiValueDict, self))

def _itervalues(self):
"""Yield the last value on every key list."""
for key in self:
yield self[key]

if six.PY3:
items = _iteritems
lists = _iterlists
values = _itervalues
else:
iteritems = _iteritems
iterlists = _iterlists
itervalues = _itervalues

def items(self):
return list(self.iteritems())

def lists(self):
return list(self.iterlists())

def values(self):
return list(self.itervalues())

def copy(self):
"""Returns a shallow copy of this object."""
return copy.copy(self)

def update(self, *args, **kwargs):
"""
update() extends rather than replaces existing key lists.
Also accepts keyword args.
"""
if len(args) > 1:
raise TypeError("update expected at most 1 arguments, got %d" % len(args))
if args:
other_dict = args[0]
if isinstance(other_dict, MultiValueDict):
for key, value_list in other_dict.lists():
self.setlistdefault(key).extend(value_list)
else:
try:
for key, value in other_dict.items():
self.setlistdefault(key).append(value)
except TypeError:
raise ValueError("MultiValueDict.update() takes either a MultiValueDict or dictionary")
for key, value in six.iteritems(kwargs):
self.setlistdefault(key).append(value)

def dict(self):
"""
Returns current object as a dict with singular values.
"""
return {key: self[key] for key in self}

class ImmutableList(tuple):
"""
A tuple-like object that raises useful errors when it is asked to mutate.

Example::

>>> a = ImmutableList(range(5), warning="You cannot mutate this.")
>>> a[3] = '4'
Traceback (most recent call last):
...
AttributeError: You cannot mutate this.
"""

def __new__(cls, *args, **kwargs):
if 'warning' in kwargs:
warning = kwargs['warning']
del kwargs['warning']
else:
warning = 'ImmutableList object is immutable.'
self = tuple.__new__(cls, *args, **kwargs)
self.warning = warning
return self

def complain(self, *wargs, **kwargs):
if isinstance(self.warning, Exception):
raise self.warning
else:
raise AttributeError(self.warning)

# All list mutation functions complain.
__delitem__ = complain
__delslice__ = complain
__iadd__ = complain
__imul__ = complain
__setitem__ = complain
__setslice__ = complain
append = complain
extend = complain
insert = complain
pop = complain
remove = complain
sort = complain
reverse = complain

class DictWrapper(dict):
"""
Wraps accesses to a dictionary so that certain values (those starting with
the specified prefix) are passed through a function before being returned.
The prefix is removed before looking up the real value.

Used by the SQL construction code to ensure that values are correctly
quoted before being used.
"""
def __init__(self, data, func, prefix):
super(DictWrapper, self).__init__(data)
self.func = func
self.prefix = prefix

def __getitem__(self, key):
"""
Retrieves the real value after stripping the prefix string (if
present). If the prefix is present, pass the value through self.func
before returning, otherwise return the raw value.
"""
if key.startswith(self.prefix):
use_func = True
key = key[len(self.prefix):]
else:
use_func = False
value = super(DictWrapper, self).__getitem__(key)
if use_func:
return self.func(value)
return value

Source code for django.utils.functional

import copy
import operator
from functools import total_ordering, wraps

from django.utils import six

# You can't trivially replace this with `functools.partial` because this binds
# to classes and returns bound instances, whereas functools.partial (on
# CPython) is a type and its instances don't bind.
def curry(_curried_func, *args, **kwargs):
def _curried(*moreargs, **morekwargs):
return _curried_func(*(args + moreargs), **dict(kwargs, **morekwargs))
return _curried

[docs]class cached_property(object):
"""
Decorator that converts a method with a single self argument into a
property cached on the instance.

Optional ``name`` argument allows you to make cached properties of other
methods. (e.g.  url = cached_property(get_absolute_url, name='url') )
"""
def __init__(self, func, name=None):
self.func = func
self.__doc__ = getattr(func, '__doc__')
self.name = name or func.__name__

def __get__(self, instance, type=None):
if instance is None:
return self
res = instance.__dict__[self.name] = self.func(instance)
return res

class Promise(object):
"""
This is just a base class for the proxy class created in
the closure of the lazy function. It can be used to recognize
promises in code.
"""
pass

def lazy(func, *resultclasses):
"""
Turns any callable into a lazy evaluated callable. You need to give result
classes or types -- at least one is needed so that the automatic forcing of
the lazy evaluation code is triggered. Results are not memoized; the
function is evaluated on every access.
"""

@total_ordering
class __proxy__(Promise):
"""
Encapsulate a function call and act as a proxy for methods that are
called on the result of that function. The function is not evaluated
until one of the methods on the result is called.
"""
__prepared = False

def __init__(self, args, kw):
self.__args = args
self.__kw = kw
if not self.__prepared:
self.__prepare_class__()
self.__prepared = True

def __reduce__(self):
return (
_lazy_proxy_unpickle,
(func, self.__args, self.__kw) + resultclasses
)

@classmethod
def __prepare_class__(cls):
for resultclass in resultclasses:
for type_ in resultclass.mro():
for method_name in type_.__dict__.keys():
# All __promise__ return the same wrapper method, they
# look up the correct implementation when called.
if hasattr(cls, method_name):
continue
meth = cls.__promise__(method_name)
setattr(cls, method_name, meth)
cls._delegate_bytes = bytes in resultclasses
cls._delegate_text = six.text_type in resultclasses
assert not (cls._delegate_bytes and cls._delegate_text), (
"Cannot call lazy() with both bytes and text return types.")
if cls._delegate_text:
if six.PY3:
cls.__str__ = cls.__text_cast
else:
cls.__unicode__ = cls.__text_cast
cls.__str__ = cls.__bytes_cast_encoded
elif cls._delegate_bytes:
if six.PY3:
cls.__bytes__ = cls.__bytes_cast
else:
cls.__str__ = cls.__bytes_cast

@classmethod
def __promise__(cls, method_name):
# Builds a wrapper around some magic method
def __wrapper__(self, *args, **kw):
# Automatically triggers the evaluation of a lazy value and
# applies the given magic method of the result type.
res = func(*self.__args, **self.__kw)
return getattr(res, method_name)(*args, **kw)
return __wrapper__

def __text_cast(self):
return func(*self.__args, **self.__kw)

def __bytes_cast(self):
return bytes(func(*self.__args, **self.__kw))

def __bytes_cast_encoded(self):
return func(*self.__args, **self.__kw).encode('utf-8')

def __cast(self):
if self._delegate_bytes:
return self.__bytes_cast()
elif self._delegate_text:
return self.__text_cast()
else:
return func(*self.__args, **self.__kw)

def __str__(self):
# object defines __str__(), so __prepare_class__() won't overload
# a __str__() method from the proxied class.
return str(self.__cast())

def __ne__(self, other):
if isinstance(other, Promise):
other = other.__cast()
return self.__cast() != other

def __eq__(self, other):
if isinstance(other, Promise):
other = other.__cast()
return self.__cast() == other

def __lt__(self, other):
if isinstance(other, Promise):
other = other.__cast()
return self.__cast() < other

def __hash__(self):
return hash(self.__cast())

def __mod__(self, rhs):
if self._delegate_bytes and six.PY2:
return bytes(self) % rhs
elif self._delegate_text:
return six.text_type(self) % rhs
return self.__cast() % rhs

def __deepcopy__(self, memo):
# Instances of this class are effectively immutable. It's just a
# collection of functions. So we don't need to do anything
# complicated for copying.
memo[id(self)] = self
return self

@wraps(func)
def __wrapper__(*args, **kw):
# Creates the proxy object, instead of the actual value.
return __proxy__(args, kw)

return __wrapper__

def _lazy_proxy_unpickle(func, args, kwargs, *resultclasses):
return lazy(func, *resultclasses)(*args, **kwargs)

[docs]def allow_lazy(func, *resultclasses):
"""
A decorator that allows a function to be called with one or more lazy
arguments. If none of the args are lazy, the function is evaluated
immediately, otherwise a __proxy__ is returned that will evaluate the
function when needed.
"""
lazy_func = lazy(func, *resultclasses)

@wraps(func)
def wrapper(*args, **kwargs):
for arg in list(args) + list(kwargs.values()):
if isinstance(arg, Promise):
break
else:
return func(*args, **kwargs)
return lazy_func(*args, **kwargs)
return wrapper

empty = object()

def new_method_proxy(func):
def inner(self, *args):
if self._wrapped is empty:
self._setup()
return func(self._wrapped, *args)
return inner

class LazyObject(object):
"""
A wrapper for another class that can be used to delay instantiation of the
wrapped class.

By subclassing, you have the opportunity to intercept and alter the
instantiation. If you don't need to do that, use SimpleLazyObject.
"""

# Avoid infinite recursion when tracing __init__ (#19456).
_wrapped = None

def __init__(self):
# Note: if a subclass overrides __init__(), it will likely need to
# override __copy__() and __deepcopy__() as well.
self._wrapped = empty

__getattr__ = new_method_proxy(getattr)

def __setattr__(self, name, value):
if name == "_wrapped":
# Assign to __dict__ to avoid infinite __setattr__ loops.
self.__dict__["_wrapped"] = value
else:
if self._wrapped is empty:
self._setup()
setattr(self._wrapped, name, value)

def __delattr__(self, name):
if name == "_wrapped":
raise TypeError("can't delete _wrapped.")
if self._wrapped is empty:
self._setup()
delattr(self._wrapped, name)

def _setup(self):
"""
Must be implemented by subclasses to initialize the wrapped object.
"""
raise NotImplementedError('subclasses of LazyObject must provide a _setup() method')

# Because we have messed with __class__ below, we confuse pickle as to what
# class we are pickling. We're going to have to initialize the wrapped
# object to successfully pickle it, so we might as well just pickle the
# wrapped object since they're supposed to act the same way.
#
# Unfortunately, if we try to simply act like the wrapped object, the ruse
# will break down when pickle gets our id(). Thus we end up with pickle
# thinking, in effect, that we are a distinct object from the wrapped
# object, but with the same __dict__. This can cause problems (see #25389).
#
# So instead, we define our own __reduce__ method and custom unpickler. We
# pickle the wrapped object as the unpickler's argument, so that pickle
# will pickle it normally, and then the unpickler simply returns its
# argument.
def __reduce__(self):
if self._wrapped is empty:
self._setup()
return (unpickle_lazyobject, (self._wrapped,))

# We have to explicitly override __getstate__ so that older versions of
# pickle don't try to pickle the __dict__ (which in the case of a
# SimpleLazyObject may contain a lambda). The value will end up being
# ignored by our __reduce__ and custom unpickler.
def __getstate__(self):
return {}

def __copy__(self):
if self._wrapped is empty:
# If uninitialized, copy the wrapper. Use type(self), not
# self.__class__, because the latter is proxied.
return type(self)()
else:
# If initialized, return a copy of the wrapped object.
return copy.copy(self._wrapped)

def __deepcopy__(self, memo):
if self._wrapped is empty:
# We have to use type(self), not self.__class__, because the
# latter is proxied.
result = type(self)()
memo[id(self)] = result
return result
return copy.deepcopy(self._wrapped, memo)

if six.PY3:
__bytes__ = new_method_proxy(bytes)
__str__ = new_method_proxy(str)
__bool__ = new_method_proxy(bool)
else:
__str__ = new_method_proxy(str)
__unicode__ = new_method_proxy(unicode)  # NOQA: unicode undefined on PY3
__nonzero__ = new_method_proxy(bool)

# Introspection support
__dir__ = new_method_proxy(dir)

# Need to pretend to be the wrapped class, for the sake of objects that
# care about this (especially in equality tests)
__class__ = property(new_method_proxy(operator.attrgetter("__class__")))
__eq__ = new_method_proxy(operator.eq)
__ne__ = new_method_proxy(operator.ne)
__hash__ = new_method_proxy(hash)

# List/Tuple/Dictionary methods support
__getitem__ = new_method_proxy(operator.getitem)
__setitem__ = new_method_proxy(operator.setitem)
__delitem__ = new_method_proxy(operator.delitem)
__iter__ = new_method_proxy(iter)
__len__ = new_method_proxy(len)
__contains__ = new_method_proxy(operator.contains)

def unpickle_lazyobject(wrapped):
"""
Used to unpickle lazy objects. Just return its argument, which will be the
wrapped object.
"""
return wrapped
unpickle_lazyobject.__safe_for_unpickling__ = True

class SimpleLazyObject(LazyObject):
"""
A lazy object initialized from any function.

Designed for compound objects of unknown type. For builtins or objects of
known type, use django.utils.functional.lazy.
"""
def __init__(self, func):
"""
Pass in a callable that returns the object to be wrapped.

If copies are made of the resulting SimpleLazyObject, which can happen
in various circumstances within Django, then you must ensure that the
callable can be safely run more than once and will return the same
value.
"""
self.__dict__['_setupfunc'] = func
super(SimpleLazyObject, self).__init__()

def _setup(self):
self._wrapped = self._setupfunc()

# Return a meaningful representation of the lazy object for debugging
# without evaluating the wrapped object.
def __repr__(self):
if self._wrapped is empty:
repr_attr = self._setupfunc
else:
repr_attr = self._wrapped
return '<%s: %r>' % (type(self).__name__, repr_attr)

def __copy__(self):
if self._wrapped is empty:
# If uninitialized, copy the wrapper. Use SimpleLazyObject, not
# self.__class__, because the latter is proxied.
return SimpleLazyObject(self._setupfunc)
else:
# If initialized, return a copy of the wrapped object.
return copy.copy(self._wrapped)

def __deepcopy__(self, memo):
if self._wrapped is empty:
# We have to use SimpleLazyObject, not self.__class__, because the
# latter is proxied.
result = SimpleLazyObject(self._setupfunc)
memo[id(self)] = result
return result
return copy.deepcopy(self._wrapped, memo)

class lazy_property(property):
"""
A property that works with subclasses by wrapping the decorated
functions of the base class.
"""
def __new__(cls, fget=None, fset=None, fdel=None, doc=None):
if fget is not None:
@wraps(fget)
def fget(instance, instance_type=None, name=fget.__name__):
return getattr(instance, name)()
if fset is not None:
@wraps(fset)
def fset(instance, value, name=fset.__name__):
return getattr(instance, name)(value)
if fdel is not None:
@wraps(fdel)
def fdel(instance, name=fdel.__name__):
return getattr(instance, name)()
return property(fget, fset, fdel, doc)

def partition(predicate, values):
"""
Splits the values into two sets, based on the return value of the function
(True/False). e.g.:

>>> partition(lambda x: x > 3, range(5))
[0, 1, 2, 3], [4]
"""
results = ([], [])
for item in values:
results[predicate(item)].append(item)
return results

Source code for django.utils.http

from __future__ import unicode_literals

import base64
import calendar
import datetime
import re
import sys
import unicodedata
from binascii import Error as BinasciiError
from email.utils import formatdate

from django.utils import six
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_bytes, force_str, force_text
from django.utils.functional import allow_lazy
from django.utils.six.moves.urllib.parse import (
quote, quote_plus, unquote, unquote_plus, urlencode as original_urlencode,
urlparse,
)

ETAG_MATCH = re.compile(r'(?:W/)?"((?:\\.|[^"])*)"')

MONTHS = 'jan feb mar apr may jun jul aug sep oct nov dec'.split()
__D = r'(?P<day>\d{2})'
__D2 = r'(?P<day>[ \d]\d)'
__M = r'(?P<mon>\w{3})'
__Y = r'(?P<year>\d{4})'
__Y2 = r'(?P<year>\d{2})'
__T = r'(?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})'
RFC1123_DATE = re.compile(r'^\w{3}, %s %s %s %s GMT$' % (__D, __M, __Y, __T))
RFC850_DATE = re.compile(r'^\w{6,9}, %s-%s-%s %s GMT$' % (__D, __M, __Y2, __T))
ASCTIME_DATE = re.compile(r'^\w{3} %s %s %s %s$' % (__M, __D2, __T, __Y))

RFC3986_GENDELIMS = str(":/?#[]@")
RFC3986_SUBDELIMS = str("!$&'()*+,;=")

PROTOCOL_TO_PORT = {
'http': 80,
'https': 443,
}

[docs]def urlquote(url, safe='/'):
"""
A version of Python's urllib.quote() function that can operate on unicode
strings. The url is first UTF-8 encoded before quoting. The returned string
can safely be used as part of an argument to a subsequent iri_to_uri() call
without double-quoting occurring.
"""
return force_text(quote(force_str(url), force_str(safe)))

urlquote = allow_lazy(urlquote, six.text_type)

[docs]def urlquote_plus(url, safe=''):
"""
A version of Python's urllib.quote_plus() function that can operate on
unicode strings. The url is first UTF-8 encoded before quoting. The
returned string can safely be used as part of an argument to a subsequent
iri_to_uri() call without double-quoting occurring.
"""
return force_text(quote_plus(force_str(url), force_str(safe)))

urlquote_plus = allow_lazy(urlquote_plus, six.text_type)

def urlunquote(quoted_url):
"""
A wrapper for Python's urllib.unquote() function that can operate on
the result of django.utils.http.urlquote().
"""
return force_text(unquote(force_str(quoted_url)))
urlunquote = allow_lazy(urlunquote, six.text_type)

def urlunquote_plus(quoted_url):
"""
A wrapper for Python's urllib.unquote_plus() function that can operate on
the result of django.utils.http.urlquote_plus().
"""
return force_text(unquote_plus(force_str(quoted_url)))
urlunquote_plus = allow_lazy(urlunquote_plus, six.text_type)

[docs]def urlencode(query, doseq=0):
"""
A version of Python's urllib.urlencode() function that can operate on
unicode strings. The parameters are first cast to UTF-8 encoded strings and
then encoded as per normal.
"""
if isinstance(query, MultiValueDict):
query = query.lists()
elif hasattr(query, 'items'):
query = query.items()
return original_urlencode(
[(force_str(k),
[force_str(i) for i in v] if isinstance(v, (list, tuple)) else force_str(v))
for k, v in query],
doseq)

[docs]def cookie_date(epoch_seconds=None):
"""
Formats the time to ensure compatibility with Netscape's cookie standard.

Accepts a floating point number expressed in seconds since the epoch, in
UTC - such as that outputted by time.time(). If set to None, defaults to
the current time.

Outputs a string in the format 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'.
"""
rfcdate = formatdate(epoch_seconds)
return '%s-%s-%s GMT' % (rfcdate[:7], rfcdate[8:11], rfcdate[12:25])

[docs]def http_date(epoch_seconds=None):
"""
Formats the time to match the RFC1123 date format as specified by HTTP
RFC7231 section 7.1.1.1.

Accepts a floating point number expressed in seconds since the epoch, in
UTC - such as that outputted by time.time(). If set to None, defaults to
the current time.

Outputs a string in the format 'Wdy, DD Mon YYYY HH:MM:SS GMT'.
"""
return formatdate(epoch_seconds, usegmt=True)

def parse_http_date(date):
"""
Parses a date format as specified by HTTP RFC7231 section 7.1.1.1.

The three formats allowed by the RFC are accepted, even if only the first
one is still in widespread use.

Returns an integer expressed in seconds since the epoch, in UTC.
"""
# emails.Util.parsedate does the job for RFC1123 dates; unfortunately
# RFC7231 makes it mandatory to support RFC850 dates too. So we roll
# our own RFC-compliant parsing.
for regex in RFC1123_DATE, RFC850_DATE, ASCTIME_DATE:
m = regex.match(date)
if m is not None:
break
else:
raise ValueError("%r is not in a valid HTTP date format" % date)
try:
year = int(m.group('year'))
if year < 100:
if year < 70:
year += 2000
else:
year += 1900
month = MONTHS.index(m.group('mon').lower()) + 1
day = int(m.group('day'))
hour = int(m.group('hour'))
min = int(m.group('min'))
sec = int(m.group('sec'))
result = datetime.datetime(year, month, day, hour, min, sec)
return calendar.timegm(result.utctimetuple())
except Exception:
six.reraise(ValueError, ValueError("%r is not a valid date" % date), sys.exc_info()[2])

def parse_http_date_safe(date):
"""
Same as parse_http_date, but returns None if the input is invalid.
"""
try:
return parse_http_date(date)
except Exception:
pass

# Base 36 functions: useful for generating compact URLs

[docs]def base36_to_int(s):
"""
Converts a base 36 string to an ``int``. Raises ``ValueError` if the
input won't fit into an int.
"""
# To prevent overconsumption of server resources, reject any
# base36 string that is long than 13 base36 digits (13 digits
# is sufficient to base36-encode any 64-bit integer)
if len(s) > 13:
raise ValueError("Base36 input too large")
value = int(s, 36)
# ... then do a final check that the value will fit into an int to avoid
# returning a long (#15067). The long type was removed in Python 3.
if six.PY2 and value > sys.maxint:
raise ValueError("Base36 input too large")
return value

[docs]def int_to_base36(i):
"""
Converts an integer to a base36 string
"""
char_set = '0123456789abcdefghijklmnopqrstuvwxyz'
if i < 0:
raise ValueError("Negative base36 conversion input.")
if six.PY2:
if not isinstance(i, six.integer_types):
raise TypeError("Non-integer base36 conversion input.")
if i > sys.maxint:
raise ValueError("Base36 conversion input too large.")
if i < 36:
return char_set[i]
b36 = ''
while i != 0:
i, n = divmod(i, 36)
b36 = char_set[n] + b36
return b36

[docs]def urlsafe_base64_encode(s):
"""
Encodes a bytestring in base64 for use in URLs, stripping any trailing
equal signs.
"""
return base64.urlsafe_b64encode(s).rstrip(b'\n=')

[docs]def urlsafe_base64_decode(s):
"""
Decodes a base64 encoded string, adding back any trailing equal signs that
might have been stripped.
"""
s = force_bytes(s)
try:
return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'='))
except (LookupError, BinasciiError) as e:
raise ValueError(e)

def parse_etags(etag_str):
"""
Parses a string with one or several etags passed in If-None-Match and
If-Match headers by the rules in RFC 2616. Returns a list of etags
without surrounding double quotes (") and unescaped from \<CHAR>.
"""
etags = ETAG_MATCH.findall(etag_str)
if not etags:
# etag_str has wrong format, treat it as an opaque string then
return [etag_str]
etags = [e.encode('ascii').decode('unicode_escape') for e in etags]
return etags

def quote_etag(etag):
"""
Wraps a string in double quotes escaping contents as necessary.
"""
return '"%s"' % etag.replace('\\', '\\\\').replace('"', '\\"')

def unquote_etag(etag):
"""
Unquote an ETag string; i.e. revert quote_etag().
"""
return etag.strip('"').replace('\\"', '"').replace('\\\\', '\\') if etag else etag

def is_same_domain(host, pattern):
"""
Return ``True`` if the host is either an exact match or a match
to the wildcard pattern.

Any pattern beginning with a period matches a domain and all of its
subdomains. (e.g. ``.example.com`` matches ``example.com`` and
``foo.example.com``). Anything else is an exact string match.
"""
if not pattern:
return False

pattern = pattern.lower()
return (
pattern[0] == '.' and (host.endswith(pattern) or host == pattern[1:]) or
pattern == host
)

def is_safe_url(url, host=None):
"""
Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
a different host and uses a safe scheme).

Always returns ``False`` on an empty url.
"""
if url is not None:
url = url.strip()
if not url:
return False
if six.PY2:
try:
url = force_text(url)
except UnicodeDecodeError:
return False
# Chrome treats \ completely as / in paths but it could be part of some
# basic auth credentials so we need to check both URLs.
return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host)

def _is_safe_url(url, host):
# Chrome considers any URL with more than two slashes to be absolute, but
# urlparse is not so flexible. Treat any url with three slashes as unsafe.
if url.startswith('///'):
return False
url_info = urlparse(url)
# Forbid URLs like http:///example.com - with a scheme, but without a hostname.
# In that URL, example.com is not the hostname but, a path component. However,
# Chrome will still consider example.com to be the hostname, so we must not
# allow this syntax.
if not url_info.netloc and url_info.scheme:
return False
# Forbid URLs that start with control characters. Some browsers (like
# Chrome) ignore quite a few control characters at the start of a
# URL and might consider the URL as scheme relative.
if unicodedata.category(url[0])[0] == 'C':
return False
return ((not url_info.netloc or url_info.netloc == host) and
(not url_info.scheme or url_info.scheme in ['http', 'https']))

Source code for django.utils.timezone

"""
Timezone-related classes and functions.

This module uses pytz when it's available and fallbacks when it isn't.
"""

import sys
import time as _time
from datetime import datetime, timedelta, tzinfo
from threading import local

from django.conf import settings
from django.utils import lru_cache, six
from django.utils.decorators import ContextDecorator

try:
import pytz
except ImportError:
pytz = None

__all__ = [
'utc', 'get_fixed_timezone',
'get_default_timezone', 'get_default_timezone_name',
'get_current_timezone', 'get_current_timezone_name',
'activate', 'deactivate', 'override',
'localtime', 'now',
'is_aware', 'is_naive', 'make_aware', 'make_naive',
]

# UTC and local time zones

ZERO = timedelta(0)

class UTC(tzinfo):
"""
UTC implementation taken from Python's docs.

Used only when pytz isn't available.
"""

def __repr__(self):
return "<UTC>"

def utcoffset(self, dt):
return ZERO

def tzname(self, dt):
return "UTC"

def dst(self, dt):
return ZERO

[docs]class FixedOffset(tzinfo):
"""
Fixed offset in minutes east from UTC. Taken from Python's docs.

Kept as close as possible to the reference version. __init__ was changed
to make its arguments optional, according to Python's requirement that
tzinfo subclasses can be instantiated without arguments.
"""

def __init__(self, offset=None, name=None):
if offset is not None:
self.__offset = timedelta(minutes=offset)
if name is not None:
self.__name = name

def utcoffset(self, dt):
return self.__offset

def tzname(self, dt):
return self.__name

def dst(self, dt):
return ZERO

class ReferenceLocalTimezone(tzinfo):
"""
Local time. Taken from Python's docs.

Used only when pytz isn't available, and most likely inaccurate. If you're
having trouble with this class, don't waste your time, just install pytz.

Kept as close as possible to the reference version. __init__ was added to
delay the computation of STDOFFSET, DSTOFFSET and DSTDIFF which is
performed at import time in the example.

Subclasses contain further improvements.
"""

def __init__(self):
self.STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
self.DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
self.DSTOFFSET = self.STDOFFSET
self.DSTDIFF = self.DSTOFFSET - self.STDOFFSET
tzinfo.__init__(self)

def utcoffset(self, dt):
if self._isdst(dt):
return self.DSTOFFSET
else:
return self.STDOFFSET

def dst(self, dt):
if self._isdst(dt):
return self.DSTDIFF
else:
return ZERO

def tzname(self, dt):
return _time.tzname[self._isdst(dt)]

def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0

class LocalTimezone(ReferenceLocalTimezone):
"""
Slightly improved local time implementation focusing on correctness.

It still crashes on dates before 1970 or after 2038, but at least the
error message is helpful.
"""

def tzname(self, dt):
is_dst = False if dt is None else self._isdst(dt)
return _time.tzname[is_dst]

def _isdst(self, dt):
try:
return super(LocalTimezone, self)._isdst(dt)
except (OverflowError, ValueError) as exc:
exc_type = type(exc)
exc_value = exc_type(
"Unsupported value: %r. You should install pytz." % dt)
exc_value.__cause__ = exc
six.reraise(exc_type, exc_value, sys.exc_info()[2])

utc = pytz.utc if pytz else UTC()
"""UTC time zone as a tzinfo instance."""

[docs]def get_fixed_timezone(offset):
"""
Returns a tzinfo instance with a fixed offset from UTC.
"""
if isinstance(offset, timedelta):
offset = offset.seconds // 60
sign = '-' if offset < 0 else '+'
hhmm = '%02d%02d' % divmod(abs(offset), 60)
name = sign + hhmm
return FixedOffset(offset, name)

# In order to avoid accessing settings at compile time,
# wrap the logic in a function and cache the result.
@lru_cache.lru_cache()

[docs]def get_default_timezone():
"""
Returns the default time zone as a tzinfo instance.

This is the time zone defined by settings.TIME_ZONE.
"""
if isinstance(settings.TIME_ZONE, six.string_types) and pytz is not None:
return pytz.timezone(settings.TIME_ZONE)
else:
# This relies on os.environ['TZ'] being set to settings.TIME_ZONE.
return LocalTimezone()

# This function exists for consistency with get_current_timezone_name

[docs]def get_default_timezone_name():
"""
Returns the name of the default time zone.
"""
return _get_timezone_name(get_default_timezone())

_active = local()

[docs]def get_current_timezone():
"""
Returns the currently active time zone as a tzinfo instance.
"""
return getattr(_active, "value", get_default_timezone())

[docs]def get_current_timezone_name():
"""
Returns the name of the currently active time zone.
"""
return _get_timezone_name(get_current_timezone())

def _get_timezone_name(timezone):
"""
Returns the name of ``timezone``.
"""
try:
# for pytz timezones
return timezone.zone
except AttributeError:
# for regular tzinfo objects
return timezone.tzname(None)

# Timezone selection functions.

# These functions don't change os.environ['TZ'] and call time.tzset()
# because it isn't thread safe.

[docs]def activate(timezone):
"""
Sets the time zone for the current thread.

The ``timezone`` argument must be an instance of a tzinfo subclass or a
time zone name. If it is a time zone name, pytz is required.
"""
if isinstance(timezone, tzinfo):
_active.value = timezone
elif isinstance(timezone, six.string_types) and pytz is not None:
_active.value = pytz.timezone(timezone)
else:
raise ValueError("Invalid timezone: %r" % timezone)

[docs]def deactivate():
"""
Unsets the time zone for the current thread.

Django will then use the time zone defined by settings.TIME_ZONE.
"""
if hasattr(_active, "value"):
del _active.value

[docs]class override(ContextDecorator):
"""
Temporarily set the time zone for the current thread.

This is a context manager that uses ``~django.utils.timezone.activate()``
to set the timezone on entry, and restores the previously active timezone
on exit.

The ``timezone`` argument must be an instance of a ``tzinfo`` subclass, a
time zone name, or ``None``. If is it a time zone name, pytz is required.
If it is ``None``, Django enables the default time zone.
"""
def __init__(self, timezone):
self.timezone = timezone

def __enter__(self):
self.old_timezone = getattr(_active, 'value', None)
if self.timezone is None:
deactivate()
else:
activate(self.timezone)

def __exit__(self, exc_type, exc_value, traceback):
if self.old_timezone is None:
deactivate()
else:
_active.value = self.old_timezone

# Templates

def template_localtime(value, use_tz=None):
"""
Checks if value is a datetime and converts it to local time if necessary.

If use_tz is provided and is not None, that will force the value to
be converted (or not), overriding the value of settings.USE_TZ.

This function is designed for use by the template engine.
"""
should_convert = (isinstance(value, datetime)
and (settings.USE_TZ if use_tz is None else use_tz)
and not is_naive(value)
and getattr(value, 'convert_to_local_time', True))
return localtime(value) if should_convert else value

# Utilities

[docs]def localtime(value, timezone=None):
"""
Converts an aware datetime.datetime to local time.

Local time is defined by the current time zone, unless another time zone
is specified.
"""
if timezone is None:
timezone = get_current_timezone()
# If `value` is naive, astimezone() will raise a ValueError,
# so we don't need to perform a redundant check.
value = value.astimezone(timezone)
if hasattr(timezone, 'normalize'):
# This method is available for pytz time zones.
value = timezone.normalize(value)
return value

[docs]def now():
"""
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ.
"""
if settings.USE_TZ:
# timeit shows that datetime.now(tz=utc) is 24% slower
return datetime.utcnow().replace(tzinfo=utc)
else:
return datetime.now()

# By design, these four functions don't perform any checks on their arguments.
# The caller should ensure that they don't receive an invalid value like None.

[docs]def is_aware(value):
"""
Determines if a given datetime.datetime is aware.

The concept is defined in Python's docs:
http://docs.python.org/library/datetime.html#datetime.tzinfo

Assuming value.tzinfo is either None or a proper datetime.tzinfo,
value.utcoffset() implements the appropriate logic.
"""
return value.utcoffset() is not None

[docs]def is_naive(value):
"""
Determines if a given datetime.datetime is naive.

The concept is defined in Python's docs:
http://docs.python.org/library/datetime.html#datetime.tzinfo

Assuming value.tzinfo is either None or a proper datetime.tzinfo,
value.utcoffset() implements the appropriate logic.
"""
return value.utcoffset() is None

[docs]def make_aware(value, timezone=None, is_dst=None):
"""
Makes a naive datetime.datetime in a given time zone aware.
"""
if timezone is None:
timezone = get_current_timezone()
if hasattr(timezone, 'localize'):
# This method is available for pytz time zones.
return timezone.localize(value, is_dst=is_dst)
else:
# Check that we won't overwrite the timezone of an aware datetime.
if is_aware(value):
raise ValueError(
"make_aware expects a naive datetime, got %s" % value)
# This may be wrong around DST changes!
return value.replace(tzinfo=timezone)

[docs]def make_naive(value, timezone=None):
"""
Makes an aware datetime.datetime naive in a given time zone.
"""
if timezone is None:
timezone = get_current_timezone()
# If `value` is naive, astimezone() will raise a ValueError,
# so we don't need to perform a redundant check.
value = value.astimezone(timezone)
if hasattr(timezone, 'normalize'):
# This method is available for pytz time zones.
value = timezone.normalize(value)
return value.replace(tzinfo=None)

Source code for django.utils.dateparse

"""Functions to parse datetime objects."""

# We're using regular expressions rather than time.strptime because:
# - They provide both validation and parsing.
# - They're more flexible for datetimes.
# - The date/datetime/time constructors produce friendlier error messages.

import datetime
import re

from django.utils import six
from django.utils.timezone import get_fixed_timezone, utc

date_re = re.compile(
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$'
)

time_re = re.compile(
r'(?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
)

datetime_re = re.compile(
r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})'
r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})'
r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?'
r'(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$'
)

standard_duration_re = re.compile(
r'^'
r'(?:(?P<days>-?\d+) (days?, )?)?'
r'((?:(?P<hours>\d+):)(?=\d+:\d+))?'
r'(?:(?P<minutes>\d+):)?'
r'(?P<seconds>\d+)'
r'(?:\.(?P<microseconds>\d{1,6})\d{0,6})?'
r'$'
)

# Support the sections of ISO 8601 date representation that are accepted by
# timedelta
iso8601_duration_re = re.compile(
r'^P'
r'(?:(?P<days>\d+(.\d+)?)D)?'
r'(?:T'
r'(?:(?P<hours>\d+(.\d+)?)H)?'
r'(?:(?P<minutes>\d+(.\d+)?)M)?'
r'(?:(?P<seconds>\d+(.\d+)?)S)?'
r')?'
r'$'
)

[docs]def parse_date(value):
"""Parses a string and return a datetime.date.

Raises ValueError if the input is well formatted but not a valid date.
Returns None if the input isn't well formatted.
"""
match = date_re.match(value)
if match:
kw = {k: int(v) for k, v in six.iteritems(match.groupdict())}
return datetime.date(**kw)

[docs]def parse_time(value):
"""Parses a string and return a datetime.time.

This function doesn't support time zone offsets.

Raises ValueError if the input is well formatted but not a valid time.
Returns None if the input isn't well formatted, in particular if it
contains an offset.
"""
match = time_re.match(value)
if match:
kw = match.groupdict()
if kw['microsecond']:
kw['microsecond'] = kw['microsecond'].ljust(6, '0')
kw = {k: int(v) for k, v in six.iteritems(kw) if v is not None}
return datetime.time(**kw)

[docs]def parse_datetime(value):
"""Parses a string and return a datetime.datetime.

This function supports time zone offsets. When the input contains one,
the output uses a timezone with a fixed offset from UTC.

Raises ValueError if the input is well formatted but not a valid datetime.
Returns None if the input isn't well formatted.
"""
match = datetime_re.match(value)
if match:
kw = match.groupdict()
if kw['microsecond']:
kw['microsecond'] = kw['microsecond'].ljust(6, '0')
tzinfo = kw.pop('tzinfo')
if tzinfo == 'Z':
tzinfo = utc
elif tzinfo is not None:
offset_mins = int(tzinfo[-2:]) if len(tzinfo) > 3 else 0
offset = 60 * int(tzinfo[1:3]) + offset_mins
if tzinfo[0] == '-':
offset = -offset
tzinfo = get_fixed_timezone(offset)
kw = {k: int(v) for k, v in six.iteritems(kw) if v is not None}
kw['tzinfo'] = tzinfo
return datetime.datetime(**kw)

[docs]def parse_duration(value):
"""Parses a duration string and returns a datetime.timedelta.

The preferred format for durations in Django is '%d %H:%M:%S.%f'.

Also supports ISO 8601 representation.
"""
match = standard_duration_re.match(value)
if not match:
match = iso8601_duration_re.match(value)
if match:
kw = match.groupdict()
if kw.get('microseconds'):
kw['microseconds'] = kw['microseconds'].ljust(6, '0')
kw = {k: float(v) for k, v in six.iteritems(kw) if v is not None}
return datetime.timedelta(**kw)

Source code for django.utils.cache

"""
This module contains helper functions for controlling caching. It does so by
managing the "Vary" header of responses. It includes functions to patch the
header of response objects directly and decorators that change functions to do
that header-patching themselves.

For information on the Vary header, see:

https://tools.ietf.org/html/rfc7231#section-7.1.4

Essentially, the "Vary" HTTP header defines which headers a cache should take
into account when building its cache key. Requests with the same path but
different header content for headers named in "Vary" need to get different
cache keys to prevent delivery of wrong content.

An example: i18n middleware would need to distinguish caches by the
"Accept-language" header.
"""
from __future__ import unicode_literals

import hashlib
import logging
import re
import time

from django.conf import settings
from django.core.cache import caches
from django.http import HttpResponse, HttpResponseNotModified
from django.utils.encoding import force_bytes, force_text, iri_to_uri
from django.utils.http import (
http_date, parse_etags, parse_http_date_safe, quote_etag,
)
from django.utils.timezone import get_current_timezone_name
from django.utils.translation import get_language

cc_delim_re = re.compile(r'\s*,\s*')

logger = logging.getLogger('django.request')

[docs]def patch_cache_control(response, **kwargs):
"""
This function patches the Cache-Control header by adding all
keyword arguments to it. The transformation is as follows:

* All keyword parameter names are turned to lowercase, and underscores
are converted to hyphens.
* If the value of a parameter is True (exactly True, not just a
true value), only the parameter name is added to the header.
* All other parameters are added with their value, after applying
str() to it.
"""
def dictitem(s):
t = s.split('=', 1)
if len(t) > 1:
return (t[0].lower(), t[1])
else:
return (t[0].lower(), True)

def dictvalue(t):
if t[1] is True:
return t[0]
else:
return '%s=%s' % (t[0], t[1])

if response.has_header('Cache-Control'):
cc = cc_delim_re.split(response['Cache-Control'])
cc = dict(dictitem(el) for el in cc)
else:
cc = {}

# If there's already a max-age header but we're being asked to set a new
# max-age, use the minimum of the two ages. In practice this happens when
# a decorator and a piece of middleware both operate on a given view.
if 'max-age' in cc and 'max_age' in kwargs:
kwargs['max_age'] = min(int(cc['max-age']), kwargs['max_age'])

# Allow overriding private caching and vice versa
if 'private' in cc and 'public' in kwargs:
del cc['private']
elif 'public' in cc and 'private' in kwargs:
del cc['public']

for (k, v) in kwargs.items():
cc[k.replace('_', '-')] = v
cc = ', '.join(dictvalue(el) for el in cc.items())
response['Cache-Control'] = cc

[docs]def get_max_age(response):
"""
Returns the max-age from the response Cache-Control header as an integer
(or ``None`` if it wasn't found or wasn't an integer.
"""
if not response.has_header('Cache-Control'):
return
cc = dict(_to_tuple(el) for el in
cc_delim_re.split(response['Cache-Control']))
if 'max-age' in cc:
try:
return int(cc['max-age'])
except (ValueError, TypeError):
pass

def set_response_etag(response):
if not response.streaming:
response['ETag'] = quote_etag(hashlib.md5(response.content).hexdigest())
return response

def _precondition_failed(request):
logger.warning('Precondition Failed: %s', request.path,
extra={
'status_code': 412,
'request': request,
},
)
return HttpResponse(status=412)

def _not_modified(request, response=None):
if response:
# We need to keep the cookies, see ticket #4994.
cookies = response.cookies
response = HttpResponseNotModified()
response.cookies = cookies
return response
else:
return HttpResponseNotModified()

def get_conditional_response(request, etag=None, last_modified=None, response=None):
# Get HTTP request headers
if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
if if_modified_since:
if_modified_since = parse_http_date_safe(if_modified_since)
if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
if if_unmodified_since:
if_unmodified_since = parse_http_date_safe(if_unmodified_since)
if_none_match = request.META.get('HTTP_IF_NONE_MATCH')
if_match = request.META.get('HTTP_IF_MATCH')
etags = []
if if_none_match or if_match:
# There can be more than one ETag in the request, so we
# consider the list of values.
try:
etags = parse_etags(if_none_match or if_match)
except ValueError:
# In case of an invalid ETag, ignore all ETag headers.
# Apparently Opera sends invalidly quoted headers at times
# (we should be returning a 400 response, but that's a
# little extreme) -- this is bug #10681.
if_none_match = None
if_match = None

# If-None-Match must be ignored if original result would be anything
# other than a 2XX or 304 status. 304 status would result in no change.
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
if response and not (200 <= response.status_code < 300):
if_none_match = None
if_match = None

# If-Modified-Since must be ignored if the original result was not a 200.
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
if response and response.status_code != 200:
if_modified_since = None
if_unmodified_since = None

if not ((if_match and if_modified_since) or
(if_none_match and if_unmodified_since) or
(if_modified_since and if_unmodified_since) or
(if_match and if_none_match)):
# We only get here if no undefined combinations of headers are
# specified.
if ((if_none_match and (etag in etags or
'*' in etags and etag)) and
(not if_modified_since or
(last_modified and if_modified_since and
last_modified <= if_modified_since))):
if request.method in ('GET', 'HEAD'):
return _not_modified(request, response)
else:
return _precondition_failed(request)
elif (if_match and ((not etag and '*' in etags) or
(etag and etag not in etags) or
(last_modified and if_unmodified_since and
last_modified > if_unmodified_since))):
return _precondition_failed(request)
elif (not if_none_match and request.method in ('GET', 'HEAD') and
last_modified and if_modified_since and
last_modified <= if_modified_since):
return _not_modified(request, response)
elif (not if_match and
last_modified and if_unmodified_since and
last_modified > if_unmodified_since):
return _precondition_failed(request)

return response

[docs]def patch_response_headers(response, cache_timeout=None):
"""
Adds some useful headers to the given HttpResponse object:
ETag, Last-Modified, Expires and Cache-Control

Each header is only added if it isn't already set.

cache_timeout is in seconds. The CACHE_MIDDLEWARE_SECONDS setting is used
by default.
"""
if cache_timeout is None:
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
if cache_timeout < 0:
cache_timeout = 0  # Can't have max-age negative
if settings.USE_ETAGS and not response.has_header('ETag'):
if hasattr(response, 'render') and callable(response.render):
response.add_post_render_callback(set_response_etag)
else:
response = set_response_etag(response)
if not response.has_header('Last-Modified'):
response['Last-Modified'] = http_date()
if not response.has_header('Expires'):
response['Expires'] = http_date(time.time() + cache_timeout)
patch_cache_control(response, max_age=cache_timeout)

[docs]def add_never_cache_headers(response):
"""
Adds headers to a response to indicate that a page should never be cached.
"""
patch_response_headers(response, cache_timeout=-1)
patch_cache_control(response, no_cache=True, no_store=True, must_revalidate=True)

[docs]def patch_vary_headers(response, newheaders):
"""
Adds (or updates) the "Vary" header in the given HttpResponse object.
newheaders is a list of header names that should be in "Vary". Existing
headers in "Vary" aren't removed.
"""
# Note that we need to keep the original order intact, because cache
# implementations may rely on the order of the Vary contents in, say,
# computing an MD5 hash.
if response.has_header('Vary'):
vary_headers = cc_delim_re.split(response['Vary'])
else:
vary_headers = []
# Use .lower() here so we treat headers as case-insensitive.
existing_headers = set(header.lower() for header in vary_headers)
additional_headers = [newheader for newheader in newheaders
if newheader.lower() not in existing_headers]
response['Vary'] = ', '.join(vary_headers + additional_headers)

def has_vary_header(response, header_query):
"""
Checks to see if the response has a given header name in its Vary header.
"""
if not response.has_header('Vary'):
return False
vary_headers = cc_delim_re.split(response['Vary'])
existing_headers = set(header.lower() for header in vary_headers)
return header_query.lower() in existing_headers

def _i18n_cache_key_suffix(request, cache_key):
"""If necessary, adds the current locale or time zone to the cache key."""
if settings.USE_I18N or settings.USE_L10N:
# first check if LocaleMiddleware or another middleware added
# LANGUAGE_CODE to request, then fall back to the active language
# which in turn can also fall back to settings.LANGUAGE_CODE
cache_key += '.%s' % getattr(request, 'LANGUAGE_CODE', get_language())
if settings.USE_TZ:
# The datetime module doesn't restrict the output of tzname().
# Windows is known to use non-standard, locale-dependent names.
# User-defined tzinfo classes may return absolutely anything.
# Hence this paranoid conversion to create a valid cache key.
tz_name = force_text(get_current_timezone_name(), errors='ignore')
cache_key += '.%s' % tz_name.encode('ascii', 'ignore').decode('ascii').replace(' ', '_')
return cache_key

def _generate_cache_key(request, method, headerlist, key_prefix):
"""Returns a cache key from the headers given in the header list."""
ctx = hashlib.md5()
for header in headerlist:
value = request.META.get(header)
if value is not None:
ctx.update(force_bytes(value))
url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri())))
cache_key = 'views.decorators.cache.cache_page.%s.%s.%s.%s' % (
key_prefix, method, url.hexdigest(), ctx.hexdigest())
return _i18n_cache_key_suffix(request, cache_key)

def _generate_cache_header_key(key_prefix, request):
"""Returns a cache key for the header cache."""
url = hashlib.md5(force_bytes(iri_to_uri(request.build_absolute_uri())))
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
key_prefix, url.hexdigest())
return _i18n_cache_key_suffix(request, cache_key)

[docs]def get_cache_key(request, key_prefix=None, method='GET', cache=None):
"""
Returns a cache key based on the request URL and query. It can be used
in the request phase because it pulls the list of headers to take into
account from the global URL registry and uses those to build a cache key
to check against.

If there is no headerlist stored, the page needs to be rebuilt, so this
function returns None.
"""
if key_prefix is None:
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
cache_key = _generate_cache_header_key(key_prefix, request)
if cache is None:
cache = caches[settings.CACHE_MIDDLEWARE_ALIAS]
headerlist = cache.get(cache_key)
if headerlist is not None:
return _generate_cache_key(request, method, headerlist, key_prefix)
else:
return None

[docs]def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cache=None):
"""
Learns what headers to take into account for some request URL from the
response object. It stores those headers in a global URL registry so that
later access to that URL will know what headers to take into account
without building the response object itself. The headers are named in the
Vary header of the response, but we want to prevent response generation.

The list of headers to use for cache key generation is stored in the same
cache as the pages themselves. If the cache ages some data out of the
cache, this just means that we have to build the response once to get at
the Vary header and so at the list of headers to use for the cache key.
"""
if key_prefix is None:
key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
if cache_timeout is None:
cache_timeout = settings.CACHE_MIDDLEWARE_SECONDS
cache_key = _generate_cache_header_key(key_prefix, request)
if cache is None:
cache = caches[settings.CACHE_MIDDLEWARE_ALIAS]
if response.has_header('Vary'):
is_accept_language_redundant = settings.USE_I18N or settings.USE_L10N
# If i18n or l10n are used, the generated cache key will be suffixed
# with the current locale. Adding the raw value of Accept-Language is
# redundant in that case and would result in storing the same content
# under multiple keys in the cache. See #18191 for details.
headerlist = []
for header in cc_delim_re.split(response['Vary']):
header = header.upper().replace('-', '_')
if header == 'ACCEPT_LANGUAGE' and is_accept_language_redundant:
continue
headerlist.append('HTTP_' + header)
headerlist.sort()
cache.set(cache_key, headerlist, cache_timeout)
return _generate_cache_key(request, request.method, headerlist, key_prefix)
else:
# if there is no Vary header, we still need a cache key
# for the request.build_absolute_uri()
cache.set(cache_key, [], cache_timeout)
return _generate_cache_key(request, request.method, [], key_prefix)

def _to_tuple(s):
t = s.split('=', 1)
if len(t) == 2:
return t[0].lower(), t[1]
return t[0].lower(), True

Source code for django.utils.six

"""Utilities for writing code that runs on Python 2 and 3"""

# Copyright (c) 2010-2015 Benjamin Peterson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import absolute_import

import functools
import itertools
import operator
import sys
import types

__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.10.0"

# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
PY34 = sys.version_info[0:2] >= (3, 4)

if PY3:
string_types = str,
integer_types = int,
class_types = type,
text_type = str
binary_type = bytes

MAXSIZE = sys.maxsize
else:
string_types = basestring,
integer_types = (int, long)
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str

if sys.platform.startswith("java"):
# Jython always uses 32 bits.
MAXSIZE = int((1 << 31) - 1)
else:
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
class X(object):

def __len__(self):
return 1 << 31
try:
len(X())
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
del X

def _add_doc(func, doc):
"""Add documentation to a function."""
func.__doc__ = doc

def _import_module(name):
"""Import module, returning the module after the last dot."""
__import__(name)
return sys.modules[name]

class _LazyDescr(object):

def __init__(self, name):
self.name = name

def __get__(self, obj, tp):
result = self._resolve()
setattr(obj, self.name, result)  # Invokes __set__.
try:
# This is a bit ugly, but it avoids running this again by
# removing this descriptor.
delattr(obj.__class__, self.name)
except AttributeError:
pass
return result

class MovedModule(_LazyDescr):

def __init__(self, name, old, new=None):
super(MovedModule, self).__init__(name)
if PY3:
if new is None:
new = name
self.mod = new
else:
self.mod = old

def _resolve(self):
return _import_module(self.mod)

def __getattr__(self, attr):
_module = self._resolve()
value = getattr(_module, attr)
setattr(self, attr, value)
return value

class _LazyModule(types.ModuleType):

def __init__(self, name):
super(_LazyModule, self).__init__(name)
self.__doc__ = self.__class__.__doc__

def __dir__(self):
attrs = ["__doc__", "__name__"]
attrs += [attr.name for attr in self._moved_attributes]
return attrs

# Subclasses should override this
_moved_attributes = []

class MovedAttribute(_LazyDescr):

def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
super(MovedAttribute, self).__init__(name)
if PY3:
if new_mod is None:
new_mod = name
self.mod = new_mod
if new_attr is None:
if old_attr is None:
new_attr = name
else:
new_attr = old_attr
self.attr = new_attr
else:
self.mod = old_mod
if old_attr is None:
old_attr = name
self.attr = old_attr

def _resolve(self):
module = _import_module(self.mod)
return getattr(module, self.attr)

class _SixMetaPathImporter(object):

"""
A meta path importer to import six.moves and its submodules.

This class implements a PEP302 finder and loader. It should be compatible
with Python 2.5 and all existing versions of Python3
"""

def __init__(self, six_module_name):
self.name = six_module_name
self.known_modules = {}

def _add_module(self, mod, *fullnames):
for fullname in fullnames:
self.known_modules[self.name + "." + fullname] = mod

def _get_module(self, fullname):
return self.known_modules[self.name + "." + fullname]

def find_module(self, fullname, path=None):
if fullname in self.known_modules:
return self
return None

def __get_module(self, fullname):
try:
return self.known_modules[fullname]
except KeyError:
raise ImportError("This loader does not know module " + fullname)

def load_module(self, fullname):
try:
# in case of a reload
return sys.modules[fullname]
except KeyError:
pass
mod = self.__get_module(fullname)
if isinstance(mod, MovedModule):
mod = mod._resolve()
else:
mod.__loader__ = self
sys.modules[fullname] = mod
return mod

def is_package(self, fullname):
"""
Return true, if the named module is a package.

We need this method to get correct spec objects with
Python 3.4 (see PEP451)
"""
return hasattr(self.__get_module(fullname), "__path__")

def get_code(self, fullname):
"""Return None

Required, if is_package is implemented"""
self.__get_module(fullname)  # eventually raises ImportError
return None
get_source = get_code  # same as get_code

_importer = _SixMetaPathImporter(__name__)

class _MovedItems(_LazyModule):

"""Lazy loading of moved objects"""
__path__ = []  # mark as package

_moved_attributes = [
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
MovedAttribute("intern", "__builtin__", "sys"),
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
MovedAttribute("reduce", "__builtin__", "functools"),
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
MovedAttribute("StringIO", "StringIO", "io"),
MovedAttribute("UserDict", "UserDict", "collections"),
MovedAttribute("UserList", "UserList", "collections"),
MovedAttribute("UserString", "UserString", "collections"),
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
MovedModule("builtins", "__builtin__"),
MovedModule("configparser", "ConfigParser"),
MovedModule("copyreg", "copy_reg"),
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
MovedModule("http_cookies", "Cookie", "http.cookies"),
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
MovedModule("html_parser", "HTMLParser", "html.parser"),
MovedModule("http_client", "httplib", "http.client"),
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
MovedModule("cPickle", "cPickle", "pickle"),
MovedModule("queue", "Queue"),
MovedModule("reprlib", "repr"),
MovedModule("socketserver", "SocketServer"),
MovedModule("_thread", "thread", "_thread"),
MovedModule("tkinter", "Tkinter"),
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
MovedModule("tkinter_colorchooser", "tkColorChooser",
"tkinter.colorchooser"),
MovedModule("tkinter_commondialog", "tkCommonDialog",
"tkinter.commondialog"),
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
"tkinter.simpledialog"),
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
]
# Add windows specific modules.
if sys.platform == "win32":
_moved_attributes += [
MovedModule("winreg", "_winreg"),
]

for attr in _moved_attributes:
setattr(_MovedItems, attr.name, attr)
if isinstance(attr, MovedModule):
_importer._add_module(attr, "moves." + attr.name)
del attr

_MovedItems._moved_attributes = _moved_attributes

moves = _MovedItems(__name__ + ".moves")
_importer._add_module(moves, "moves")

class Module_six_moves_urllib_parse(_LazyModule):

"""Lazy loading of moved objects in six.moves.urllib_parse"""

_urllib_parse_moved_attributes = [
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
MovedAttribute("quote", "urllib", "urllib.parse"),
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
MovedAttribute("unquote", "urllib", "urllib.parse"),
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
MovedAttribute("urlencode", "urllib", "urllib.parse"),
MovedAttribute("splitquery", "urllib", "urllib.parse"),
MovedAttribute("splittag", "urllib", "urllib.parse"),
MovedAttribute("splituser", "urllib", "urllib.parse"),
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
]
for attr in _urllib_parse_moved_attributes:
setattr(Module_six_moves_urllib_parse, attr.name, attr)
del attr

Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes

_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
"moves.urllib_parse", "moves.urllib.parse")

class Module_six_moves_urllib_error(_LazyModule):

"""Lazy loading of moved objects in six.moves.urllib_error"""

_urllib_error_moved_attributes = [
MovedAttribute("URLError", "urllib2", "urllib.error"),
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
]
for attr in _urllib_error_moved_attributes:
setattr(Module_six_moves_urllib_error, attr.name, attr)
del attr

Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes

_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
"moves.urllib_error", "moves.urllib.error")

class Module_six_moves_urllib_request(_LazyModule):

"""Lazy loading of moved objects in six.moves.urllib_request"""

_urllib_request_moved_attributes = [
MovedAttribute("urlopen", "urllib2", "urllib.request"),
MovedAttribute("install_opener", "urllib2", "urllib.request"),
MovedAttribute("build_opener", "urllib2", "urllib.request"),
MovedAttribute("pathname2url", "urllib", "urllib.request"),
MovedAttribute("url2pathname", "urllib", "urllib.request"),
MovedAttribute("getproxies", "urllib", "urllib.request"),
MovedAttribute("Request", "urllib2", "urllib.request"),
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
MovedAttribute("URLopener", "urllib", "urllib.request"),
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
]
for attr in _urllib_request_moved_attributes:
setattr(Module_six_moves_urllib_request, attr.name, attr)
del attr

Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes

_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
"moves.urllib_request", "moves.urllib.request")

class Module_six_moves_urllib_response(_LazyModule):

"""Lazy loading of moved objects in six.moves.urllib_response"""

_urllib_response_moved_attributes = [
MovedAttribute("addbase", "urllib", "urllib.response"),
MovedAttribute("addclosehook", "urllib", "urllib.response"),
MovedAttribute("addinfo", "urllib", "urllib.response"),
MovedAttribute("addinfourl", "urllib", "urllib.response"),
]
for attr in _urllib_response_moved_attributes:
setattr(Module_six_moves_urllib_response, attr.name, attr)
del attr

Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes

_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
"moves.urllib_response", "moves.urllib.response")

class Module_six_moves_urllib_robotparser(_LazyModule):

"""Lazy loading of moved objects in six.moves.urllib_robotparser"""

_urllib_robotparser_moved_attributes = [
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
]
for attr in _urllib_robotparser_moved_attributes:
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
del attr

Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes

_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
"moves.urllib_robotparser", "moves.urllib.robotparser")

class Module_six_moves_urllib(types.ModuleType):

"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
__path__ = []  # mark as package
parse = _importer._get_module("moves.urllib_parse")
error = _importer._get_module("moves.urllib_error")
request = _importer._get_module("moves.urllib_request")
response = _importer._get_module("moves.urllib_response")
robotparser = _importer._get_module("moves.urllib_robotparser")

def __dir__(self):
return ['parse', 'error', 'request', 'response', 'robotparser']

_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
"moves.urllib")

def add_move(move):
"""Add an item to six.moves."""
setattr(_MovedItems, move.name, move)

def remove_move(name):
"""Remove item from six.moves."""
try:
delattr(_MovedItems, name)
except AttributeError:
try:
del moves.__dict__[name]
except KeyError:
raise AttributeError("no such move, %r" % (name,))

if PY3:
_meth_func = "__func__"
_meth_self = "__self__"

_func_closure = "__closure__"
_func_code = "__code__"
_func_defaults = "__defaults__"
_func_globals = "__globals__"
else:
_meth_func = "im_func"
_meth_self = "im_self"

_func_closure = "func_closure"
_func_code = "func_code"
_func_defaults = "func_defaults"
_func_globals = "func_globals"

try:
advance_iterator = next
except NameError:
def advance_iterator(it):
return it.next()
next = advance_iterator

try:
callable = callable
except NameError:
def callable(obj):
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)

if PY3:
def get_unbound_function(unbound):
return unbound

create_bound_method = types.MethodType

def create_unbound_method(func, cls):
return func

Iterator = object
else:
def get_unbound_function(unbound):
return unbound.im_func

def create_bound_method(func, obj):
return types.MethodType(func, obj, obj.__class__)

def create_unbound_method(func, cls):
return types.MethodType(func, None, cls)

class Iterator(object):

def next(self):
return type(self).__next__(self)

callable = callable
_add_doc(get_unbound_function,
"""Get the function out of a possibly unbound function""")

get_method_function = operator.attrgetter(_meth_func)
get_method_self = operator.attrgetter(_meth_self)
get_function_closure = operator.attrgetter(_func_closure)
get_function_code = operator.attrgetter(_func_code)
get_function_defaults = operator.attrgetter(_func_defaults)
get_function_globals = operator.attrgetter(_func_globals)

if PY3:
def iterkeys(d, **kw):
return iter(d.keys(**kw))

def itervalues(d, **kw):
return iter(d.values(**kw))

def iteritems(d, **kw):
return iter(d.items(**kw))

def iterlists(d, **kw):
return iter(d.lists(**kw))

viewkeys = operator.methodcaller("keys")

viewvalues = operator.methodcaller("values")

viewitems = operator.methodcaller("items")
else:
def iterkeys(d, **kw):
return d.iterkeys(**kw)

def itervalues(d, **kw):
return d.itervalues(**kw)

def iteritems(d, **kw):
return d.iteritems(**kw)

def iterlists(d, **kw):
return d.iterlists(**kw)

viewkeys = operator.methodcaller("viewkeys")

viewvalues = operator.methodcaller("viewvalues")

viewitems = operator.methodcaller("viewitems")

_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
_add_doc(iteritems,
"Return an iterator over the (key, value) pairs of a dictionary.")
_add_doc(iterlists,
"Return an iterator over the (key, [values]) pairs of a dictionary.")

if PY3:
def b(s):
return s.encode("latin-1")

def u(s):
return s
unichr = chr
import struct
int2byte = struct.Struct(">B").pack
del struct
byte2int = operator.itemgetter(0)
indexbytes = operator.getitem
iterbytes = iter
import io
StringIO = io.StringIO
BytesIO = io.BytesIO
_assertCountEqual = "assertCountEqual"
if sys.version_info[1] <= 1:
_assertRaisesRegex = "assertRaisesRegexp"
_assertRegex = "assertRegexpMatches"
else:
_assertRaisesRegex = "assertRaisesRegex"
_assertRegex = "assertRegex"
else:
def b(s):
return s
# Workaround for standalone backslash

def u(s):
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
unichr = unichr
int2byte = chr

def byte2int(bs):
return ord(bs[0])

def indexbytes(buf, i):
return ord(buf[i])
iterbytes = functools.partial(itertools.imap, ord)
import StringIO
StringIO = BytesIO = StringIO.StringIO
_assertCountEqual = "assertItemsEqual"
_assertRaisesRegex = "assertRaisesRegexp"
_assertRegex = "assertRegexpMatches"
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")

def assertCountEqual(self, *args, **kwargs):
return getattr(self, _assertCountEqual)(*args, **kwargs)

def assertRaisesRegex(self, *args, **kwargs):
return getattr(self, _assertRaisesRegex)(*args, **kwargs)

def assertRegex(self, *args, **kwargs):
return getattr(self, _assertRegex)(*args, **kwargs)

if PY3:
exec_ = getattr(moves.builtins, "exec")

def reraise(tp, value, tb=None):
if value is None:
value = tp()
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value

else:
def exec_(_code_, _globs_=None, _locs_=None):
"""Execute code in a namespace."""
if _globs_ is None:
frame = sys._getframe(1)
_globs_ = frame.f_globals
if _locs_ is None:
_locs_ = frame.f_locals
del frame
elif _locs_ is None:
_locs_ = _globs_
exec("""exec _code_ in _globs_, _locs_""")

exec_("""def reraise(tp, value, tb=None):
raise tp, value, tb
""")

if sys.version_info[:2] == (3, 2):
exec_("""def raise_from(value, from_value):
if from_value is None:
raise value
raise value from from_value
""")
elif sys.version_info[:2] > (3, 2):
exec_("""def raise_from(value, from_value):
raise value from from_value
""")
else:
def raise_from(value, from_value):
raise value

print_ = getattr(moves.builtins, "print", None)
if print_ is None:
def print_(*args, **kwargs):
"""The new-style print function for Python 2.4 and 2.5."""
fp = kwargs.pop("file", sys.stdout)
if fp is None:
return

def write(data):
if not isinstance(data, basestring):
data = str(data)
# If the file has an encoding, encode unicode with it.
if (isinstance(fp, file) and
isinstance(data, unicode) and
fp.encoding is not None):
errors = getattr(fp, "errors", None)
if errors is None:
errors = "strict"
data = data.encode(fp.encoding, errors)
fp.write(data)
want_unicode = False
sep = kwargs.pop("sep", None)
if sep is not None:
if isinstance(sep, unicode):
want_unicode = True
elif not isinstance(sep, str):
raise TypeError("sep must be None or a string")
end = kwargs.pop("end", None)
if end is not None:
if isinstance(end, unicode):
want_unicode = True
elif not isinstance(end, str):
raise TypeError("end must be None or a string")
if kwargs:
raise TypeError("invalid keyword arguments to print()")
if not want_unicode:
for arg in args:
if isinstance(arg, unicode):
want_unicode = True
break
if want_unicode:
newline = unicode("\n")
space = unicode(" ")
else:
newline = "\n"
space = " "
if sep is None:
sep = space
if end is None:
end = newline
for i, arg in enumerate(args):
if i:
write(sep)
write(arg)
write(end)
if sys.version_info[:2] < (3, 3):
_print = print_

def print_(*args, **kwargs):
fp = kwargs.get("file", sys.stdout)
flush = kwargs.pop("flush", False)
_print(*args, **kwargs)
if flush and fp is not None:
fp.flush()

_add_doc(reraise, """Reraise an exception.""")

if sys.version_info[0:2] < (3, 4):
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
updated=functools.WRAPPER_UPDATES):
def wrapper(f):
f = functools.wraps(wrapped, assigned, updated)(f)
f.__wrapped__ = wrapped
return f
return wrapper
else:
wraps = functools.wraps

def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(meta):

def __new__(cls, name, this_bases, d):
return meta(name, bases, d)
return type.__new__(metaclass, 'temporary_class', (), {})

def add_metaclass(metaclass):
"""Class decorator for creating a class with a metaclass."""
def wrapper(cls):
orig_vars = cls.__dict__.copy()
slots = orig_vars.get('__slots__')
if slots is not None:
if isinstance(slots, str):
slots = [slots]
for slots_var in slots:
orig_vars.pop(slots_var)
orig_vars.pop('__dict__', None)
orig_vars.pop('__weakref__', None)
return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper

[docs]def python_2_unicode_compatible(klass):
"""
A decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.

To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if PY2:
if '__str__' not in klass.__dict__:
raise ValueError("@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." %
klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass

# Complete the moves implementation.
# This code is at the end of this module to speed up module loading.
# Turn this module into a package.
__path__ = []  # required for PEP 302 and PEP 451
__package__ = __name__  # see PEP 366 @ReservedAssignment
if globals().get("__spec__") is not None:
__spec__.submodule_search_locations = []  # PEP 451 @UndefinedVariable
# Remove other six meta path importers, since they cause problems. This can
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
# this for some reason.)
if sys.meta_path:
for i, importer in enumerate(sys.meta_path):
# Here's some real nastiness: Another "instance" of the six module might
# be floating around. Therefore, we can't use isinstance() to check for
# the six meta path importer, since the other six instance will have
# inserted an importer with different class.
if (type(importer).__name__ == "_SixMetaPathImporter" and
importer.name == __name__):
del sys.meta_path[i]
break
del i, importer
# Finally, add the importer to the meta path import hook.
sys.meta_path.append(_importer)

### Additional customizations for Django ###

if PY3:
memoryview = memoryview
buffer_types = (bytes, bytearray, memoryview)
else:
# memoryview and buffer are not strictly equivalent, but should be fine for
# django core usage (mainly BinaryField). However, Jython doesn't support
# buffer (see http://bugs.jython.org/issue1521), so we have to be careful.
if sys.platform.startswith('java'):
memoryview = memoryview
else:
memoryview = buffer
buffer_types = (bytearray, memoryview)

Source code for django.utils.encoding

# -*- encoding: utf-8 -*-
from __future__ import unicode_literals

import codecs
import datetime
import locale
from decimal import Decimal

from django.utils import six
from django.utils.functional import Promise
from django.utils.six.moves.urllib.parse import quote, unquote

if six.PY3:
from urllib.parse import unquote_to_bytes

class DjangoUnicodeDecodeError(UnicodeDecodeError):
def __init__(self, obj, *args):
self.obj = obj
UnicodeDecodeError.__init__(self, *args)

def __str__(self):
original = UnicodeDecodeError.__str__(self)
return '%s. You passed in %r (%s)' % (original, self.obj,
type(self.obj))

# For backwards compatibility. (originally in Django, then added to six 1.9)
python_2_unicode_compatible = six.python_2_unicode_compatible

[docs]def smart_text(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Returns a text object representing 's' -- unicode on Python 2 and str on
Python 3. Treats bytestrings using the 'encoding' codec.

If strings_only is True, don't convert (some) non-string-like objects.
"""
if isinstance(s, Promise):
# The input is the result of a gettext_lazy() call.
return s
return force_text(s, encoding, strings_only, errors)

_PROTECTED_TYPES = six.integer_types + (type(None), float, Decimal,
datetime.datetime, datetime.date, datetime.time)

[docs]def is_protected_type(obj):
"""Determine if the object instance is of a protected type.

Objects of protected types are preserved as-is when passed to
force_text(strings_only=True).
"""
return isinstance(obj, _PROTECTED_TYPES)

[docs]def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Similar to smart_text, except that lazy instances are resolved to
strings, rather than kept as lazy objects.

If strings_only is True, don't convert (some) non-string-like objects.
"""
# Handle the common case first for performance reasons.
if issubclass(type(s), six.text_type):
return s
if strings_only and is_protected_type(s):
return s
try:
if not issubclass(type(s), six.string_types):
if six.PY3:
if isinstance(s, bytes):
s = six.text_type(s, encoding, errors)
else:
s = six.text_type(s)
elif hasattr(s, '__unicode__'):
s = six.text_type(s)
else:
s = six.text_type(bytes(s), encoding, errors)
else:
# Note: We use .decode() here, instead of six.text_type(s, encoding,
# errors), so that if s is a SafeBytes, it ends up being a
# SafeText at the end.
s = s.decode(encoding, errors)
except UnicodeDecodeError as e:
if not isinstance(s, Exception):
raise DjangoUnicodeDecodeError(s, *e.args)
else:
# If we get to here, the caller has passed in an Exception
# subclass populated with non-ASCII bytestring data without a
# working unicode method. Try to handle this without raising a
# further exception by individually forcing the exception args
# to unicode.
s = ' '.join(force_text(arg, encoding, strings_only, errors)
for arg in s)
return s

[docs]def smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Returns a bytestring version of 's', encoded as specified in 'encoding'.

If strings_only is True, don't convert (some) non-string-like objects.
"""
if isinstance(s, Promise):
# The input is the result of a gettext_lazy() call.
return s
return force_bytes(s, encoding, strings_only, errors)

[docs]def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Similar to smart_bytes, except that lazy instances are resolved to
strings, rather than kept as lazy objects.

If strings_only is True, don't convert (some) non-string-like objects.
"""
# Handle the common case first for performance reasons.
if isinstance(s, bytes):
if encoding == 'utf-8':
return s
else:
return s.decode('utf-8', errors).encode(encoding, errors)
if strings_only and is_protected_type(s):
return s
if isinstance(s, six.memoryview):
return bytes(s)
if isinstance(s, Promise):
return six.text_type(s).encode(encoding, errors)
if not isinstance(s, six.string_types):
try:
if six.PY3:
return six.text_type(s).encode(encoding)
else:
return bytes(s)
except UnicodeEncodeError:
if isinstance(s, Exception):
# An Exception subclass containing non-ASCII data that doesn't
# know how to print itself properly. We shouldn't raise a
# further exception.
return b' '.join(force_bytes(arg, encoding, strings_only, errors)
for arg in s)
return six.text_type(s).encode(encoding, errors)
else:
return s.encode(encoding, errors)

if six.PY3:
smart_str = smart_text
force_str = force_text
else:
smart_str = smart_bytes
force_str = force_bytes
# backwards compatibility for Python 2
smart_unicode = smart_text
force_unicode = force_text

smart_str.__doc__ = """
Apply smart_text in Python 3 and smart_bytes in Python 2.

This is suitable for writing to sys.stdout (for instance).
"""

force_str.__doc__ = """
Apply force_text in Python 3 and force_bytes in Python 2.
"""

[docs]def iri_to_uri(iri):
"""
Convert an Internationalized Resource Identifier (IRI) portion to a URI
portion that is suitable for inclusion in a URL.

This is the algorithm from section 3.1 of RFC 3987.  However, since we are
assuming input is either UTF-8 or unicode already, we can simplify things a
little from the full method.

Takes an IRI in UTF-8 bytes (e.g. '/I \xe2\x99\xa5 Django/') or unicode
(e.g. '/I ♥ Django/') and returns ASCII bytes containing the encoded result
(e.g. '/I%20%E2%99%A5%20Django/').
"""
# The list of safe characters here is constructed from the "reserved" and
# "unreserved" characters specified in sections 2.2 and 2.3 of RFC 3986:
#     reserved    = gen-delims / sub-delims
#     gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
#     sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
#                   / "*" / "+" / "," / ";" / "="
#     unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
# Of the unreserved characters, urllib.quote already considers all but
# the ~ safe.
# The % character is also added to the list of safe characters here, as the
# end of section 3.1 of RFC 3987 specifically mentions that % must not be
# converted.
if iri is None:
return iri
return quote(force_bytes(iri), safe=b"/#%[]=:;$&()+,!?*@'~")

[docs]def uri_to_iri(uri):
"""
Converts a Uniform Resource Identifier(URI) into an Internationalized
Resource Identifier(IRI).

This is the algorithm from section 3.2 of RFC 3987.

Takes an URI in ASCII bytes (e.g. '/I%20%E2%99%A5%20Django/') and returns
unicode containing the encoded result (e.g. '/I \xe2\x99\xa5 Django/').
"""
if uri is None:
return uri
uri = force_bytes(uri)
iri = unquote_to_bytes(uri) if six.PY3 else unquote(uri)
return repercent_broken_unicode(iri).decode('utf-8')

[docs]def escape_uri_path(path):
"""
Escape the unsafe characters from the path portion of a Uniform Resource
Identifier (URI).
"""
# These are the "reserved" and "unreserved" characters specified in
# sections 2.2 and 2.3 of RFC 2396:
#   reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
#   unreserved  = alphanum | mark
#   mark        = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
# The list of safe characters here is constructed subtracting ";", "=",
# and "?" according to section 3.3 of RFC 2396.
# The reason for not subtracting and escaping "/" is that we are escaping
# the entire path, not a path segment.
return quote(force_bytes(path), safe=b"/:@&+$,-_.!~*'()")

def repercent_broken_unicode(path):
"""
As per section 3.2 of RFC 3987, step three of converting a URI into an IRI,
we need to re-percent-encode any octet produced that is not part of a
strictly legal UTF-8 octet sequence.
"""
try:
path.decode('utf-8')
except UnicodeDecodeError as e:
repercent = quote(path[e.start:e.end], safe=b"/#%[]=:;$&()+,!?*@'~")
path = repercent_broken_unicode(
path[:e.start] + force_bytes(repercent) + path[e.end:])
return path

[docs]def filepath_to_uri(path):
"""Convert a file system path to a URI portion that is suitable for
inclusion in a URL.

We are assuming input is either UTF-8 or unicode already.

This method will encode certain chars that would normally be recognized as
special chars for URIs.  Note that this method does not encode the '
character, as it is a valid character within URIs.  See
encodeURIComponent() JavaScript function for more details.

Returns an ASCII string containing the encoded result.
"""
if path is None:
return path
# I know about `os.sep` and `os.altsep` but I want to leave
# some flexibility for hardcoding separators.
return quote(force_bytes(path).replace(b"\\", b"/"), safe=b"/~!*()'")

def get_system_encoding():
"""
The encoding of the default system locale but falls back to the given
fallback encoding if the encoding is unsupported by python or could
not be determined.  See tickets #10335 and #5846
"""
try:
encoding = locale.getdefaultlocale()[1] or 'ascii'
codecs.lookup(encoding)
except Exception:
encoding = 'ascii'
return encoding

DEFAULT_LOCALE_ENCODING = get_system_encoding()

Source code for django.utils.log

from __future__ import unicode_literals

import logging
import logging.config  # needed when logging_config doesn't start with logging.config
import sys
import warnings
from copy import copy

from django.conf import settings
from django.core import mail
from django.core.mail import get_connection
from django.utils.deprecation import RemovedInNextVersionWarning
from django.utils.module_loading import import_string
from django.views.debug import ExceptionReporter

# Default logging for Django. This sends an email to the site admins on every
# HTTP 500 error. Depending on DEBUG, all other log records are either sent to
# the console (DEBUG=True) or discarded (DEBUG=False) by means of the
# require_debug_true filter.
DEFAULT_LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
},
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
},
'py.warnings': {
'handlers': ['console'],
},
}
}

def configure_logging(logging_config, logging_settings):
if not sys.warnoptions:
# Route warnings through python logging
logging.captureWarnings(True)
# RemovedInNextVersionWarning is a subclass of DeprecationWarning which
# is hidden by default, hence we force the "default" behavior
warnings.simplefilter("default", RemovedInNextVersionWarning)

if logging_config:
# First find the logging configuration function ...
logging_config_func = import_string(logging_config)

logging.config.dictConfig(DEFAULT_LOGGING)

# ... then invoke it with the logging settings
if logging_settings:
logging_config_func(logging_settings)

[docs]class AdminEmailHandler(logging.Handler):
"""An exception log handler that emails log entries to site admins.

If the request is passed as the first argument to the log record,
request data will be provided in the email report.
"""

def __init__(self, include_html=False, email_backend=None):
logging.Handler.__init__(self)
self.include_html = include_html
self.email_backend = email_backend

def emit(self, record):
try:
request = record.request
subject = '%s (%s IP): %s' % (
record.levelname,
('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS
else 'EXTERNAL'),
record.getMessage()
)
except Exception:
subject = '%s: %s' % (
record.levelname,
record.getMessage()
)
request = None
subject = self.format_subject(subject)

# Since we add a nicely formatted traceback on our own, create a copy
# of the log record without the exception data.
no_exc_record = copy(record)
no_exc_record.exc_info = None
no_exc_record.exc_text = None

if record.exc_info:
exc_info = record.exc_info
else:
exc_info = (None, record.getMessage(), None)

reporter = ExceptionReporter(request, is_email=True, *exc_info)
message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text())
html_message = reporter.get_traceback_html() if self.include_html else None
self.send_mail(subject, message, fail_silently=True, html_message=html_message)

[docs]    def send_mail(self, subject, message, *args, **kwargs):
mail.mail_admins(subject, message, *args, connection=self.connection(), **kwargs)

def connection(self):
return get_connection(backend=self.email_backend, fail_silently=True)

def format_subject(self, subject):
"""
Escape CR and LF characters, and limit length.
RFC 2822's hard limit is 998 characters per line. So, minus "Subject: "
the actual subject must be no longer than 989 characters.
"""
formatted_subject = subject.replace('\n', '\\n').replace('\r', '\\r')
return formatted_subject[:989]

[docs]class CallbackFilter(logging.Filter):
"""
A logging filter that checks the return value of a given callable (which
takes the record-to-be-logged as its only parameter) to decide whether to
log a record.
"""
def __init__(self, callback):
self.callback = callback

def filter(self, record):
if self.callback(record):
return 1
return 0

[docs]class RequireDebugFalse(logging.Filter):
def filter(self, record):
return not settings.DEBUG

[docs]class RequireDebugTrue(logging.Filter):
def filter(self, record):
return settings.DEBUG

Source code for django.utils.translation

"""
Internationalization support.
"""
from __future__ import unicode_literals

import re

from django.utils import six
from django.utils.decorators import ContextDecorator
from django.utils.encoding import force_text
from django.utils.functional import lazy

__all__ = [
'activate', 'deactivate', 'override', 'deactivate_all',
'get_language', 'get_language_from_request',
'get_language_info', 'get_language_bidi',
'check_for_language', 'to_locale', 'templatize', 'string_concat',
'gettext', 'gettext_lazy', 'gettext_noop',
'ugettext', 'ugettext_lazy', 'ugettext_noop',
'ngettext', 'ngettext_lazy',
'ungettext', 'ungettext_lazy',
'pgettext', 'pgettext_lazy',
'npgettext', 'npgettext_lazy',
'LANGUAGE_SESSION_KEY',
]

LANGUAGE_SESSION_KEY = '_language'

class TranslatorCommentWarning(SyntaxWarning):
pass

# Here be dragons, so a short explanation of the logic won't hurt:
# We are trying to solve two problems: (1) access settings, in particular
# settings.USE_I18N, as late as possible, so that modules can be imported
# without having to first configure Django, and (2) if some other code creates
# a reference to one of these functions, don't break that reference when we
# replace the functions with their real counterparts (once we do access the
# settings).

class Trans(object):
"""
The purpose of this class is to store the actual translation function upon
receiving the first call to that function. After this is done, changes to
USE_I18N will have no effect to which function is served upon request. If
your tests rely on changing USE_I18N, you can delete all the functions
from _trans.__dict__.

Note that storing the function with setattr will have a noticeable
performance effect, as access to the function goes the normal path,
instead of using __getattr__.
"""

def __getattr__(self, real_name):
from django.conf import settings
if settings.USE_I18N:
from django.utils.translation import trans_real as trans
else:
from django.utils.translation import trans_null as trans
setattr(self, real_name, getattr(trans, real_name))
return getattr(trans, real_name)

_trans = Trans()

# The Trans class is no more needed, so remove it from the namespace.
del Trans

[docs]def gettext_noop(message):
return _trans.gettext_noop(message)

ugettext_noop = gettext_noop

[docs]def gettext(message):
return _trans.gettext(message)

[docs]def ngettext(singular, plural, number):
return _trans.ngettext(singular, plural, number)

[docs]def ugettext(message):
return _trans.ugettext(message)

[docs]def ungettext(singular, plural, number):
return _trans.ungettext(singular, plural, number)

[docs]def pgettext(context, message):
return _trans.pgettext(context, message)

[docs]def npgettext(context, singular, plural, number):
return _trans.npgettext(context, singular, plural, number)

gettext_lazy = lazy(gettext, str)
ugettext_lazy = lazy(ugettext, six.text_type)
pgettext_lazy = lazy(pgettext, six.text_type)

def lazy_number(func, resultclass, number=None, **kwargs):
if isinstance(number, six.integer_types):
kwargs['number'] = number
proxy = lazy(func, resultclass)(**kwargs)
else:
original_kwargs = kwargs.copy()

class NumberAwareString(resultclass):
def __mod__(self, rhs):
if isinstance(rhs, dict) and number:
try:
number_value = rhs[number]
except KeyError:
raise KeyError('Your dictionary lacks key \'%s\'. '
'Please provide it, because it is required to '
'determine whether string is singular or plural.'
% number)
else:
number_value = rhs
kwargs['number'] = number_value
translated = func(**kwargs)
try:
translated = translated % rhs
except TypeError:
# String doesn't contain a placeholder for the number
pass
return translated

proxy = lazy(lambda **kwargs: NumberAwareString(), NumberAwareString)(**kwargs)
proxy.__reduce__ = lambda: (_lazy_number_unpickle, (func, resultclass, number, original_kwargs))
return proxy

def _lazy_number_unpickle(func, resultclass, number, kwargs):
return lazy_number(func, resultclass, number=number, **kwargs)

[docs]def ngettext_lazy(singular, plural, number=None):
return lazy_number(ngettext, str, singular=singular, plural=plural, number=number)

[docs]def ungettext_lazy(singular, plural, number=None):
return lazy_number(ungettext, six.text_type, singular=singular, plural=plural, number=number)

[docs]def npgettext_lazy(context, singular, plural, number=None):
return lazy_number(npgettext, six.text_type, context=context, singular=singular, plural=plural, number=number)

[docs]def activate(language):
return _trans.activate(language)

[docs]def deactivate():
return _trans.deactivate()

[docs]class override(ContextDecorator):
def __init__(self, language, deactivate=False):
self.language = language
self.deactivate = deactivate

def __enter__(self):
self.old_language = get_language()
if self.language is not None:
activate(self.language)
else:
deactivate_all()

def __exit__(self, exc_type, exc_value, traceback):
if self.old_language is None:
deactivate_all()
elif self.deactivate:
deactivate()
else:
activate(self.old_language)

[docs]def get_language():
return _trans.get_language()

[docs]def get_language_bidi():
return _trans.get_language_bidi()

[docs]def check_for_language(lang_code):
return _trans.check_for_language(lang_code)

[docs]def to_locale(language):
return _trans.to_locale(language)

[docs]def get_language_from_request(request, check_path=False):
return _trans.get_language_from_request(request, check_path)

def get_language_from_path(path):
return _trans.get_language_from_path(path)

[docs]def templatize(src, origin=None):
return _trans.templatize(src, origin)

[docs]def deactivate_all():
return _trans.deactivate_all()

def _string_concat(*strings):
"""
Lazy variant of string concatenation, needed for translations that are
constructed from multiple parts.
"""
return ''.join(force_text(s) for s in strings)
string_concat = lazy(_string_concat, six.text_type)

[docs]def get_language_info(lang_code):
from django.conf.locale import LANG_INFO
try:
lang_info = LANG_INFO[lang_code]
if 'fallback' in lang_info and 'name' not in lang_info:
info = get_language_info(lang_info['fallback'][0])
else:
info = lang_info
except KeyError:
if '-' not in lang_code:
raise KeyError("Unknown language code %s." % lang_code)
generic_lang_code = lang_code.split('-')[0]
try:
info = LANG_INFO[generic_lang_code]
except KeyError:
raise KeyError("Unknown language code %s and %s." % (lang_code, generic_lang_code))

if info:
info['name_translated'] = ugettext_lazy(info['name'])
return info

trim_whitespace_re = re.compile('\s*\n\s*')

def trim_whitespace(s):
return trim_whitespace_re.sub(' ', s.strip())

Source code for django.dispatch.dispatcher

import sys
import threading
import warnings
import weakref

from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.inspect import func_accepts_kwargs
from django.utils.six.moves import range

if six.PY2:
from .weakref_backports import WeakMethod
else:
from weakref import WeakMethod

def _make_id(target):
if hasattr(target, '__func__'):
return (id(target.__self__), id(target.__func__))
return id(target)
NONE_ID = _make_id(None)

# A marker for caching
NO_RECEIVERS = object()

[docs]class Signal(object):
"""
Base class for all signals

Internal attributes:

receivers
{ receiverkey (id) : weakref(receiver) }
"""
def __init__(self, providing_args=None, use_caching=False):
"""
Create a new signal.

providing_args
A list of the arguments this signal can pass along in a send() call.
"""
self.receivers = []
if providing_args is None:
providing_args = []
self.providing_args = set(providing_args)
self.lock = threading.Lock()
self.use_caching = use_caching
# For convenience we create empty caches even if they are not used.
# A note about caching: if use_caching is defined, then for each
# distinct sender we cache the receivers that sender has in
# 'sender_receivers_cache'. The cache is cleaned when .connect() or
# .disconnect() is called and populated on send().
self.sender_receivers_cache = weakref.WeakKeyDictionary() if use_caching else {}
self._dead_receivers = False

[docs]    def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
"""
Connect receiver to sender for signal.

Arguments:

receiver
A function or an instance method which is to receive signals.
Receivers must be hashable objects.

If weak is True, then receiver must be weak referenceable.

Receivers must be able to accept keyword arguments.

If a receiver is connected with a dispatch_uid argument, it
will not be added if another receiver was already connected
with that dispatch_uid.

sender
The sender to which the receiver should respond. Must either be
of type Signal, or None to receive events from any sender.

weak
Whether to use weak references to the receiver. By default, the
module will attempt to use weak references to the receiver
objects. If this parameter is false, then strong references will
be used.

dispatch_uid
An identifier used to uniquely identify a particular instance of
a receiver. This will usually be a string, though it may be
anything hashable.
"""
from django.conf import settings

# If DEBUG is on, check that we got a good receiver
if settings.configured and settings.DEBUG:
assert callable(receiver), "Signal receivers must be callable."

# Check for **kwargs
if not func_accepts_kwargs(receiver):
raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")

if dispatch_uid:
lookup_key = (dispatch_uid, _make_id(sender))
else:
lookup_key = (_make_id(receiver), _make_id(sender))

if weak:
ref = weakref.ref
receiver_object = receiver
# Check for bound methods
if hasattr(receiver, '__self__') and hasattr(receiver, '__func__'):
ref = WeakMethod
receiver_object = receiver.__self__
if six.PY3:
receiver = ref(receiver)
weakref.finalize(receiver_object, self._remove_receiver)
else:
receiver = ref(receiver, self._remove_receiver)

with self.lock:
self._clear_dead_receivers()
for r_key, _ in self.receivers:
if r_key == lookup_key:
break
else:
self.receivers.append((lookup_key, receiver))
self.sender_receivers_cache.clear()

[docs]    def disconnect(self, receiver=None, sender=None, weak=None, dispatch_uid=None):
"""
Disconnect receiver from sender for signal.

If weak references are used, disconnect need not be called. The receiver
will be remove from dispatch automatically.

Arguments:

receiver
The registered receiver to disconnect. May be none if
dispatch_uid is specified.

sender
The registered sender to disconnect

dispatch_uid
the unique identifier of the receiver to disconnect
"""
if weak is not None:
warnings.warn("Passing `weak` to disconnect has no effect.",
RemovedInDjango20Warning, stacklevel=2)
if dispatch_uid:
lookup_key = (dispatch_uid, _make_id(sender))
else:
lookup_key = (_make_id(receiver), _make_id(sender))

disconnected = False
with self.lock:
self._clear_dead_receivers()
for index in range(len(self.receivers)):
(r_key, _) = self.receivers[index]
if r_key == lookup_key:
disconnected = True
del self.receivers[index]
break
self.sender_receivers_cache.clear()
return disconnected

def has_listeners(self, sender=None):
return bool(self._live_receivers(sender))

[docs]    def send(self, sender, **named):
"""
Send signal from sender to all connected receivers.

If any receiver raises an error, the error propagates back through send,
terminating the dispatch loop. So it's possible that all receivers
won't be called if an error is raised.

Arguments:

sender
The sender of the signal. Either a specific object or None.

named
Named arguments which will be passed to receivers.

Returns a list of tuple pairs [(receiver, response), ... ].
"""
responses = []
if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
return responses

for receiver in self._live_receivers(sender):
response = receiver(signal=self, sender=sender, **named)
responses.append((receiver, response))
return responses

[docs]    def send_robust(self, sender, **named):
"""
Send signal from sender to all connected receivers catching errors.

Arguments:

sender
The sender of the signal. Can be any python object (normally one
registered with a connect if you actually want something to
occur).

named
Named arguments which will be passed to receivers. These
arguments must be a subset of the argument names defined in
providing_args.

Return a list of tuple pairs [(receiver, response), ... ]. May raise
DispatcherKeyError.

If any receiver raises an error (specifically any subclass of
Exception), the error instance is returned as the result for that
receiver. The traceback is always attached to the error at
``__traceback__``.
"""
responses = []
if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
return responses

# Call each receiver with whatever arguments it can accept.
# Return a list of tuple pairs [(receiver, response), ... ].
for receiver in self._live_receivers(sender):
try:
response = receiver(signal=self, sender=sender, **named)
except Exception as err:
if not hasattr(err, '__traceback__'):
err.__traceback__ = sys.exc_info()[2]
responses.append((receiver, err))
else:
responses.append((receiver, response))
return responses

def _clear_dead_receivers(self):
# Note: caller is assumed to hold self.lock.
if self._dead_receivers:
self._dead_receivers = False
new_receivers = []
for r in self.receivers:
if isinstance(r[1], weakref.ReferenceType) and r[1]() is None:
continue
new_receivers.append(r)
self.receivers = new_receivers

def _live_receivers(self, sender):
"""
Filter sequence of receivers to get resolved, live receivers.

This checks for weak references and resolves them, then returning only
live receivers.
"""
receivers = None
if self.use_caching and not self._dead_receivers:
receivers = self.sender_receivers_cache.get(sender)
# We could end up here with NO_RECEIVERS even if we do check this case in
# .send() prior to calling _live_receivers() due to concurrent .send() call.
if receivers is NO_RECEIVERS:
return []
if receivers is None:
with self.lock:
self._clear_dead_receivers()
senderkey = _make_id(sender)
receivers = []
for (receiverkey, r_senderkey), receiver in self.receivers:
if r_senderkey == NONE_ID or r_senderkey == senderkey:
receivers.append(receiver)
if self.use_caching:
if not receivers:
self.sender_receivers_cache[sender] = NO_RECEIVERS
else:
# Note, we must cache the weakref versions.
self.sender_receivers_cache[sender] = receivers
non_weak_receivers = []
for receiver in receivers:
if isinstance(receiver, weakref.ReferenceType):
# Dereference the weak reference.
receiver = receiver()
if receiver is not None:
non_weak_receivers.append(receiver)
else:
non_weak_receivers.append(receiver)
return non_weak_receivers

def _remove_receiver(self, receiver=None):
# Mark that the self.receivers list has dead weakrefs. If so, we will
# clean those up in connect, disconnect and _live_receivers while
# holding self.lock. Note that doing the cleanup here isn't a good
# idea, _remove_receiver() will be called as side effect of garbage
# collection, and so the call can happen while we are already holding
# self.lock.
self._dead_receivers = True

[docs]def receiver(signal, **kwargs):
"""
A decorator for connecting receivers to signals. Used by passing in the
signal (or list of signals) and keyword arguments to connect::

@receiver(post_save, sender=MyModel)
def signal_receiver(sender, **kwargs):
...

@receiver([post_save, post_delete], sender=MyModel)
def signals_receiver(sender, **kwargs):
...
"""
def _decorator(func):
if isinstance(signal, (list, tuple)):
for s in signal:
s.connect(func, **kwargs)
else:
signal.connect(func, **kwargs)
return func
return _decorator

Source code for django.core.signing

"""
Functions for creating and restoring url-safe signed JSON objects.

The format used looks like this:

>>> signing.dumps("hello")
'ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk'

There are two components here, separated by a ':'. The first component is a
URLsafe base64 encoded JSON of the object passed to dumps(). The second
component is a base64 encoded hmac/SHA1 hash of "$first_component:$secret"

signing.loads(s) checks the signature and returns the deserialized object.
If the signature fails, a BadSignature exception is raised.

>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk")
u'hello'
>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk-modified")
...
BadSignature: Signature failed: ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk-modified

You can optionally compress the JSON prior to base64 encoding it to save
space, using the compress=True argument. This checks if compression actually
helps and only applies compression if the result is a shorter string:

>>> signing.dumps(range(1, 20), compress=True)
'.eJwFwcERACAIwLCF-rCiILN47r-GyZVJsNgkxaFxoDgxcOHGxMKD_T7vhAml:1QaUaL:BA0thEZrp4FQVXIXuOvYJtLJSrQ'

The fact that the string is compressed is signalled by the prefixed '.' at the
start of the base64 JSON.

There are 65 url-safe characters: the 64 used by url-safe base64 and the ':'.
These functions make use of all of them.
"""

from __future__ import unicode_literals

import base64
import datetime
import json
import re
import time
import warnings
import zlib

from django.conf import settings
from django.utils import baseconv
from django.utils.crypto import constant_time_compare, salted_hmac
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_bytes, force_str, force_text
from django.utils.module_loading import import_string

_SEP_UNSAFE = re.compile(r'^[A-z0-9-_=]*$')

class BadSignature(Exception):
"""
Signature does not match
"""
pass

class SignatureExpired(BadSignature):
"""
Signature timestamp is older than required max_age
"""
pass

def b64_encode(s):
return base64.urlsafe_b64encode(s).strip(b'=')

def b64_decode(s):
pad = b'=' * (-len(s) % 4)
return base64.urlsafe_b64decode(s + pad)

def base64_hmac(salt, value, key):
return b64_encode(salted_hmac(salt, value, key).digest())

def get_cookie_signer(salt='django.core.signing.get_cookie_signer'):
Signer = import_string(settings.SIGNING_BACKEND)
key = force_bytes(settings.SECRET_KEY)
return Signer(b'django.http.cookies' + key, salt=salt)

class JSONSerializer(object):
"""
Simple wrapper around json to be used in signing.dumps and
signing.loads.
"""
def dumps(self, obj):
return json.dumps(obj, separators=(',', ':')).encode('latin-1')

def loads(self, data):
return json.loads(data.decode('latin-1'))

[docs]def dumps(obj, key=None, salt='django.core.signing', serializer=JSONSerializer, compress=False):
"""
Returns URL-safe, sha1 signed base64 compressed JSON string. If key is
None, settings.SECRET_KEY is used instead.

If compress is True (not the default) checks if compressing using zlib can
save some space. Prepends a '.' to signify compression. This is included
in the signature, to protect against zip bombs.

Salt can be used to namespace the hash, so that a signed string is
only valid for a given namespace. Leaving this at the default
value or re-using a salt value across different parts of your
application without good cause is a security risk.

The serializer is expected to return a bytestring.
"""
data = serializer().dumps(obj)

# Flag for if it's been compressed or not
is_compressed = False

if compress:
# Avoid zlib dependency unless compress is being used
compressed = zlib.compress(data)
if len(compressed) < (len(data) - 1):
data = compressed
is_compressed = True
base64d = b64_encode(data)
if is_compressed:
base64d = b'.' + base64d
return TimestampSigner(key, salt=salt).sign(base64d)

[docs]def loads(s, key=None, salt='django.core.signing', serializer=JSONSerializer, max_age=None):
"""
Reverse of dumps(), raises BadSignature if signature fails.

The serializer is expected to accept a bytestring.
"""
# TimestampSigner.unsign always returns unicode but base64 and zlib
# compression operate on bytes.
base64d = force_bytes(TimestampSigner(key, salt=salt).unsign(s, max_age=max_age))
decompress = False
if base64d[:1] == b'.':
# It's compressed; uncompress it first
base64d = base64d[1:]
decompress = True
data = b64_decode(base64d)
if decompress:
data = zlib.decompress(data)
return serializer().loads(data)

[docs]class Signer(object):

def __init__(self, key=None, sep=':', salt=None):
# Use of native strings in all versions of Python
self.key = key or settings.SECRET_KEY
self.sep = force_str(sep)
if _SEP_UNSAFE.match(self.sep):
warnings.warn('Unsafe Signer separator: %r (cannot be empty or consist of only A-z0-9-_=)' % sep,
RemovedInDjango110Warning)
self.salt = force_str(salt or
'%s.%s' % (self.__class__.__module__, self.__class__.__name__))

def signature(self, value):
signature = base64_hmac(self.salt + 'signer', value, self.key)
# Convert the signature from bytes to str only on Python 3
return force_str(signature)

def sign(self, value):
value = force_str(value)
return str('%s%s%s') % (value, self.sep, self.signature(value))

def unsign(self, signed_value):
signed_value = force_str(signed_value)
if self.sep not in signed_value:
raise BadSignature('No "%s" found in value' % self.sep)
value, sig = signed_value.rsplit(self.sep, 1)
if constant_time_compare(sig, self.signature(value)):
return force_text(value)
raise BadSignature('Signature "%s" does not match' % sig)

[docs]class TimestampSigner(Signer):

def timestamp(self):
return baseconv.base62.encode(int(time.time()))

[docs]    def sign(self, value):
value = force_str(value)
value = str('%s%s%s') % (value, self.sep, self.timestamp())
return super(TimestampSigner, self).sign(value)

[docs]    def unsign(self, value, max_age=None):
"""
Retrieve original value and check it wasn't signed more
than max_age seconds ago.
"""
result = super(TimestampSigner, self).unsign(value)
value, timestamp = result.rsplit(self.sep, 1)
timestamp = baseconv.base62.decode(timestamp)
if max_age is not None:
if isinstance(max_age, datetime.timedelta):
max_age = max_age.total_seconds()
# Check timestamp is not older than max_age
age = time.time() - timestamp
if age > max_age:
raise SignatureExpired(
'Signature age %s > %s seconds' % (age, max_age))
return value

Source code for django.core.mail

"""
Tools for sending email.
"""
from __future__ import unicode_literals

from django.conf import settings
# Imported for backwards compatibility and for the sake
# of a cleaner namespace. These symbols used to be in
# django/core/mail.py before the introduction of email
# backends and the subsequent reorganization (See #10355)
from django.core.mail.message import (
DEFAULT_ATTACHMENT_MIME_TYPE, BadHeaderError, EmailMessage,
EmailMultiAlternatives, SafeMIMEMultipart, SafeMIMEText,
forbid_multi_line_headers, make_msgid,
)
from django.core.mail.utils import DNS_NAME, CachedDnsName
from django.utils.module_loading import import_string

__all__ = [
'CachedDnsName', 'DNS_NAME', 'EmailMessage', 'EmailMultiAlternatives',
'SafeMIMEText', 'SafeMIMEMultipart', 'DEFAULT_ATTACHMENT_MIME_TYPE',
'make_msgid', 'BadHeaderError', 'forbid_multi_line_headers',
'get_connection', 'send_mail', 'send_mass_mail', 'mail_admins',
'mail_managers',
]

[docs]def get_connection(backend=None, fail_silently=False, **kwds):
"""Load an email backend and return an instance of it.

If backend is None (default) settings.EMAIL_BACKEND is used.

Both fail_silently and other keyword arguments are used in the
constructor of the backend.
"""
klass = import_string(backend or settings.EMAIL_BACKEND)
return klass(fail_silently=fail_silently, **kwds)

[docs]def send_mail(subject, message, from_email, recipient_list,
fail_silently=False, auth_user=None, auth_password=None,
connection=None, html_message=None):
"""
Easy wrapper for sending a single message to a recipient list. All members
of the recipient list will see the other recipients in the 'To' field.

If auth_user is None, the EMAIL_HOST_USER setting is used.
If auth_password is None, the EMAIL_HOST_PASSWORD setting is used.

Note: The API for this method is frozen. New code wanting to extend the
functionality should use the EmailMessage class directly.
"""
connection = connection or get_connection(username=auth_user,
password=auth_password,
fail_silently=fail_silently)
mail = EmailMultiAlternatives(subject, message, from_email, recipient_list,
connection=connection)
if html_message:
mail.attach_alternative(html_message, 'text/html')

return mail.send()

[docs]def send_mass_mail(datatuple, fail_silently=False, auth_user=None,
auth_password=None, connection=None):
"""
Given a datatuple of (subject, message, from_email, recipient_list), sends
each message to each recipient list. Returns the number of emails sent.

If from_email is None, the DEFAULT_FROM_EMAIL setting is used.
If auth_user and auth_password are set, they're used to log in.
If auth_user is None, the EMAIL_HOST_USER setting is used.
If auth_password is None, the EMAIL_HOST_PASSWORD setting is used.

Note: The API for this method is frozen. New code wanting to extend the
functionality should use the EmailMessage class directly.
"""
connection = connection or get_connection(username=auth_user,
password=auth_password,
fail_silently=fail_silently)
messages = [EmailMessage(subject, message, sender, recipient,
connection=connection)
for subject, message, sender, recipient in datatuple]
return connection.send_messages(messages)

[docs]def mail_admins(subject, message, fail_silently=False, connection=None,
html_message=None):
"""Sends a message to the admins, as defined by the ADMINS setting."""
if not settings.ADMINS:
return
mail = EmailMultiAlternatives('%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject),
message, settings.SERVER_EMAIL, [a[1] for a in settings.ADMINS],
connection=connection)
if html_message:
mail.attach_alternative(html_message, 'text/html')
mail.send(fail_silently=fail_silently)

[docs]def mail_managers(subject, message, fail_silently=False, connection=None,
html_message=None):
"""Sends a message to the managers, as defined by the MANAGERS setting."""
if not settings.MANAGERS:
return
mail = EmailMultiAlternatives('%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject),
message, settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS],
connection=connection)
if html_message:
mail.attach_alternative(html_message, 'text/html')
mail.send(fail_silently=fail_silently)

Source code for django.core.paginator

import collections
from math import ceil

from django.utils import six

[docs]class InvalidPage(Exception):
pass

[docs]class PageNotAnInteger(InvalidPage):
pass

[docs]class EmptyPage(InvalidPage):
pass

[docs]class Paginator(object):

def __init__(self, object_list, per_page, orphans=0,
allow_empty_first_page=True):
self.object_list = object_list
self.per_page = int(per_page)
self.orphans = int(orphans)
self.allow_empty_first_page = allow_empty_first_page
self._num_pages = self._count = None

def validate_number(self, number):
"""
Validates the given 1-based page number.
"""
try:
number = int(number)
except (TypeError, ValueError):
raise PageNotAnInteger('That page number is not an integer')
if number < 1:
raise EmptyPage('That page number is less than 1')
if number > self.num_pages:
if number == 1 and self.allow_empty_first_page:
pass
else:
raise EmptyPage('That page contains no results')
return number

[docs]    def page(self, number):
"""
Returns a Page object for the given 1-based page number.
"""
number = self.validate_number(number)
bottom = (number - 1) * self.per_page
top = bottom + self.per_page
if top + self.orphans >= self.count:
top = self.count
return self._get_page(self.object_list[bottom:top], number, self)

def _get_page(self, *args, **kwargs):
"""
Returns an instance of a single page.

This hook can be used by subclasses to use an alternative to the
standard :cls:`Page` object.
"""
return Page(*args, **kwargs)

def _get_count(self):
"""
Returns the total number of objects, across all pages.
"""
if self._count is None:
try:
self._count = self.object_list.count()
except (AttributeError, TypeError):
# AttributeError if object_list has no count() method.
# TypeError if object_list.count() requires arguments
# (i.e. is of type list).
self._count = len(self.object_list)
return self._count
count = property(_get_count)

def _get_num_pages(self):
"""
Returns the total number of pages.
"""
if self._num_pages is None:
if self.count == 0 and not self.allow_empty_first_page:
self._num_pages = 0
else:
hits = max(1, self.count - self.orphans)
self._num_pages = int(ceil(hits / float(self.per_page)))
return self._num_pages
num_pages = property(_get_num_pages)

def _get_page_range(self):
"""
Returns a 1-based range of pages for iterating through within
a template for loop.
"""
return six.moves.range(1, self.num_pages + 1)
page_range = property(_get_page_range)

QuerySetPaginator = Paginator   # For backwards-compatibility.

[docs]class Page(collections.Sequence):

def __init__(self, object_list, number, paginator):
self.object_list = object_list
self.number = number
self.paginator = paginator

def __repr__(self):
return '<Page %s of %s>' % (self.number, self.paginator.num_pages)

def __len__(self):
return len(self.object_list)

def __getitem__(self, index):
if not isinstance(index, (slice,) + six.integer_types):
raise TypeError
# The object_list is converted to a list so that if it was a QuerySet
# it won't be a database hit per __getitem__.
if not isinstance(self.object_list, list):
self.object_list = list(self.object_list)
return self.object_list[index]

[docs]    def has_next(self):
return self.number < self.paginator.num_pages

[docs]    def has_previous(self):
return self.number > 1

[docs]    def has_other_pages(self):
return self.has_previous() or self.has_next()

[docs]    def next_page_number(self):
return self.paginator.validate_number(self.number + 1)

[docs]    def previous_page_number(self):
return self.paginator.validate_number(self.number - 1)

[docs]    def start_index(self):
"""
Returns the 1-based index of the first object on this page,
relative to total objects in the paginator.
"""
# Special case, return zero if no items.
if self.paginator.count == 0:
return 0
return (self.paginator.per_page * (self.number - 1)) + 1

[docs]    def end_index(self):
"""
Returns the 1-based index of the last object on this page,
relative to total objects found (hits).
"""
# Special case for the last page because there can be orphans.
if self.number == self.paginator.num_pages:
return self.paginator.count
return self.number * self.paginator.per_page

Source code for django.core.urlresolvers

"""
This module converts requested URLs to callback view functions.

RegexURLResolver is the main class here. Its resolve() method takes a URL (as
a string) and returns a ResolverMatch object which provides access to all
attributes of the resolved URL match.
"""
from __future__ import unicode_literals

import functools
import re
import warnings
from importlib import import_module
from threading import local

from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.http import Http404
from django.utils import lru_cache, six
from django.utils.datastructures import MultiValueDict
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_str, force_text, iri_to_uri
from django.utils.functional import cached_property, lazy
from django.utils.http import RFC3986_SUBDELIMS, urlquote
from django.utils.module_loading import module_has_submodule
from django.utils.regex_helper import normalize
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
from django.utils.translation import get_language, override

# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
# the current thread (which is the only one we ever access), it is assumed to
# be empty.
_prefixes = local()

# Overridden URLconfs for each thread are stored here.
_urlconfs = local()

[docs]class ResolverMatch(object):
def __init__(self, func, args, kwargs, url_name=None, app_names=None, namespaces=None):
self.func = func
self.args = args
self.kwargs = kwargs
self.url_name = url_name

# If a URLRegexResolver doesn't have a namespace or app_name, it passes
# in an empty value.
self.app_names = [x for x in app_names if x] if app_names else []
self.app_name = ':'.join(self.app_names)

if namespaces:
self.namespaces = [x for x in namespaces if x]
else:
self.namespaces = []
self.namespace = ':'.join(self.namespaces)

if not hasattr(func, '__name__'):
# A class-based view
self._func_path = '.'.join([func.__class__.__module__, func.__class__.__name__])
else:
# A function-based view
self._func_path = '.'.join([func.__module__, func.__name__])

view_path = url_name or self._func_path
self.view_name = ':'.join(self.namespaces + [view_path])

def __getitem__(self, index):
return (self.func, self.args, self.kwargs)[index]

def __repr__(self):
return "ResolverMatch(func=%s, args=%s, kwargs=%s, url_name=%s, app_names=%s, namespaces=%s)" % (
self._func_path, self.args, self.kwargs, self.url_name, self.app_names, self.namespaces)

[docs]class Resolver404(Http404):
pass

[docs]class NoReverseMatch(Exception):
pass

@lru_cache.lru_cache(maxsize=None)
def get_callable(lookup_view, can_fail=False):
"""
Return a callable corresponding to lookup_view. This function is used
by both resolve() and reverse(), so can_fail allows the caller to choose
between returning the input as is and raising an exception when the input
string can't be interpreted as an import path.

If lookup_view is already a callable, return it.
If lookup_view is a string import path that can be resolved to a callable,
import that callable and return it.
If lookup_view is some other kind of string and can_fail is True, the string
is returned as is. If can_fail is False, an exception is raised (either
ImportError or ViewDoesNotExist).
"""
if callable(lookup_view):
return lookup_view

if not isinstance(lookup_view, six.string_types):
raise ViewDoesNotExist(
"'%s' is not a callable or a dot-notation path" % lookup_view
)

mod_name, func_name = get_mod_func(lookup_view)
if not func_name:  # No '.' in lookup_view
if can_fail:
return lookup_view
else:
raise ImportError(
"Could not import '%s'. The path must be fully qualified." %
lookup_view)

try:
mod = import_module(mod_name)
except ImportError:
if can_fail:
return lookup_view
else:
parentmod, submod = get_mod_func(mod_name)
if submod and not module_has_submodule(import_module(parentmod), submod):
raise ViewDoesNotExist(
"Could not import '%s'. Parent module %s does not exist." %
(lookup_view, mod_name))
else:
raise
else:
try:
view_func = getattr(mod, func_name)
except AttributeError:
if can_fail:
return lookup_view
else:
raise ViewDoesNotExist(
"Could not import '%s'. View does not exist in module %s." %
(lookup_view, mod_name))
else:
if not callable(view_func):
# For backwards compatibility this is raised regardless of can_fail
raise ViewDoesNotExist(
"Could not import '%s.%s'. View is not callable." %
(mod_name, func_name))

return view_func

@lru_cache.lru_cache(maxsize=None)
def get_resolver(urlconf=None):
if urlconf is None:
from django.conf import settings
urlconf = settings.ROOT_URLCONF
return RegexURLResolver(r'^/', urlconf)

@lru_cache.lru_cache(maxsize=None)
def get_ns_resolver(ns_pattern, resolver):
# Build a namespaced resolver for the given parent URLconf pattern.
# This makes it possible to have captured parameters in the parent
# URLconf pattern.
ns_resolver = RegexURLResolver(ns_pattern, resolver.url_patterns)
return RegexURLResolver(r'^/', [ns_resolver])

def get_mod_func(callback):
# Converts 'django.views.news.stories.story_detail' to
# ['django.views.news.stories', 'story_detail']
try:
dot = callback.rindex('.')
except ValueError:
return callback, ''
return callback[:dot], callback[dot + 1:]

class LocaleRegexProvider(object):
"""
A mixin to provide a default regex property which can vary by active
language.
"""
def __init__(self, regex):
# regex is either a string representing a regular expression, or a
# translatable string (using ugettext_lazy) representing a regular
# expression.
self._regex = regex
self._regex_dict = {}

@property
def regex(self):
"""
Returns a compiled regular expression, depending upon the activated
language-code.
"""
language_code = get_language()
if language_code not in self._regex_dict:
if isinstance(self._regex, six.string_types):
regex = self._regex
else:
regex = force_text(self._regex)
try:
compiled_regex = re.compile(regex, re.UNICODE)
except re.error as e:
raise ImproperlyConfigured(
'"%s" is not a valid regular expression: %s' %
(regex, six.text_type(e)))

self._regex_dict[language_code] = compiled_regex
return self._regex_dict[language_code]

class RegexURLPattern(LocaleRegexProvider):
def __init__(self, regex, callback, default_args=None, name=None):
LocaleRegexProvider.__init__(self, regex)
# callback is either a string like 'foo.views.news.stories.story_detail'
# which represents the path to a module and a view function name, or a
# callable object (view).
if callable(callback):
self._callback = callback
else:
self._callback = None
self._callback_str = callback
self.default_args = default_args or {}
self.name = name

def __repr__(self):
return force_str('<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern))

def add_prefix(self, prefix):
"""
Adds the prefix string to a string-based callback.
"""
if not prefix or not hasattr(self, '_callback_str'):
return
self._callback_str = prefix + '.' + self._callback_str

def resolve(self, path):
match = self.regex.search(path)
if match:
# If there are any named groups, use those as kwargs, ignoring
# non-named groups. Otherwise, pass all non-named arguments as
# positional arguments.
kwargs = match.groupdict()
if kwargs:
args = ()
else:
args = match.groups()
# In both cases, pass any extra_kwargs as **kwargs.
kwargs.update(self.default_args)

return ResolverMatch(self.callback, args, kwargs, self.name)

@property
def callback(self):
if self._callback is not None:
return self._callback

self._callback = get_callable(self._callback_str)
return self._callback

class RegexURLResolver(LocaleRegexProvider):
def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
LocaleRegexProvider.__init__(self, regex)
# urlconf_name is the dotted Python path to the module defining
# urlpatterns. It may also be an object with an urlpatterns attribute
# or urlpatterns itself.
self.urlconf_name = urlconf_name
self.callback = None
self.default_kwargs = default_kwargs or {}
self.namespace = namespace
self.app_name = app_name
self._reverse_dict = {}
self._namespace_dict = {}
self._app_dict = {}
# set of dotted paths to all functions and classes that are used in
# urlpatterns
self._callback_strs = set()
self._populated = False

def __repr__(self):
if isinstance(self.urlconf_name, list) and len(self.urlconf_name):
# Don't bother to output the whole list, it can be huge
urlconf_repr = '<%s list>' % self.urlconf_name[0].__class__.__name__
else:
urlconf_repr = repr(self.urlconf_name)
return str('<%s %s (%s:%s) %s>') % (
self.__class__.__name__, urlconf_repr, self.app_name,
self.namespace, self.regex.pattern)

def _populate(self):
lookups = MultiValueDict()
namespaces = {}
apps = {}
language_code = get_language()
for pattern in reversed(self.url_patterns):
if hasattr(pattern, '_callback_str'):
self._callback_strs.add(pattern._callback_str)
elif hasattr(pattern, '_callback'):
callback = pattern._callback
if isinstance(callback, functools.partial):
callback = callback.func

if not hasattr(callback, '__name__'):
lookup_str = callback.__module__ + "." + callback.__class__.__name__
else:
lookup_str = callback.__module__ + "." + callback.__name__
self._callback_strs.add(lookup_str)
p_pattern = pattern.regex.pattern
if p_pattern.startswith('^'):
p_pattern = p_pattern[1:]
if isinstance(pattern, RegexURLResolver):
if pattern.namespace:
namespaces[pattern.namespace] = (p_pattern, pattern)
if pattern.app_name:
apps.setdefault(pattern.app_name, []).append(pattern.namespace)
else:
parent_pat = pattern.regex.pattern
for name in pattern.reverse_dict:
for matches, pat, defaults in pattern.reverse_dict.getlist(name):
new_matches = normalize(parent_pat + pat)
lookups.appendlist(
name,
(
new_matches,
p_pattern + pat,
dict(defaults, **pattern.default_kwargs),
)
)
for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
namespaces[namespace] = (p_pattern + prefix, sub_pattern)
for app_name, namespace_list in pattern.app_dict.items():
apps.setdefault(app_name, []).extend(namespace_list)
self._callback_strs.update(pattern._callback_strs)
else:
bits = normalize(p_pattern)
lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args))
if pattern.name is not None:
lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args))
self._reverse_dict[language_code] = lookups
self._namespace_dict[language_code] = namespaces
self._app_dict[language_code] = apps
self._populated = True

@property
def reverse_dict(self):
language_code = get_language()
if language_code not in self._reverse_dict:
self._populate()
return self._reverse_dict[language_code]

@property
def namespace_dict(self):
language_code = get_language()
if language_code not in self._namespace_dict:
self._populate()
return self._namespace_dict[language_code]

@property
def app_dict(self):
language_code = get_language()
if language_code not in self._app_dict:
self._populate()
return self._app_dict[language_code]

def _is_callback(self, name):
if not self._populated:
self._populate()
return name in self._callback_strs

def resolve(self, path):
path = force_text(path)  # path may be a reverse_lazy object
tried = []
match = self.regex.search(path)
if match:
new_path = path[match.end():]
for pattern in self.url_patterns:
try:
sub_match = pattern.resolve(new_path)
except Resolver404 as e:
sub_tried = e.args[0].get('tried')
if sub_tried is not None:
tried.extend([pattern] + t for t in sub_tried)
else:
tried.append([pattern])
else:
if sub_match:
# Merge captured arguments in match with submatch
sub_match_dict = dict(match.groupdict(), **self.default_kwargs)
sub_match_dict.update(sub_match.kwargs)

# If there are *any* named groups, ignore all non-named groups.
# Otherwise, pass all non-named arguments as positional arguments.
sub_match_args = sub_match.args
if not sub_match_dict:
sub_match_args = match.groups() + sub_match.args

return ResolverMatch(
sub_match.func,
sub_match_args,
sub_match_dict,
sub_match.url_name,
[self.app_name] + sub_match.app_names,
[self.namespace] + sub_match.namespaces
)
tried.append([pattern])
raise Resolver404({'tried': tried, 'path': new_path})
raise Resolver404({'path': path})

@cached_property
def urlconf_module(self):
if isinstance(self.urlconf_name, six.string_types):
return import_module(self.urlconf_name)
else:
return self.urlconf_name

@cached_property
def url_patterns(self):
# urlconf_module might be a valid set of patterns, so we default to it
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
try:
iter(patterns)
except TypeError:
msg = (
"The included URLconf '{name}' does not appear to have any "
"patterns in it. If you see valid patterns in the file then "
"the issue is probably caused by a circular import."
)
raise ImproperlyConfigured(msg.format(name=self.urlconf_name))
return patterns

def resolve_error_handler(self, view_type):
callback = getattr(self.urlconf_module, 'handler%s' % view_type, None)
if not callback:
# No handler specified in file; use default
# Lazy import, since django.urls imports this file
from django.conf import urls
callback = getattr(urls, 'handler%s' % view_type)
return get_callable(callback), {}

def reverse(self, lookup_view, *args, **kwargs):
return self._reverse_with_prefix(lookup_view, '', *args, **kwargs)

def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
if args and kwargs:
raise ValueError("Don't mix *args and **kwargs in call to reverse()!")
text_args = [force_text(v) for v in args]
text_kwargs = {k: force_text(v) for (k, v) in kwargs.items()}

if not self._populated:
self._populate()

original_lookup = lookup_view
try:
if self._is_callback(lookup_view):
lookup_view = get_callable(lookup_view, True)
except (ImportError, AttributeError) as e:
raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e))
else:
if not callable(original_lookup) and callable(lookup_view):
warnings.warn(
'Reversing by dotted path is deprecated (%s).' % original_lookup,
RemovedInDjango110Warning, stacklevel=3
)
possibilities = self.reverse_dict.getlist(lookup_view)

for possibility, pattern, defaults in possibilities:
for result, params in possibility:
if args:
if len(args) != len(params):
continue
candidate_subs = dict(zip(params, text_args))
else:
if (set(kwargs.keys()) | set(defaults.keys()) != set(params) |
set(defaults.keys())):
continue
matches = True
for k, v in defaults.items():
if kwargs.get(k, v) != v:
matches = False
break
if not matches:
continue
candidate_subs = text_kwargs
# WSGI provides decoded URLs, without %xx escapes, and the URL
# resolver operates on such URLs. First substitute arguments
# without quoting to build a decoded URL and look for a match.
# Then, if we have a match, redo the substitution with quoted
# arguments in order to return a properly encoded URL.
candidate_pat = _prefix.replace('%', '%%') + result
if re.search('^%s%s' % (re.escape(_prefix), pattern), candidate_pat % candidate_subs, re.UNICODE):
# safe characters from `pchar` definition of RFC 3986
url = urlquote(candidate_pat % candidate_subs, safe=RFC3986_SUBDELIMS + str('/~:@'))
# Don't allow construction of scheme relative urls.
if url.startswith('//'):
url = '/%%2F%s' % url[2:]
return url
# lookup_view can be URL label, or dotted path, or callable, Any of
# these can be passed in at the top, but callables are not friendly in
# error messages.
m = getattr(lookup_view, '__module__', None)
n = getattr(lookup_view, '__name__', None)
if m is not None and n is not None:
lookup_view_s = "%s.%s" % (m, n)
else:
lookup_view_s = lookup_view

patterns = [pattern for (possibility, pattern, defaults) in possibilities]
raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword "
"arguments '%s' not found. %d pattern(s) tried: %s" %
(lookup_view_s, args, kwargs, len(patterns), patterns))

class LocaleRegexURLResolver(RegexURLResolver):
"""
A URL resolver that always matches the active language code as URL prefix.

Rather than taking a regex argument, we just override the ``regex``
function to always return the active language-code as regex.
"""
def __init__(self, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
super(LocaleRegexURLResolver, self).__init__(
None, urlconf_name, default_kwargs, app_name, namespace)

@property
def regex(self):
language_code = get_language()
if language_code not in self._regex_dict:
regex_compiled = re.compile('^%s/' % language_code, re.UNICODE)
self._regex_dict[language_code] = regex_compiled
return self._regex_dict[language_code]

[docs]def resolve(path, urlconf=None):
if urlconf is None:
urlconf = get_urlconf()
return get_resolver(urlconf).resolve(path)

[docs]def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
if urlconf is None:
urlconf = get_urlconf()
resolver = get_resolver(urlconf)
args = args or []
kwargs = kwargs or {}

prefix = get_script_prefix()

if not isinstance(viewname, six.string_types):
view = viewname
else:
parts = viewname.split(':')
parts.reverse()
view = parts[0]
path = parts[1:]

if current_app:
current_path = current_app.split(':')
current_path.reverse()
else:
current_path = None

resolved_path = []
ns_pattern = ''
while path:
ns = path.pop()
current_ns = current_path.pop() if current_path else None

# Lookup the name to see if it could be an app identifier
try:
app_list = resolver.app_dict[ns]
# Yes! Path part matches an app in the current Resolver
if current_ns and current_ns in app_list:
# If we are reversing for a particular app,
# use that namespace
ns = current_ns
elif ns not in app_list:
# The name isn't shared by one of the instances
# (i.e., the default) so just pick the first instance
# as the default.
ns = app_list[0]
except KeyError:
pass

if ns != current_ns:
current_path = None

try:
extra, resolver = resolver.namespace_dict[ns]
resolved_path.append(ns)
ns_pattern = ns_pattern + extra
except KeyError as key:
if resolved_path:
raise NoReverseMatch(
"%s is not a registered namespace inside '%s'" %
(key, ':'.join(resolved_path)))
else:
raise NoReverseMatch("%s is not a registered namespace" %
key)
if ns_pattern:
resolver = get_ns_resolver(ns_pattern, resolver)

return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))

reverse_lazy = lazy(reverse, six.text_type)

def clear_url_caches():
get_callable.cache_clear()
get_resolver.cache_clear()
get_ns_resolver.cache_clear()

def set_script_prefix(prefix):
"""
Sets the script prefix for the current thread.
"""
if not prefix.endswith('/'):
prefix += '/'
_prefixes.value = prefix

[docs]def get_script_prefix():
"""
Returns the currently active script prefix. Useful for client code that
wishes to construct their own URLs manually (although accessing the request
instance is normally going to be a lot cleaner).
"""
return getattr(_prefixes, "value", '/')

def clear_script_prefix():
"""
Unsets the script prefix for the current thread.
"""
try:
del _prefixes.value
except AttributeError:
pass

def set_urlconf(urlconf_name):
"""
Sets the URLconf for the current thread (overriding the default one in
settings). Set to None to revert back to the default.
"""
if urlconf_name:
_urlconfs.value = urlconf_name
else:
if hasattr(_urlconfs, "value"):
del _urlconfs.value

def get_urlconf(default=None):
"""
Returns the root URLconf to use for the current thread if it has been
changed from the default one.
"""
return getattr(_urlconfs, "value", default)

def is_valid_path(path, urlconf=None):
"""
Returns True if the given path resolves against the default URL resolver,
False otherwise.

This is a convenience method to make working with "is this a match?" cases
easier, avoiding unnecessarily indented try...except blocks.
"""
try:
resolve(path, urlconf)
return True
except Resolver404:
return False

def translate_url(url, lang_code):
"""
Given a URL (absolute or relative), try to get its translated version in
the `lang_code` language (either by i18n_patterns or by translated regex).
Return the original URL if no translated version is found.
"""
parsed = urlsplit(url)
try:
match = resolve(parsed.path)
except Resolver404:
pass
else:
to_be_reversed = "%s:%s" % (match.namespace, match.url_name) if match.namespace else match.url_name
with override(lang_code):
try:
url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs)
except NoReverseMatch:
pass
else:
url = urlunsplit((parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment))
return url

Source code for django.core.validators

from __future__ import unicode_literals

import re

from django.core.exceptions import ValidationError
from django.utils import six
from django.utils.deconstruct import deconstructible
from django.utils.encoding import force_text
from django.utils.functional import SimpleLazyObject
from django.utils.ipv6 import is_valid_ipv6_address
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
from django.utils.translation import ugettext_lazy as _, ungettext_lazy

# These values, if given to validate(), will trigger the self.required check.
EMPTY_VALUES = (None, '', [], (), {})

def _lazy_re_compile(regex, flags=0):
"""Lazily compile a regex with flags."""
def _compile():
# Compile the regex if it was not passed pre-compiled.
if isinstance(regex, six.string_types):
return re.compile(regex, flags)
else:
assert not flags, "flags must be empty if regex is passed pre-compiled"
return regex
return SimpleLazyObject(_compile)

@deconstructible

[docs]class RegexValidator(object):
regex = ''
message = _('Enter a valid value.')
code = 'invalid'
inverse_match = False
flags = 0

def __init__(self, regex=None, message=None, code=None, inverse_match=None, flags=None):
if regex is not None:
self.regex = regex
if message is not None:
self.message = message
if code is not None:
self.code = code
if inverse_match is not None:
self.inverse_match = inverse_match
if flags is not None:
self.flags = flags
if self.flags and not isinstance(self.regex, six.string_types):
raise TypeError("If the flags are set, regex must be a regular expression string.")

self.regex = _lazy_re_compile(self.regex, self.flags)

def __call__(self, value):
"""
Validates that the input matches the regular expression
if inverse_match is False, otherwise raises ValidationError.
"""
if not (self.inverse_match is not bool(self.regex.search(
force_text(value)))):
raise ValidationError(self.message, code=self.code)

def __eq__(self, other):
return (
isinstance(other, RegexValidator) and
self.regex.pattern == other.regex.pattern and
self.regex.flags == other.regex.flags and
(self.message == other.message) and
(self.code == other.code) and
(self.inverse_match == other.inverse_match)
)

def __ne__(self, other):
return not (self == other)

@deconstructible

[docs]class URLValidator(RegexValidator):
ul = '\u00a1-\uffff'  # unicode letters range (must be a unicode string, not a raw string)

# IP patterns
ipv4_re = r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
ipv6_re = r'\[[0-9a-f:\.]+\]'  # (simple regex, validated later)

# Host patterns
hostname_re = r'[a-z' + ul + r'0-9](?:[a-z' + ul + r'0-9-]*[a-z' + ul + r'0-9])?'
domain_re = r'(?:\.(?!-)[a-z' + ul + r'0-9-]+(?<!-))*'
tld_re = (
'\.'                                # dot
'(?!-)'                             # can't start with a dash
'(?:[a-z' + ul + '-]{2,}'           # domain label
'|xn--[a-z0-9]+)'                   # or punycode label
'(?<!-)'                            # can't end with a dash
'\.?'                               # may have a trailing dot
)
host_re = '(' + hostname_re + domain_re + tld_re + '|localhost)'

regex = _lazy_re_compile(
r'^(?:[a-z0-9\.\-]*)://'  # scheme is validated separately
r'(?:\S+(?::\S*)?@)?'  # user:pass authentication
r'(?:' + ipv4_re + '|' + ipv6_re + '|' + host_re + ')'
r'(?::\d{2,5})?'  # port
r'(?:[/?#][^\s]*)?'  # resource path
r'\Z', re.IGNORECASE)
message = _('Enter a valid URL.')
schemes = ['http', 'https', 'ftp', 'ftps']

def __init__(self, schemes=None, **kwargs):
super(URLValidator, self).__init__(**kwargs)
if schemes is not None:
self.schemes = schemes

def __call__(self, value):
value = force_text(value)
# Check first if the scheme is valid
scheme = value.split('://')[0].lower()
if scheme not in self.schemes:
raise ValidationError(self.message, code=self.code)

# Then check full URL
try:
super(URLValidator, self).__call__(value)
except ValidationError as e:
# Trivial case failed. Try for possible IDN domain
if value:
scheme, netloc, path, query, fragment = urlsplit(value)
try:
netloc = netloc.encode('idna').decode('ascii')  # IDN -> ACE
except UnicodeError:  # invalid domain part
raise e
url = urlunsplit((scheme, netloc, path, query, fragment))
super(URLValidator, self).__call__(url)
else:
raise
else:
# Now verify IPv6 in the netloc part
host_match = re.search(r'^\[(.+)\](?::\d{2,5})?$', urlsplit(value).netloc)
if host_match:
potential_ip = host_match.groups()[0]
try:
validate_ipv6_address(potential_ip)
except ValidationError:
raise ValidationError(self.message, code=self.code)
url = value

integer_validator = RegexValidator(
_lazy_re_compile('^-?\d+\Z'),
message=_('Enter a valid integer.'),
code='invalid',
)

def validate_integer(value):
return integer_validator(value)

@deconstructible

[docs]class EmailValidator(object):
message = _('Enter a valid email address.')
code = 'invalid'
user_regex = _lazy_re_compile(
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z"  # dot-atom
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)',  # quoted-string
re.IGNORECASE)
domain_regex = _lazy_re_compile(
# max length for domain name labels is 63 characters per RFC 1034
r'((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63}(?<!-))\Z',
re.IGNORECASE)
literal_regex = _lazy_re_compile(
# literal form, ipv4 or ipv6 address (SMTP 4.1.3)
r'\[([A-f0-9:\.]+)\]\Z',
re.IGNORECASE)
domain_whitelist = ['localhost']

def __init__(self, message=None, code=None, whitelist=None):
if message is not None:
self.message = message
if code is not None:
self.code = code
if whitelist is not None:
self.domain_whitelist = whitelist

def __call__(self, value):
value = force_text(value)

if not value or '@' not in value:
raise ValidationError(self.message, code=self.code)

user_part, domain_part = value.rsplit('@', 1)

if not self.user_regex.match(user_part):
raise ValidationError(self.message, code=self.code)

if (domain_part not in self.domain_whitelist and
not self.validate_domain_part(domain_part)):
# Try for possible IDN domain-part
try:
domain_part = domain_part.encode('idna').decode('ascii')
if self.validate_domain_part(domain_part):
return
except UnicodeError:
pass
raise ValidationError(self.message, code=self.code)

def validate_domain_part(self, domain_part):
if self.domain_regex.match(domain_part):
return True

literal_match = self.literal_regex.match(domain_part)
if literal_match:
ip_address = literal_match.group(1)
try:
validate_ipv46_address(ip_address)
return True
except ValidationError:
pass
return False

def __eq__(self, other):
return (
isinstance(other, EmailValidator) and
(self.domain_whitelist == other.domain_whitelist) and
(self.message == other.message) and
(self.code == other.code)
)

validate_email = EmailValidator()

slug_re = _lazy_re_compile(r'^[-a-zA-Z0-9_]+\Z')
validate_slug = RegexValidator(
slug_re,
_("Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."),
'invalid'
)

slug_unicode_re = _lazy_re_compile(r'^[-\w]+\Z', re.U)
validate_unicode_slug = RegexValidator(
slug_unicode_re,
_("Enter a valid 'slug' consisting of Unicode letters, numbers, underscores, or hyphens."),
'invalid'
)

ipv4_re = _lazy_re_compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z')
validate_ipv4_address = RegexValidator(ipv4_re, _('Enter a valid IPv4 address.'), 'invalid')

[docs]def validate_ipv6_address(value):
if not is_valid_ipv6_address(value):
raise ValidationError(_('Enter a valid IPv6 address.'), code='invalid')

[docs]def validate_ipv46_address(value):
try:
validate_ipv4_address(value)
except ValidationError:
try:
validate_ipv6_address(value)
except ValidationError:
raise ValidationError(_('Enter a valid IPv4 or IPv6 address.'), code='invalid')

ip_address_validator_map = {
'both': ([validate_ipv46_address], _('Enter a valid IPv4 or IPv6 address.')),
'ipv4': ([validate_ipv4_address], _('Enter a valid IPv4 address.')),
'ipv6': ([validate_ipv6_address], _('Enter a valid IPv6 address.')),
}

def ip_address_validators(protocol, unpack_ipv4):
"""
Depending on the given parameters returns the appropriate validators for
the GenericIPAddressField.

This code is here, because it is exactly the same for the model and the form field.
"""
if protocol != 'both' and unpack_ipv4:
raise ValueError(
"You can only use `unpack_ipv4` if `protocol` is set to 'both'")
try:
return ip_address_validator_map[protocol.lower()]
except KeyError:
raise ValueError("The protocol '%s' is unknown. Supported: %s"
% (protocol, list(ip_address_validator_map)))

[docs]def int_list_validator(sep=',', message=None, code='invalid'):
regexp = _lazy_re_compile('^\d+(?:%s\d+)*\Z' % re.escape(sep))
return RegexValidator(regexp, message=message, code=code)

validate_comma_separated_integer_list = int_list_validator(
message=_('Enter only digits separated by commas.'),
)

@deconstructible
class BaseValidator(object):
compare = lambda self, a, b: a is not b
clean = lambda self, x: x
message = _('Ensure this value is %(limit_value)s (it is %(show_value)s).')
code = 'limit_value'

def __init__(self, limit_value, message=None):
self.limit_value = limit_value
if message:
self.message = message

def __call__(self, value):
cleaned = self.clean(value)
params = {'limit_value': self.limit_value, 'show_value': cleaned, 'value': value}
if self.compare(cleaned, self.limit_value):
raise ValidationError(self.message, code=self.code, params=params)

def __eq__(self, other):
return (
isinstance(other, self.__class__) and
(self.limit_value == other.limit_value)
and (self.message == other.message)
and (self.code == other.code)
)

@deconstructible

[docs]class MaxValueValidator(BaseValidator):
compare = lambda self, a, b: a > b
message = _('Ensure this value is less than or equal to %(limit_value)s.')
code = 'max_value'

@deconstructible

[docs]class MinValueValidator(BaseValidator):
compare = lambda self, a, b: a < b
message = _('Ensure this value is greater than or equal to %(limit_value)s.')
code = 'min_value'

@deconstructible

[docs]class MinLengthValidator(BaseValidator):
compare = lambda self, a, b: a < b
clean = lambda self, x: len(x)
message = ungettext_lazy(
'Ensure this value has at least %(limit_value)d character (it has %(show_value)d).',
'Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).',
'limit_value')
code = 'min_length'

@deconstructible

[docs]class MaxLengthValidator(BaseValidator):
compare = lambda self, a, b: a > b
clean = lambda self, x: len(x)
message = ungettext_lazy(
'Ensure this value has at most %(limit_value)d character (it has %(show_value)d).',
'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).',
'limit_value')
code = 'max_length'

@deconstructible

[docs]class DecimalValidator(object):
"""
Validate that the input does not exceed the maximum number of digits
expected, otherwise raise ValidationError.
"""
messages = {
'max_digits': ungettext_lazy(
'Ensure that there are no more than %(max)s digit in total.',
'Ensure that there are no more than %(max)s digits in total.',
'max'
),
'max_decimal_places': ungettext_lazy(
'Ensure that there are no more than %(max)s decimal place.',
'Ensure that there are no more than %(max)s decimal places.',
'max'
),
'max_whole_digits': ungettext_lazy(
'Ensure that there are no more than %(max)s digit before the decimal point.',
'Ensure that there are no more than %(max)s digits before the decimal point.',
'max'
),
}

def __init__(self, max_digits, decimal_places):
self.max_digits = max_digits
self.decimal_places = decimal_places

def __call__(self, value):
digit_tuple, exponent = value.as_tuple()[1:]
decimals = abs(exponent)
# digit_tuple doesn't include any leading zeros.
digits = len(digit_tuple)
if decimals > digits:
# We have leading zeros up to or past the decimal point. Count
# everything past the decimal point as a digit. We do not count
# 0 before the decimal point as a digit since that would mean
# we would not allow max_digits = decimal_places.
digits = decimals
whole_digits = digits - decimals

if self.max_digits is not None and digits > self.max_digits:
raise ValidationError(
self.messages['max_digits'],
code='max_digits',
params={'max': self.max_digits},
)
if self.decimal_places is not None and decimals > self.decimal_places:
raise ValidationError(
self.messages['max_decimal_places'],
code='max_decimal_places',
params={'max': self.decimal_places},
)
if (self.max_digits is not None and self.decimal_places is not None
and whole_digits > (self.max_digits - self.decimal_places)):
raise ValidationError(
self.messages['max_whole_digits'],
code='max_whole_digits',
params={'max': (self.max_digits - self.decimal_places)},
)

def __eq__(self, other):
return (
isinstance(other, self.__class__) and
self.max_digits == other.max_digits and
self.decimal_places == other.decimal_places
)

Source code for django.core.exceptions

"""
Global Django exception and warning classes.
"""
from django.utils import six
from django.utils.encoding import force_text

[docs]class FieldDoesNotExist(Exception):
"""The requested model field does not exist"""
pass

class DjangoRuntimeWarning(RuntimeWarning):
pass

class AppRegistryNotReady(Exception):
"""The django.apps registry is not populated yet"""
pass

[docs]class ObjectDoesNotExist(Exception):
"""The requested object does not exist"""
silent_variable_failure = True

[docs]class MultipleObjectsReturned(Exception):
"""The query returned multiple objects when only one was expected."""
pass

[docs]class SuspiciousOperation(Exception):
"""The user did something suspicious"""

class SuspiciousMultipartForm(SuspiciousOperation):
"""Suspect MIME request in multipart form data"""
pass

class SuspiciousFileOperation(SuspiciousOperation):
"""A Suspicious filesystem operation was attempted"""
pass

class DisallowedHost(SuspiciousOperation):
"""HTTP_HOST header contains invalid value"""
pass

class DisallowedRedirect(SuspiciousOperation):
"""Redirect to scheme not in allowed list"""
pass

[docs]class PermissionDenied(Exception):
"""The user did not have permission to do that"""
pass

[docs]class ViewDoesNotExist(Exception):
"""The requested view does not exist"""
pass

[docs]class MiddlewareNotUsed(Exception):
"""This middleware is not used in this server configuration"""
pass

[docs]class ImproperlyConfigured(Exception):
"""Django is somehow improperly configured"""
pass

[docs]class FieldError(Exception):
"""Some kind of problem with a model field."""
pass

NON_FIELD_ERRORS = '__all__'

[docs]class ValidationError(Exception):
"""An error while validating data."""
def __init__(self, message, code=None, params=None):
"""
The `message` argument can be a single error, a list of errors, or a
dictionary that maps field names to lists of errors. What we define as
an "error" can be either a simple string or an instance of
ValidationError with its message attribute set, and what we define as
list or dictionary can be an actual `list` or `dict` or an instance
of ValidationError with its `error_list` or `error_dict` attribute set.
"""

# PY2 can't pickle naive exception: http://bugs.python.org/issue1692335.
super(ValidationError, self).__init__(message, code, params)

if isinstance(message, ValidationError):
if hasattr(message, 'error_dict'):
message = message.error_dict
# PY2 has a `message` property which is always there so we can't
# duck-type on it. It was introduced in Python 2.5 and already
# deprecated in Python 2.6.
elif not hasattr(message, 'message' if six.PY3 else 'code'):
message = message.error_list
else:
message, code, params = message.message, message.code, message.params

if isinstance(message, dict):
self.error_dict = {}
for field, messages in message.items():
if not isinstance(messages, ValidationError):
messages = ValidationError(messages)
self.error_dict[field] = messages.error_list

elif isinstance(message, list):
self.error_list = []
for message in message:
# Normalize plain strings to instances of ValidationError.
if not isinstance(message, ValidationError):
message = ValidationError(message)
if hasattr(message, 'error_dict'):
self.error_list.extend(sum(message.error_dict.values(), []))
else:
self.error_list.extend(message.error_list)

else:
self.message = message
self.code = code
self.params = params
self.error_list = [self]

@property
def message_dict(self):
# Trigger an AttributeError if this ValidationError
# doesn't have an error_dict.
getattr(self, 'error_dict')

return dict(self)

@property
def messages(self):
if hasattr(self, 'error_dict'):
return sum(dict(self).values(), [])
return list(self)

def update_error_dict(self, error_dict):
if hasattr(self, 'error_dict'):
for field, error_list in self.error_dict.items():
error_dict.setdefault(field, []).extend(error_list)
else:
error_dict.setdefault(NON_FIELD_ERRORS, []).extend(self.error_list)
return error_dict

def __iter__(self):
if hasattr(self, 'error_dict'):
for field, errors in self.error_dict.items():
yield field, list(ValidationError(errors))
else:
for error in self.error_list:
message = error.message
if error.params:
message %= error.params
yield force_text(message)

def __str__(self):
if hasattr(self, 'error_dict'):
return repr(dict(self))
return repr(list(self))

def __repr__(self):
return 'ValidationError(%s)' % self

Source code for django.core.files.base

from __future__ import unicode_literals

import os
from io import BytesIO, StringIO, UnsupportedOperation

from django.core.files.utils import FileProxyMixin
from django.utils import six
from django.utils.encoding import (
force_bytes, force_str, python_2_unicode_compatible, smart_text,
)

@python_2_unicode_compatible

[docs]class File(FileProxyMixin):
DEFAULT_CHUNK_SIZE = 64 * 2 ** 10

def __init__(self, file, name=None):
self.file = file
if name is None:
name = getattr(file, 'name', None)
self.name = name
if hasattr(file, 'mode'):
self.mode = file.mode

def __str__(self):
return smart_text(self.name or '')

def __repr__(self):
return force_str("<%s: %s>" % (self.__class__.__name__, self or "None"))

def __bool__(self):
return bool(self.name)

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

def __len__(self):
return self.size

def _get_size_from_underlying_file(self):
if hasattr(self.file, 'size'):
return self.file.size
if hasattr(self.file, 'name'):
try:
return os.path.getsize(self.file.name)
except (OSError, TypeError):
pass
if hasattr(self.file, 'tell') and hasattr(self.file, 'seek'):
pos = self.file.tell()
self.file.seek(0, os.SEEK_END)
size = self.file.tell()
self.file.seek(pos)
return size
raise AttributeError("Unable to determine the file's size.")

def _get_size(self):
if hasattr(self, '_size'):
return self._size
self._size = self._get_size_from_underlying_file()
return self._size

def _set_size(self, size):
self._size = size

size = property(_get_size, _set_size)

def _get_closed(self):
return not self.file or self.file.closed
closed = property(_get_closed)

[docs]    def chunks(self, chunk_size=None):
"""
Read the file and yield chunks of ``chunk_size`` bytes (defaults to
``UploadedFile.DEFAULT_CHUNK_SIZE``).
"""
if not chunk_size:
chunk_size = self.DEFAULT_CHUNK_SIZE

try:
self.seek(0)
except (AttributeError, UnsupportedOperation):
pass

while True:
data = self.read(chunk_size)
if not data:
break
yield data

[docs]    def multiple_chunks(self, chunk_size=None):
"""
Returns ``True`` if you can expect multiple chunks.

NB: If a particular file representation is in memory, subclasses should
always return ``False`` -- there's no good reason to read from memory in
chunks.
"""
if not chunk_size:
chunk_size = self.DEFAULT_CHUNK_SIZE
return self.size > chunk_size

[docs]    def __iter__(self):
# Iterate over this file-like object by newlines
buffer_ = None
for chunk in self.chunks():
for line in chunk.splitlines(True):
if buffer_:
if endswith_cr(buffer_) and not equals_lf(line):
# Line split after a \r newline; yield buffer_.
yield buffer_
# Continue with line.
else:
# Line either split without a newline (line
# continues after buffer_) or with \r\n
# newline (line == b'\n').
line = buffer_ + line
# buffer_ handled, clear it.
buffer_ = None

# If this is the end of a \n or \r\n line, yield.
if endswith_lf(line):
yield line
else:
buffer_ = line

if buffer_ is not None:
yield buffer_

def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, tb):
self.close()

[docs]    def open(self, mode=None):
if not self.closed:
self.seek(0)
elif self.name and os.path.exists(self.name):
self.file = open(self.name, mode or self.mode)
else:
raise ValueError("The file cannot be reopened.")

[docs]    def close(self):
self.file.close()

@python_2_unicode_compatible

[docs]class ContentFile(File):
"""
A File-like object that takes just raw content, rather than an actual file.
"""
def __init__(self, content, name=None):
if six.PY3:
stream_class = StringIO if isinstance(content, six.text_type) else BytesIO
else:
stream_class = BytesIO
content = force_bytes(content)
super(ContentFile, self).__init__(stream_class(content), name=name)
self.size = len(content)

def __str__(self):
return 'Raw content'

def __bool__(self):
return True

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

def open(self, mode=None):
self.seek(0)

def close(self):
pass

def endswith_cr(line):
"""
Return True if line (a text or byte string) ends with '\r'.
"""
return line.endswith('\r' if isinstance(line, six.text_type) else b'\r')

def endswith_lf(line):
"""
Return True if line (a text or byte string) ends with '\n'.
"""
return line.endswith('\n' if isinstance(line, six.text_type) else b'\n')

def equals_lf(line):
"""
Return True if line (a text or byte string) equals '\n'.
"""
return line == ('\n' if isinstance(line, six.text_type) else b'\n')

Source code for django.core.files.uploadhandler

"""
Base file upload handler classes, and the built-in concrete subclasses
"""

from __future__ import unicode_literals

from io import BytesIO

from django.conf import settings
from django.core.files.uploadedfile import (
InMemoryUploadedFile, TemporaryUploadedFile,
)
from django.utils.encoding import python_2_unicode_compatible
from django.utils.module_loading import import_string

__all__ = [
'UploadFileException', 'StopUpload', 'SkipFile', 'FileUploadHandler',
'TemporaryFileUploadHandler', 'MemoryFileUploadHandler', 'load_handler',
'StopFutureHandlers'
]

class UploadFileException(Exception):
"""
Any error having to do with uploading files.
"""
pass

@python_2_unicode_compatible
class StopUpload(UploadFileException):
"""
This exception is raised when an upload must abort.
"""
def __init__(self, connection_reset=False):
"""
If ``connection_reset`` is ``True``, Django knows will halt the upload
without consuming the rest of the upload. This will cause the browser to
show a "connection reset" error.
"""
self.connection_reset = connection_reset

def __str__(self):
if self.connection_reset:
return 'StopUpload: Halt current upload.'
else:
return 'StopUpload: Consume request data, then halt.'

class SkipFile(UploadFileException):
"""
This exception is raised by an upload handler that wants to skip a given file.
"""
pass

class StopFutureHandlers(UploadFileException):
"""
Upload handers that have handled a file and do not want future handlers to
run should raise this exception instead of returning None.
"""
pass

[docs]class FileUploadHandler(object):
"""
Base class for streaming upload handlers.
"""
chunk_size = 64 * 2 ** 10  # : The default chunk size is 64 KB.

def __init__(self, request=None):
self.file_name = None
self.content_type = None
self.content_length = None
self.charset = None
self.content_type_extra = None
self.request = request

[docs]    def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
"""
Handle the raw input from the client.

Parameters:

:input_data:
An object that supports reading via .read().
:META:
``request.META``.
:content_length:
The (integer) value of the Content-Length header from the
client.
:boundary: The boundary from the Content-Type header. Be sure to
prepend two '--'.
"""
pass

[docs]    def new_file(self, field_name, file_name, content_type, content_length, charset=None, content_type_extra=None):
"""
Signal that a new file has been started.

Warning: As with any data from the client, you should not trust
content_length (and sometimes won't even get it).
"""
self.field_name = field_name
self.file_name = file_name
self.content_type = content_type
self.content_length = content_length
self.charset = charset
self.content_type_extra = content_type_extra

[docs]    def receive_data_chunk(self, raw_data, start):
"""
Receive data from the streamed upload parser. ``start`` is the position
in the file of the chunk.
"""
raise NotImplementedError('subclasses of FileUploadHandler must provide a receive_data_chunk() method')

[docs]    def file_complete(self, file_size):
"""
Signal that a file has completed. File size corresponds to the actual
size accumulated by all the chunks.

Subclasses should return a valid ``UploadedFile`` object.
"""
raise NotImplementedError('subclasses of FileUploadHandler must provide a file_complete() method')

[docs]    def upload_complete(self):
"""
Signal that the upload is complete. Subclasses should perform cleanup
that is necessary for this handler.
"""
pass

[docs]class TemporaryFileUploadHandler(FileUploadHandler):
"""
Upload handler that streams data into a temporary file.
"""
def __init__(self, *args, **kwargs):
super(TemporaryFileUploadHandler, self).__init__(*args, **kwargs)

def new_file(self, *args, **kwargs):
"""
Create the file object to append to as data is coming in.
"""
super(TemporaryFileUploadHandler, self).new_file(*args, **kwargs)
self.file = TemporaryUploadedFile(self.file_name, self.content_type, 0, self.charset, self.content_type_extra)

def receive_data_chunk(self, raw_data, start):
self.file.write(raw_data)

def file_complete(self, file_size):
self.file.seek(0)
self.file.size = file_size
return self.file

[docs]class MemoryFileUploadHandler(FileUploadHandler):
"""
File upload handler to stream uploads into memory (used for small files).
"""

def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
"""
Use the content_length to signal whether or not this handler should be in use.
"""
# Check the content-length header to see if we should
# If the post is too large, we cannot use the Memory handler.
if content_length > settings.FILE_UPLOAD_MAX_MEMORY_SIZE:
self.activated = False
else:
self.activated = True

def new_file(self, *args, **kwargs):
super(MemoryFileUploadHandler, self).new_file(*args, **kwargs)
if self.activated:
self.file = BytesIO()
raise StopFutureHandlers()

def receive_data_chunk(self, raw_data, start):
"""
Add the data to the BytesIO file.
"""
if self.activated:
self.file.write(raw_data)
else:
return raw_data

def file_complete(self, file_size):
"""
Return a file object if we're activated.
"""
if not self.activated:
return

self.file.seek(0)
return InMemoryUploadedFile(
file=self.file,
field_name=self.field_name,
name=self.file_name,
content_type=self.content_type,
size=file_size,
charset=self.charset,
content_type_extra=self.content_type_extra
)

def load_handler(path, *args, **kwargs):
"""
Given a path to a handler, return an instance of that handler.

E.g.::
>>> from django.http import HttpRequest
>>> request = HttpRequest()
>>> load_handler('django.core.files.uploadhandler.TemporaryFileUploadHandler', request)
<TemporaryFileUploadHandler object at 0x...>
"""
return import_string(path)(*args, **kwargs)

Source code for django.core.files.uploadedfile

"""
Classes representing uploaded files.
"""

import errno
import os
from io import BytesIO

from django.conf import settings
from django.core.files import temp as tempfile
from django.core.files.base import File
from django.utils.encoding import force_str

__all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile',
'SimpleUploadedFile')

[docs]class UploadedFile(File):
"""
A abstract uploaded file (``TemporaryUploadedFile`` and
``InMemoryUploadedFile`` are the built-in concrete subclasses).

An ``UploadedFile`` object behaves somewhat like a file object and
represents some file data that the user submitted with a form.
"""
DEFAULT_CHUNK_SIZE = 64 * 2 ** 10

def __init__(self, file=None, name=None, content_type=None, size=None, charset=None, content_type_extra=None):
super(UploadedFile, self).__init__(file, name)
self.size = size
self.content_type = content_type
self.charset = charset
self.content_type_extra = content_type_extra

def __repr__(self):
return force_str("<%s: %s (%s)>" % (
self.__class__.__name__, self.name, self.content_type))

def _get_name(self):
return self._name

def _set_name(self, name):
# Sanitize the file name so that it can't be dangerous.
if name is not None:
# Just use the basename of the file -- anything else is dangerous.
name = os.path.basename(name)

# File names longer than 255 characters can cause problems on older OSes.
if len(name) > 255:
name, ext = os.path.splitext(name)
ext = ext[:255]
name = name[:255 - len(ext)] + ext

self._name = name

name = property(_get_name, _set_name)

[docs]class TemporaryUploadedFile(UploadedFile):
"""
A file uploaded to a temporary location (i.e. stream-to-disk).
"""
def __init__(self, name, content_type, size, charset, content_type_extra=None):
if settings.FILE_UPLOAD_TEMP_DIR:
file = tempfile.NamedTemporaryFile(suffix='.upload',
dir=settings.FILE_UPLOAD_TEMP_DIR)
else:
file = tempfile.NamedTemporaryFile(suffix='.upload')
super(TemporaryUploadedFile, self).__init__(file, name, content_type, size, charset, content_type_extra)

[docs]    def temporary_file_path(self):
"""
Returns the full path of this file.
"""
return self.file.name

def close(self):
try:
return self.file.close()
except OSError as e:
if e.errno != errno.ENOENT:
# Means the file was moved or deleted before the tempfile
# could unlink it.  Still sets self.file.close_called and
# calls self.file.file.close() before the exception
raise

[docs]class InMemoryUploadedFile(UploadedFile):
"""
A file uploaded into memory (i.e. stream-to-memory).
"""
def __init__(self, file, field_name, name, content_type, size, charset, content_type_extra=None):
super(InMemoryUploadedFile, self).__init__(file, name, content_type, size, charset, content_type_extra)
self.field_name = field_name

def open(self, mode=None):
self.file.seek(0)

def chunks(self, chunk_size=None):
self.file.seek(0)
yield self.read()

def multiple_chunks(self, chunk_size=None):
# Since it's in memory, we'll never have multiple chunks.
return False

class SimpleUploadedFile(InMemoryUploadedFile):
"""
A simple representation of a file, which just has content, size, and a name.
"""
def __init__(self, name, content, content_type='text/plain'):
content = content or b''
super(SimpleUploadedFile, self).__init__(BytesIO(content), None, name,
content_type, len(content), None, None)

@classmethod
def from_dict(cls, file_dict):
"""
Creates a SimpleUploadedFile object from
a dictionary object with the following keys:
- filename
- content-type
- content
"""
return cls(file_dict['filename'],
file_dict['content'],
file_dict.get('content-type', 'text/plain'))

Source code for django.core.files.storage

import errno
import os
import warnings
from datetime import datetime

from django.conf import settings
from django.core.exceptions import SuspiciousFileOperation
from django.core.files import File, locks
from django.core.files.move import file_move_safe
from django.utils._os import abspathu, safe_join
from django.utils.crypto import get_random_string
from django.utils.deconstruct import deconstructible
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import filepath_to_uri, force_text
from django.utils.functional import LazyObject
from django.utils.inspect import func_supports_parameter
from django.utils.module_loading import import_string
from django.utils.six.moves.urllib.parse import urljoin
from django.utils.text import get_valid_filename

__all__ = ('Storage', 'FileSystemStorage', 'DefaultStorage', 'default_storage')

[docs]class Storage(object):
"""
A base storage class, providing some default behaviors that all other
storage systems can inherit or override, as necessary.
"""

# The following methods represent a public interface to private methods.
# These shouldn't be overridden by subclasses unless absolutely necessary.

[docs]    def open(self, name, mode='rb'):
"""
Retrieves the specified file from storage.
"""
return self._open(name, mode)

[docs]    def save(self, name, content, max_length=None):
"""
Saves new content to the file specified by name. The content should be
a proper File object or any python file-like object, ready to be read
from the beginning.
"""
# Get the proper name for the file, as it will actually be saved.
if name is None:
name = content.name

if not hasattr(content, 'chunks'):
content = File(content)

if func_supports_parameter(self.get_available_name, 'max_length'):
name = self.get_available_name(name, max_length=max_length)
else:
warnings.warn(
'Backwards compatibility for storage backends without '
'support for the `max_length` argument in '
'Storage.get_available_name() will be removed in Django 1.10.',
RemovedInDjango110Warning, stacklevel=2
)
name = self.get_available_name(name)

name = self._save(name, content)

# Store filenames with forward slashes, even on Windows
return force_text(name.replace('\\', '/'))

# These methods are part of the public API, with default implementations.

[docs]    def get_valid_name(self, name):
"""
Returns a filename, based on the provided filename, that's suitable for
use in the target storage system.
"""
return get_valid_filename(name)

[docs]    def get_available_name(self, name, max_length=None):
"""
Returns a filename that's free on the target storage system, and
available for new content to be written to.
"""
dir_name, file_name = os.path.split(name)
file_root, file_ext = os.path.splitext(file_name)
# If the filename already exists, add an underscore and a random 7
# character alphanumeric string (before the file extension, if one
# exists) to the filename until the generated filename doesn't exist.
# Truncate original name if required, so the new filename does not
# exceed the max_length.
while self.exists(name) or (max_length and len(name) > max_length):
# file_ext includes the dot.
name = os.path.join(dir_name, "%s_%s%s" % (file_root, get_random_string(7), file_ext))
if max_length is None:
continue
# Truncate file_root if max_length exceeded.
truncation = len(name) - max_length
if truncation > 0:
file_root = file_root[:-truncation]
# Entire file_root was truncated in attempt to find an available filename.
if not file_root:
raise SuspiciousFileOperation(
'Storage can not find an available filename for "%s". '
'Please make sure that the corresponding file field '
'allows sufficient "max_length".' % name
)
name = os.path.join(dir_name, "%s_%s%s" % (file_root, get_random_string(7), file_ext))
return name

[docs]    def path(self, name):
"""
Returns a local filesystem path where the file can be retrieved using
Python's built-in open() function. Storage systems that can't be
accessed using open() should *not* implement this method.
"""
raise NotImplementedError("This backend doesn't support absolute paths.")

# The following methods form the public API for storage systems, but with
# no default implementations. Subclasses must implement *all* of these.

[docs]    def delete(self, name):
"""
Deletes the specified file from the storage system.
"""
raise NotImplementedError('subclasses of Storage must provide a delete() method')

[docs]    def exists(self, name):
"""
Returns True if a file referenced by the given name already exists in the
storage system, or False if the name is available for a new file.
"""
raise NotImplementedError('subclasses of Storage must provide an exists() method')

[docs]    def listdir(self, path):
"""
Lists the contents of the specified path, returning a 2-tuple of lists;
the first item being directories, the second item being files.
"""
raise NotImplementedError('subclasses of Storage must provide a listdir() method')

[docs]    def size(self, name):
"""
Returns the total size, in bytes, of the file specified by name.
"""
raise NotImplementedError('subclasses of Storage must provide a size() method')

[docs]    def url(self, name):
"""
Returns an absolute URL where the file's contents can be accessed
directly by a Web browser.
"""
raise NotImplementedError('subclasses of Storage must provide a url() method')

[docs]    def accessed_time(self, name):
"""
Returns the last accessed time (as datetime object) of the file
specified by name.
"""
raise NotImplementedError('subclasses of Storage must provide an accessed_time() method')

[docs]    def created_time(self, name):
"""
Returns the creation time (as datetime object) of the file
specified by name.
"""
raise NotImplementedError('subclasses of Storage must provide a created_time() method')

[docs]    def modified_time(self, name):
"""
Returns the last modified time (as datetime object) of the file
specified by name.
"""
raise NotImplementedError('subclasses of Storage must provide a modified_time() method')

@deconstructible

[docs]class FileSystemStorage(Storage):
"""
Standard filesystem storage
"""

def __init__(self, location=None, base_url=None, file_permissions_mode=None,
directory_permissions_mode=None):
if location is None:
location = settings.MEDIA_ROOT
self.base_location = location
self.location = abspathu(self.base_location)
if base_url is None:
base_url = settings.MEDIA_URL
elif not base_url.endswith('/'):
base_url += '/'
self.base_url = base_url
self.file_permissions_mode = (
file_permissions_mode if file_permissions_mode is not None
else settings.FILE_UPLOAD_PERMISSIONS
)
self.directory_permissions_mode = (
directory_permissions_mode if directory_permissions_mode is not None
else settings.FILE_UPLOAD_DIRECTORY_PERMISSIONS
)

def _open(self, name, mode='rb'):
return File(open(self.path(name), mode))

def _save(self, name, content):
full_path = self.path(name)

# Create any intermediate directories that do not exist.
# Note that there is a race between os.path.exists and os.makedirs:
# if os.makedirs fails with EEXIST, the directory was created
# concurrently, and we can continue normally. Refs #16082.
directory = os.path.dirname(full_path)
if not os.path.exists(directory):
try:
if self.directory_permissions_mode is not None:
# os.makedirs applies the global umask, so we reset it,
# for consistency with file_permissions_mode behavior.
old_umask = os.umask(0)
try:
os.makedirs(directory, self.directory_permissions_mode)
finally:
os.umask(old_umask)
else:
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if not os.path.isdir(directory):
raise IOError("%s exists and is not a directory." % directory)

# There's a potential race condition between get_available_name and
# saving the file; it's possible that two threads might return the
# same name, at which point all sorts of fun happens. So we need to
# try to create the file, but if it already exists we have to go back
# to get_available_name() and try again.

while True:
try:
# This file has a file path that we can move.
if hasattr(content, 'temporary_file_path'):
file_move_safe(content.temporary_file_path(), full_path)

# This is a normal uploadedfile that we can stream.
else:
# This fun binary flag incantation makes os.open throw an
# OSError if the file already exists before we open it.
flags = (os.O_WRONLY | os.O_CREAT | os.O_EXCL |
getattr(os, 'O_BINARY', 0))
# The current umask value is masked out by os.open!
fd = os.open(full_path, flags, 0o666)
_file = None
try:
locks.lock(fd, locks.LOCK_EX)
for chunk in content.chunks():
if _file is None:
mode = 'wb' if isinstance(chunk, bytes) else 'wt'
_file = os.fdopen(fd, mode)
_file.write(chunk)
finally:
locks.unlock(fd)
if _file is not None:
_file.close()
else:
os.close(fd)
except OSError as e:
if e.errno == errno.EEXIST:
# Ooops, the file exists. We need a new file name.
name = self.get_available_name(name)
full_path = self.path(name)
else:
raise
else:
# OK, the file save worked. Break out of the loop.
break

if self.file_permissions_mode is not None:
os.chmod(full_path, self.file_permissions_mode)

return name

def delete(self, name):
assert name, "The name argument is not allowed to be empty."
name = self.path(name)
# If the file exists, delete it from the filesystem.
# Note that there is a race between os.path.exists and os.remove:
# if os.remove fails with ENOENT, the file was removed
# concurrently, and we can continue normally.
if os.path.exists(name):
try:
os.remove(name)
except OSError as e:
if e.errno != errno.ENOENT:
raise

def exists(self, name):
return os.path.exists(self.path(name))

def listdir(self, path):
path = self.path(path)
directories, files = [], []
for entry in os.listdir(path):
if os.path.isdir(os.path.join(path, entry)):
directories.append(entry)
else:
files.append(entry)
return directories, files

def path(self, name):
return safe_join(self.location, name)

def size(self, name):
return os.path.getsize(self.path(name))

def url(self, name):
if self.base_url is None:
raise ValueError("This file is not accessible via a URL.")
return urljoin(self.base_url, filepath_to_uri(name))

def accessed_time(self, name):
return datetime.fromtimestamp(os.path.getatime(self.path(name)))

def created_time(self, name):
return datetime.fromtimestamp(os.path.getctime(self.path(name)))

def modified_time(self, name):
return datetime.fromtimestamp(os.path.getmtime(self.path(name)))

[docs]def get_storage_class(import_path=None):
return import_string(import_path or settings.DEFAULT_FILE_STORAGE)

[docs]class DefaultStorage(LazyObject):
def _setup(self):
self._wrapped = get_storage_class()()

default_storage = DefaultStorage()

Source code for django.core.files.images

"""
Utility functions for handling images.

Requires Pillow as you might imagine.
"""
import struct
import zlib

from django.core.files import File

[docs]class ImageFile(File):
"""
A mixin for use alongside django.core.files.base.File, which provides
additional features for dealing with images.
"""
def _get_width(self):
return self._get_image_dimensions()[0]
width = property(_get_width)

def _get_height(self):
return self._get_image_dimensions()[1]
height = property(_get_height)

def _get_image_dimensions(self):
if not hasattr(self, '_dimensions_cache'):
close = self.closed
self.open()
self._dimensions_cache = get_image_dimensions(self, close=close)
return self._dimensions_cache

def get_image_dimensions(file_or_path, close=False):
"""
Returns the (width, height) of an image, given an open file or a path.  Set
'close' to True to close the file at the end if it is initially in an open
state.
"""
from PIL import ImageFile as PillowImageFile

p = PillowImageFile.Parser()
if hasattr(file_or_path, 'read'):
file = file_or_path
file_pos = file.tell()
file.seek(0)
else:
file = open(file_or_path, 'rb')
close = True
try:
# Most of the time Pillow only needs a small chunk to parse the image
# and get the dimensions, but with some TIFF files Pillow needs to
# parse the whole file.
chunk_size = 1024
while 1:
data = file.read(chunk_size)
if not data:
break
try:
p.feed(data)
except zlib.error as e:
# ignore zlib complaining on truncated stream, just feed more
# data to parser (ticket #19457).
if e.args[0].startswith("Error -5"):
pass
else:
raise
except struct.error:
# Ignore PIL failing on a too short buffer when reads return
# less bytes than expected. Skip and feed more data to the
# parser (ticket #24544).
pass
if p.image:
return p.image.size
chunk_size *= 2
return (None, None)
finally:
if close:
file.close()
else:
file.seek(file_pos)

Source code for django.core.management.base

# -*- coding: utf-8 -*-
"""
Base classes for writing management commands (named commands which can
be executed through ``django-admin`` or ``manage.py``).
"""
from __future__ import unicode_literals

import os
import sys
import warnings
from argparse import ArgumentParser
from optparse import OptionParser

import django
from django.core import checks
from django.core.management.color import color_style, no_style
from django.db import connections
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_str

[docs]class CommandError(Exception):
"""
Exception class indicating a problem while executing a management
command.

If this exception is raised during the execution of a management
command, it will be caught and turned into a nicely-printed error
message to the appropriate output stream (i.e., stderr); as a
result, raising this exception (with a sensible description of the
error) is the preferred way to indicate that something has gone
wrong in the execution of a command.
"""
pass

class SystemCheckError(CommandError):
"""
The system check framework detected unrecoverable errors.
"""
pass

class CommandParser(ArgumentParser):
"""
Customized ArgumentParser class to improve some error messages and prevent
SystemExit in several occasions, as SystemExit is unacceptable when a
command is called programmatically.
"""
def __init__(self, cmd, **kwargs):
self.cmd = cmd
super(CommandParser, self).__init__(**kwargs)

def parse_args(self, args=None, namespace=None):
# Catch missing argument for a better error message
if (hasattr(self.cmd, 'missing_args_message') and
not (args or any(not arg.startswith('-') for arg in args))):
self.error(self.cmd.missing_args_message)
return super(CommandParser, self).parse_args(args, namespace)

def error(self, message):
if self.cmd._called_from_command_line:
super(CommandParser, self).error(message)
else:
raise CommandError("Error: %s" % message)

def handle_default_options(options):
"""
Include any default options that all commands should accept here
so that ManagementUtility can handle them before searching for
user commands.
"""
if options.settings:
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
if options.pythonpath:
sys.path.insert(0, options.pythonpath)

class OutputWrapper(object):
"""
Wrapper around stdout/stderr
"""
@property
def style_func(self):
return self._style_func

@style_func.setter
def style_func(self, style_func):
if style_func and self.isatty():
self._style_func = style_func
else:
self._style_func = lambda x: x

def __init__(self, out, style_func=None, ending='\n'):
self._out = out
self.style_func = None
self.ending = ending

def __getattr__(self, name):
return getattr(self._out, name)

def isatty(self):
return hasattr(self._out, 'isatty') and self._out.isatty()

def write(self, msg, style_func=None, ending=None):
ending = self.ending if ending is None else ending
if ending and not msg.endswith(ending):
msg += ending
style_func = style_func or self.style_func
self._out.write(force_str(style_func(msg)))

[docs]class BaseCommand(object):
"""
The base class from which all management commands ultimately
derive.

Use this class if you want access to all of the mechanisms which
parse the command-line arguments and work out what code to call in
response; if you don't need to change any of that behavior,
consider using one of the subclasses defined in this file.

If you are interested in overriding/customizing various aspects of
the command-parsing and -execution behavior, the normal flow works
as follows:

1. ``django-admin`` or ``manage.py`` loads the command class
and calls its ``run_from_argv()`` method.

2. The ``run_from_argv()`` method calls ``create_parser()`` to get
an ``ArgumentParser`` for the arguments, parses them, performs
any environment changes requested by options like
``pythonpath``, and then calls the ``execute()`` method,
passing the parsed arguments.

3. The ``execute()`` method attempts to carry out the command by
calling the ``handle()`` method with the parsed arguments; any
output produced by ``handle()`` will be printed to standard
output and, if the command is intended to produce a block of
SQL statements, will be wrapped in ``BEGIN`` and ``COMMIT``.

4. If ``handle()`` or ``execute()`` raised any exception (e.g.
``CommandError``), ``run_from_argv()`` will  instead print an error
message to ``stderr``.

Thus, the ``handle()`` method is typically the starting point for
subclasses; many built-in commands and command types either place
all of their logic in ``handle()``, or perform some additional
parsing work in ``handle()`` and then delegate from it to more
specialized methods as needed.

Several attributes affect behavior at various steps along the way:

``args``
A string listing the arguments accepted by the command,
suitable for use in help messages; e.g., a command which takes
a list of application names might set this to '<app_label
app_label ...>'.

``can_import_settings``
A boolean indicating whether the command needs to be able to
import Django settings; if ``True``, ``execute()`` will verify
that this is possible before proceeding. Default value is
``True``.

``help``
A short description of the command, which will be printed in
help messages.

``option_list``
This is the list of ``optparse`` options which will be fed
into the command's ``OptionParser`` for parsing arguments.
Deprecated and will be removed in Django 1.10.
Use ``add_arguments`` instead.

``output_transaction``
A boolean indicating whether the command outputs SQL
statements; if ``True``, the output will automatically be
wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
``False``.

``requires_system_checks``
A boolean; if ``True``, entire Django project will be checked for errors
prior to executing the command. Default value is ``True``.
To validate an individual application's models
rather than all applications' models, call
``self.check(app_configs)`` from ``handle()``, where ``app_configs``
is the list of application's configuration provided by the
app registry.

``leave_locale_alone``
A boolean indicating whether the locale set in settings should be
preserved during the execution of the command instead of translations
being deactivated.

Default value is ``False``.

Make sure you know what you are doing if you decide to change the value
of this option in your custom command if it creates database content
that is locale-sensitive and such content shouldn't contain any
translations (like it happens e.g. with django.contrib.auth
permissions) as activating any locale might cause unintended effects.

This option can't be False when the can_import_settings option is set
to False too because attempting to deactivate translations needs access
to settings. This condition will generate a CommandError.
"""
# Metadata about this command.
option_list = ()
help = ''
args = ''

# Configuration shortcuts that alter various logic.
_called_from_command_line = False
can_import_settings = True
output_transaction = False  # Whether to wrap the output in a "BEGIN; COMMIT;"
leave_locale_alone = False
requires_system_checks = True

def __init__(self, stdout=None, stderr=None, no_color=False):
self.stdout = OutputWrapper(stdout or sys.stdout)
self.stderr = OutputWrapper(stderr or sys.stderr)
if no_color:
self.style = no_style()
else:
self.style = color_style()
self.stderr.style_func = self.style.ERROR

@property
def use_argparse(self):
return not bool(self.option_list)

[docs]    def get_version(self):
"""
Return the Django version, which should be correct for all built-in
Django commands. User-supplied commands can override this method to
return their own version.
"""
return django.get_version()

def usage(self, subcommand):
"""
Return a brief description of how to use this command, by
default from the attribute ``self.help``.
"""
usage = '%%prog %s [options] %s' % (subcommand, self.args)
if self.help:
return '%s\n\n%s' % (usage, self.help)
else:
return usage

def create_parser(self, prog_name, subcommand):
"""
Create and return the ``ArgumentParser`` which will be used to
parse the arguments to this command.
"""
if not self.use_argparse:
def store_as_int(option, opt_str, value, parser):
setattr(parser.values, option.dest, int(value))

# Backwards compatibility: use deprecated optparse module
warnings.warn("OptionParser usage for Django management commands "
"is deprecated, use ArgumentParser instead",
RemovedInDjango110Warning, stacklevel=3)
parser = OptionParser(prog=prog_name,
usage=self.usage(subcommand),
version=self.get_version())
parser.add_option('-v', '--verbosity', action='callback', dest='verbosity', default=1,
type='choice', choices=['0', '1', '2', '3'], callback=store_as_int,
help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output')
parser.add_option('--settings',
help=(
'The Python path to a settings module, e.g. '
'"myproject.settings.main". If this isn\'t provided, the '
'DJANGO_SETTINGS_MODULE environment variable will be used.'
),
)
parser.add_option('--pythonpath',
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
parser.add_option('--traceback', action='store_true',
help='Raise on CommandError exceptions')
parser.add_option('--no-color', action='store_true', dest='no_color', default=False,
help="Don't colorize the command output.")
for opt in self.option_list:
parser.add_option(opt)
else:
parser = CommandParser(self, prog="%s %s" % (os.path.basename(prog_name), subcommand),
description=self.help or None)
parser.add_argument('--version', action='version', version=self.get_version())
parser.add_argument('-v', '--verbosity', action='store', dest='verbosity', default='1',
type=int, choices=[0, 1, 2, 3],
help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output')
parser.add_argument('--settings',
help=(
'The Python path to a settings module, e.g. '
'"myproject.settings.main". If this isn\'t provided, the '
'DJANGO_SETTINGS_MODULE environment variable will be used.'
),
)
parser.add_argument('--pythonpath',
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".')
parser.add_argument('--traceback', action='store_true',
help='Raise on CommandError exceptions')
parser.add_argument('--no-color', action='store_true', dest='no_color', default=False,
help="Don't colorize the command output.")
if self.args:
# Keep compatibility and always accept positional arguments, like optparse when args is set
parser.add_argument('args', nargs='*')
self.add_arguments(parser)
return parser

[docs]    def add_arguments(self, parser):
"""
Entry point for subclassed commands to add custom arguments.
"""
pass

def print_help(self, prog_name, subcommand):
"""
Print the help message for this command, derived from
``self.usage()``.
"""
parser = self.create_parser(prog_name, subcommand)
parser.print_help()

def run_from_argv(self, argv):
"""
Set up any environment changes requested (e.g., Python path
and Django settings), then run this command. If the
command raises a ``CommandError``, intercept it and print it sensibly
to stderr. If the ``--traceback`` option is present or the raised
``Exception`` is not ``CommandError``, raise it.
"""
self._called_from_command_line = True
parser = self.create_parser(argv[0], argv[1])

if self.use_argparse:
options = parser.parse_args(argv[2:])
cmd_options = vars(options)
# Move positional args out of options to mimic legacy optparse
args = cmd_options.pop('args', ())
else:
options, args = parser.parse_args(argv[2:])
cmd_options = vars(options)
handle_default_options(options)
try:
self.execute(*args, **cmd_options)
except Exception as e:
if options.traceback or not isinstance(e, CommandError):
raise

# SystemCheckError takes care of its own formatting.
if isinstance(e, SystemCheckError):
self.stderr.write(str(e), lambda x: x)
else:
self.stderr.write('%s: %s' % (e.__class__.__name__, e))
sys.exit(1)
finally:
connections.close_all()

[docs]    def execute(self, *args, **options):
"""
Try to execute this command, performing system checks if needed (as
controlled by the ``requires_system_checks`` attribute, except if
force-skipped).
"""
if options.get('no_color'):
self.style = no_style()
self.stderr.style_func = None
if options.get('stdout'):
self.stdout = OutputWrapper(options['stdout'])
if options.get('stderr'):
self.stderr = OutputWrapper(options.get('stderr'), self.stderr.style_func)

saved_locale = None
if not self.leave_locale_alone:
# Only mess with locales if we can assume we have a working
# settings file, because django.utils.translation requires settings
# (The final saying about whether the i18n machinery is active will be
# found in the value of the USE_I18N setting)
if not self.can_import_settings:
raise CommandError("Incompatible values of 'leave_locale_alone' "
"(%s) and 'can_import_settings' (%s) command "
"options." % (self.leave_locale_alone,
self.can_import_settings))
# Deactivate translations, because django-admin creates database
# content like permissions, and those shouldn't contain any
# translations.
from django.utils import translation
saved_locale = translation.get_language()
translation.deactivate_all()

try:
if (self.requires_system_checks and
not options.get('skip_validation') and  # Remove at the end of deprecation for `skip_validation`.
not options.get('skip_checks')):
self.check()
output = self.handle(*args, **options)
if output:
if self.output_transaction:
# This needs to be imported here, because it relies on
# settings.
from django.db import connections, DEFAULT_DB_ALIAS
connection = connections[options.get('database', DEFAULT_DB_ALIAS)]
if connection.ops.start_transaction_sql():
self.stdout.write(self.style.SQL_KEYWORD(connection.ops.start_transaction_sql()))
self.stdout.write(output)
if self.output_transaction:
self.stdout.write('\n' + self.style.SQL_KEYWORD(connection.ops.end_transaction_sql()))
finally:
if saved_locale is not None:
translation.activate(saved_locale)

[docs]    def check(self, app_configs=None, tags=None, display_num_errors=False,
include_deployment_checks=False):
"""
Uses the system check framework to validate entire Django project.
Raises CommandError for any serious message (error or critical errors).
If there are only light messages (like warnings), they are printed to
stderr and no exception is raised.
"""
all_issues = checks.run_checks(
app_configs=app_configs,
tags=tags,
include_deployment_checks=include_deployment_checks,
)

header, body, footer = "", "", ""
visible_issue_count = 0  # excludes silenced warnings

if all_issues:
debugs = [e for e in all_issues if e.level < checks.INFO and not e.is_silenced()]
infos = [e for e in all_issues if checks.INFO <= e.level < checks.WARNING and not e.is_silenced()]
warnings = [e for e in all_issues if checks.WARNING <= e.level < checks.ERROR and not e.is_silenced()]
errors = [e for e in all_issues if checks.ERROR <= e.level < checks.CRITICAL and not e.is_silenced()]
criticals = [e for e in all_issues if checks.CRITICAL <= e.level and not e.is_silenced()]
sorted_issues = [
(criticals, 'CRITICALS'),
(errors, 'ERRORS'),
(warnings, 'WARNINGS'),
(infos, 'INFOS'),
(debugs, 'DEBUGS'),
]

for issues, group_name in sorted_issues:
if issues:
visible_issue_count += len(issues)
formatted = (
self.style.ERROR(force_str(e))
if e.is_serious()
else self.style.WARNING(force_str(e))
for e in issues)
formatted = "\n".join(sorted(formatted))
body += '\n%s:\n%s\n' % (group_name, formatted)

if visible_issue_count:
header = "System check identified some issues:\n"

if display_num_errors:
if visible_issue_count:
footer += '\n'
footer += "System check identified %s (%s silenced)." % (
"no issues" if visible_issue_count == 0 else
"1 issue" if visible_issue_count == 1 else
"%s issues" % visible_issue_count,
len(all_issues) - visible_issue_count,
)

if any(e.is_serious() and not e.is_silenced() for e in all_issues):
msg = self.style.ERROR("SystemCheckError: %s" % header) + body + footer
raise SystemCheckError(msg)
else:
msg = header + body + footer

if msg:
if visible_issue_count:
self.stderr.write(msg, lambda x: x)
else:
self.stdout.write(msg)

[docs]    def handle(self, *args, **options):
"""
The actual logic of the command. Subclasses must implement
this method.
"""
raise NotImplementedError('subclasses of BaseCommand must provide a handle() method')

class AppCommand(BaseCommand):
"""
A management command which takes one or more installed application labels
as arguments, and does something with each of them.

Rather than implementing ``handle()``, subclasses must implement
``handle_app_config()``, which will be called once for each application.
"""
missing_args_message = "Enter at least one application label."

def add_arguments(self, parser):
parser.add_argument('args', metavar='app_label', nargs='+',
help='One or more application label.')

def handle(self, *app_labels, **options):
from django.apps import apps
try:
app_configs = [apps.get_app_config(app_label) for app_label in app_labels]
except (LookupError, ImportError) as e:
raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
output = []
for app_config in app_configs:
app_output = self.handle_app_config(app_config, **options)
if app_output:
output.append(app_output)
return '\n'.join(output)

def handle_app_config(self, app_config, **options):
"""
Perform the command's actions for app_config, an AppConfig instance
corresponding to an application label given on the command line.
"""
raise NotImplementedError(
"Subclasses of AppCommand must provide"
"a handle_app_config() method.")

class LabelCommand(BaseCommand):
"""
A management command which takes one or more arbitrary arguments
(labels) on the command line, and does something with each of
them.

Rather than implementing ``handle()``, subclasses must implement
``handle_label()``, which will be called once for each label.

If the arguments should be names of installed applications, use
``AppCommand`` instead.
"""
label = 'label'
missing_args_message = "Enter at least one %s." % label

def add_arguments(self, parser):
parser.add_argument('args', metavar=self.label, nargs='+')

def handle(self, *labels, **options):
output = []
for label in labels:
label_output = self.handle_label(label, **options)
if label_output:
output.append(label_output)
return '\n'.join(output)

def handle_label(self, label, **options):
"""
Perform the command's actions for ``label``, which will be the
string as given on the command line.
"""
raise NotImplementedError('subclasses of LabelCommand must provide a handle_label() method')

class NoArgsCommand(BaseCommand):
"""
A command which takes no arguments on the command line.

Rather than implementing ``handle()``, subclasses must implement
``handle_noargs()``; ``handle()`` itself is overridden to ensure
no arguments are passed to the command.

Attempting to pass arguments will raise ``CommandError``.
"""
args = ''

def __init__(self):
warnings.warn(
"NoArgsCommand class is deprecated and will be removed in Django 1.10. "
"Use BaseCommand instead, which takes no arguments by default.",
RemovedInDjango110Warning
)
super(NoArgsCommand, self).__init__()

def handle(self, *args, **options):
if args:
raise CommandError("Command doesn't accept any arguments")
return self.handle_noargs(**options)

def handle_noargs(self, **options):
"""
Perform this command's actions.
"""
raise NotImplementedError('subclasses of NoArgsCommand must provide a handle_noargs() method')

Source code for django.core.checks.registry

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from itertools import chain

from django.utils.itercompat import is_iterable

class Tags(object):
"""
Built-in tags for internal checks.
"""
admin = 'admin'
caches = 'caches'
compatibility = 'compatibility'
models = 'models'
security = 'security'
signals = 'signals'
templates = 'templates'
urls = 'urls'

class CheckRegistry(object):

def __init__(self):
self.registered_checks = []
self.deployment_checks = []

def register(self, check=None, *tags, **kwargs):
"""
Can be used as a function or a decorator. Register given function
`f` labeled with given `tags`. The function should receive **kwargs
and return list of Errors and Warnings.

Example::

registry = CheckRegistry()
@registry.register('mytag', 'anothertag')
def my_check(apps, **kwargs):
# ... perform checks and collect `errors` ...
return errors
# or
registry.register(my_check, 'mytag', 'anothertag')
"""
kwargs.setdefault('deploy', False)

def inner(check):
check.tags = tags
if kwargs['deploy']:
if check not in self.deployment_checks:
self.deployment_checks.append(check)
elif check not in self.registered_checks:
self.registered_checks.append(check)
return check

if callable(check):
return inner(check)
else:
if check:
tags += (check, )
return inner

def run_checks(self, app_configs=None, tags=None, include_deployment_checks=False):
"""
Run all registered checks and return list of Errors and Warnings.
"""
errors = []
checks = self.get_checks(include_deployment_checks)

if tags is not None:
checks = [check for check in checks
if hasattr(check, 'tags') and set(check.tags) & set(tags)]

for check in checks:
new_errors = check(app_configs=app_configs)
assert is_iterable(new_errors), (
"The function %r did not return a list. All functions registered "
"with the checks registry must return a list." % check)
errors.extend(new_errors)
return errors

def tag_exists(self, tag, include_deployment_checks=False):
return tag in self.tags_available(include_deployment_checks)

def tags_available(self, deployment_checks=False):
return set(chain(*[check.tags for check in self.get_checks(deployment_checks) if hasattr(check, 'tags')]))

def get_checks(self, include_deployment_checks=False):
checks = list(self.registered_checks)
if include_deployment_checks:
checks.extend(self.deployment_checks)
return checks

registry = CheckRegistry()
register = registry.register
run_checks = registry.run_checks
tag_exists = registry.tag_exists

Source code for django.core.checks.messages

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.utils.encoding import force_str, python_2_unicode_compatible

# Levels
DEBUG = 10
INFO = 20
WARNING = 30
ERROR = 40
CRITICAL = 50

@python_2_unicode_compatible

[docs]class CheckMessage(object):

def __init__(self, level, msg, hint=None, obj=None, id=None):
assert isinstance(level, int), "The first argument should be level."
self.level = level
self.msg = msg
self.hint = hint
self.obj = obj
self.id = id

def __eq__(self, other):
return all(getattr(self, attr) == getattr(other, attr)
for attr in ['level', 'msg', 'hint', 'obj', 'id'])

def __ne__(self, other):
return not (self == other)

def __str__(self):
from django.db import models

if self.obj is None:
obj = "?"
elif isinstance(self.obj, models.base.ModelBase):
# We need to hardcode ModelBase and Field cases because its __str__
# method doesn't return "applabel.modellabel" and cannot be changed.
obj = self.obj._meta.label
else:
obj = force_str(self.obj)
id = "(%s) " % self.id if self.id else ""
hint = "\n\tHINT: %s" % self.hint if self.hint else ''
return "%s: %s%s%s" % (obj, id, self.msg, hint)

def __repr__(self):
return "<%s: level=%r, msg=%r, hint=%r, obj=%r, id=%r>" % \
(self.__class__.__name__, self.level, self.msg, self.hint, self.obj, self.id)

def is_serious(self):
return self.level >= ERROR

def is_silenced(self):
from django.conf import settings
return self.id in settings.SILENCED_SYSTEM_CHECKS

[docs]class Debug(CheckMessage):
def __init__(self, *args, **kwargs):
super(Debug, self).__init__(DEBUG, *args, **kwargs)

[docs]class Info(CheckMessage):
def __init__(self, *args, **kwargs):
super(Info, self).__init__(INFO, *args, **kwargs)

[docs]class Warning(CheckMessage):
def __init__(self, *args, **kwargs):
super(Warning, self).__init__(WARNING, *args, **kwargs)

[docs]class Error(CheckMessage):
def __init__(self, *args, **kwargs):
super(Error, self).__init__(ERROR, *args, **kwargs)

[docs]class Critical(CheckMessage):
def __init__(self, *args, **kwargs):
super(Critical, self).__init__(CRITICAL, *args, **kwargs)

Source code for django.core.mail.message

from __future__ import unicode_literals

import mimetypes
import os
import random
import time
from email import (
charset as Charset, encoders as Encoders, generator, message_from_string,
)
from email.header import Header
from email.message import Message
from email.mime.base import MIMEBase
from email.mime.message import MIMEMessage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr, formatdate, getaddresses, parseaddr
from io import BytesIO

from django.conf import settings
from django.core.mail.utils import DNS_NAME
from django.utils import six
from django.utils.encoding import force_text

# Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from
# some spam filters.
utf8_charset = Charset.Charset('utf-8')
utf8_charset.body_encoding = None  # Python defaults to BASE64

# Default MIME type to use on attachments (if it is not explicitly given
# and cannot be guessed).
DEFAULT_ATTACHMENT_MIME_TYPE = 'application/octet-stream'

class BadHeaderError(ValueError):
pass

# Copied from Python 3.2+ standard library, with the following modifications:
# * Used cached hostname for performance.
# TODO: replace with email.utils.make_msgid(.., domain=DNS_NAME) when dropping
# Python 2 (Python 2's version doesn't have domain parameter) (#23905).
def make_msgid(idstring=None, domain=None):
"""Returns a string suitable for RFC 2822 compliant Message-ID, e.g:

<20020201195627.33539.96671@nightshade.la.mastaler.com>

Optional idstring if given is a string used to strengthen the
uniqueness of the message id.  Optional domain if given provides the
portion of the message id after the '@'.  It defaults to the locally
defined hostname.
"""
timeval = time.time()
utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval))
pid = os.getpid()
randint = random.randrange(100000)
if idstring is None:
idstring = ''
else:
idstring = '.' + idstring
if domain is None:
# stdlib uses socket.getfqdn() here instead
domain = DNS_NAME
msgid = '<%s.%s.%s%s@%s>' % (utcdate, pid, randint, idstring, domain)
return msgid

# Header names that contain structured address data (RFC #5322)
ADDRESS_HEADERS = {
'from',
'sender',
'reply-to',
'to',
'cc',
'bcc',
'resent-from',
'resent-sender',
'resent-to',
'resent-cc',
'resent-bcc',
}

def forbid_multi_line_headers(name, val, encoding):
"""Forbids multi-line headers, to prevent header injection."""
encoding = encoding or settings.DEFAULT_CHARSET
val = force_text(val)
if '\n' in val or '\r' in val:
raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name))
try:
val.encode('ascii')
except UnicodeEncodeError:
if name.lower() in ADDRESS_HEADERS:
val = ', '.join(sanitize_address(addr, encoding)
for addr in getaddresses((val,)))
else:
val = Header(val, encoding).encode()
else:
if name.lower() == 'subject':
val = Header(val).encode()
return str(name), val

def sanitize_address(addr, encoding):
if not isinstance(addr, tuple):
addr = parseaddr(force_text(addr))
nm, addr = addr
nm = Header(nm, encoding).encode()
try:
addr.encode('ascii')
except UnicodeEncodeError:  # IDN
if '@' in addr:
localpart, domain = addr.split('@', 1)
localpart = str(Header(localpart, encoding))
domain = domain.encode('idna').decode('ascii')
addr = '@'.join([localpart, domain])
else:
addr = Header(addr, encoding).encode()
return formataddr((nm, addr))

class MIMEMixin():
def as_string(self, unixfrom=False, linesep='\n'):
"""Return the entire formatted message as a string.
Optional `unixfrom' when True, means include the Unix From_ envelope
header.

This overrides the default as_string() implementation to not mangle
lines that begin with 'From '. See bug #13433 for details.
"""
fp = six.StringIO()
g = generator.Generator(fp, mangle_from_=False)
if six.PY2:
g.flatten(self, unixfrom=unixfrom)
else:
g.flatten(self, unixfrom=unixfrom, linesep=linesep)
return fp.getvalue()

if six.PY2:
as_bytes = as_string
else:
def as_bytes(self, unixfrom=False, linesep='\n'):
"""Return the entire formatted message as bytes.
Optional `unixfrom' when True, means include the Unix From_ envelope
header.

This overrides the default as_bytes() implementation to not mangle
lines that begin with 'From '. See bug #13433 for details.
"""
fp = BytesIO()
g = generator.BytesGenerator(fp, mangle_from_=False)
g.flatten(self, unixfrom=unixfrom, linesep=linesep)
return fp.getvalue()

class SafeMIMEMessage(MIMEMixin, MIMEMessage):

def __setitem__(self, name, val):
# message/rfc822 attachments must be ASCII
name, val = forbid_multi_line_headers(name, val, 'ascii')
MIMEMessage.__setitem__(self, name, val)

class SafeMIMEText(MIMEMixin, MIMEText):

def __init__(self, _text, _subtype='plain', _charset=None):
self.encoding = _charset
if _charset == 'utf-8':
# Unfortunately, Python < 3.5 doesn't support setting a Charset instance
# as MIMEText init parameter (http://bugs.python.org/issue16324).
# We do it manually and trigger re-encoding of the payload.
MIMEText.__init__(self, _text, _subtype, None)
del self['Content-Transfer-Encoding']
self.set_payload(_text, utf8_charset)
self.replace_header('Content-Type', 'text/%s; charset="%s"' % (_subtype, _charset))
elif _charset is None:
# the default value of '_charset' is 'us-ascii' on Python 2
MIMEText.__init__(self, _text, _subtype)
else:
MIMEText.__init__(self, _text, _subtype, _charset)

def __setitem__(self, name, val):
name, val = forbid_multi_line_headers(name, val, self.encoding)
MIMEText.__setitem__(self, name, val)

class SafeMIMEMultipart(MIMEMixin, MIMEMultipart):

def __init__(self, _subtype='mixed', boundary=None, _subparts=None, encoding=None, **_params):
self.encoding = encoding
MIMEMultipart.__init__(self, _subtype, boundary, _subparts, **_params)

def __setitem__(self, name, val):
name, val = forbid_multi_line_headers(name, val, self.encoding)
MIMEMultipart.__setitem__(self, name, val)

[docs]class EmailMessage(object):
"""
A container for email information.
"""
content_subtype = 'plain'
mixed_subtype = 'mixed'
encoding = None     # None => use settings default

def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
connection=None, attachments=None, headers=None, cc=None,
reply_to=None):
"""
Initialize a single email message (which can be sent to multiple
recipients).

All strings used to create the message can be unicode strings
(or UTF-8 bytestrings). The SafeMIMEText class will handle any
necessary encoding conversions.
"""
if to:
if isinstance(to, six.string_types):
raise TypeError('"to" argument must be a list or tuple')
self.to = list(to)
else:
self.to = []
if cc:
if isinstance(cc, six.string_types):
raise TypeError('"cc" argument must be a list or tuple')
self.cc = list(cc)
else:
self.cc = []
if bcc:
if isinstance(bcc, six.string_types):
raise TypeError('"bcc" argument must be a list or tuple')
self.bcc = list(bcc)
else:
self.bcc = []
if reply_to:
if isinstance(reply_to, six.string_types):
raise TypeError('"reply_to" argument must be a list or tuple')
self.reply_to = list(reply_to)
else:
self.reply_to = []
self.from_email = from_email or settings.DEFAULT_FROM_EMAIL
self.subject = subject
self.body = body
self.attachments = attachments or []
self.extra_headers = headers or {}
self.connection = connection

def get_connection(self, fail_silently=False):
from django.core.mail import get_connection
if not self.connection:
self.connection = get_connection(fail_silently=fail_silently)
return self.connection

def message(self):
encoding = self.encoding or settings.DEFAULT_CHARSET
msg = SafeMIMEText(self.body, self.content_subtype, encoding)
msg = self._create_message(msg)
msg['Subject'] = self.subject
msg['From'] = self.extra_headers.get('From', self.from_email)
msg['To'] = self.extra_headers.get('To', ', '.join(map(force_text, self.to)))
if self.cc:
msg['Cc'] = ', '.join(map(force_text, self.cc))
if self.reply_to:
msg['Reply-To'] = self.extra_headers.get('Reply-To', ', '.join(map(force_text, self.reply_to)))

# Email header names are case-insensitive (RFC 2045), so we have to
# accommodate that when doing comparisons.
header_names = [key.lower() for key in self.extra_headers]
if 'date' not in header_names:
msg['Date'] = formatdate()
if 'message-id' not in header_names:
# Use cached DNS_NAME for performance
msg['Message-ID'] = make_msgid(domain=DNS_NAME)
for name, value in self.extra_headers.items():
if name.lower() in ('from', 'to'):  # From and To are already handled
continue
msg[name] = value
return msg

def recipients(self):
"""
Returns a list of all recipients of the email (includes direct
addressees as well as Cc and Bcc entries).
"""
return self.to + self.cc + self.bcc

def send(self, fail_silently=False):
"""Sends the email message."""
if not self.recipients():
# Don't bother creating the network connection if there's nobody to
# send to.
return 0
return self.get_connection(fail_silently).send_messages([self])

def attach(self, filename=None, content=None, mimetype=None):
"""
Attaches a file with the given filename and content. The filename can
be omitted and the mimetype is guessed, if not provided.

If the first parameter is a MIMEBase subclass it is inserted directly
into the resulting message attachments.
"""
if isinstance(filename, MIMEBase):
assert content is None
assert mimetype is None
self.attachments.append(filename)
else:
assert content is not None
self.attachments.append((filename, content, mimetype))

def attach_file(self, path, mimetype=None):
"""
Attaches a file from the filesystem.

The mimetype will be set to the DEFAULT_ATTACHMENT_MIME_TYPE if it is
not specified and cannot be guessed or (PY3 only) if it suggests
text/* for a binary file.
"""
filename = os.path.basename(path)
if not mimetype:
mimetype, _ = mimetypes.guess_type(filename)
if not mimetype:
mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
basetype, subtype = mimetype.split('/', 1)
read_mode = 'r' if basetype == 'text' else 'rb'
content = None

with open(path, read_mode) as f:
try:
content = f.read()
except UnicodeDecodeError:
# If mimetype suggests the file is text but it's actually
# binary, read() will raise a UnicodeDecodeError on Python 3.
pass

# If the previous read in text mode failed, try binary mode.
if content is None:
with open(path, 'rb') as f:
content = f.read()
mimetype = DEFAULT_ATTACHMENT_MIME_TYPE

self.attach(filename, content, mimetype)

def _create_message(self, msg):
return self._create_attachments(msg)

def _create_attachments(self, msg):
if self.attachments:
encoding = self.encoding or settings.DEFAULT_CHARSET
body_msg = msg
msg = SafeMIMEMultipart(_subtype=self.mixed_subtype, encoding=encoding)
if self.body:
msg.attach(body_msg)
for attachment in self.attachments:
if isinstance(attachment, MIMEBase):
msg.attach(attachment)
else:
msg.attach(self._create_attachment(*attachment))
return msg

def _create_mime_attachment(self, content, mimetype):
"""
Converts the content, mimetype pair into a MIME attachment object.

If the mimetype is message/rfc822, content may be an
email.Message or EmailMessage object, as well as a str.
"""
basetype, subtype = mimetype.split('/', 1)
if basetype == 'text':
encoding = self.encoding or settings.DEFAULT_CHARSET
attachment = SafeMIMEText(content, subtype, encoding)
elif basetype == 'message' and subtype == 'rfc822':
# Bug #18967: per RFC2046 s5.2.1, message/rfc822 attachments
# must not be base64 encoded.
if isinstance(content, EmailMessage):
# convert content into an email.Message first
content = content.message()
elif not isinstance(content, Message):
# For compatibility with existing code, parse the message
# into an email.Message object if it is not one already.
content = message_from_string(content)

attachment = SafeMIMEMessage(content, subtype)
else:
# Encode non-text attachments with base64.
attachment = MIMEBase(basetype, subtype)
attachment.set_payload(content)
Encoders.encode_base64(attachment)
return attachment

def _create_attachment(self, filename, content, mimetype=None):
"""
Converts the filename, content, mimetype triple into a MIME attachment
object.
"""
if mimetype is None:
mimetype, _ = mimetypes.guess_type(filename)
if mimetype is None:
mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
attachment = self._create_mime_attachment(content, mimetype)
if filename:
try:
filename.encode('ascii')
except UnicodeEncodeError:
if six.PY2:
filename = filename.encode('utf-8')
filename = ('utf-8', '', filename)
attachment.add_header('Content-Disposition', 'attachment',
filename=filename)
return attachment

class EmailMultiAlternatives(EmailMessage):
"""
A version of EmailMessage that makes it easy to send multipart/alternative
messages. For example, including text and HTML versions of the text is
made easier.
"""
alternative_subtype = 'alternative'

def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
connection=None, attachments=None, headers=None, alternatives=None,
cc=None, reply_to=None):
"""
Initialize a single email message (which can be sent to multiple
recipients).

All strings used to create the message can be unicode strings (or UTF-8
bytestrings). The SafeMIMEText class will handle any necessary encoding
conversions.
"""
super(EmailMultiAlternatives, self).__init__(
subject, body, from_email, to, bcc, connection, attachments,
headers, cc, reply_to,
)
self.alternatives = alternatives or []

def attach_alternative(self, content, mimetype):
"""Attach an alternative content representation."""
assert content is not None
assert mimetype is not None
self.alternatives.append((content, mimetype))

def _create_message(self, msg):
return self._create_attachments(self._create_alternatives(msg))

def _create_alternatives(self, msg):
encoding = self.encoding or settings.DEFAULT_CHARSET
if self.alternatives:
body_msg = msg
msg = SafeMIMEMultipart(_subtype=self.alternative_subtype, encoding=encoding)
if self.body:
msg.attach(body_msg)
for alternative in self.alternatives:
msg.attach(self._create_mime_attachment(*alternative))
return msg

Source code for django.forms.widgets

"""
HTML Widget classes
"""

from __future__ import unicode_literals

import copy
import datetime
import re
from itertools import chain

from django.conf import settings
from django.forms.utils import flatatt, to_current_timezone
from django.utils import datetime_safe, formats, six
from django.utils.datastructures import MultiValueDict
from django.utils.dates import MONTHS
from django.utils.encoding import (
force_str, force_text, python_2_unicode_compatible,
)
from django.utils.formats import get_format
from django.utils.html import conditional_escape, format_html, html_safe
from django.utils.safestring import mark_safe
from django.utils.six.moves import range
from django.utils.six.moves.urllib.parse import urljoin
from django.utils.translation import ugettext_lazy

__all__ = (
'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'NumberInput',
'EmailInput', 'URLInput', 'PasswordInput', 'HiddenInput',
'MultipleHiddenInput', 'FileInput', 'ClearableFileInput', 'Textarea',
'DateInput', 'DateTimeInput', 'TimeInput', 'CheckboxInput', 'Select',
'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget',
'SplitHiddenDateTimeWidget', 'SelectDateWidget',
)

MEDIA_TYPES = ('css', 'js')

@html_safe
@python_2_unicode_compatible
class Media(object):
def __init__(self, media=None, **kwargs):
if media:
media_attrs = media.__dict__
else:
media_attrs = kwargs

self._css = {}
self._js = []

for name in MEDIA_TYPES:
getattr(self, 'add_' + name)(media_attrs.get(name))

def __str__(self):
return self.render()

def render(self):
return mark_safe('\n'.join(chain(*[getattr(self, 'render_' + name)() for name in MEDIA_TYPES])))

def render_js(self):
return [
format_html(
'<script type="text/javascript" src="{}"></script>',
self.absolute_path(path)
) for path in self._js
]

def render_css(self):
# To keep rendering order consistent, we can't just iterate over items().
# We need to sort the keys, and iterate over the sorted list.
media = sorted(self._css.keys())
return chain(*[[
format_html(
'<link href="{}" type="text/css" media="{}" rel="stylesheet" />',
self.absolute_path(path), medium
) for path in self._css[medium]
] for medium in media])

def absolute_path(self, path, prefix=None):
if path.startswith(('http://', 'https://', '/')):
return path
if prefix is None:
if settings.STATIC_URL is None:
# backwards compatibility
prefix = settings.MEDIA_URL
else:
prefix = settings.STATIC_URL
return urljoin(prefix, path)

def __getitem__(self, name):
"Returns a Media object that only contains media of the given type"
if name in MEDIA_TYPES:
return Media(**{str(name): getattr(self, '_' + name)})
raise KeyError('Unknown media type "%s"' % name)

def add_js(self, data):
if data:
for path in data:
if path not in self._js:
self._js.append(path)

def add_css(self, data):
if data:
for medium, paths in data.items():
for path in paths:
if not self._css.get(medium) or path not in self._css[medium]:
self._css.setdefault(medium, []).append(path)

def __add__(self, other):
combined = Media()
for name in MEDIA_TYPES:
getattr(combined, 'add_' + name)(getattr(self, '_' + name, None))
getattr(combined, 'add_' + name)(getattr(other, '_' + name, None))
return combined

def media_property(cls):
def _media(self):
# Get the media property of the superclass, if it exists
sup_cls = super(cls, self)
try:
base = sup_cls.media
except AttributeError:
base = Media()

# Get the media definition for this class
definition = getattr(cls, 'Media', None)
if definition:
extend = getattr(definition, 'extend', True)
if extend:
if extend is True:
m = base
else:
m = Media()
for medium in extend:
m = m + base[medium]
return m + Media(definition)
else:
return Media(definition)
else:
return base
return property(_media)

class MediaDefiningClass(type):
"""
Metaclass for classes that can have media definitions.
"""
def __new__(mcs, name, bases, attrs):
new_class = (super(MediaDefiningClass, mcs)
.__new__(mcs, name, bases, attrs))

if 'media' not in attrs:
new_class.media = media_property(new_class)

return new_class

@html_safe
@python_2_unicode_compatible
class SubWidget(object):
"""
Some widgets are made of multiple HTML elements -- namely, RadioSelect.
This is a class that represents the "inner" HTML element of a widget.
"""
def __init__(self, parent_widget, name, value, attrs, choices):
self.parent_widget = parent_widget
self.name, self.value = name, value
self.attrs, self.choices = attrs, choices

def __str__(self):
args = [self.name, self.value, self.attrs]
if self.choices:
args.append(self.choices)
return self.parent_widget.render(*args)

[docs]class Widget(six.with_metaclass(MediaDefiningClass)):
needs_multipart_form = False  # Determines does this widget need multipart form
is_localized = False
is_required = False
supports_microseconds = True

def __init__(self, attrs=None):
if attrs is not None:
self.attrs = attrs.copy()
else:
self.attrs = {}

def __deepcopy__(self, memo):
obj = copy.copy(self)
obj.attrs = self.attrs.copy()
memo[id(self)] = obj
return obj

@property
def is_hidden(self):
return self.input_type == 'hidden' if hasattr(self, 'input_type') else False

def subwidgets(self, name, value, attrs=None, choices=()):
"""
Yields all "subwidgets" of this widget. Used only by RadioSelect to
allow template access to individual <input type="radio"> buttons.

Arguments are the same as for render().
"""
yield SubWidget(self, name, value, attrs, choices)

[docs]    def render(self, name, value, attrs=None):
"""
Returns this Widget rendered as HTML, as a Unicode string.

The 'value' given is not guaranteed to be valid input, so subclass
implementations should program defensively.
"""
raise NotImplementedError('subclasses of Widget must provide a render() method')

def build_attrs(self, extra_attrs=None, **kwargs):
"Helper function for building an attribute dictionary."
attrs = dict(self.attrs, **kwargs)
if extra_attrs:
attrs.update(extra_attrs)
return attrs

[docs]    def value_from_datadict(self, data, files, name):
"""
Given a dictionary of data and this widget's name, returns the value
of this widget. Returns None if it's not provided.
"""
return data.get(name)

[docs]    def id_for_label(self, id_):
"""
Returns the HTML ID attribute of this Widget for use by a <label>,
given the ID of the field. Returns None if no ID is available.

This hook is necessary because some widgets have multiple HTML
elements and, thus, multiple IDs. In that case, this method should
return an ID value that corresponds to the first ID in the widget's
tags.
"""
return id_

class Input(Widget):
"""
Base class for all <input> widgets (except type='checkbox' and
type='radio', which are special).
"""
input_type = None  # Subclasses must define this.

def _format_value(self, value):
if self.is_localized:
return formats.localize_input(value)
return value

def render(self, name, value, attrs=None):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if value != '':
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_text(self._format_value(value))
return format_html('<input{} />', flatatt(final_attrs))

[docs]class TextInput(Input):
input_type = 'text'

def __init__(self, attrs=None):
if attrs is not None:
self.input_type = attrs.pop('type', self.input_type)
super(TextInput, self).__init__(attrs)

[docs]class NumberInput(TextInput):
input_type = 'number'

[docs]class EmailInput(TextInput):
input_type = 'email'

[docs]class URLInput(TextInput):
input_type = 'url'

[docs]class PasswordInput(TextInput):
input_type = 'password'

def __init__(self, attrs=None, render_value=False):
super(PasswordInput, self).__init__(attrs)
self.render_value = render_value

def render(self, name, value, attrs=None):
if not self.render_value:
value = None
return super(PasswordInput, self).render(name, value, attrs)

[docs]class HiddenInput(Input):
input_type = 'hidden'

[docs]class MultipleHiddenInput(HiddenInput):
"""
A widget that handles <input type="hidden"> for fields that have a list
of values.
"""
def __init__(self, attrs=None, choices=()):
super(MultipleHiddenInput, self).__init__(attrs)
# choices can be any iterable
self.choices = choices

def render(self, name, value, attrs=None, choices=()):
if value is None:
value = []
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
id_ = final_attrs.get('id')
inputs = []
for i, v in enumerate(value):
input_attrs = dict(value=force_text(v), **final_attrs)
if id_:
# An ID attribute was given. Add a numeric index as a suffix
# so that the inputs don't all have the same ID attribute.
input_attrs['id'] = '%s_%s' % (id_, i)
inputs.append(format_html('<input{} />', flatatt(input_attrs)))
return mark_safe('\n'.join(inputs))

def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict):
return data.getlist(name)
return data.get(name)

[docs]class FileInput(Input):
input_type = 'file'
needs_multipart_form = True

def render(self, name, value, attrs=None):
return super(FileInput, self).render(name, None, attrs=attrs)

def value_from_datadict(self, data, files, name):
"File widgets take data from FILES, not POST"
return files.get(name)

FILE_INPUT_CONTRADICTION = object()

[docs]class ClearableFileInput(FileInput):
initial_text = ugettext_lazy('Currently')
input_text = ugettext_lazy('Change')
clear_checkbox_label = ugettext_lazy('Clear')

template_with_initial = (
'%(initial_text)s: <a href="%(initial_url)s">%(initial)s</a> '
'%(clear_template)s<br />%(input_text)s: %(input)s'
)

template_with_clear = '%(clear)s <label for="%(clear_checkbox_id)s">%(clear_checkbox_label)s</label>'

def clear_checkbox_name(self, name):
"""
Given the name of the file input, return the name of the clear checkbox
input.
"""
return name + '-clear'

def clear_checkbox_id(self, name):
"""
Given the name of the clear checkbox input, return the HTML id for it.
"""
return name + '_id'

def is_initial(self, value):
"""
Return whether value is considered to be initial value.
"""
return bool(value and hasattr(value, 'url'))

def get_template_substitution_values(self, value):
"""
Return value-related substitutions.
"""
return {
'initial': conditional_escape(value),
'initial_url': conditional_escape(value.url),
}

def render(self, name, value, attrs=None):
substitutions = {
'initial_text': self.initial_text,
'input_text': self.input_text,
'clear_template': '',
'clear_checkbox_label': self.clear_checkbox_label,
}
template = '%(input)s'
substitutions['input'] = super(ClearableFileInput, self).render(name, value, attrs)

if self.is_initial(value):
template = self.template_with_initial
substitutions.update(self.get_template_substitution_values(value))
if not self.is_required:
checkbox_name = self.clear_checkbox_name(name)
checkbox_id = self.clear_checkbox_id(checkbox_name)
substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name)
substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id)
substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
substitutions['clear_template'] = self.template_with_clear % substitutions

return mark_safe(template % substitutions)

def value_from_datadict(self, data, files, name):
upload = super(ClearableFileInput, self).value_from_datadict(data, files, name)
if not self.is_required and CheckboxInput().value_from_datadict(
data, files, self.clear_checkbox_name(name)):

if upload:
# If the user contradicts themselves (uploads a new file AND
# checks the "clear" checkbox), we return a unique marker
# object that FileField will turn into a ValidationError.
return FILE_INPUT_CONTRADICTION
# False signals to clear any existing value, as opposed to just None
return False
return upload

[docs]class Textarea(Widget):
def __init__(self, attrs=None):
# Use slightly better defaults than HTML's 20x2 box
default_attrs = {'cols': '40', 'rows': '10'}
if attrs:
default_attrs.update(attrs)
super(Textarea, self).__init__(default_attrs)

def render(self, name, value, attrs=None):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, name=name)
return format_html('<textarea{}>\r\n{}</textarea>',
flatatt(final_attrs),
force_text(value))

class DateTimeBaseInput(TextInput):
format_key = ''
supports_microseconds = False

def __init__(self, attrs=None, format=None):
super(DateTimeBaseInput, self).__init__(attrs)
self.format = format if format else None

def _format_value(self, value):
return formats.localize_input(value,
self.format or formats.get_format(self.format_key)[0])

[docs]class DateInput(DateTimeBaseInput):
format_key = 'DATE_INPUT_FORMATS'

[docs]class DateTimeInput(DateTimeBaseInput):
format_key = 'DATETIME_INPUT_FORMATS'

[docs]class TimeInput(DateTimeBaseInput):
format_key = 'TIME_INPUT_FORMATS'

# Defined at module level so that CheckboxInput is picklable (#17976)
def boolean_check(v):
return not (v is False or v is None or v == '')

[docs]class CheckboxInput(Widget):
def __init__(self, attrs=None, check_test=None):
super(CheckboxInput, self).__init__(attrs)
# check_test is a callable that takes a value and returns True
# if the checkbox should be checked for that value.
self.check_test = boolean_check if check_test is None else check_test

def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
if self.check_test(value):
final_attrs['checked'] = 'checked'
if not (value is True or value is False or value is None or value == ''):
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_text(value)
return format_html('<input{} />', flatatt(final_attrs))

def value_from_datadict(self, data, files, name):
if name not in data:
# A missing value means False because HTML form submission does not
# send results for unselected checkboxes.
return False
value = data.get(name)
# Translate true and false strings to boolean values.
values = {'true': True, 'false': False}
if isinstance(value, six.string_types):
value = values.get(value.lower(), value)
return bool(value)

[docs]class Select(Widget):
allow_multiple_selected = False

def __init__(self, attrs=None, choices=()):
super(Select, self).__init__(attrs)
# choices can be any iterable, but we may need to render this widget
# multiple times. Thus, collapse it into a list so it can be consumed
# more than once.
self.choices = list(choices)

def __deepcopy__(self, memo):
obj = copy.copy(self)
obj.attrs = self.attrs.copy()
obj.choices = copy.copy(self.choices)
memo[id(self)] = obj
return obj

def render(self, name, value, attrs=None, choices=()):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, name=name)
output = [format_html('<select{}>', flatatt(final_attrs))]
options = self.render_options(choices, [value])
if options:
output.append(options)
output.append('</select>')
return mark_safe('\n'.join(output))

def render_option(self, selected_choices, option_value, option_label):
if option_value is None:
option_value = ''
option_value = force_text(option_value)
if option_value in selected_choices:
selected_html = mark_safe(' selected="selected"')
if not self.allow_multiple_selected:
# Only allow for a single selection.
selected_choices.remove(option_value)
else:
selected_html = ''
return format_html('<option value="{}"{}>{}</option>',
option_value,
selected_html,
force_text(option_label))

def render_options(self, choices, selected_choices):
# Normalize to strings.
selected_choices = set(force_text(v) for v in selected_choices)
output = []
for option_value, option_label in chain(self.choices, choices):
if isinstance(option_label, (list, tuple)):
output.append(format_html('<optgroup label="{}">', force_text(option_value)))
for option in option_label:
output.append(self.render_option(selected_choices, *option))
output.append('</optgroup>')
else:
output.append(self.render_option(selected_choices, option_value, option_label))
return '\n'.join(output)

[docs]class NullBooleanSelect(Select):
"""
A Select Widget intended to be used with NullBooleanField.
"""
def __init__(self, attrs=None):
choices = (('1', ugettext_lazy('Unknown')),
('2', ugettext_lazy('Yes')),
('3', ugettext_lazy('No')))
super(NullBooleanSelect, self).__init__(attrs, choices)

def render(self, name, value, attrs=None, choices=()):
try:
value = {True: '2', False: '3', '2': '2', '3': '3'}[value]
except KeyError:
value = '1'
return super(NullBooleanSelect, self).render(name, value, attrs, choices)

def value_from_datadict(self, data, files, name):
value = data.get(name)
return {'2': True,
True: True,
'True': True,
'3': False,
'False': False,
False: False}.get(value)

[docs]class SelectMultiple(Select):
allow_multiple_selected = True

def render(self, name, value, attrs=None, choices=()):
if value is None:
value = []
final_attrs = self.build_attrs(attrs, name=name)
output = [format_html('<select multiple="multiple"{}>', flatatt(final_attrs))]
options = self.render_options(choices, value)
if options:
output.append(options)
output.append('</select>')
return mark_safe('\n'.join(output))

def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict):
return data.getlist(name)
return data.get(name)

@html_safe
@python_2_unicode_compatible
class ChoiceInput(SubWidget):
"""
An object used by ChoiceFieldRenderer that represents a single
<input type='$input_type'>.
"""
input_type = None  # Subclasses must define this

def __init__(self, name, value, attrs, choice, index):
self.name = name
self.value = value
self.attrs = attrs
self.choice_value = force_text(choice[0])
self.choice_label = force_text(choice[1])
self.index = index
if 'id' in self.attrs:
self.attrs['id'] += "_%d" % self.index

def __str__(self):
return self.render()

def render(self, name=None, value=None, attrs=None, choices=()):
if self.id_for_label:
label_for = format_html(' for="{}"', self.id_for_label)
else:
label_for = ''
attrs = dict(self.attrs, **attrs) if attrs else self.attrs
return format_html(
'<label{}>{} {}</label>', label_for, self.tag(attrs), self.choice_label
)

def is_checked(self):
return self.value == self.choice_value

def tag(self, attrs=None):
attrs = attrs or self.attrs
final_attrs = dict(attrs, type=self.input_type, name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return format_html('<input{} />', flatatt(final_attrs))

@property
def id_for_label(self):
return self.attrs.get('id', '')

class RadioChoiceInput(ChoiceInput):
input_type = 'radio'

def __init__(self, *args, **kwargs):
super(RadioChoiceInput, self).__init__(*args, **kwargs)
self.value = force_text(self.value)

class CheckboxChoiceInput(ChoiceInput):
input_type = 'checkbox'

def __init__(self, *args, **kwargs):
super(CheckboxChoiceInput, self).__init__(*args, **kwargs)
self.value = set(force_text(v) for v in self.value)

def is_checked(self):
return self.choice_value in self.value

@html_safe
@python_2_unicode_compatible
class ChoiceFieldRenderer(object):
"""
An object used by RadioSelect to enable customization of radio widgets.
"""

choice_input_class = None
outer_html = '<ul{id_attr}>{content}</ul>'
inner_html = '<li>{choice_value}{sub_widgets}</li>'

def __init__(self, name, value, attrs, choices):
self.name = name
self.value = value
self.attrs = attrs
self.choices = choices

def __getitem__(self, idx):
choice = self.choices[idx]  # Let the IndexError propagate
return self.choice_input_class(self.name, self.value, self.attrs.copy(), choice, idx)

def __str__(self):
return self.render()

def render(self):
"""
Outputs a <ul> for this set of choice fields.
If an id was given to the field, it is applied to the <ul> (each
item in the list will get an id of `$id_$i`).
"""
id_ = self.attrs.get('id')
output = []
for i, choice in enumerate(self.choices):
choice_value, choice_label = choice
if isinstance(choice_label, (tuple, list)):
attrs_plus = self.attrs.copy()
if id_:
attrs_plus['id'] += '_{}'.format(i)
sub_ul_renderer = self.__class__(
name=self.name,
value=self.value,
attrs=attrs_plus,
choices=choice_label,
)
sub_ul_renderer.choice_input_class = self.choice_input_class
output.append(format_html(self.inner_html, choice_value=choice_value,
sub_widgets=sub_ul_renderer.render()))
else:
w = self.choice_input_class(self.name, self.value,
self.attrs.copy(), choice, i)
output.append(format_html(self.inner_html,
choice_value=force_text(w), sub_widgets=''))
return format_html(self.outer_html,
id_attr=format_html(' id="{}"', id_) if id_ else '',
content=mark_safe('\n'.join(output)))

class RadioFieldRenderer(ChoiceFieldRenderer):
choice_input_class = RadioChoiceInput

class CheckboxFieldRenderer(ChoiceFieldRenderer):
choice_input_class = CheckboxChoiceInput

class RendererMixin(object):
renderer = None  # subclasses must define this
_empty_value = None

def __init__(self, *args, **kwargs):
# Override the default renderer if we were passed one.
renderer = kwargs.pop('renderer', None)
if renderer:
self.renderer = renderer
super(RendererMixin, self).__init__(*args, **kwargs)

def subwidgets(self, name, value, attrs=None, choices=()):
for widget in self.get_renderer(name, value, attrs, choices):
yield widget

def get_renderer(self, name, value, attrs=None, choices=()):
"""Returns an instance of the renderer."""
if value is None:
value = self._empty_value
final_attrs = self.build_attrs(attrs)
choices = list(chain(self.choices, choices))
return self.renderer(name, value, final_attrs, choices)

def render(self, name, value, attrs=None, choices=()):
return self.get_renderer(name, value, attrs, choices).render()

def id_for_label(self, id_):
# Widgets using this RendererMixin are made of a collection of
# subwidgets, each with their own <label>, and distinct ID.
# The IDs are made distinct by y "_X" suffix, where X is the zero-based
# index of the choice field. Thus, the label for the main widget should
# reference the first subwidget, hence the "_0" suffix.
if id_:
id_ += '_0'
return id_

[docs]class RadioSelect(RendererMixin, Select):
renderer = RadioFieldRenderer
_empty_value = ''

[docs]class CheckboxSelectMultiple(RendererMixin, SelectMultiple):
renderer = CheckboxFieldRenderer
_empty_value = []

[docs]class MultiWidget(Widget):
"""
A widget that is composed of multiple widgets.

Its render() method is different than other widgets', because it has to
figure out how to split a single value for display in multiple widgets.
The ``value`` argument can be one of two things:

* A list.
* A normal value (e.g., a string) that has been "compressed" from
a list of values.

In the second case -- i.e., if the value is NOT a list -- render() will
first "decompress" the value into a list before rendering it. It does so by
calling the decompress() method, which MultiWidget subclasses must
implement. This method takes a single "compressed" value and returns a
list.

When render() does its HTML rendering, each value in the list is rendered
with the corresponding widget -- the first value is rendered in the first
widget, the second value is rendered in the second widget, etc.

Subclasses may implement format_output(), which takes the list of rendered
widgets and returns a string of HTML that formats them any way you'd like.

You'll probably want to use this class with MultiValueField.
"""
def __init__(self, widgets, attrs=None):
self.widgets = [w() if isinstance(w, type) else w for w in widgets]
super(MultiWidget, self).__init__(attrs)

@property
def is_hidden(self):
return all(w.is_hidden for w in self.widgets)

[docs]    def render(self, name, value, attrs=None):
if self.is_localized:
for widget in self.widgets:
widget.is_localized = self.is_localized
# value is a list of values, each corresponding to a widget
# in self.widgets.
if not isinstance(value, list):
value = self.decompress(value)
output = []
final_attrs = self.build_attrs(attrs)
id_ = final_attrs.get('id')
for i, widget in enumerate(self.widgets):
try:
widget_value = value[i]
except IndexError:
widget_value = None
if id_:
final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
return mark_safe(self.format_output(output))

def id_for_label(self, id_):
# See the comment for RadioSelect.id_for_label()
if id_:
id_ += '_0'
return id_

def value_from_datadict(self, data, files, name):
return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]

[docs]    def format_output(self, rendered_widgets):
"""
Given a list of rendered widgets (as strings), returns a Unicode string
representing the HTML for the whole lot.

This hook allows you to format the HTML design of the widgets, if
needed.
"""
return ''.join(rendered_widgets)

[docs]    def decompress(self, value):
"""
Returns a list of decompressed values for the given compressed value.
The given value can be assumed to be valid, but not necessarily
non-empty.
"""
raise NotImplementedError('Subclasses must implement this method.')

def _get_media(self):
"Media for a multiwidget is the combination of all media of the subwidgets"
media = Media()
for w in self.widgets:
media = media + w.media
return media
media = property(_get_media)

def __deepcopy__(self, memo):
obj = super(MultiWidget, self).__deepcopy__(memo)
obj.widgets = copy.deepcopy(self.widgets)
return obj

@property
def needs_multipart_form(self):
return any(w.needs_multipart_form for w in self.widgets)

[docs]class SplitDateTimeWidget(MultiWidget):
"""
A Widget that splits datetime input into two <input type="text"> boxes.
"""
supports_microseconds = False

def __init__(self, attrs=None, date_format=None, time_format=None):
widgets = (DateInput(attrs=attrs, format=date_format),
TimeInput(attrs=attrs, format=time_format))
super(SplitDateTimeWidget, self).__init__(widgets, attrs)

def decompress(self, value):
if value:
value = to_current_timezone(value)
return [value.date(), value.time().replace(microsecond=0)]
return [None, None]

[docs]class SplitHiddenDateTimeWidget(SplitDateTimeWidget):
"""
A Widget that splits datetime input into two <input type="hidden"> inputs.
"""
def __init__(self, attrs=None, date_format=None, time_format=None):
super(SplitHiddenDateTimeWidget, self).__init__(attrs, date_format, time_format)
for widget in self.widgets:
widget.input_type = 'hidden'

[docs]class SelectDateWidget(Widget):
"""
A Widget that splits date input into three <select> boxes.

This also serves as an example of a Widget that has more than one HTML
element and hence implements value_from_datadict.
"""
none_value = (0, '---')
month_field = '%s_month'
day_field = '%s_day'
year_field = '%s_year'
select_widget = Select

date_re = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')

def __init__(self, attrs=None, years=None, months=None, empty_label=None):
self.attrs = attrs or {}

# Optional list or tuple of years to use in the "year" select box.
if years:
self.years = years
else:
this_year = datetime.date.today().year
self.years = range(this_year, this_year + 10)

# Optional dict of months to use in the "month" select box.
if months:
self.months = months
else:
self.months = MONTHS

# Optional string, list, or tuple to use as empty_label.
if isinstance(empty_label, (list, tuple)):
if not len(empty_label) == 3:
raise ValueError('empty_label list/tuple must have 3 elements.')

self.year_none_value = (0, empty_label[0])
self.month_none_value = (0, empty_label[1])
self.day_none_value = (0, empty_label[2])
else:
if empty_label is not None:
self.none_value = (0, empty_label)

self.year_none_value = self.none_value
self.month_none_value = self.none_value
self.day_none_value = self.none_value

@staticmethod
def _parse_date_fmt():
fmt = get_format('DATE_FORMAT')
escaped = False
for char in fmt:
if escaped:
escaped = False
elif char == '\\':
escaped = True
elif char in 'Yy':
yield 'year'
elif char in 'bEFMmNn':
yield 'month'
elif char in 'dj':
yield 'day'

def render(self, name, value, attrs=None):
try:
year_val, month_val, day_val = value.year, value.month, value.day
except AttributeError:
year_val = month_val = day_val = None
if isinstance(value, six.string_types):
if settings.USE_L10N:
try:
input_format = get_format('DATE_INPUT_FORMATS')[0]
v = datetime.datetime.strptime(force_str(value), input_format)
year_val, month_val, day_val = v.year, v.month, v.day
except ValueError:
pass
if year_val is None:
match = self.date_re.match(value)
if match:
year_val, month_val, day_val = [int(val) for val in match.groups()]
html = {}
choices = [(i, i) for i in self.years]
html['year'] = self.create_select(name, self.year_field, value, year_val, choices, self.year_none_value)
choices = list(self.months.items())
html['month'] = self.create_select(name, self.month_field, value, month_val, choices, self.month_none_value)
choices = [(i, i) for i in range(1, 32)]
html['day'] = self.create_select(name, self.day_field, value, day_val, choices, self.day_none_value)

output = []
for field in self._parse_date_fmt():
output.append(html[field])
return mark_safe('\n'.join(output))

def id_for_label(self, id_):
for first_select in self._parse_date_fmt():
return '%s_%s' % (id_, first_select)
else:
return '%s_month' % id_

def value_from_datadict(self, data, files, name):
y = data.get(self.year_field % name)
m = data.get(self.month_field % name)
d = data.get(self.day_field % name)
if y == m == d == "0":
return None
if y and m and d:
if settings.USE_L10N:
input_format = get_format('DATE_INPUT_FORMATS')[0]
try:
date_value = datetime.date(int(y), int(m), int(d))
except ValueError:
return '%s-%s-%s' % (y, m, d)
else:
date_value = datetime_safe.new_date(date_value)
return date_value.strftime(input_format)
else:
return '%s-%s-%s' % (y, m, d)
return data.get(name)

def create_select(self, name, field, value, val, choices, none_value):
if 'id' in self.attrs:
id_ = self.attrs['id']
else:
id_ = 'id_%s' % name
if not self.is_required:
choices.insert(0, none_value)
local_attrs = self.build_attrs(id=field % id_)
s = self.select_widget(choices=choices)
select_html = s.render(field % name, val, local_attrs)
return select_html

Source code for django.forms.fields

"""
Field classes.
"""

from __future__ import unicode_literals

import copy
import datetime
import os
import re
import sys
import uuid
import warnings
from decimal import Decimal, DecimalException
from io import BytesIO

from django.core import validators
from django.core.exceptions import ValidationError
# Provide this import for backwards compatibility.
from django.core.validators import EMPTY_VALUES  # NOQA
from django.forms.boundfield import BoundField
from django.forms.utils import from_current_timezone, to_current_timezone
from django.forms.widgets import (
FILE_INPUT_CONTRADICTION, CheckboxInput, ClearableFileInput, DateInput,
DateTimeInput, EmailInput, HiddenInput, MultipleHiddenInput,
NullBooleanSelect, NumberInput, Select, SelectMultiple,
SplitDateTimeWidget, SplitHiddenDateTimeWidget, TextInput, TimeInput,
URLInput,
)
from django.utils import formats, six
from django.utils.dateparse import parse_duration
from django.utils.deprecation import (
RemovedInDjango110Warning, RenameMethodsBase,
)
from django.utils.duration import duration_string
from django.utils.encoding import force_str, force_text, smart_text
from django.utils.ipv6 import clean_ipv6_address
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
from django.utils.translation import ugettext_lazy as _, ungettext_lazy

__all__ = (
'Field', 'CharField', 'IntegerField',
'DateField', 'TimeField', 'DateTimeField', 'DurationField',
'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
'SplitDateTimeField', 'GenericIPAddressField', 'FilePathField',
'SlugField', 'TypedChoiceField', 'TypedMultipleChoiceField', 'UUIDField',
)

class RenameFieldMethods(RenameMethodsBase):
renamed_methods = (
('_has_changed', 'has_changed', RemovedInDjango110Warning),
)

[docs]class Field(six.with_metaclass(RenameFieldMethods, object)):
widget = TextInput  # Default widget to use when rendering this type of Field.
hidden_widget = HiddenInput  # Default widget to use when rendering this as "hidden".
default_validators = []  # Default set of validators
# Add an 'invalid' entry to default_error_message if you want a specific
# field error message not raised by the field validators.
default_error_messages = {
'required': _('This field is required.'),
}
empty_values = list(validators.EMPTY_VALUES)

# Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0

def __init__(self, required=True, widget=None, label=None, initial=None,
help_text='', error_messages=None, show_hidden_initial=False,
validators=[], localize=False, disabled=False, label_suffix=None):
# required -- Boolean that specifies whether the field is required.
#             True by default.
# widget -- A Widget class, or instance of a Widget class, that should
#           be used for this Field when displaying it. Each Field has a
#           default Widget that it'll use if you don't specify this. In
#           most cases, the default widget is TextInput.
# label -- A verbose name for this field, for use in displaying this
#          field in a form. By default, Django will use a "pretty"
#          version of the form field name, if the Field is part of a
#          Form.
# initial -- A value to use in this Field's initial display. This value
#            is *not* used as a fallback if data isn't given.
# help_text -- An optional string to use as "help text" for this Field.
# error_messages -- An optional dictionary to override the default
#                   messages that the field will raise.
# show_hidden_initial -- Boolean that specifies if it is needed to render a
#                        hidden widget with initial value after widget.
# validators -- List of additional validators to use
# localize -- Boolean that specifies if the field should be localized.
# disabled -- Boolean that specifies whether the field is disabled, that
#             is its widget is shown in the form but not editable.
# label_suffix -- Suffix to be added to the label. Overrides
#                 form's label_suffix.
self.required, self.label, self.initial = required, label, initial
self.show_hidden_initial = show_hidden_initial
self.help_text = help_text
self.disabled = disabled
self.label_suffix = label_suffix
widget = widget or self.widget
if isinstance(widget, type):
widget = widget()

# Trigger the localization machinery if needed.
self.localize = localize
if self.localize:
widget.is_localized = True

# Let the widget know whether it should display as required.
widget.is_required = self.required

# Hook into self.widget_attrs() for any Field-specific HTML attributes.
extra_attrs = self.widget_attrs(widget)
if extra_attrs:
widget.attrs.update(extra_attrs)

self.widget = widget

# Increase the creation counter, and save our local copy.
self.creation_counter = Field.creation_counter
Field.creation_counter += 1

messages = {}
for c in reversed(self.__class__.__mro__):
messages.update(getattr(c, 'default_error_messages', {}))
messages.update(error_messages or {})
self.error_messages = messages

self.validators = self.default_validators + validators
super(Field, self).__init__()

def prepare_value(self, value):
return value

def to_python(self, value):
return value

def validate(self, value):
if value in self.empty_values and self.required:
raise ValidationError(self.error_messages['required'], code='required')

def run_validators(self, value):
if value in self.empty_values:
return
errors = []
for v in self.validators:
try:
v(value)
except ValidationError as e:
if hasattr(e, 'code') and e.code in self.error_messages:
e.message = self.error_messages[e.code]
errors.extend(e.error_list)
if errors:
raise ValidationError(errors)

[docs]    def clean(self, value):
"""
Validates the given value and returns its "cleaned" value as an
appropriate Python object.

Raises ValidationError for any errors.
"""
value = self.to_python(value)
self.validate(value)
self.run_validators(value)
return value

def bound_data(self, data, initial):
"""
Return the value that should be shown for this field on render of a
bound form, given the submitted POST data for the field and the initial
data, if any.

For most fields, this will simply be data; FileFields need to handle it
a bit differently.
"""
if self.disabled:
return initial
return data

def widget_attrs(self, widget):
"""
Given a Widget instance (*not* a Widget class), returns a dictionary of
any HTML attributes that should be added to the Widget, based on this
Field.
"""
return {}

[docs]    def has_changed(self, initial, data):
"""
Return True if data differs from initial.
"""
try:
data = self.to_python(data)
if hasattr(self, '_coerce'):
return self._coerce(data) != self._coerce(initial)
except ValidationError:
return True
# For purposes of seeing whether something has changed, None is
# the same as an empty string, if the data or initial value we get
# is None, replace it with ''.
initial_value = initial if initial is not None else ''
data_value = data if data is not None else ''
return initial_value != data_value

[docs]    def get_bound_field(self, form, field_name):
"""
Return a BoundField instance that will be used when accessing the form
field in a template.
"""
return BoundField(form, self, field_name)

def __deepcopy__(self, memo):
result = copy.copy(self)
memo[id(self)] = result
result.widget = copy.deepcopy(self.widget, memo)
result.validators = self.validators[:]
return result

[docs]class CharField(Field):
def __init__(self, max_length=None, min_length=None, strip=True, *args, **kwargs):
self.max_length = max_length
self.min_length = min_length
self.strip = strip
super(CharField, self).__init__(*args, **kwargs)
if min_length is not None:
self.validators.append(validators.MinLengthValidator(int(min_length)))
if max_length is not None:
self.validators.append(validators.MaxLengthValidator(int(max_length)))

def to_python(self, value):
"Returns a Unicode object."
if value in self.empty_values:
return ''
value = force_text(value)
if self.strip:
value = value.strip()
return value

def widget_attrs(self, widget):
attrs = super(CharField, self).widget_attrs(widget)
if self.max_length is not None:
# The HTML attribute is maxlength, not max_length.
attrs.update({'maxlength': str(self.max_length)})
return attrs

[docs]class IntegerField(Field):
widget = NumberInput
default_error_messages = {
'invalid': _('Enter a whole number.'),
}
re_decimal = re.compile(r'\.0*\s*$')

def __init__(self, max_value=None, min_value=None, *args, **kwargs):
self.max_value, self.min_value = max_value, min_value
if kwargs.get('localize') and self.widget == NumberInput:
# Localized number input is not well supported on most browsers
kwargs.setdefault('widget', super(IntegerField, self).widget)
super(IntegerField, self).__init__(*args, **kwargs)

if max_value is not None:
self.validators.append(validators.MaxValueValidator(max_value))
if min_value is not None:
self.validators.append(validators.MinValueValidator(min_value))

def to_python(self, value):
"""
Validates that int() can be called on the input. Returns the result
of int(). Returns None for empty values.
"""
value = super(IntegerField, self).to_python(value)
if value in self.empty_values:
return None
if self.localize:
value = formats.sanitize_separators(value)
# Strip trailing decimal and zeros.
try:
value = int(self.re_decimal.sub('', str(value)))
except (ValueError, TypeError):
raise ValidationError(self.error_messages['invalid'], code='invalid')
return value

def widget_attrs(self, widget):
attrs = super(IntegerField, self).widget_attrs(widget)
if isinstance(widget, NumberInput):
if self.min_value is not None:
attrs['min'] = self.min_value
if self.max_value is not None:
attrs['max'] = self.max_value
return attrs

[docs]class FloatField(IntegerField):
default_error_messages = {
'invalid': _('Enter a number.'),
}

def to_python(self, value):
"""
Validates that float() can be called on the input. Returns the result
of float(). Returns None for empty values.
"""
value = super(IntegerField, self).to_python(value)
if value in self.empty_values:
return None
if self.localize:
value = formats.sanitize_separators(value)
try:
value = float(value)
except (ValueError, TypeError):
raise ValidationError(self.error_messages['invalid'], code='invalid')
return value

def validate(self, value):
super(FloatField, self).validate(value)

# Check for NaN (which is the only thing not equal to itself) and +/- infinity
if value != value or value in (Decimal('Inf'), Decimal('-Inf')):
raise ValidationError(self.error_messages['invalid'], code='invalid')

return value

def widget_attrs(self, widget):
attrs = super(FloatField, self).widget_attrs(widget)
if isinstance(widget, NumberInput) and 'step' not in widget.attrs:
attrs.setdefault('step', 'any')
return attrs

[docs]class DecimalField(IntegerField):
default_error_messages = {
'invalid': _('Enter a number.'),
}

def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs):
self.max_digits, self.decimal_places = max_digits, decimal_places
super(DecimalField, self).__init__(max_value, min_value, *args, **kwargs)
self.validators.append(validators.DecimalValidator(max_digits, decimal_places))

def to_python(self, value):
"""
Validates that the input is a decimal number. Returns a Decimal
instance. Returns None for empty values. Ensures that there are no more
than max_digits in the number, and no more than decimal_places digits
after the decimal point.
"""
if value in self.empty_values:
return None
if self.localize:
value = formats.sanitize_separators(value)
value = smart_text(value).strip()
try:
value = Decimal(value)
except DecimalException:
raise ValidationError(self.error_messages['invalid'], code='invalid')
return value

def validate(self, value):
super(DecimalField, self).validate(value)
if value in self.empty_values:
return
# Check for NaN, Inf and -Inf values. We can't compare directly for NaN,
# since it is never equal to itself. However, NaN is the only value that
# isn't equal to itself, so we can use this to identify NaN
if value != value or value == Decimal("Inf") or value == Decimal("-Inf"):
raise ValidationError(self.error_messages['invalid'], code='invalid')

def widget_attrs(self, widget):
attrs = super(DecimalField, self).widget_attrs(widget)
if isinstance(widget, NumberInput) and 'step' not in widget.attrs:
if self.decimal_places is not None:
# Use exponential notation for small values since they might
# be parsed as 0 otherwise. ref #20765
step = str(Decimal('1') / 10 ** self.decimal_places).lower()
else:
step = 'any'
attrs.setdefault('step', step)
return attrs

class BaseTemporalField(Field):

def __init__(self, input_formats=None, *args, **kwargs):
super(BaseTemporalField, self).__init__(*args, **kwargs)
if input_formats is not None:
self.input_formats = input_formats

def to_python(self, value):
# Try to coerce the value to unicode.
unicode_value = force_text(value, strings_only=True)
if isinstance(unicode_value, six.text_type):
value = unicode_value.strip()
# If unicode, try to strptime against each input format.
if isinstance(value, six.text_type):
for format in self.input_formats:
try:
return self.strptime(value, format)
except (ValueError, TypeError):
continue
raise ValidationError(self.error_messages['invalid'], code='invalid')

def strptime(self, value, format):
raise NotImplementedError('Subclasses must define this method.')

[docs]class DateField(BaseTemporalField):
widget = DateInput
input_formats = formats.get_format_lazy('DATE_INPUT_FORMATS')
default_error_messages = {
'invalid': _('Enter a valid date.'),
}

def to_python(self, value):
"""
Validates that the input can be converted to a date. Returns a Python
datetime.date object.
"""
if value in self.empty_values:
return None
if isinstance(value, datetime.datetime):
return value.date()
if isinstance(value, datetime.date):
return value
return super(DateField, self).to_python(value)

def strptime(self, value, format):
return datetime.datetime.strptime(force_str(value), format).date()

[docs]class TimeField(BaseTemporalField):
widget = TimeInput
input_formats = formats.get_format_lazy('TIME_INPUT_FORMATS')
default_error_messages = {
'invalid': _('Enter a valid time.')
}

def to_python(self, value):
"""
Validates that the input can be converted to a time. Returns a Python
datetime.time object.
"""
if value in self.empty_values:
return None
if isinstance(value, datetime.time):
return value
return super(TimeField, self).to_python(value)

def strptime(self, value, format):
return datetime.datetime.strptime(force_str(value), format).time()

[docs]class DateTimeField(BaseTemporalField):
widget = DateTimeInput
input_formats = formats.get_format_lazy('DATETIME_INPUT_FORMATS')
default_error_messages = {
'invalid': _('Enter a valid date/time.'),
}

def prepare_value(self, value):
if isinstance(value, datetime.datetime):
value = to_current_timezone(value)
return value

def to_python(self, value):
"""
Validates that the input can be converted to a datetime. Returns a
Python datetime.datetime object.
"""
if value in self.empty_values:
return None
if isinstance(value, datetime.datetime):
return from_current_timezone(value)
if isinstance(value, datetime.date):
result = datetime.datetime(value.year, value.month, value.day)
return from_current_timezone(result)
result = super(DateTimeField, self).to_python(value)
return from_current_timezone(result)

def strptime(self, value, format):
return datetime.datetime.strptime(force_str(value), format)

[docs]class DurationField(Field):
default_error_messages = {
'invalid': _('Enter a valid duration.'),
}

def prepare_value(self, value):
if isinstance(value, datetime.timedelta):
return duration_string(value)
return value

def to_python(self, value):
if value in self.empty_values:
return None
if isinstance(value, datetime.timedelta):
return value
value = parse_duration(value)
if value is None:
raise ValidationError(self.error_messages['invalid'], code='invalid')
return value

[docs]class RegexField(CharField):
def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs):
"""
regex can be either a string or a compiled regular expression object.
error_message is an optional error message to use, if
'Enter a valid value' is too generic for you.
"""
kwargs.setdefault('strip', False)
# error_message is just kept for backwards compatibility:
if error_message is not None:
warnings.warn(
"The 'error_message' argument is deprecated. Use "
"Field.error_messages['invalid'] instead.",
RemovedInDjango110Warning, stacklevel=2
)
error_messages = kwargs.get('error_messages') or {}
error_messages['invalid'] = error_message
kwargs['error_messages'] = error_messages
super(RegexField, self).__init__(max_length, min_length, *args, **kwargs)
self._set_regex(regex)

def _get_regex(self):
return self._regex

def _set_regex(self, regex):
if isinstance(regex, six.string_types):
regex = re.compile(regex, re.UNICODE)
self._regex = regex
if hasattr(self, '_regex_validator') and self._regex_validator in self.validators:
self.validators.remove(self._regex_validator)
self._regex_validator = validators.RegexValidator(regex=regex)
self.validators.append(self._regex_validator)

regex = property(_get_regex, _set_regex)

[docs]class EmailField(CharField):
widget = EmailInput
default_validators = [validators.validate_email]

def clean(self, value):
value = self.to_python(value).strip()
return super(EmailField, self).clean(value)

[docs]class FileField(Field):
widget = ClearableFileInput
default_error_messages = {
'invalid': _("No file was submitted. Check the encoding type on the form."),
'missing': _("No file was submitted."),
'empty': _("The submitted file is empty."),
'max_length': ungettext_lazy(
'Ensure this filename has at most %(max)d character (it has %(length)d).',
'Ensure this filename has at most %(max)d characters (it has %(length)d).',
'max'),
'contradiction': _('Please either submit a file or check the clear checkbox, not both.')
}

def __init__(self, *args, **kwargs):
self.max_length = kwargs.pop('max_length', None)
self.allow_empty_file = kwargs.pop('allow_empty_file', False)
super(FileField, self).__init__(*args, **kwargs)

def to_python(self, data):
if data in self.empty_values:
return None

# UploadedFile objects should have name and size attributes.
try:
file_name = data.name
file_size = data.size
except AttributeError:
raise ValidationError(self.error_messages['invalid'], code='invalid')

if self.max_length is not None and len(file_name) > self.max_length:
params = {'max': self.max_length, 'length': len(file_name)}
raise ValidationError(self.error_messages['max_length'], code='max_length', params=params)
if not file_name:
raise ValidationError(self.error_messages['invalid'], code='invalid')
if not self.allow_empty_file and not file_size:
raise ValidationError(self.error_messages['empty'], code='empty')

return data

def clean(self, data, initial=None):
# If the widget got contradictory inputs, we raise a validation error
if data is FILE_INPUT_CONTRADICTION:
raise ValidationError(self.error_messages['contradiction'], code='contradiction')
# False means the field value should be cleared; further validation is
# not needed.
if data is False:
if not self.required:
return False
# If the field is required, clearing is not possible (the widget
# shouldn't return False data in that case anyway). False is not
# in self.empty_value; if a False value makes it this far
# it should be validated from here on out as None (so it will be
# caught by the required check).
data = None
if not data and initial:
return initial
return super(FileField, self).clean(data)

def bound_data(self, data, initial):
if data in (None, FILE_INPUT_CONTRADICTION):
return initial
return data

def has_changed(self, initial, data):
if data is None:
return False
return True

[docs]class ImageField(FileField):
default_error_messages = {
'invalid_image': _(
"Upload a valid image. The file you uploaded was either not an "
"image or a corrupted image."
),
}

def to_python(self, data):
"""
Checks that the file-upload field data contains a valid image (GIF, JPG,
PNG, possibly others -- whatever the Python Imaging Library supports).
"""
f = super(ImageField, self).to_python(data)
if f is None:
return None

from PIL import Image

# We need to get a file object for Pillow. We might have a path or we might
# have to read the data into memory.
if hasattr(data, 'temporary_file_path'):
file = data.temporary_file_path()
else:
if hasattr(data, 'read'):
file = BytesIO(data.read())
else:
file = BytesIO(data['content'])

try:
# load() could spot a truncated JPEG, but it loads the entire
# image in memory, which is a DoS vector. See #3848 and #18520.
image = Image.open(file)
# verify() must be called immediately after the constructor.
image.verify()

# Annotating so subclasses can reuse it for their own validation
f.image = image
# Pillow doesn't detect the MIME type of all formats. In those
# cases, content_type will be None.
f.content_type = Image.MIME.get(image.format)
except Exception:
# Pillow doesn't recognize it as an image.
six.reraise(ValidationError, ValidationError(
self.error_messages['invalid_image'],
code='invalid_image',
), sys.exc_info()[2])
if hasattr(f, 'seek') and callable(f.seek):
f.seek(0)
return f

[docs]class URLField(CharField):
widget = URLInput
default_error_messages = {
'invalid': _('Enter a valid URL.'),
}
default_validators = [validators.URLValidator()]

def to_python(self, value):

def split_url(url):
"""
Returns a list of url parts via ``urlparse.urlsplit`` (or raises a
``ValidationError`` exception for certain).
"""
try:
return list(urlsplit(url))
except ValueError:
# urlparse.urlsplit can raise a ValueError with some
# misformatted URLs.
raise ValidationError(self.error_messages['invalid'], code='invalid')

value = super(URLField, self).to_python(value)
if value:
url_fields = split_url(value)
if not url_fields[0]:
# If no URL scheme given, assume http://
url_fields[0] = 'http'
if not url_fields[1]:
# Assume that if no domain is provided, that the path segment
# contains the domain.
url_fields[1] = url_fields[2]
url_fields[2] = ''
# Rebuild the url_fields list, since the domain segment may now
# contain the path too.
url_fields = split_url(urlunsplit(url_fields))
value = urlunsplit(url_fields)
return value

def clean(self, value):
value = self.to_python(value).strip()
return super(URLField, self).clean(value)

[docs]class BooleanField(Field):
widget = CheckboxInput

def to_python(self, value):
"""Returns a Python boolean object."""
# Explicitly check for the string 'False', which is what a hidden field
# will submit for False. Also check for '0', since this is what
# RadioSelect will provide. Because bool("True") == bool('1') == True,
# we don't need to handle that explicitly.
if isinstance(value, six.string_types) and value.lower() in ('false', '0'):
value = False
else:
value = bool(value)
return super(BooleanField, self).to_python(value)

def validate(self, value):
if not value and self.required:
raise ValidationError(self.error_messages['required'], code='required')

def has_changed(self, initial, data):
# Sometimes data or initial could be None or '' which should be the
# same thing as False.
if initial == 'False':
# show_hidden_initial may have transformed False to 'False'
initial = False
return bool(initial) != bool(data)

[docs]class NullBooleanField(BooleanField):
"""
A field whose valid values are None, True and False. Invalid values are
cleaned to None.
"""
widget = NullBooleanSelect

def to_python(self, value):
"""
Explicitly checks for the string 'True' and 'False', which is what a
hidden field will submit for True and False, for 'true' and 'false',
which are likely to be returned by JavaScript serializations of forms,
and for '1' and '0', which is what a RadioField will submit. Unlike
the Booleanfield we need to explicitly check for True, because we are
not using the bool() function
"""
if value in (True, 'True', 'true', '1'):
return True
elif value in (False, 'False', 'false', '0'):
return False
else:
return None

def validate(self, value):
pass

def has_changed(self, initial, data):
# None (unknown) and False (No) are not the same
if initial is not None:
initial = bool(initial)
if data is not None:
data = bool(data)
return initial != data

class CallableChoiceIterator(object):
def __init__(self, choices_func):
self.choices_func = choices_func

def __iter__(self):
for e in self.choices_func():
yield e

[docs]class ChoiceField(Field):
widget = Select
default_error_messages = {
'invalid_choice': _('Select a valid choice. %(value)s is not one of the available choices.'),
}

def __init__(self, choices=(), required=True, widget=None, label=None,
initial=None, help_text='', *args, **kwargs):
super(ChoiceField, self).__init__(required=required, widget=widget, label=label,
initial=initial, help_text=help_text, *args, **kwargs)
self.choices = choices

def __deepcopy__(self, memo):
result = super(ChoiceField, self).__deepcopy__(memo)
result._choices = copy.deepcopy(self._choices, memo)
return result

def _get_choices(self):
return self._choices

def _set_choices(self, value):
# Setting choices also sets the choices on the widget.
# choices can be any iterable, but we call list() on it because
# it will be consumed more than once.
if callable(value):
value = CallableChoiceIterator(value)
else:
value = list(value)

self._choices = self.widget.choices = value

choices = property(_get_choices, _set_choices)

def to_python(self, value):
"Returns a Unicode object."
if value in self.empty_values:
return ''
return smart_text(value)

def validate(self, value):
"""
Validates that the input is in self.choices.
"""
super(ChoiceField, self).validate(value)
if value and not self.valid_value(value):
raise ValidationError(
self.error_messages['invalid_choice'],
code='invalid_choice',
params={'value': value},
)

def valid_value(self, value):
"Check to see if the provided value is a valid choice"
text_value = force_text(value)
for k, v in self.choices:
if isinstance(v, (list, tuple)):
# This is an optgroup, so look inside the group for options
for k2, v2 in v:
if value == k2 or text_value == force_text(k2):
return True
else:
if value == k or text_value == force_text(k):
return True
return False

[docs]class TypedChoiceField(ChoiceField):
def __init__(self, *args, **kwargs):
self.coerce = kwargs.pop('coerce', lambda val: val)
self.empty_value = kwargs.pop('empty_value', '')
super(TypedChoiceField, self).__init__(*args, **kwargs)

def _coerce(self, value):
"""
Validate that the value can be coerced to the right type (if not empty).
"""
if value == self.empty_value or value in self.empty_values:
return self.empty_value
try:
value = self.coerce(value)
except (ValueError, TypeError, ValidationError):
raise ValidationError(
self.error_messages['invalid_choice'],
code='invalid_choice',
params={'value': value},
)
return value

def clean(self, value):
value = super(TypedChoiceField, self).clean(value)
return self._coerce(value)

[docs]class MultipleChoiceField(ChoiceField):
hidden_widget = MultipleHiddenInput
widget = SelectMultiple
default_error_messages = {
'invalid_choice': _('Select a valid choice. %(value)s is not one of the available choices.'),
'invalid_list': _('Enter a list of values.'),
}

def to_python(self, value):
if not value:
return []
elif not isinstance(value, (list, tuple)):
raise ValidationError(self.error_messages['invalid_list'], code='invalid_list')
return [smart_text(val) for val in value]

def validate(self, value):
"""
Validates that the input is a list or tuple.
"""
if self.required and not value:
raise ValidationError(self.error_messages['required'], code='required')
# Validate that each value in the value list is in self.choices.
for val in value:
if not self.valid_value(val):
raise ValidationError(
self.error_messages['invalid_choice'],
code='invalid_choice',
params={'value': val},
)

def has_changed(self, initial, data):
if initial is None:
initial = []
if data is None:
data = []
if len(initial) != len(data):
return True
initial_set = set(force_text(value) for value in initial)
data_set = set(force_text(value) for value in data)
return data_set != initial_set

[docs]class TypedMultipleChoiceField(MultipleChoiceField):
def __init__(self, *args, **kwargs):
self.coerce = kwargs.pop('coerce', lambda val: val)
self.empty_value = kwargs.pop('empty_value', [])
super(TypedMultipleChoiceField, self).__init__(*args, **kwargs)

def _coerce(self, value):
"""
Validates that the values are in self.choices and can be coerced to the
right type.
"""
if value == self.empty_value or value in self.empty_values:
return self.empty_value
new_value = []
for choice in value:
try:
new_value.append(self.coerce(choice))
except (ValueError, TypeError, ValidationError):
raise ValidationError(
self.error_messages['invalid_choice'],
code='invalid_choice',
params={'value': choice},
)
return new_value

def clean(self, value):
value = super(TypedMultipleChoiceField, self).clean(value)
return self._coerce(value)

def validate(self, value):
if value != self.empty_value:
super(TypedMultipleChoiceField, self).validate(value)
elif self.required:
raise ValidationError(self.error_messages['required'], code='required')

[docs]class ComboField(Field):
"""
A Field whose clean() method calls multiple Field clean() methods.
"""
def __init__(self, fields=(), *args, **kwargs):
super(ComboField, self).__init__(*args, **kwargs)
# Set 'required' to False on the individual fields, because the
# required validation will be handled by ComboField, not by those
# individual fields.
for f in fields:
f.required = False
self.fields = fields

def clean(self, value):
"""
Validates the given value against all of self.fields, which is a
list of Field instances.
"""
super(ComboField, self).clean(value)
for field in self.fields:
value = field.clean(value)
return value

[docs]class MultiValueField(Field):
"""
A Field that aggregates the logic of multiple Fields.

Its clean() method takes a "decompressed" list of values, which are then
cleaned into a single value according to self.fields. Each value in
this list is cleaned by the corresponding field -- the first value is
cleaned by the first field, the second value is cleaned by the second
field, etc. Once all fields are cleaned, the list of clean values is
"compressed" into a single value.

Subclasses should not have to implement clean(). Instead, they must
implement compress(), which takes a list of valid values and returns a
"compressed" version of those values -- a single value.

You'll probably want to use this with MultiWidget.
"""
default_error_messages = {
'invalid': _('Enter a list of values.'),
'incomplete': _('Enter a complete value.'),
}

def __init__(self, fields=(), *args, **kwargs):
self.require_all_fields = kwargs.pop('require_all_fields', True)
super(MultiValueField, self).__init__(*args, **kwargs)
for f in fields:
f.error_messages.setdefault('incomplete',
self.error_messages['incomplete'])
if self.require_all_fields:
# Set 'required' to False on the individual fields, because the
# required validation will be handled by MultiValueField, not
# by those individual fields.
f.required = False
self.fields = fields

def __deepcopy__(self, memo):
result = super(MultiValueField, self).__deepcopy__(memo)
result.fields = tuple(x.__deepcopy__(memo) for x in self.fields)
return result

def validate(self, value):
pass

def clean(self, value):
"""
Validates every value in the given list. A value is validated against
the corresponding Field in self.fields.

For example, if this MultiValueField was instantiated with
fields=(DateField(), TimeField()), clean() would call
DateField.clean(value[0]) and TimeField.clean(value[1]).
"""
clean_data = []
errors = []
if not value or isinstance(value, (list, tuple)):
if not value or not [v for v in value if v not in self.empty_values]:
if self.required:
raise ValidationError(self.error_messages['required'], code='required')
else:
return self.compress([])
else:
raise ValidationError(self.error_messages['invalid'], code='invalid')
for i, field in enumerate(self.fields):
try:
field_value = value[i]
except IndexError:
field_value = None
if field_value in self.empty_values:
if self.require_all_fields:
# Raise a 'required' error if the MultiValueField is
# required and any field is empty.
if self.required:
raise ValidationError(self.error_messages['required'], code='required')
elif field.required:
# Otherwise, add an 'incomplete' error to the list of
# collected errors and skip field cleaning, if a required
# field is empty.
if field.error_messages['incomplete'] not in errors:
errors.append(field.error_messages['incomplete'])
continue
try:
clean_data.append(field.clean(field_value))
except ValidationError as e:
# Collect all validation errors in a single list, which we'll
# raise at the end of clean(), rather than raising a single
# exception for the first error we encounter. Skip duplicates.
errors.extend(m for m in e.error_list if m not in errors)
if errors:
raise ValidationError(errors)

out = self.compress(clean_data)
self.validate(out)
self.run_validators(out)
return out

[docs]    def compress(self, data_list):
"""
Returns a single value for the given list of values. The values can be
assumed to be valid.

For example, if this MultiValueField was instantiated with
fields=(DateField(), TimeField()), this might return a datetime
object created by combining the date and time in data_list.
"""
raise NotImplementedError('Subclasses must implement this method.')

def has_changed(self, initial, data):
if initial is None:
initial = ['' for x in range(0, len(data))]
else:
if not isinstance(initial, list):
initial = self.widget.decompress(initial)
for field, initial, data in zip(self.fields, initial, data):
try:
initial = field.to_python(initial)
except ValidationError:
return True
if field.has_changed(initial, data):
return True
return False

[docs]class FilePathField(ChoiceField):
def __init__(self, path, match=None, recursive=False, allow_files=True,
allow_folders=False, required=True, widget=None, label=None,
initial=None, help_text='', *args, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
self.allow_files, self.allow_folders = allow_files, allow_folders
super(FilePathField, self).__init__(choices=(), required=required,
widget=widget, label=label, initial=initial, help_text=help_text,
*args, **kwargs)

if self.required:
self.choices = []
else:
self.choices = [("", "---------")]

if self.match is not None:
self.match_re = re.compile(self.match)

if recursive:
for root, dirs, files in sorted(os.walk(self.path)):
if self.allow_files:
for f in files:
if self.match is None or self.match_re.search(f):
f = os.path.join(root, f)
self.choices.append((f, f.replace(path, "", 1)))
if self.allow_folders:
for f in dirs:
if f == '__pycache__':
continue
if self.match is None or self.match_re.search(f):
f = os.path.join(root, f)
self.choices.append((f, f.replace(path, "", 1)))
else:
try:
for f in sorted(os.listdir(self.path)):
if f == '__pycache__':
continue
full_file = os.path.join(self.path, f)
if (((self.allow_files and os.path.isfile(full_file)) or
(self.allow_folders and os.path.isdir(full_file))) and
(self.match is None or self.match_re.search(f))):
self.choices.append((full_file, f))
except OSError:
pass

self.widget.choices = self.choices

[docs]class SplitDateTimeField(MultiValueField):
widget = SplitDateTimeWidget
hidden_widget = SplitHiddenDateTimeWidget
default_error_messages = {
'invalid_date': _('Enter a valid date.'),
'invalid_time': _('Enter a valid time.'),
}

def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kwargs):
errors = self.default_error_messages.copy()
if 'error_messages' in kwargs:
errors.update(kwargs['error_messages'])
localize = kwargs.get('localize', False)
fields = (
DateField(input_formats=input_date_formats,
error_messages={'invalid': errors['invalid_date']},
localize=localize),
TimeField(input_formats=input_time_formats,
error_messages={'invalid': errors['invalid_time']},
localize=localize),
)
super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)

def compress(self, data_list):
if data_list:
# Raise a validation error if time or date is empty
# (possible if SplitDateTimeField has required=False).
if data_list[0] in self.empty_values:
raise ValidationError(self.error_messages['invalid_date'], code='invalid_date')
if data_list[1] in self.empty_values:
raise ValidationError(self.error_messages['invalid_time'], code='invalid_time')
result = datetime.datetime.combine(*data_list)
return from_current_timezone(result)
return None

[docs]class GenericIPAddressField(CharField):
def __init__(self, protocol='both', unpack_ipv4=False, *args, **kwargs):
self.unpack_ipv4 = unpack_ipv4
self.default_validators = validators.ip_address_validators(protocol, unpack_ipv4)[0]
super(GenericIPAddressField, self).__init__(*args, **kwargs)

def to_python(self, value):
if value in self.empty_values:
return ''
value = value.strip()
if value and ':' in value:
return clean_ipv6_address(value, self.unpack_ipv4)
return value

[docs]class SlugField(CharField):
default_validators = [validators.validate_slug]

def __init__(self, *args, **kwargs):
self.allow_unicode = kwargs.pop('allow_unicode', False)
if self.allow_unicode:
self.default_validators = [validators.validate_unicode_slug]
super(SlugField, self).__init__(*args, **kwargs)

[docs]class UUIDField(CharField):
default_error_messages = {
'invalid': _('Enter a valid UUID.'),
}

def prepare_value(self, value):
if isinstance(value, uuid.UUID):
return value.hex
return value

def to_python(self, value):
value = super(UUIDField, self).to_python(value)
if value in self.empty_values:
return None
if not isinstance(value, uuid.UUID):
try:
value = uuid.UUID(value)
except ValueError:
raise ValidationError(self.error_messages['invalid'], code='invalid')
return value

Source code for django.forms.boundfield

from __future__ import unicode_literals

import datetime

from django.forms.utils import flatatt, pretty_name
from django.forms.widgets import Textarea, TextInput
from django.utils import six
from django.utils.encoding import (
force_text, python_2_unicode_compatible, smart_text,
)
from django.utils.html import conditional_escape, format_html, html_safe
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _

__all__ = ('BoundField',)

UNSET = object()

@html_safe
@python_2_unicode_compatible

[docs]class BoundField(object):
"A Field plus data"
def __init__(self, form, field, name):
self.form = form
self.field = field
self.name = name
self.html_name = form.add_prefix(name)
self.html_initial_name = form.add_initial_prefix(name)
self.html_initial_id = form.add_initial_prefix(self.auto_id)
if self.field.label is None:
self.label = pretty_name(name)
else:
self.label = self.field.label
self.help_text = field.help_text or ''
self._initial_value = UNSET

def __str__(self):
"""Renders this field as an HTML widget."""
if self.field.show_hidden_initial:
return self.as_widget() + self.as_hidden(only_initial=True)
return self.as_widget()

def __iter__(self):
"""
Yields rendered strings that comprise all widgets in this BoundField.

This really is only useful for RadioSelect widgets, so that you can
iterate over individual radio buttons in a template.
"""
id_ = self.field.widget.attrs.get('id') or self.auto_id
attrs = {'id': id_} if id_ else {}
for subwidget in self.field.widget.subwidgets(self.html_name, self.value(), attrs):
yield subwidget

def __len__(self):
return len(list(self.__iter__()))

def __getitem__(self, idx):
# Prevent unnecessary reevaluation when accessing BoundField's attrs
# from templates.
if not isinstance(idx, six.integer_types + (slice,)):
raise TypeError
return list(self.__iter__())[idx]

@property
def errors(self):
"""
Returns an ErrorList for this field. Returns an empty ErrorList
if there are none.
"""
return self.form.errors.get(self.name, self.form.error_class())

[docs]    def as_widget(self, widget=None, attrs=None, only_initial=False):
"""
Renders the field by rendering the passed widget, adding any HTML
attributes passed as attrs.  If no widget is specified, then the
field's default widget will be used.
"""
if not widget:
widget = self.field.widget

if self.field.localize:
widget.is_localized = True

attrs = attrs or {}
if self.field.disabled:
attrs['disabled'] = True
auto_id = self.auto_id
if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
if not only_initial:
attrs['id'] = auto_id
else:
attrs['id'] = self.html_initial_id

if not only_initial:
name = self.html_name
else:
name = self.html_initial_name
return force_text(widget.render(name, self.value(), attrs=attrs))

def as_text(self, attrs=None, **kwargs):
"""
Returns a string of HTML for representing this as an <input type="text">.
"""
return self.as_widget(TextInput(), attrs, **kwargs)

def as_textarea(self, attrs=None, **kwargs):
"Returns a string of HTML for representing this as a <textarea>."
return self.as_widget(Textarea(), attrs, **kwargs)

[docs]    def as_hidden(self, attrs=None, **kwargs):
"""
Returns a string of HTML for representing this as an <input type="hidden">.
"""
return self.as_widget(self.field.hidden_widget(), attrs, **kwargs)

@property
def data(self):
"""
Returns the data for this BoundField, or None if it wasn't given.
"""
return self.field.widget.value_from_datadict(self.form.data, self.form.files, self.html_name)

[docs]    def value(self):
"""
Returns the value for this BoundField, using the initial value if
the form is not bound or the data otherwise.
"""
if not self.form.is_bound:
data = self.form.initial.get(self.name, self.field.initial)
if callable(data):
if self._initial_value is not UNSET:
data = self._initial_value
else:
data = data()
# If this is an auto-generated default date, nix the
# microseconds for standardized handling. See #22502.
if (isinstance(data, (datetime.datetime, datetime.time)) and
not self.field.widget.supports_microseconds):
data = data.replace(microsecond=0)
self._initial_value = data
else:
data = self.field.bound_data(
self.data, self.form.initial.get(self.name, self.field.initial)
)
return self.field.prepare_value(data)

[docs]    def label_tag(self, contents=None, attrs=None, label_suffix=None):
"""
Wraps the given contents in a <label>, if the field has an ID attribute.
contents should be 'mark_safe'd to avoid HTML escaping. If contents
aren't given, uses the field's HTML-escaped label.

If attrs are given, they're used as HTML attributes on the <label> tag.

label_suffix allows overriding the form's label_suffix.
"""
contents = contents or self.label
if label_suffix is None:
label_suffix = (self.field.label_suffix if self.field.label_suffix is not None
else self.form.label_suffix)
# Only add the suffix if the label does not end in punctuation.
# Translators: If found as last label character, these punctuation
# characters will prevent the default label_suffix to be appended to the label
if label_suffix and contents and contents[-1] not in _(':?.!'):
contents = format_html('{}{}', contents, label_suffix)
widget = self.field.widget
id_ = widget.attrs.get('id') or self.auto_id
if id_:
id_for_label = widget.id_for_label(id_)
if id_for_label:
attrs = dict(attrs or {}, **{'for': id_for_label})
if self.field.required and hasattr(self.form, 'required_css_class'):
attrs = attrs or {}
if 'class' in attrs:
attrs['class'] += ' ' + self.form.required_css_class
else:
attrs['class'] = self.form.required_css_class
attrs = flatatt(attrs) if attrs else ''
contents = format_html('<label{}>{}</label>', attrs, contents)
else:
contents = conditional_escape(contents)
return mark_safe(contents)

[docs]    def css_classes(self, extra_classes=None):
"""
Returns a string of space-separated CSS classes for this field.
"""
if hasattr(extra_classes, 'split'):
extra_classes = extra_classes.split()
extra_classes = set(extra_classes or [])
if self.errors and hasattr(self.form, 'error_css_class'):
extra_classes.add(self.form.error_css_class)
if self.field.required and hasattr(self.form, 'required_css_class'):
extra_classes.add(self.form.required_css_class)
return ' '.join(extra_classes)

@property
def is_hidden(self):
"Returns True if this BoundField's widget is hidden."
return self.field.widget.is_hidden

@property
def auto_id(self):
"""
Calculates and returns the ID attribute for this BoundField, if the
associated Form has specified auto_id. Returns an empty string otherwise.
"""
auto_id = self.form.auto_id
if auto_id and '%s' in smart_text(auto_id):
return smart_text(auto_id) % self.html_name
elif auto_id:
return self.html_name
return ''

@property
def id_for_label(self):
"""
Wrapper around the field widget's `id_for_label` method.
Useful, for example, for focusing on this field regardless of whether
it has a single widget or a MultiWidget.
"""
widget = self.field.widget
id_ = widget.attrs.get('id') or self.auto_id
return widget.id_for_label(id_)

Source code for django.forms.models

"""
Helper functions for creating Form classes from Django models
and database field objects.
"""

from __future__ import unicode_literals

from collections import OrderedDict
from itertools import chain

from django.core.exceptions import (
NON_FIELD_ERRORS, FieldError, ImproperlyConfigured, ValidationError,
)
from django.forms.fields import ChoiceField, Field
from django.forms.forms import BaseForm, DeclarativeFieldsMetaclass
from django.forms.formsets import BaseFormSet, formset_factory
from django.forms.utils import ErrorList
from django.forms.widgets import (
HiddenInput, MultipleHiddenInput, SelectMultiple,
)
from django.utils import six
from django.utils.encoding import force_text, smart_text
from django.utils.text import capfirst, get_text_list
from django.utils.translation import ugettext, ugettext_lazy as _

__all__ = (
'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
'ModelChoiceField', 'ModelMultipleChoiceField', 'ALL_FIELDS',
'BaseModelFormSet', 'modelformset_factory', 'BaseInlineFormSet',
'inlineformset_factory', 'modelform_factory',
)

ALL_FIELDS = '__all__'

def construct_instance(form, instance, fields=None, exclude=None):
"""
Constructs and returns a model instance from the bound ``form``'s
``cleaned_data``, but does not save the returned instance to the
database.
"""
from django.db import models
opts = instance._meta

cleaned_data = form.cleaned_data
file_field_list = []
for f in opts.fields:
if not f.editable or isinstance(f, models.AutoField) \
or f.name not in cleaned_data:
continue
if fields is not None and f.name not in fields:
continue
if exclude and f.name in exclude:
continue
# Defer saving file-type fields until after the other fields, so a
# callable upload_to can use the values from other fields.
if isinstance(f, models.FileField):
file_field_list.append(f)
else:
f.save_form_data(instance, cleaned_data[f.name])

for f in file_field_list:
f.save_form_data(instance, cleaned_data[f.name])

return instance

# ModelForms #################################################################

def model_to_dict(instance, fields=None, exclude=None):
"""
Returns a dict containing the data in ``instance`` suitable for passing as
a Form's ``initial`` keyword argument.

``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned dict.

``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned dict, even if they are listed in
the ``fields`` argument.
"""
# avoid a circular import
from django.db.models.fields.related import ManyToManyField
opts = instance._meta
data = {}
for f in chain(opts.concrete_fields, opts.virtual_fields, opts.many_to_many):
if not getattr(f, 'editable', False):
continue
if fields and f.name not in fields:
continue
if exclude and f.name in exclude:
continue
if isinstance(f, ManyToManyField):
# If the object doesn't have a primary key yet, just use an empty
# list for its m2m fields. Calling f.value_from_object will raise
# an exception.
if instance.pk is None:
data[f.name] = []
else:
# MultipleChoiceWidget needs a list of pks, not object instances.
qs = f.value_from_object(instance)
if qs._result_cache is not None:
data[f.name] = [item.pk for item in qs]
else:
data[f.name] = list(qs.values_list('pk', flat=True))
else:
data[f.name] = f.value_from_object(instance)
return data

def fields_for_model(model, fields=None, exclude=None, widgets=None,
formfield_callback=None, localized_fields=None,
labels=None, help_texts=None, error_messages=None,
field_classes=None):
"""
Returns a ``OrderedDict`` containing form fields for the given model.

``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned fields.

``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned fields, even if they are listed
in the ``fields`` argument.

``widgets`` is a dictionary of model field names mapped to a widget.

``formfield_callback`` is a callable that takes a model field and returns
a form field.

``localized_fields`` is a list of names of fields which should be localized.

``labels`` is a dictionary of model field names mapped to a label.

``help_texts`` is a dictionary of model field names mapped to a help text.

``error_messages`` is a dictionary of model field names mapped to a
dictionary of error messages.

``field_classes`` is a dictionary of model field names mapped to a form
field class.
"""
field_list = []
ignored = []
opts = model._meta
# Avoid circular import
from django.db.models.fields import Field as ModelField
sortable_virtual_fields = [f for f in opts.virtual_fields
if isinstance(f, ModelField)]
for f in sorted(chain(opts.concrete_fields, sortable_virtual_fields, opts.many_to_many)):
if not getattr(f, 'editable', False):
continue
if fields is not None and f.name not in fields:
continue
if exclude and f.name in exclude:
continue

kwargs = {}
if widgets and f.name in widgets:
kwargs['widget'] = widgets[f.name]
if localized_fields == ALL_FIELDS or (localized_fields and f.name in localized_fields):
kwargs['localize'] = True
if labels and f.name in labels:
kwargs['label'] = labels[f.name]
if help_texts and f.name in help_texts:
kwargs['help_text'] = help_texts[f.name]
if error_messages and f.name in error_messages:
kwargs['error_messages'] = error_messages[f.name]
if field_classes and f.name in field_classes:
kwargs['form_class'] = field_classes[f.name]

if formfield_callback is None:
formfield = f.formfield(**kwargs)
elif not callable(formfield_callback):
raise TypeError('formfield_callback must be a function or callable')
else:
formfield = formfield_callback(f, **kwargs)

if formfield:
field_list.append((f.name, formfield))
else:
ignored.append(f.name)
field_dict = OrderedDict(field_list)
if fields:
field_dict = OrderedDict(
[(f, field_dict.get(f)) for f in fields
if ((not exclude) or (exclude and f not in exclude)) and (f not in ignored)]
)
return field_dict

class ModelFormOptions(object):
def __init__(self, options=None):
self.model = getattr(options, 'model', None)
self.fields = getattr(options, 'fields', None)
self.exclude = getattr(options, 'exclude', None)
self.widgets = getattr(options, 'widgets', None)
self.localized_fields = getattr(options, 'localized_fields', None)
self.labels = getattr(options, 'labels', None)
self.help_texts = getattr(options, 'help_texts', None)
self.error_messages = getattr(options, 'error_messages', None)
self.field_classes = getattr(options, 'field_classes', None)

class ModelFormMetaclass(DeclarativeFieldsMetaclass):
def __new__(mcs, name, bases, attrs):
formfield_callback = attrs.pop('formfield_callback', None)

new_class = super(ModelFormMetaclass, mcs).__new__(mcs, name, bases, attrs)

if bases == (BaseModelForm,):
return new_class

opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))

# We check if a string was passed to `fields` or `exclude`,
# which is likely to be a mistake where the user typed ('foo') instead
# of ('foo',)
for opt in ['fields', 'exclude', 'localized_fields']:
value = getattr(opts, opt)
if isinstance(value, six.string_types) and value != ALL_FIELDS:
msg = ("%(model)s.Meta.%(opt)s cannot be a string. "
"Did you mean to type: ('%(value)s',)?" % {
'model': new_class.__name__,
'opt': opt,
'value': value,
})
raise TypeError(msg)

if opts.model:
# If a model is defined, extract form fields from it.
if opts.fields is None and opts.exclude is None:
raise ImproperlyConfigured(
"Creating a ModelForm without either the 'fields' attribute "
"or the 'exclude' attribute is prohibited; form %s "
"needs updating." % name
)

if opts.fields == ALL_FIELDS:
# Sentinel for fields_for_model to indicate "get the list of
# fields from the model"
opts.fields = None

fields = fields_for_model(opts.model, opts.fields, opts.exclude,
opts.widgets, formfield_callback,
opts.localized_fields, opts.labels,
opts.help_texts, opts.error_messages,
opts.field_classes)

# make sure opts.fields doesn't specify an invalid field
none_model_fields = [k for k, v in six.iteritems(fields) if not v]
missing_fields = (set(none_model_fields) -
set(new_class.declared_fields.keys()))
if missing_fields:
message = 'Unknown field(s) (%s) specified for %s'
message = message % (', '.join(missing_fields),
opts.model.__name__)
raise FieldError(message)
# Override default model fields with any custom declared ones
# (plus, include all the other declared fields).
fields.update(new_class.declared_fields)
else:
fields = new_class.declared_fields

new_class.base_fields = fields

return new_class

class BaseModelForm(BaseForm):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
empty_permitted=False, instance=None):
opts = self._meta
if opts.model is None:
raise ValueError('ModelForm has no model class specified.')
if instance is None:
# if we didn't get an instance, instantiate a new one
self.instance = opts.model()
object_data = {}
else:
self.instance = instance
object_data = model_to_dict(instance, opts.fields, opts.exclude)
# if initial was provided, it should override the values from instance
if initial is not None:
object_data.update(initial)
# self._validate_unique will be set to True by BaseModelForm.clean().
# It is False by default so overriding self.clean() and failing to call
# super will stop validate_unique from being called.
self._validate_unique = False
super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
error_class, label_suffix, empty_permitted)
# Apply ``limit_choices_to`` to each field.
for field_name in self.fields:
formfield = self.fields[field_name]
if hasattr(formfield, 'queryset') and hasattr(formfield, 'get_limit_choices_to'):
limit_choices_to = formfield.get_limit_choices_to()
if limit_choices_to is not None:
formfield.queryset = formfield.queryset.complex_filter(limit_choices_to)

def _get_validation_exclusions(self):
"""
For backwards-compatibility, several types of fields need to be
excluded from model validation. See the following tickets for
details: #12507, #12521, #12553
"""
exclude = []
# Build up a list of fields that should be excluded from model field
# validation and unique checks.
for f in self.instance._meta.fields:
field = f.name
# Exclude fields that aren't on the form. The developer may be
# adding these values to the model after form validation.
if field not in self.fields:
exclude.append(f.name)

# Don't perform model validation on fields that were defined
# manually on the form and excluded via the ModelForm's Meta
# class. See #12901.
elif self._meta.fields and field not in self._meta.fields:
exclude.append(f.name)
elif self._meta.exclude and field in self._meta.exclude:
exclude.append(f.name)

# Exclude fields that failed form validation. There's no need for
# the model fields to validate them as well.
elif field in self._errors.keys():
exclude.append(f.name)

# Exclude empty fields that are not required by the form, if the
# underlying model field is required. This keeps the model field
# from raising a required error. Note: don't exclude the field from
# validation if the model field allows blanks. If it does, the blank
# value may be included in a unique check, so cannot be excluded
# from validation.
else:
form_field = self.fields[field]
field_value = self.cleaned_data.get(field)
if not f.blank and not form_field.required and field_value in form_field.empty_values:
exclude.append(f.name)
return exclude

def clean(self):
self._validate_unique = True
return self.cleaned_data

def _update_errors(self, errors):
# Override any validation error messages defined at the model level
# with those defined at the form level.
opts = self._meta

# Allow the model generated by construct_instance() to raise
# ValidationError and have them handled in the same way as others.
if hasattr(errors, 'error_dict'):
error_dict = errors.error_dict
else:
error_dict = {NON_FIELD_ERRORS: errors}

for field, messages in error_dict.items():
if (field == NON_FIELD_ERRORS and opts.error_messages and
NON_FIELD_ERRORS in opts.error_messages):
error_messages = opts.error_messages[NON_FIELD_ERRORS]
elif field in self.fields:
error_messages = self.fields[field].error_messages
else:
continue

for message in messages:
if (isinstance(message, ValidationError) and
message.code in error_messages):
message.message = error_messages[message.code]

self.add_error(None, errors)

def _post_clean(self):
opts = self._meta

exclude = self._get_validation_exclusions()

try:
self.instance = construct_instance(self, self.instance, opts.fields, exclude)
except ValidationError as e:
self._update_errors(e)

# Foreign Keys being used to represent inline relationships
# are excluded from basic field value validation. This is for two
# reasons: firstly, the value may not be supplied (#12507; the
# case of providing new values to the admin); secondly the
# object being referred to may not yet fully exist (#12749).
# However, these fields *must* be included in uniqueness checks,
# so this can't be part of _get_validation_exclusions().
for name, field in self.fields.items():
if isinstance(field, InlineForeignKeyField):
exclude.append(name)

try:
self.instance.full_clean(exclude=exclude, validate_unique=False)
except ValidationError as e:
self._update_errors(e)

# Validate uniqueness if needed.
if self._validate_unique:
self.validate_unique()

def validate_unique(self):
"""
Calls the instance's validate_unique() method and updates the form's
validation errors if any were raised.
"""
exclude = self._get_validation_exclusions()
try:
self.instance.validate_unique(exclude=exclude)
except ValidationError as e:
self._update_errors(e)

def _save_m2m(self):
"""
Save the many-to-many fields and generic relations for this form.
"""
cleaned_data = self.cleaned_data
exclude = self._meta.exclude
fields = self._meta.fields
opts = self.instance._meta
# Note that for historical reasons we want to include also
# virtual_fields here. (GenericRelation was previously a fake
# m2m field).
for f in chain(opts.many_to_many, opts.virtual_fields):
if not hasattr(f, 'save_form_data'):
continue
if fields and f.name not in fields:
continue
if exclude and f.name in exclude:
continue
if f.name in cleaned_data:
f.save_form_data(self.instance, cleaned_data[f.name])

def save(self, commit=True):
"""
Save this form's self.instance object if commit=True. Otherwise, add
a save_m2m() method to the form which can be called after the instance
is saved manually at a later time. Return the model instance.
"""
if self.errors:
raise ValueError(
"The %s could not be %s because the data didn't validate." % (
self.instance._meta.object_name,
'created' if self.instance._state.adding else 'changed',
)
)
if commit:
# If committing, save the instance and the m2m data immediately.
self.instance.save()
self._save_m2m()
else:
# If not committing, add a method to the form to allow deferred
# saving of m2m data.
self.save_m2m = self._save_m2m
return self.instance

save.alters_data = True

[docs]class ModelForm(six.with_metaclass(ModelFormMetaclass, BaseModelForm)):
pass

[docs]def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
formfield_callback=None, widgets=None, localized_fields=None,
labels=None, help_texts=None, error_messages=None,
field_classes=None):
"""
Returns a ModelForm containing form fields for the given model.

``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned fields. If omitted or '__all__',
all fields will be used.

``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned fields, even if they are listed
in the ``fields`` argument.

``widgets`` is a dictionary of model field names mapped to a widget.

``localized_fields`` is a list of names of fields which should be localized.

``formfield_callback`` is a callable that takes a model field and returns
a form field.

``labels`` is a dictionary of model field names mapped to a label.

``help_texts`` is a dictionary of model field names mapped to a help text.

``error_messages`` is a dictionary of model field names mapped to a
dictionary of error messages.

``field_classes`` is a dictionary of model field names mapped to a form
field class.
"""
# Create the inner Meta class. FIXME: ideally, we should be able to
# construct a ModelForm without creating and passing in a temporary
# inner class.

# Build up a list of attributes that the Meta object will have.
attrs = {'model': model}
if fields is not None:
attrs['fields'] = fields
if exclude is not None:
attrs['exclude'] = exclude
if widgets is not None:
attrs['widgets'] = widgets
if localized_fields is not None:
attrs['localized_fields'] = localized_fields
if labels is not None:
attrs['labels'] = labels
if help_texts is not None:
attrs['help_texts'] = help_texts
if error_messages is not None:
attrs['error_messages'] = error_messages
if field_classes is not None:
attrs['field_classes'] = field_classes

# If parent form class already has an inner Meta, the Meta we're
# creating needs to inherit from the parent's inner meta.
parent = (object,)
if hasattr(form, 'Meta'):
parent = (form.Meta, object)
Meta = type(str('Meta'), parent, attrs)

# Give this new form class a reasonable name.
class_name = model.__name__ + str('Form')

# Class attributes for the new form class.
form_class_attrs = {
'Meta': Meta,
'formfield_callback': formfield_callback
}

if (getattr(Meta, 'fields', None) is None and
getattr(Meta, 'exclude', None) is None):
raise ImproperlyConfigured(
"Calling modelform_factory without defining 'fields' or "
"'exclude' explicitly is prohibited."
)

# Instantiate type(form) in order to use the same metaclass as form.
return type(form)(class_name, (form,), form_class_attrs)

# ModelFormSets ##############################################################

class BaseModelFormSet(BaseFormSet):
"""
A ``FormSet`` for editing a queryset and/or adding new objects to it.
"""
model = None

def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
queryset=None, **kwargs):
self.queryset = queryset
self.initial_extra = kwargs.pop('initial', None)
defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
defaults.update(kwargs)
super(BaseModelFormSet, self).__init__(**defaults)

def initial_form_count(self):
"""Returns the number of forms that are required in this FormSet."""
if not (self.data or self.files):
return len(self.get_queryset())
return super(BaseModelFormSet, self).initial_form_count()

def _existing_object(self, pk):
if not hasattr(self, '_object_dict'):
self._object_dict = {o.pk: o for o in self.get_queryset()}
return self._object_dict.get(pk)

def _get_to_python(self, field):
"""
If the field is a related field, fetch the concrete field's (that
is, the ultimate pointed-to field's) to_python.
"""
while field.remote_field is not None:
field = field.remote_field.get_related_field()
return field.to_python

def _construct_form(self, i, **kwargs):
if self.is_bound and i < self.initial_form_count():
pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
pk = self.data[pk_key]
pk_field = self.model._meta.pk
to_python = self._get_to_python(pk_field)
pk = to_python(pk)
kwargs['instance'] = self._existing_object(pk)
if i < self.initial_form_count() and 'instance' not in kwargs:
kwargs['instance'] = self.get_queryset()[i]
if i >= self.initial_form_count() and self.initial_extra:
# Set initial values for extra forms
try:
kwargs['initial'] = self.initial_extra[i - self.initial_form_count()]
except IndexError:
pass
return super(BaseModelFormSet, self)._construct_form(i, **kwargs)

def get_queryset(self):
if not hasattr(self, '_queryset'):
if self.queryset is not None:
qs = self.queryset
else:
qs = self.model._default_manager.get_queryset()

# If the queryset isn't already ordered we need to add an
# artificial ordering here to make sure that all formsets
# constructed from this queryset have the same form order.
if not qs.ordered:
qs = qs.order_by(self.model._meta.pk.name)

# Removed queryset limiting here. As per discussion re: #13023
# on django-dev, max_num should not prevent existing
# related objects/inlines from being displayed.
self._queryset = qs
return self._queryset

def save_new(self, form, commit=True):
"""Saves and returns a new model instance for the given form."""
return form.save(commit=commit)

def save_existing(self, form, instance, commit=True):
"""Saves and returns an existing model instance for the given form."""
return form.save(commit=commit)

def delete_existing(self, obj, commit=True):
"""Deletes an existing model instance."""
if commit:
obj.delete()

def save(self, commit=True):
"""Saves model instances for every form, adding and changing instances
as necessary, and returns the list of instances.
"""
if not commit:
self.saved_forms = []

def save_m2m():
for form in self.saved_forms:
form.save_m2m()
self.save_m2m = save_m2m
return self.save_existing_objects(commit) + self.save_new_objects(commit)

save.alters_data = True

def clean(self):
self.validate_unique()

def validate_unique(self):
# Collect unique_checks and date_checks to run from all the forms.
all_unique_checks = set()
all_date_checks = set()
forms_to_delete = self.deleted_forms
valid_forms = [form for form in self.forms if form.is_valid() and form not in forms_to_delete]
for form in valid_forms:
exclude = form._get_validation_exclusions()
unique_checks, date_checks = form.instance._get_unique_checks(exclude=exclude)
all_unique_checks = all_unique_checks.union(set(unique_checks))
all_date_checks = all_date_checks.union(set(date_checks))

errors = []
# Do each of the unique checks (unique and unique_together)
for uclass, unique_check in all_unique_checks:
seen_data = set()
for form in valid_forms:
# get data for each field of each of unique_check
row_data = (form.cleaned_data[field]
for field in unique_check if field in form.cleaned_data)
# Reduce Model instances to their primary key values
row_data = tuple(d._get_pk_val() if hasattr(d, '_get_pk_val') else d
for d in row_data)
if row_data and None not in row_data:
# if we've already seen it then we have a uniqueness failure
if row_data in seen_data:
# poke error messages into the right places and mark
# the form as invalid
errors.append(self.get_unique_error_message(unique_check))
form._errors[NON_FIELD_ERRORS] = self.error_class([self.get_form_error()])
# remove the data from the cleaned_data dict since it was invalid
for field in unique_check:
if field in form.cleaned_data:
del form.cleaned_data[field]
# mark the data as seen
seen_data.add(row_data)
# iterate over each of the date checks now
for date_check in all_date_checks:
seen_data = set()
uclass, lookup, field, unique_for = date_check
for form in valid_forms:
# see if we have data for both fields
if (form.cleaned_data and form.cleaned_data[field] is not None
and form.cleaned_data[unique_for] is not None):
# if it's a date lookup we need to get the data for all the fields
if lookup == 'date':
date = form.cleaned_data[unique_for]
date_data = (date.year, date.month, date.day)
# otherwise it's just the attribute on the date/datetime
# object
else:
date_data = (getattr(form.cleaned_data[unique_for], lookup),)
data = (form.cleaned_data[field],) + date_data
# if we've already seen it then we have a uniqueness failure
if data in seen_data:
# poke error messages into the right places and mark
# the form as invalid
errors.append(self.get_date_error_message(date_check))
form._errors[NON_FIELD_ERRORS] = self.error_class([self.get_form_error()])
# remove the data from the cleaned_data dict since it was invalid
del form.cleaned_data[field]
# mark the data as seen
seen_data.add(data)

if errors:
raise ValidationError(errors)

def get_unique_error_message(self, unique_check):
if len(unique_check) == 1:
return ugettext("Please correct the duplicate data for %(field)s.") % {
"field": unique_check[0],
}
else:
return ugettext("Please correct the duplicate data for %(field)s, "
"which must be unique.") % {
"field": get_text_list(unique_check, six.text_type(_("and"))),
}

def get_date_error_message(self, date_check):
return ugettext("Please correct the duplicate data for %(field_name)s "
"which must be unique for the %(lookup)s in %(date_field)s.") % {
'field_name': date_check[2],
'date_field': date_check[3],
'lookup': six.text_type(date_check[1]),
}

def get_form_error(self):
return ugettext("Please correct the duplicate values below.")

def save_existing_objects(self, commit=True):
self.changed_objects = []
self.deleted_objects = []
if not self.initial_forms:
return []

saved_instances = []
forms_to_delete = self.deleted_forms
for form in self.initial_forms:
obj = form.instance
if form in forms_to_delete:
# If the pk is None, it means that the object can't be
# deleted again. Possible reason for this is that the
# object was already deleted from the DB. Refs #14877.
if obj.pk is None:
continue
self.deleted_objects.append(obj)
self.delete_existing(obj, commit=commit)
elif form.has_changed():
self.changed_objects.append((obj, form.changed_data))
saved_instances.append(self.save_existing(form, obj, commit=commit))
if not commit:
self.saved_forms.append(form)
return saved_instances

def save_new_objects(self, commit=True):
self.new_objects = []
for form in self.extra_forms:
if not form.has_changed():
continue
# If someone has marked an add form for deletion, don't save the
# object.
if self.can_delete and self._should_delete_form(form):
continue
self.new_objects.append(self.save_new(form, commit=commit))
if not commit:
self.saved_forms.append(form)
return self.new_objects

def add_fields(self, form, index):
"""Add a hidden field for the object's primary key."""
from django.db.models import AutoField, OneToOneField, ForeignKey
self._pk_field = pk = self.model._meta.pk
# If a pk isn't editable, then it won't be on the form, so we need to
# add it here so we can tell which object is which when we get the
# data back. Generally, pk.editable should be false, but for some
# reason, auto_created pk fields and AutoField's editable attribute is
# True, so check for that as well.

def pk_is_not_editable(pk):
return (
(not pk.editable) or (pk.auto_created or isinstance(pk, AutoField)) or (
pk.remote_field and pk.remote_field.parent_link
and pk_is_not_editable(pk.remote_field.model._meta.pk)
)
)
if pk_is_not_editable(pk) or pk.name not in form.fields:
if form.is_bound:
# If we're adding the related instance, ignore its primary key
# as it could be an auto-generated default which isn't actually
# in the database.
pk_value = None if form.instance._state.adding else form.instance.pk
else:
try:
if index is not None:
pk_value = self.get_queryset()[index].pk
else:
pk_value = None
except IndexError:
pk_value = None
if isinstance(pk, OneToOneField) or isinstance(pk, ForeignKey):
qs = pk.remote_field.model._default_manager.get_queryset()
else:
qs = self.model._default_manager.get_queryset()
qs = qs.using(form.instance._state.db)
if form._meta.widgets:
widget = form._meta.widgets.get(self._pk_field.name, HiddenInput)
else:
widget = HiddenInput
form.fields[self._pk_field.name] = ModelChoiceField(qs, initial=pk_value, required=False, widget=widget)
super(BaseModelFormSet, self).add_fields(form, index)

[docs]def modelformset_factory(model, form=ModelForm, formfield_callback=None,
formset=BaseModelFormSet, extra=1, can_delete=False,
can_order=False, max_num=None, fields=None, exclude=None,
widgets=None, validate_max=False, localized_fields=None,
labels=None, help_texts=None, error_messages=None,
min_num=None, validate_min=False, field_classes=None):
"""
Returns a FormSet class for the given Django model class.
"""
meta = getattr(form, 'Meta', None)
if meta is None:
meta = type(str('Meta'), (object,), {})
if (getattr(meta, 'fields', fields) is None and
getattr(meta, 'exclude', exclude) is None):
raise ImproperlyConfigured(
"Calling modelformset_factory without defining 'fields' or "
"'exclude' explicitly is prohibited."
)

form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
formfield_callback=formfield_callback,
widgets=widgets, localized_fields=localized_fields,
labels=labels, help_texts=help_texts,
error_messages=error_messages, field_classes=field_classes)
FormSet = formset_factory(form, formset, extra=extra, min_num=min_num, max_num=max_num,
can_order=can_order, can_delete=can_delete,
validate_min=validate_min, validate_max=validate_max)
FormSet.model = model
return FormSet

# InlineFormSets #############################################################

class BaseInlineFormSet(BaseModelFormSet):
"""A formset for child objects related to a parent."""
def __init__(self, data=None, files=None, instance=None,
save_as_new=False, prefix=None, queryset=None, **kwargs):
if instance is None:
self.instance = self.fk.remote_field.model()
else:
self.instance = instance
self.save_as_new = save_as_new
if queryset is None:
queryset = self.model._default_manager
if self.instance.pk is not None:
qs = queryset.filter(**{self.fk.name: self.instance})
else:
qs = queryset.none()
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
queryset=qs, **kwargs)

def initial_form_count(self):
if self.save_as_new:
return 0
return super(BaseInlineFormSet, self).initial_form_count()

def _construct_form(self, i, **kwargs):
form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
if self.save_as_new:
# Remove the primary key from the form's data, we are only
# creating new instances
form.data[form.add_prefix(self._pk_field.name)] = None

# Remove the foreign key from the form's data
form.data[form.add_prefix(self.fk.name)] = None

# Set the fk value here so that the form can do its validation.
fk_value = self.instance.pk
if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name:
fk_value = getattr(self.instance, self.fk.remote_field.field_name)
fk_value = getattr(fk_value, 'pk', fk_value)
setattr(form.instance, self.fk.get_attname(), fk_value)
return form

@classmethod
def get_default_prefix(cls):
return cls.fk.remote_field.get_accessor_name(model=cls.model).replace('+', '')

def save_new(self, form, commit=True):
# Ensure the latest copy of the related instance is present on each
# form (it may have been saved after the formset was originally
# instantiated).
setattr(form.instance, self.fk.name, self.instance)
# Use commit=False so we can assign the parent key afterwards, then
# save the object.
obj = form.save(commit=False)
pk_value = getattr(self.instance, self.fk.remote_field.field_name)
setattr(obj, self.fk.get_attname(), getattr(pk_value, 'pk', pk_value))
if commit:
obj.save()
# form.save_m2m() can be called via the formset later on if commit=False
if commit and hasattr(form, 'save_m2m'):
form.save_m2m()
return obj

def add_fields(self, form, index):
super(BaseInlineFormSet, self).add_fields(form, index)
if self._pk_field == self.fk:
name = self._pk_field.name
kwargs = {'pk_field': True}
else:
# The foreign key field might not be on the form, so we poke at the
# Model field to get the label, since we need that for error messages.
name = self.fk.name
kwargs = {
'label': getattr(form.fields.get(name), 'label', capfirst(self.fk.verbose_name))
}
if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name:
kwargs['to_field'] = self.fk.remote_field.field_name

# If we're adding a new object, ignore a parent's auto-generated key
# as it will be regenerated on the save request.
if self.instance._state.adding:
if kwargs.get('to_field') is not None:
to_field = self.instance._meta.get_field(kwargs['to_field'])
else:
to_field = self.instance._meta.pk
if to_field.has_default():
setattr(self.instance, to_field.attname, None)

form.fields[name] = InlineForeignKeyField(self.instance, **kwargs)

# Add the generated field to form._meta.fields if it's defined to make
# sure validation isn't skipped on that field.
if form._meta.fields:
if isinstance(form._meta.fields, tuple):
form._meta.fields = list(form._meta.fields)
form._meta.fields.append(self.fk.name)

def get_unique_error_message(self, unique_check):
unique_check = [field for field in unique_check if field != self.fk.name]
return super(BaseInlineFormSet, self).get_unique_error_message(unique_check)

def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):
"""
Finds and returns the ForeignKey from model to parent if there is one
(returns None if can_fail is True and no such field exists). If fk_name is
provided, assume it is the name of the ForeignKey field. Unless can_fail is
True, an exception is raised if there is no ForeignKey from model to
parent_model.
"""
# avoid circular import
from django.db.models import ForeignKey
opts = model._meta
if fk_name:
fks_to_parent = [f for f in opts.fields if f.name == fk_name]
if len(fks_to_parent) == 1:
fk = fks_to_parent[0]
if not isinstance(fk, ForeignKey) or \
(fk.remote_field.model != parent_model and
fk.remote_field.model not in parent_model._meta.get_parent_list()):
raise ValueError(
"fk_name '%s' is not a ForeignKey to '%s'." % (fk_name, parent_model._meta.label)
)
elif len(fks_to_parent) == 0:
raise ValueError(
"'%s' has no field named '%s'." % (model._meta.label, fk_name)
)
else:
# Try to discover what the ForeignKey from model to parent_model is
fks_to_parent = [
f for f in opts.fields
if isinstance(f, ForeignKey)
and (f.remote_field.model == parent_model
or f.remote_field.model in parent_model._meta.get_parent_list())
]
if len(fks_to_parent) == 1:
fk = fks_to_parent[0]
elif len(fks_to_parent) == 0:
if can_fail:
return
raise ValueError(
"'%s' has no ForeignKey to '%s'." % (
model._meta.label,
parent_model._meta.label,
)
)
else:
raise ValueError(
"'%s' has more than one ForeignKey to '%s'." % (
model._meta.label,
parent_model._meta.label,
)
)
return fk

[docs]def inlineformset_factory(parent_model, model, form=ModelForm,
formset=BaseInlineFormSet, fk_name=None,
fields=None, exclude=None, extra=3, can_order=False,
can_delete=True, max_num=None, formfield_callback=None,
widgets=None, validate_max=False, localized_fields=None,
labels=None, help_texts=None, error_messages=None,
min_num=None, validate_min=False, field_classes=None):
"""
Returns an ``InlineFormSet`` for the given kwargs.

You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
to ``parent_model``.
"""
fk = _get_foreign_key(parent_model, model, fk_name=fk_name)
# enforce a max_num=1 when the foreign key to the parent model is unique.
if fk.unique:
max_num = 1
kwargs = {
'form': form,
'formfield_callback': formfield_callback,
'formset': formset,
'extra': extra,
'can_delete': can_delete,
'can_order': can_order,
'fields': fields,
'exclude': exclude,
'min_num': min_num,
'max_num': max_num,
'widgets': widgets,
'validate_min': validate_min,
'validate_max': validate_max,
'localized_fields': localized_fields,
'labels': labels,
'help_texts': help_texts,
'error_messages': error_messages,
'field_classes': field_classes,
}
FormSet = modelformset_factory(model, **kwargs)
FormSet.fk = fk
return FormSet

# Fields #####################################################################

class InlineForeignKeyField(Field):
"""
A basic integer field that deals with validating the given value to a
given parent instance in an inline.
"""
widget = HiddenInput
default_error_messages = {
'invalid_choice': _('The inline foreign key did not match the parent instance primary key.'),
}

def __init__(self, parent_instance, *args, **kwargs):
self.parent_instance = parent_instance
self.pk_field = kwargs.pop("pk_field", False)
self.to_field = kwargs.pop("to_field", None)
if self.parent_instance is not None:
if self.to_field:
kwargs["initial"] = getattr(self.parent_instance, self.to_field)
else:
kwargs["initial"] = self.parent_instance.pk
kwargs["required"] = False
super(InlineForeignKeyField, self).__init__(*args, **kwargs)

def clean(self, value):
if value in self.empty_values:
if self.pk_field:
return None
# if there is no value act as we did before.
return self.parent_instance
# ensure the we compare the values as equal types.
if self.to_field:
orig = getattr(self.parent_instance, self.to_field)
else:
orig = self.parent_instance.pk
if force_text(value) != force_text(orig):
raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
return self.parent_instance

def has_changed(self, initial, data):
return False

class ModelChoiceIterator(object):
def __init__(self, field):
self.field = field
self.queryset = field.queryset

def __iter__(self):
if self.field.empty_label is not None:
yield ("", self.field.empty_label)
queryset = self.queryset.all()
# Can't use iterator() when queryset uses prefetch_related()
if not queryset._prefetch_related_lookups:
queryset = queryset.iterator()
for obj in queryset:
yield self.choice(obj)

def __len__(self):
return (len(self.queryset) +
(1 if self.field.empty_label is not None else 0))

def choice(self, obj):
return (self.field.prepare_value(obj), self.field.label_from_instance(obj))

[docs]class ModelChoiceField(ChoiceField):
"""A ChoiceField whose choices are a model QuerySet."""
# This class is a subclass of ChoiceField for purity, but it doesn't
# actually use any of ChoiceField's implementation.
default_error_messages = {
'invalid_choice': _('Select a valid choice. That choice is not one of'
' the available choices.'),
}

def __init__(self, queryset, empty_label="---------",
required=True, widget=None, label=None, initial=None,
help_text='', to_field_name=None, limit_choices_to=None,
*args, **kwargs):
if required and (initial is not None):
self.empty_label = None
else:
self.empty_label = empty_label

# Call Field instead of ChoiceField __init__() because we don't need
# ChoiceField.__init__().
Field.__init__(self, required, widget, label, initial, help_text,
*args, **kwargs)
self.queryset = queryset
self.limit_choices_to = limit_choices_to   # limit the queryset later.
self.to_field_name = to_field_name

def get_limit_choices_to(self):
"""
Returns ``limit_choices_to`` for this form field.

If it is a callable, it will be invoked and the result will be
returned.
"""
if callable(self.limit_choices_to):
return self.limit_choices_to()
return self.limit_choices_to

def __deepcopy__(self, memo):
result = super(ChoiceField, self).__deepcopy__(memo)
# Need to force a new ModelChoiceIterator to be created, bug #11183
result.queryset = result.queryset
return result

def _get_queryset(self):
return self._queryset

def _set_queryset(self, queryset):
self._queryset = queryset
self.widget.choices = self.choices

queryset = property(_get_queryset, _set_queryset)

# this method will be used to create object labels by the QuerySetIterator.
# Override it to customize the label.
def label_from_instance(self, obj):
"""
This method is used to convert objects into strings; it's used to
generate the labels for the choices presented by this object. Subclasses
can override this method to customize the display of the choices.
"""
return smart_text(obj)

def _get_choices(self):
# If self._choices is set, then somebody must have manually set
# the property self.choices. In this case, just return self._choices.
if hasattr(self, '_choices'):
return self._choices

# Otherwise, execute the QuerySet in self.queryset to determine the
# choices dynamically. Return a fresh ModelChoiceIterator that has not been
# consumed. Note that we're instantiating a new ModelChoiceIterator *each*
# time _get_choices() is called (and, thus, each time self.choices is
# accessed) so that we can ensure the QuerySet has not been consumed. This
# construct might look complicated but it allows for lazy evaluation of
# the queryset.
return ModelChoiceIterator(self)

choices = property(_get_choices, ChoiceField._set_choices)

def prepare_value(self, value):
if hasattr(value, '_meta'):
if self.to_field_name:
return value.serializable_value(self.to_field_name)
else:
return value.pk
return super(ModelChoiceField, self).prepare_value(value)

def to_python(self, value):
if value in self.empty_values:
return None
try:
key = self.to_field_name or 'pk'
value = self.queryset.get(**{key: value})
except (ValueError, TypeError, self.queryset.model.DoesNotExist):
raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
return value

def validate(self, value):
return Field.validate(self, value)

def has_changed(self, initial, data):
initial_value = initial if initial is not None else ''
data_value = data if data is not None else ''
return force_text(self.prepare_value(initial_value)) != force_text(data_value)

[docs]class ModelMultipleChoiceField(ModelChoiceField):
"""A MultipleChoiceField whose choices are a model QuerySet."""
widget = SelectMultiple
hidden_widget = MultipleHiddenInput
default_error_messages = {
'list': _('Enter a list of values.'),
'invalid_choice': _('Select a valid choice. %(value)s is not one of the'
' available choices.'),
'invalid_pk_value': _('"%(pk)s" is not a valid value for a primary key.')
}

def __init__(self, queryset, required=True, widget=None, label=None,
initial=None, help_text='', *args, **kwargs):
super(ModelMultipleChoiceField, self).__init__(queryset, None,
required, widget, label, initial, help_text, *args, **kwargs)

def to_python(self, value):
if not value:
return []
return list(self._check_values(value))

def clean(self, value):
if self.required and not value:
raise ValidationError(self.error_messages['required'], code='required')
elif not self.required and not value:
return self.queryset.none()
if not isinstance(value, (list, tuple)):
raise ValidationError(self.error_messages['list'], code='list')
qs = self._check_values(value)
# Since this overrides the inherited ModelChoiceField.clean
# we run custom validators here
self.run_validators(value)
return qs

def _check_values(self, value):
"""
Given a list of possible PK values, returns a QuerySet of the
corresponding objects. Raises a ValidationError if a given value is
invalid (not a valid PK, not in the queryset, etc.)
"""
key = self.to_field_name or 'pk'
# deduplicate given values to avoid creating many querysets or
# requiring the database backend deduplicate efficiently.
try:
value = frozenset(value)
except TypeError:
# list of lists isn't hashable, for example
raise ValidationError(
self.error_messages['list'],
code='list',
)
for pk in value:
try:
self.queryset.filter(**{key: pk})
except (ValueError, TypeError):
raise ValidationError(
self.error_messages['invalid_pk_value'],
code='invalid_pk_value',
params={'pk': pk},
)
qs = self.queryset.filter(**{'%s__in' % key: value})
pks = set(force_text(getattr(o, key)) for o in qs)
for val in value:
if force_text(val) not in pks:
raise ValidationError(
self.error_messages['invalid_choice'],
code='invalid_choice',
params={'value': val},
)
return qs

def prepare_value(self, value):
if (hasattr(value, '__iter__') and
not isinstance(value, six.text_type) and
not hasattr(value, '_meta')):
return [super(ModelMultipleChoiceField, self).prepare_value(v) for v in value]
return super(ModelMultipleChoiceField, self).prepare_value(value)

def has_changed(self, initial, data):
if initial is None:
initial = []
if data is None:
data = []
if len(initial) != len(data):
return True
initial_set = set(force_text(value) for value in self.prepare_value(initial))
data_set = set(force_text(value) for value in data)
return data_set != initial_set

def modelform_defines_fields(form_class):
return (form_class is not None and (
hasattr(form_class, '_meta') and
(form_class._meta.fields is not None or
form_class._meta.exclude is not None)
))

Source code for django.forms.forms

"""
Form classes
"""

from __future__ import unicode_literals

import copy
from collections import OrderedDict

from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
# BoundField is imported for backwards compatibility in Django 1.9
from django.forms.boundfield import BoundField  # NOQA
from django.forms.fields import Field, FileField
# pretty_name is imported for backwards compatibility in Django 1.9
from django.forms.utils import ErrorDict, ErrorList, pretty_name  # NOQA
from django.forms.widgets import Media, MediaDefiningClass
from django.utils import six
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.functional import cached_property
from django.utils.html import conditional_escape, html_safe
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _

__all__ = ('BaseForm', 'Form')

class DeclarativeFieldsMetaclass(MediaDefiningClass):
"""
Metaclass that collects Fields declared on the base classes.
"""
def __new__(mcs, name, bases, attrs):
# Collect fields from current class.
current_fields = []
for key, value in list(attrs.items()):
if isinstance(value, Field):
current_fields.append((key, value))
attrs.pop(key)
current_fields.sort(key=lambda x: x[1].creation_counter)
attrs['declared_fields'] = OrderedDict(current_fields)

new_class = (super(DeclarativeFieldsMetaclass, mcs)
.__new__(mcs, name, bases, attrs))

# Walk through the MRO.
declared_fields = OrderedDict()
for base in reversed(new_class.__mro__):
# Collect fields from base class.
if hasattr(base, 'declared_fields'):
declared_fields.update(base.declared_fields)

# Field shadowing.
for attr, value in base.__dict__.items():
if value is None and attr in declared_fields:
declared_fields.pop(attr)

new_class.base_fields = declared_fields
new_class.declared_fields = declared_fields

return new_class

@html_safe
@python_2_unicode_compatible
class BaseForm(object):
# This is the main implementation of all the Form logic. Note that this
# class is different than Form. See the comments by the Form class for more
# information. Any improvements to the form API should be made to *this*
# class, not to the Form class.
field_order = None
prefix = None

def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
empty_permitted=False, field_order=None):
self.is_bound = data is not None or files is not None
self.data = data or {}
self.files = files or {}
self.auto_id = auto_id
if prefix is not None:
self.prefix = prefix
self.initial = initial or {}
self.error_class = error_class
# Translators: This is the default suffix added to form field labels
self.label_suffix = label_suffix if label_suffix is not None else _(':')
self.empty_permitted = empty_permitted
self._errors = None  # Stores the errors after clean() has been called.

# The base_fields class attribute is the *class-wide* definition of
# fields. Because a particular *instance* of the class might want to
# alter self.fields, we create self.fields here by copying base_fields.
# Instances should always modify self.fields; they should not modify
# self.base_fields.
self.fields = copy.deepcopy(self.base_fields)
self._bound_fields_cache = {}
self.order_fields(self.field_order if field_order is None else field_order)

def order_fields(self, field_order):
"""
Rearranges the fields according to field_order.

field_order is a list of field names specifying the order. Fields not
included in the list are appended in the default order for backward
compatibility with subclasses not overriding field_order. If field_order
is None, all fields are kept in the order defined in the class.
Unknown fields in field_order are ignored to allow disabling fields in
form subclasses without redefining ordering.
"""
if field_order is None:
return
fields = OrderedDict()
for key in field_order:
try:
fields[key] = self.fields.pop(key)
except KeyError:  # ignore unknown fields
pass
fields.update(self.fields)  # add remaining fields in original order
self.fields = fields

def __str__(self):
return self.as_table()

def __repr__(self):
if self._errors is None:
is_valid = "Unknown"
else:
is_valid = self.is_bound and not bool(self._errors)
return '<%(cls)s bound=%(bound)s, valid=%(valid)s, fields=(%(fields)s)>' % {
'cls': self.__class__.__name__,
'bound': self.is_bound,
'valid': is_valid,
'fields': ';'.join(self.fields),
}

def __iter__(self):
for name in self.fields:
yield self[name]

def __getitem__(self, name):
"Returns a BoundField with the given name."
try:
field = self.fields[name]
except KeyError:
raise KeyError(
"Key %r not found in '%s'" % (name, self.__class__.__name__))
if name not in self._bound_fields_cache:
self._bound_fields_cache[name] = field.get_bound_field(self, name)
return self._bound_fields_cache[name]

@property
def errors(self):
"Returns an ErrorDict for the data provided for the form"
if self._errors is None:
self.full_clean()
return self._errors

def is_valid(self):
"""
Returns True if the form has no errors. Otherwise, False. If errors are
being ignored, returns False.
"""
return self.is_bound and not self.errors

def add_prefix(self, field_name):
"""
Returns the field name with a prefix appended, if this Form has a
prefix set.

Subclasses may wish to override.
"""
return '%s-%s' % (self.prefix, field_name) if self.prefix else field_name

def add_initial_prefix(self, field_name):
"""
Add a 'initial' prefix for checking dynamic initial values
"""
return 'initial-%s' % self.add_prefix(field_name)

def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
"Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
top_errors = self.non_field_errors()  # Errors that should be displayed above all fields.
output, hidden_fields = [], []

for name, field in self.fields.items():
html_class_attr = ''
bf = self[name]
# Escape and cache in local variable.
bf_errors = self.error_class([conditional_escape(error) for error in bf.errors])
if bf.is_hidden:
if bf_errors:
top_errors.extend(
[_('(Hidden field %(name)s) %(error)s') % {'name': name, 'error': force_text(e)}
for e in bf_errors])
hidden_fields.append(six.text_type(bf))
else:
# Create a 'class="..."' attribute if the row should have any
# CSS classes applied.
css_classes = bf.css_classes()
if css_classes:
html_class_attr = ' class="%s"' % css_classes

if errors_on_separate_row and bf_errors:
output.append(error_row % force_text(bf_errors))

if bf.label:
label = conditional_escape(force_text(bf.label))
label = bf.label_tag(label) or ''
else:
label = ''

if field.help_text:
help_text = help_text_html % force_text(field.help_text)
else:
help_text = ''

output.append(normal_row % {
'errors': force_text(bf_errors),
'label': force_text(label),
'field': six.text_type(bf),
'help_text': help_text,
'html_class_attr': html_class_attr,
'css_classes': css_classes,
'field_name': bf.html_name,
})

if top_errors:
output.insert(0, error_row % force_text(top_errors))

if hidden_fields:  # Insert any hidden fields in the last row.
str_hidden = ''.join(hidden_fields)
if output:
last_row = output[-1]
# Chop off the trailing row_ender (e.g. '</td></tr>') and
# insert the hidden fields.
if not last_row.endswith(row_ender):
# This can happen in the as_p() case (and possibly others
# that users write): if there are only top errors, we may
# not be able to conscript the last row for our purposes,
# so insert a new, empty row.
last_row = (normal_row % {
'errors': '',
'label': '',
'field': '',
'help_text': '',
'html_class_attr': html_class_attr,
'css_classes': '',
'field_name': '',
})
output.append(last_row)
output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender
else:
# If there aren't any rows in the output, just append the
# hidden fields.
output.append(str_hidden)
return mark_safe('\n'.join(output))

def as_table(self):
"Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
return self._html_output(
normal_row='<tr%(html_class_attr)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>',
error_row='<tr><td colspan="2">%s</td></tr>',
row_ender='</td></tr>',
help_text_html='<br /><span class="helptext">%s</span>',
errors_on_separate_row=False)

def as_ul(self):
"Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
return self._html_output(
normal_row='<li%(html_class_attr)s>%(errors)s%(label)s %(field)s%(help_text)s</li>',
error_row='<li>%s</li>',
row_ender='</li>',
help_text_html=' <span class="helptext">%s</span>',
errors_on_separate_row=False)

def as_p(self):
"Returns this form rendered as HTML <p>s."
return self._html_output(
normal_row='<p%(html_class_attr)s>%(label)s %(field)s%(help_text)s</p>',
error_row='%s',
row_ender='</p>',
help_text_html=' <span class="helptext">%s</span>',
errors_on_separate_row=True)

def non_field_errors(self):
"""
Returns an ErrorList of errors that aren't associated with a particular
field -- i.e., from Form.clean(). Returns an empty ErrorList if there
are none.
"""
return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))

def add_error(self, field, error):
"""
Update the content of `self._errors`.

The `field` argument is the name of the field to which the errors
should be added. If its value is None the errors will be treated as
NON_FIELD_ERRORS.

The `error` argument can be a single error, a list of errors, or a
dictionary that maps field names to lists of errors. What we define as
an "error" can be either a simple string or an instance of
ValidationError with its message attribute set and what we define as
list or dictionary can be an actual `list` or `dict` or an instance
of ValidationError with its `error_list` or `error_dict` attribute set.

If `error` is a dictionary, the `field` argument *must* be None and
errors will be added to the fields that correspond to the keys of the
dictionary.
"""
if not isinstance(error, ValidationError):
# Normalize to ValidationError and let its constructor
# do the hard work of making sense of the input.
error = ValidationError(error)

if hasattr(error, 'error_dict'):
if field is not None:
raise TypeError(
"The argument `field` must be `None` when the `error` "
"argument contains errors for multiple fields."
)
else:
error = error.error_dict
else:
error = {field or NON_FIELD_ERRORS: error.error_list}

for field, error_list in error.items():
if field not in self.errors:
if field != NON_FIELD_ERRORS and field not in self.fields:
raise ValueError(
"'%s' has no field named '%s'." % (self.__class__.__name__, field))
if field == NON_FIELD_ERRORS:
self._errors[field] = self.error_class(error_class='nonfield')
else:
self._errors[field] = self.error_class()
self._errors[field].extend(error_list)
if field in self.cleaned_data:
del self.cleaned_data[field]

def has_error(self, field, code=None):
if code is None:
return field in self.errors
if field in self.errors:
for error in self.errors.as_data()[field]:
if error.code == code:
return True
return False

def full_clean(self):
"""
Cleans all of self.data and populates self._errors and
self.cleaned_data.
"""
self._errors = ErrorDict()
if not self.is_bound:  # Stop further processing.
return
self.cleaned_data = {}
# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
return

self._clean_fields()
self._clean_form()
self._post_clean()

def _clean_fields(self):
for name, field in self.fields.items():
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
if field.disabled:
value = self.initial.get(name, field.initial)
else:
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)

def _clean_form(self):
try:
cleaned_data = self.clean()
except ValidationError as e:
self.add_error(None, e)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data

def _post_clean(self):
"""
An internal hook for performing additional cleaning after form cleaning
is complete. Used for model validation in model forms.
"""
pass

def clean(self):
"""
Hook for doing any extra form-wide cleaning after Field.clean() has been
called on every field. Any ValidationError raised by this method will
not be associated with a particular field; it will have a special-case
association with the field named '__all__'.
"""
return self.cleaned_data

def has_changed(self):
"""
Returns True if data differs from initial.
"""
return bool(self.changed_data)

@cached_property
def changed_data(self):
data = []
for name, field in self.fields.items():
prefixed_name = self.add_prefix(name)
data_value = field.widget.value_from_datadict(self.data, self.files, prefixed_name)
if not field.show_hidden_initial:
initial_value = self.initial.get(name, field.initial)
if callable(initial_value):
initial_value = initial_value()
else:
initial_prefixed_name = self.add_initial_prefix(name)
hidden_widget = field.hidden_widget()
try:
initial_value = field.to_python(hidden_widget.value_from_datadict(
self.data, self.files, initial_prefixed_name))
except ValidationError:
# Always assume data has changed if validation fails.
data.append(name)
continue
if field.has_changed(initial_value, data_value):
data.append(name)
return data

@property
def media(self):
"""
Provide a description of all media required to render the widgets on this form
"""
media = Media()
for field in self.fields.values():
media = media + field.widget.media
return media

def is_multipart(self):
"""
Returns True if the form needs to be multipart-encoded, i.e. it has
FileInput. Otherwise, False.
"""
for field in self.fields.values():
if field.widget.needs_multipart_form:
return True
return False

def hidden_fields(self):
"""
Returns a list of all the BoundField objects that are hidden fields.
Useful for manual form layout in templates.
"""
return [field for field in self if field.is_hidden]

def visible_fields(self):
"""
Returns a list of BoundField objects that aren't hidden fields.
The opposite of the hidden_fields() method.
"""
return [field for field in self if not field.is_hidden]

[docs]class Form(six.with_metaclass(DeclarativeFieldsMetaclass, BaseForm)):
"A collection of Fields, plus their associated data."

# This is a separate class from BaseForm in order to abstract the way
# self.fields is specified. This class (Form) is the one that does the
# fancy metaclass stuff purely for the semantic sugar -- it allows one
# to define a form using declarative syntax.
# BaseForm itself has no way of designating self.fields.

Source code for django.forms.formsets

from __future__ import unicode_literals

from django.core.exceptions import ValidationError
from django.forms import Form
from django.forms.fields import BooleanField, IntegerField
from django.forms.utils import ErrorList
from django.forms.widgets import HiddenInput
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible
from django.utils.functional import cached_property
from django.utils.html import html_safe
from django.utils.safestring import mark_safe
from django.utils.six.moves import range
from django.utils.translation import ugettext as _, ungettext

__all__ = ('BaseFormSet', 'formset_factory', 'all_valid')

# special field names
TOTAL_FORM_COUNT = 'TOTAL_FORMS'
INITIAL_FORM_COUNT = 'INITIAL_FORMS'
MIN_NUM_FORM_COUNT = 'MIN_NUM_FORMS'
MAX_NUM_FORM_COUNT = 'MAX_NUM_FORMS'
ORDERING_FIELD_NAME = 'ORDER'
DELETION_FIELD_NAME = 'DELETE'

# default minimum number of forms in a formset
DEFAULT_MIN_NUM = 0

# default maximum number of forms in a formset, to prevent memory exhaustion
DEFAULT_MAX_NUM = 1000

class ManagementForm(Form):
"""
``ManagementForm`` is used to keep track of how many form instances
are displayed on the page. If adding new forms via javascript, you should
increment the count field of this form as well.
"""
def __init__(self, *args, **kwargs):
self.base_fields[TOTAL_FORM_COUNT] = IntegerField(widget=HiddenInput)
self.base_fields[INITIAL_FORM_COUNT] = IntegerField(widget=HiddenInput)
# MIN_NUM_FORM_COUNT and MAX_NUM_FORM_COUNT are output with the rest of
# the management form, but only for the convenience of client-side
# code. The POST value of them returned from the client is not checked.
self.base_fields[MIN_NUM_FORM_COUNT] = IntegerField(required=False, widget=HiddenInput)
self.base_fields[MAX_NUM_FORM_COUNT] = IntegerField(required=False, widget=HiddenInput)
super(ManagementForm, self).__init__(*args, **kwargs)

@html_safe
@python_2_unicode_compatible

[docs]class BaseFormSet(object):
"""
A collection of instances of the same Form class.
"""
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, form_kwargs=None):
self.is_bound = data is not None or files is not None
self.prefix = prefix or self.get_default_prefix()
self.auto_id = auto_id
self.data = data or {}
self.files = files or {}
self.initial = initial
self.form_kwargs = form_kwargs or {}
self.error_class = error_class
self._errors = None
self._non_form_errors = None

def __str__(self):
return self.as_table()

def __iter__(self):
"""Yields the forms in the order they should be rendered"""
return iter(self.forms)

def __getitem__(self, index):
"""Returns the form at the given index, based on the rendering order"""
return self.forms[index]

def __len__(self):
return len(self.forms)

def __bool__(self):
"""All formsets have a management form which is not included in the length"""
return True

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

@property
def management_form(self):
"""Returns the ManagementForm instance for this FormSet."""
if self.is_bound:
form = ManagementForm(self.data, auto_id=self.auto_id, prefix=self.prefix)
if not form.is_valid():
raise ValidationError(
_('ManagementForm data is missing or has been tampered with'),
code='missing_management_form',
)
else:
form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial={
TOTAL_FORM_COUNT: self.total_form_count(),
INITIAL_FORM_COUNT: self.initial_form_count(),
MIN_NUM_FORM_COUNT: self.min_num,
MAX_NUM_FORM_COUNT: self.max_num
})
return form

def total_form_count(self):
"""Returns the total number of forms in this FormSet."""
if self.is_bound:
# return absolute_max if it is lower than the actual total form
# count in the data; this is DoS protection to prevent clients
# from forcing the server to instantiate arbitrary numbers of
# forms
return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max)
else:
initial_forms = self.initial_form_count()
total_forms = max(initial_forms, self.min_num) + self.extra
# Allow all existing related objects/inlines to be displayed,
# but don't allow extra beyond max_num.
if initial_forms > self.max_num >= 0:
total_forms = initial_forms
elif total_forms > self.max_num >= 0:
total_forms = self.max_num
return total_forms

def initial_form_count(self):
"""Returns the number of forms that are required in this FormSet."""
if self.is_bound:
return self.management_form.cleaned_data[INITIAL_FORM_COUNT]
else:
# Use the length of the initial data if it's there, 0 otherwise.
initial_forms = len(self.initial) if self.initial else 0
return initial_forms

@cached_property
def forms(self):
"""
Instantiate forms at first property access.
"""
# DoS protection is included in total_form_count()
forms = [self._construct_form(i, **self.get_form_kwargs(i))
for i in range(self.total_form_count())]
return forms

def get_form_kwargs(self, index):
"""
Return additional keyword arguments for each individual formset form.

index will be None if the form being constructed is a new empty
form.
"""
return self.form_kwargs.copy()

def _construct_form(self, i, **kwargs):
"""
Instantiates and returns the i-th form instance in a formset.
"""
defaults = {
'auto_id': self.auto_id,
'prefix': self.add_prefix(i),
'error_class': self.error_class,
}
if self.is_bound:
defaults['data'] = self.data
defaults['files'] = self.files
if self.initial and 'initial' not in kwargs:
try:
defaults['initial'] = self.initial[i]
except IndexError:
pass
# Allow extra forms to be empty, unless they're part of
# the minimum forms.
if i >= self.initial_form_count() and i >= self.min_num:
defaults['empty_permitted'] = True
defaults.update(kwargs)
form = self.form(**defaults)
self.add_fields(form, i)
return form

@property
def initial_forms(self):
"""Return a list of all the initial forms in this formset."""
return self.forms[:self.initial_form_count()]

@property
def extra_forms(self):
"""Return a list of all the extra forms in this formset."""
return self.forms[self.initial_form_count():]

@property
def empty_form(self):
form = self.form(
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
**self.get_form_kwargs(None)
)
self.add_fields(form, None)
return form

@property
def cleaned_data(self):
"""
Returns a list of form.cleaned_data dicts for every form in self.forms.
"""
if not self.is_valid():
raise AttributeError("'%s' object has no attribute 'cleaned_data'" % self.__class__.__name__)
return [form.cleaned_data for form in self.forms]

@property
def deleted_forms(self):
"""
Returns a list of forms that have been marked for deletion.
"""
if not self.is_valid() or not self.can_delete:
return []
# construct _deleted_form_indexes which is just a list of form indexes
# that have had their deletion widget set to True
if not hasattr(self, '_deleted_form_indexes'):
self._deleted_form_indexes = []
for i in range(0, self.total_form_count()):
form = self.forms[i]
# if this is an extra form and hasn't changed, don't consider it
if i >= self.initial_form_count() and not form.has_changed():
continue
if self._should_delete_form(form):
self._deleted_form_indexes.append(i)
return [self.forms[i] for i in self._deleted_form_indexes]

@property
def ordered_forms(self):
"""
Returns a list of form in the order specified by the incoming data.
Raises an AttributeError if ordering is not allowed.
"""
if not self.is_valid() or not self.can_order:
raise AttributeError("'%s' object has no attribute 'ordered_forms'" % self.__class__.__name__)
# Construct _ordering, which is a list of (form_index, order_field_value)
# tuples. After constructing this list, we'll sort it by order_field_value
# so we have a way to get to the form indexes in the order specified
# by the form data.
if not hasattr(self, '_ordering'):
self._ordering = []
for i in range(0, self.total_form_count()):
form = self.forms[i]
# if this is an extra form and hasn't changed, don't consider it
if i >= self.initial_form_count() and not form.has_changed():
continue
# don't add data marked for deletion to self.ordered_data
if self.can_delete and self._should_delete_form(form):
continue
self._ordering.append((i, form.cleaned_data[ORDERING_FIELD_NAME]))
# After we're done populating self._ordering, sort it.
# A sort function to order things numerically ascending, but
# None should be sorted below anything else. Allowing None as
# a comparison value makes it so we can leave ordering fields
# blank.

def compare_ordering_key(k):
if k[1] is None:
return (1, 0)  # +infinity, larger than any number
return (0, k[1])
self._ordering.sort(key=compare_ordering_key)
# Return a list of form.cleaned_data dicts in the order specified by
# the form data.
return [self.forms[i[0]] for i in self._ordering]

@classmethod
def get_default_prefix(cls):
return 'form'

def non_form_errors(self):
"""
Returns an ErrorList of errors that aren't associated with a particular
form -- i.e., from formset.clean(). Returns an empty ErrorList if there
are none.
"""
if self._non_form_errors is None:
self.full_clean()
return self._non_form_errors

@property
def errors(self):
"""
Returns a list of form.errors for every form in self.forms.
"""
if self._errors is None:
self.full_clean()
return self._errors

[docs]    def total_error_count(self):
"""
Returns the number of errors across all forms in the formset.
"""
return len(self.non_form_errors()) +\
sum(len(form_errors) for form_errors in self.errors)

def _should_delete_form(self, form):
"""
Returns whether or not the form was marked for deletion.
"""
return form.cleaned_data.get(DELETION_FIELD_NAME, False)

def is_valid(self):
"""
Returns True if every form in self.forms is valid.
"""
if not self.is_bound:
return False
# We loop over every form.errors here rather than short circuiting on the
# first failure to make sure validation gets triggered for every form.
forms_valid = True
# This triggers a full clean.
self.errors
for i in range(0, self.total_form_count()):
form = self.forms[i]
if self.can_delete:
if self._should_delete_form(form):
# This form is going to be deleted so any of its errors
# should not cause the entire formset to be invalid.
continue
forms_valid &= form.is_valid()
return forms_valid and not self.non_form_errors()

def full_clean(self):
"""
Cleans all of self.data and populates self._errors and
self._non_form_errors.
"""
self._errors = []
self._non_form_errors = self.error_class()

if not self.is_bound:  # Stop further processing.
return
for i in range(0, self.total_form_count()):
form = self.forms[i]
self._errors.append(form.errors)
try:
if (self.validate_max and
self.total_form_count() - len(self.deleted_forms) > self.max_num) or \
self.management_form.cleaned_data[TOTAL_FORM_COUNT] > self.absolute_max:
raise ValidationError(ungettext(
"Please submit %d or fewer forms.",
"Please submit %d or fewer forms.", self.max_num) % self.max_num,
code='too_many_forms',
)
if (self.validate_min and
self.total_form_count() - len(self.deleted_forms) < self.min_num):
raise ValidationError(ungettext(
"Please submit %d or more forms.",
"Please submit %d or more forms.", self.min_num) % self.min_num,
code='too_few_forms')
# Give self.clean() a chance to do cross-form validation.
self.clean()
except ValidationError as e:
self._non_form_errors = self.error_class(e.error_list)

def clean(self):
"""
Hook for doing any extra formset-wide cleaning after Form.clean() has
been called on every form. Any ValidationError raised by this method
will not be associated with a particular form; it will be accessible
via formset.non_form_errors()
"""
pass

def has_changed(self):
"""
Returns true if data in any form differs from initial.
"""
return any(form.has_changed() for form in self)

def add_fields(self, form, index):
"""A hook for adding extra fields on to each form instance."""
if self.can_order:
# Only pre-fill the ordering field for initial forms.
if index is not None and index < self.initial_form_count():
form.fields[ORDERING_FIELD_NAME] = IntegerField(label=_('Order'), initial=index + 1, required=False)
else:
form.fields[ORDERING_FIELD_NAME] = IntegerField(label=_('Order'), required=False)
if self.can_delete:
form.fields[DELETION_FIELD_NAME] = BooleanField(label=_('Delete'), required=False)

def add_prefix(self, index):
return '%s-%s' % (self.prefix, index)

def is_multipart(self):
"""
Returns True if the formset needs to be multipart, i.e. it
has FileInput. Otherwise, False.
"""
if self.forms:
return self.forms[0].is_multipart()
else:
return self.empty_form.is_multipart()

@property
def media(self):
# All the forms on a FormSet are the same, so you only need to
# interrogate the first form for media.
if self.forms:
return self.forms[0].media
else:
return self.empty_form.media

def as_table(self):
"Returns this formset rendered as HTML <tr>s -- excluding the <table></table>."
# XXX: there is no semantic division between forms here, there
# probably should be. It might make sense to render each form as a
# table row with each field as a td.
forms = ' '.join(form.as_table() for form in self)
return mark_safe('\n'.join([six.text_type(self.management_form), forms]))

def as_p(self):
"Returns this formset rendered as HTML <p>s."
forms = ' '.join(form.as_p() for form in self)
return mark_safe('\n'.join([six.text_type(self.management_form), forms]))

def as_ul(self):
"Returns this formset rendered as HTML <li>s."
forms = ' '.join(form.as_ul() for form in self)
return mark_safe('\n'.join([six.text_type(self.management_form), forms]))

[docs]def formset_factory(form, formset=BaseFormSet, extra=1, can_order=False,
can_delete=False, max_num=None, validate_max=False,
min_num=None, validate_min=False):
"""Return a FormSet for the given form class."""
if min_num is None:
min_num = DEFAULT_MIN_NUM
if max_num is None:
max_num = DEFAULT_MAX_NUM
# hard limit on forms instantiated, to prevent memory-exhaustion attacks
# limit is simply max_num + DEFAULT_MAX_NUM (which is 2*DEFAULT_MAX_NUM
# if max_num is None in the first place)
absolute_max = max_num + DEFAULT_MAX_NUM
attrs = {'form': form, 'extra': extra,
'can_order': can_order, 'can_delete': can_delete,
'min_num': min_num, 'max_num': max_num,
'absolute_max': absolute_max, 'validate_min': validate_min,
'validate_max': validate_max}
return type(form.__name__ + str('FormSet'), (formset,), attrs)

def all_valid(formsets):
"""Returns true if every formset in formsets is valid."""
valid = True
for formset in formsets:
if not formset.is_valid():
valid = False
return valid

Source code for django.views.i18n

import gettext as gettext_module
import importlib
import json
import os

from django import http
from django.apps import apps
from django.conf import settings
from django.core.urlresolvers import translate_url
from django.template import Context, Engine
from django.utils import six
from django.utils._os import upath
from django.utils.encoding import smart_text
from django.utils.formats import get_format, get_format_modules
from django.utils.http import is_safe_url
from django.utils.translation import (
LANGUAGE_SESSION_KEY, check_for_language, get_language, to_locale,
)

DEFAULT_PACKAGES = ['django.conf']
LANGUAGE_QUERY_PARAMETER = 'language'

[docs]def set_language(request):
"""
Redirect to a given url while setting the chosen language in the
session or cookie. The url and the language code need to be
specified in the request parameters.

Since this view changes how the user will see the rest of the site, it must
only be accessed as a POST request. If called as a GET request, it will
redirect to the page in the request (the 'next' parameter) without changing
any state.
"""
next = request.POST.get('next', request.GET.get('next'))
if not is_safe_url(url=next, host=request.get_host()):
next = request.META.get('HTTP_REFERER')
if not is_safe_url(url=next, host=request.get_host()):
next = '/'
response = http.HttpResponseRedirect(next)
if request.method == 'POST':
lang_code = request.POST.get(LANGUAGE_QUERY_PARAMETER)
if lang_code and check_for_language(lang_code):
next_trans = translate_url(next, lang_code)
if next_trans != next:
response = http.HttpResponseRedirect(next_trans)
if hasattr(request, 'session'):
request.session[LANGUAGE_SESSION_KEY] = lang_code
else:
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code,
max_age=settings.LANGUAGE_COOKIE_AGE,
path=settings.LANGUAGE_COOKIE_PATH,
domain=settings.LANGUAGE_COOKIE_DOMAIN)
return response

def get_formats():
"""
Returns all formats strings required for i18n to work
"""
FORMAT_SETTINGS = (
'DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT',
'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT',
'SHORT_DATETIME_FORMAT', 'FIRST_DAY_OF_WEEK', 'DECIMAL_SEPARATOR',
'THOUSAND_SEPARATOR', 'NUMBER_GROUPING',
'DATE_INPUT_FORMATS', 'TIME_INPUT_FORMATS', 'DATETIME_INPUT_FORMATS'
)
result = {}
for module in [settings] + get_format_modules(reverse=True):
for attr in FORMAT_SETTINGS:
result[attr] = get_format(attr)
formats = {}
for k, v in result.items():
if isinstance(v, (six.string_types, int)):
formats[k] = smart_text(v)
elif isinstance(v, (tuple, list)):
formats[k] = [smart_text(value) for value in v]
return formats

js_catalog_template = r"""
{% autoescape off %}
(function(globals) {

var django = globals.django || (globals.django = {});

{% if plural %}
django.pluralidx = function(n) {
var v={{ plural }};
if (typeof(v) == 'boolean') {
return v ? 1 : 0;
} else {
return v;
}
};
{% else %}
django.pluralidx = function(count) { return (count == 1) ? 0 : 1; };
{% endif %}

/* gettext library */

django.catalog = django.catalog || {};
{% if catalog_str %}
var newcatalog = {{ catalog_str }};
for (var key in newcatalog) {
django.catalog[key] = newcatalog[key];
}
{% endif %}

if (!django.jsi18n_initialized) {
django.gettext = function(msgid) {
var value = django.catalog[msgid];
if (typeof(value) == 'undefined') {
return msgid;
} else {
return (typeof(value) == 'string') ? value : value[0];
}
};

django.ngettext = function(singular, plural, count) {
var value = django.catalog[singular];
if (typeof(value) == 'undefined') {
return (count == 1) ? singular : plural;
} else {
return value[django.pluralidx(count)];
}
};

django.gettext_noop = function(msgid) { return msgid; };

django.pgettext = function(context, msgid) {
var value = django.gettext(context + '\x04' + msgid);
if (value.indexOf('\x04') != -1) {
value = msgid;
}
return value;
};

django.npgettext = function(context, singular, plural, count) {
var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count);
if (value.indexOf('\x04') != -1) {
value = django.ngettext(singular, plural, count);
}
return value;
};

django.interpolate = function(fmt, obj, named) {
if (named) {
return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
} else {
return fmt.replace(/%s/g, function(match){return String(obj.shift())});
}
};

/* formatting library */

django.formats = {{ formats_str }};

django.get_format = function(format_type) {
var value = django.formats[format_type];
if (typeof(value) == 'undefined') {
return format_type;
} else {
return value;
}
};

/* add to global namespace */
globals.pluralidx = django.pluralidx;
globals.gettext = django.gettext;
globals.ngettext = django.ngettext;
globals.gettext_noop = django.gettext_noop;
globals.pgettext = django.pgettext;
globals.npgettext = django.npgettext;
globals.interpolate = django.interpolate;
globals.get_format = django.get_format;

django.jsi18n_initialized = true;
}

}(this));
{% endautoescape %}
"""

def render_javascript_catalog(catalog=None, plural=None):
template = Engine().from_string(js_catalog_template)
indent = lambda s: s.replace('\n', '\n  ')
context = Context({
'catalog_str': indent(json.dumps(
catalog, sort_keys=True, indent=2)) if catalog else None,
'formats_str': indent(json.dumps(
get_formats(), sort_keys=True, indent=2)),
'plural': plural,
})

return http.HttpResponse(template.render(context), 'text/javascript')

def get_javascript_catalog(locale, domain, packages):
default_locale = to_locale(settings.LANGUAGE_CODE)
app_configs = apps.get_app_configs()
allowable_packages = set(app_config.name for app_config in app_configs)
allowable_packages.update(DEFAULT_PACKAGES)
packages = [p for p in packages if p in allowable_packages]
t = {}
paths = []
en_selected = locale.startswith('en')
en_catalog_missing = True
# paths of requested packages
for package in packages:
p = importlib.import_module(package)
path = os.path.join(os.path.dirname(upath(p.__file__)), 'locale')
paths.append(path)
# add the filesystem paths listed in the LOCALE_PATHS setting
paths.extend(reversed(settings.LOCALE_PATHS))
# first load all english languages files for defaults
for path in paths:
try:
catalog = gettext_module.translation(domain, path, ['en'])
t.update(catalog._catalog)
except IOError:
pass
else:
# 'en' is the selected language and at least one of the packages
# listed in `packages` has an 'en' catalog
if en_selected:
en_catalog_missing = False
# next load the settings.LANGUAGE_CODE translations if it isn't english
if default_locale != 'en':
for path in paths:
try:
catalog = gettext_module.translation(domain, path, [default_locale])
except IOError:
catalog = None
if catalog is not None:
t.update(catalog._catalog)
# last load the currently selected language, if it isn't identical to the default.
if locale != default_locale:
# If the currently selected language is English but it doesn't have a
# translation catalog (presumably due to being the language translated
# from) then a wrong language catalog might have been loaded in the
# previous step. It needs to be discarded.
if en_selected and en_catalog_missing:
t = {}
else:
locale_t = {}
for path in paths:
try:
catalog = gettext_module.translation(domain, path, [locale])
except IOError:
catalog = None
if catalog is not None:
locale_t.update(catalog._catalog)
if locale_t:
t = locale_t
plural = None
if '' in t:
for l in t[''].split('\n'):
if l.startswith('Plural-Forms:'):
plural = l.split(':', 1)[1].strip()
if plural is not None:
# this should actually be a compiled function of a typical plural-form:
# Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 :
#               n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
plural = [el.strip() for el in plural.split(';') if el.strip().startswith('plural=')][0].split('=', 1)[1]

pdict = {}
maxcnts = {}
catalog = {}
for k, v in t.items():
if k == '':
continue
if isinstance(k, six.string_types):
catalog[k] = v
elif isinstance(k, tuple):
msgid = k[0]
cnt = k[1]
maxcnts[msgid] = max(cnt, maxcnts.get(msgid, 0))
pdict.setdefault(msgid, {})[cnt] = v
else:
raise TypeError(k)
for k, v in pdict.items():
catalog[k] = [v.get(i, '') for i in range(maxcnts[msgid] + 1)]

return catalog, plural

def _get_locale(request):
language = request.GET.get(LANGUAGE_QUERY_PARAMETER)
if not (language and check_for_language(language)):
language = get_language()
return to_locale(language)

def _parse_packages(packages):
if packages is None:
packages = list(DEFAULT_PACKAGES)
elif isinstance(packages, six.string_types):
packages = packages.split('+')
return packages

def null_javascript_catalog(request, domain=None, packages=None):
"""
Returns "identity" versions of the JavaScript i18n functions -- i.e.,
versions that don't actually do anything.
"""
return render_javascript_catalog()

[docs]def javascript_catalog(request, domain='djangojs', packages=None):
"""
Returns the selected language catalog as a javascript library.

Receives the list of packages to check for translations in the
packages parameter either from an infodict or as a +-delimited
string from the request. Default is 'django.conf'.

Additionally you can override the gettext domain for this view,
but usually you don't want to do that, as JavaScript messages
go to the djangojs domain. But this might be needed if you
deliver your JavaScript source from Django templates.
"""
locale = _get_locale(request)
packages = _parse_packages(packages)
catalog, plural = get_javascript_catalog(locale, domain, packages)
return render_javascript_catalog(catalog, plural)

[docs]def json_catalog(request, domain='djangojs', packages=None):
"""
Return the selected language catalog as a JSON object.

Receives the same parameters as javascript_catalog(), but returns
a response with a JSON object of the following format:

{
"catalog": {
# Translations catalog
},
"formats": {
# Language formats for date, time, etc.
},
"plural": '...'  # Expression for plural forms, or null.
}
"""
locale = _get_locale(request)
packages = _parse_packages(packages)
catalog, plural = get_javascript_catalog(locale, domain, packages)
data = {
'catalog': catalog,
'formats': get_formats(),
'plural': plural,
}
return http.JsonResponse(data)

Source code for django.views.debug

from __future__ import unicode_literals

import re
import sys
import types

from django.conf import settings
from django.core.urlresolvers import Resolver404, resolve
from django.http import HttpResponse, HttpResponseNotFound
from django.template import Context, Engine, TemplateDoesNotExist
from django.template.defaultfilters import force_escape, pprint
from django.utils import lru_cache, six, timezone
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_bytes, smart_text
from django.utils.module_loading import import_string
from django.utils.translation import ugettext as _

# Minimal Django templates engine to render the error templates
# regardless of the project's TEMPLATES setting.
DEBUG_ENGINE = Engine(debug=True)

HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE')

CLEANSED_SUBSTITUTE = '********************'

class CallableSettingWrapper(object):
""" Object to wrap callable appearing in settings

* Not to call in the debug page (#21345).
* Not to break the debug page if the callable forbidding to set attributes (#23070).
"""
def __init__(self, callable_setting):
self._wrapped = callable_setting

def __repr__(self):
return repr(self._wrapped)

def cleanse_setting(key, value):
"""Cleanse an individual setting key/value of sensitive content.

If the value is a dictionary, recursively cleanse the keys in
that dictionary.
"""
try:
if HIDDEN_SETTINGS.search(key):
cleansed = CLEANSED_SUBSTITUTE
else:
if isinstance(value, dict):
cleansed = {k: cleanse_setting(k, v) for k, v in value.items()}
else:
cleansed = value
except TypeError:
# If the key isn't regex-able, just return as-is.
cleansed = value

if callable(cleansed):
# For fixing #21345 and #23070
cleansed = CallableSettingWrapper(cleansed)

return cleansed

def get_safe_settings():
"Returns a dictionary of the settings module, with sensitive settings blurred out."
settings_dict = {}
for k in dir(settings):
if k.isupper():
settings_dict[k] = cleanse_setting(k, getattr(settings, k))
return settings_dict

def technical_500_response(request, exc_type, exc_value, tb, status_code=500):
"""
Create a technical server error response. The last three arguments are
the values returned from sys.exc_info() and friends.
"""
reporter = ExceptionReporter(request, exc_type, exc_value, tb)
if request.is_ajax():
text = reporter.get_traceback_text()
return HttpResponse(text, status=status_code, content_type='text/plain')
else:
html = reporter.get_traceback_html()
return HttpResponse(html, status=status_code, content_type='text/html')

@lru_cache.lru_cache()
def get_default_exception_reporter_filter():
# Instantiate the default filter for the first time and cache it.
return import_string(settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()

def get_exception_reporter_filter(request):
default_filter = get_default_exception_reporter_filter()
return getattr(request, 'exception_reporter_filter', default_filter)

class ExceptionReporterFilter(object):
"""
Base for all exception reporter filter classes. All overridable hooks
contain lenient default behaviors.
"""

def get_post_parameters(self, request):
if request is None:
return {}
else:
return request.POST

def get_traceback_frame_variables(self, request, tb_frame):
return list(tb_frame.f_locals.items())

[docs]class SafeExceptionReporterFilter(ExceptionReporterFilter):
"""
Use annotations made by the sensitive_post_parameters and
sensitive_variables decorators to filter out sensitive information.
"""

[docs]    def is_active(self, request):
"""
This filter is to add safety in production environments (i.e. DEBUG
is False). If DEBUG is True then your site is not safe anyway.
This hook is provided as a convenience to easily activate or
deactivate the filter on a per request basis.
"""
return settings.DEBUG is False

def get_cleansed_multivaluedict(self, request, multivaluedict):
"""
Replaces the keys in a MultiValueDict marked as sensitive with stars.
This mitigates leaking sensitive POST parameters if something like
request.POST['nonexistent_key'] throws an exception (#21098).
"""
sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', [])
if self.is_active(request) and sensitive_post_parameters:
multivaluedict = multivaluedict.copy()
for param in sensitive_post_parameters:
if param in multivaluedict:
multivaluedict[param] = CLEANSED_SUBSTITUTE
return multivaluedict

[docs]    def get_post_parameters(self, request):
"""
Replaces the values of POST parameters marked as sensitive with
stars (*********).
"""
if request is None:
return {}
else:
sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', [])
if self.is_active(request) and sensitive_post_parameters:
cleansed = request.POST.copy()
if sensitive_post_parameters == '__ALL__':
# Cleanse all parameters.
for k, v in cleansed.items():
cleansed[k] = CLEANSED_SUBSTITUTE
return cleansed
else:
# Cleanse only the specified parameters.
for param in sensitive_post_parameters:
if param in cleansed:
cleansed[param] = CLEANSED_SUBSTITUTE
return cleansed
else:
return request.POST

def cleanse_special_types(self, request, value):
try:
# If value is lazy or a complex object of another kind, this check
# might raise an exception. isinstance checks that lazy
# MultiValueDicts will have a return value.
is_multivalue_dict = isinstance(value, MultiValueDict)
except Exception as e:
return '{!r} while evaluating {!r}'.format(e, value)

if is_multivalue_dict:
# Cleanse MultiValueDicts (request.POST is the one we usually care about)
value = self.get_cleansed_multivaluedict(request, value)
return value

[docs]    def get_traceback_frame_variables(self, request, tb_frame):
"""
Replaces the values of variables marked as sensitive with
stars (*********).
"""
# Loop through the frame's callers to see if the sensitive_variables
# decorator was used.
current_frame = tb_frame.f_back
sensitive_variables = None
while current_frame is not None:
if (current_frame.f_code.co_name == 'sensitive_variables_wrapper'
and 'sensitive_variables_wrapper' in current_frame.f_locals):
# The sensitive_variables decorator was used, so we take note
# of the sensitive variables' names.
wrapper = current_frame.f_locals['sensitive_variables_wrapper']
sensitive_variables = getattr(wrapper, 'sensitive_variables', None)
break
current_frame = current_frame.f_back

cleansed = {}
if self.is_active(request) and sensitive_variables:
if sensitive_variables == '__ALL__':
# Cleanse all variables
for name, value in tb_frame.f_locals.items():
cleansed[name] = CLEANSED_SUBSTITUTE
else:
# Cleanse specified variables
for name, value in tb_frame.f_locals.items():
if name in sensitive_variables:
value = CLEANSED_SUBSTITUTE
else:
value = self.cleanse_special_types(request, value)
cleansed[name] = value
else:
# Potentially cleanse the request and any MultiValueDicts if they
# are one of the frame variables.
for name, value in tb_frame.f_locals.items():
cleansed[name] = self.cleanse_special_types(request, value)

if (tb_frame.f_code.co_name == 'sensitive_variables_wrapper'
and 'sensitive_variables_wrapper' in tb_frame.f_locals):
# For good measure, obfuscate the decorated function's arguments in
# the sensitive_variables decorator's frame, in case the variables
# associated with those arguments were meant to be obfuscated from
# the decorated function's frame.
cleansed['func_args'] = CLEANSED_SUBSTITUTE
cleansed['func_kwargs'] = CLEANSED_SUBSTITUTE

return cleansed.items()

class ExceptionReporter(object):
"""
A class to organize and coordinate reporting on exceptions.
"""
def __init__(self, request, exc_type, exc_value, tb, is_email=False):
self.request = request
self.filter = get_exception_reporter_filter(self.request)
self.exc_type = exc_type
self.exc_value = exc_value
self.tb = tb
self.is_email = is_email

self.template_info = getattr(self.exc_value, 'template_debug', None)
self.template_does_not_exist = False
self.postmortem = None

# Handle deprecated string exceptions
if isinstance(self.exc_type, six.string_types):
self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
self.exc_type = type(self.exc_value)

def get_traceback_data(self):
"""Return a dictionary containing traceback information."""
if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist):
self.template_does_not_exist = True
self.postmortem = self.exc_value.chain or [self.exc_value]

frames = self.get_traceback_frames()
for i, frame in enumerate(frames):
if 'vars' in frame:
frame_vars = []
for k, v in frame['vars']:
v = pprint(v)
# The force_escape filter assume unicode, make sure that works
if isinstance(v, six.binary_type):
v = v.decode('utf-8', 'replace')  # don't choke on non-utf-8 input
# Trim large blobs of data
if len(v) > 4096:
v = '%s... <trimmed %d bytes string>' % (v[0:4096], len(v))
frame_vars.append((k, force_escape(v)))
frame['vars'] = frame_vars
frames[i] = frame

unicode_hint = ''
if self.exc_type and issubclass(self.exc_type, UnicodeError):
start = getattr(self.exc_value, 'start', None)
end = getattr(self.exc_value, 'end', None)
if start is not None and end is not None:
unicode_str = self.exc_value.args[1]
unicode_hint = smart_text(
unicode_str[max(start - 5, 0):min(end + 5, len(unicode_str))],
'ascii', errors='replace'
)
from django import get_version
c = {
'is_email': self.is_email,
'unicode_hint': unicode_hint,
'frames': frames,
'request': self.request,
'filtered_POST': self.filter.get_post_parameters(self.request),
'settings': get_safe_settings(),
'sys_executable': sys.executable,
'sys_version_info': '%d.%d.%d' % sys.version_info[0:3],
'server_time': timezone.now(),
'django_version_info': get_version(),
'sys_path': sys.path,
'template_info': self.template_info,
'template_does_not_exist': self.template_does_not_exist,
'postmortem': self.postmortem,
}
# Check whether exception info is available
if self.exc_type:
c['exception_type'] = self.exc_type.__name__
if self.exc_value:
c['exception_value'] = smart_text(self.exc_value, errors='replace')
if frames:
c['lastframe'] = frames[-1]
return c

def get_traceback_html(self):
"Return HTML version of debug 500 HTTP error page."
t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEMPLATE)
c = Context(self.get_traceback_data(), use_l10n=False)
return t.render(c)

def get_traceback_text(self):
"Return plain text version of debug 500 HTTP error page."
t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEXT_TEMPLATE)
c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
return t.render(c)

def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None):
"""
Returns context_lines before and after lineno from file.
Returns (pre_context_lineno, pre_context, context_line, post_context).
"""
source = None
if loader is not None and hasattr(loader, "get_source"):
try:
source = loader.get_source(module_name)
except ImportError:
pass
if source is not None:
source = source.splitlines()
if source is None:
try:
with open(filename, 'rb') as fp:
source = fp.read().splitlines()
except (OSError, IOError):
pass
if source is None:
return None, [], None, []

# If we just read the source from a file, or if the loader did not
# apply tokenize.detect_encoding to decode the source into a Unicode
# string, then we should do that ourselves.
if isinstance(source[0], six.binary_type):
encoding = 'ascii'
for line in source[:2]:
# File coding may be specified. Match pattern from PEP-263
# (http://www.python.org/dev/peps/pep-0263/)
match = re.search(br'coding[:=]\s*([-\w.]+)', line)
if match:
encoding = match.group(1).decode('ascii')
break
source = [six.text_type(sline, encoding, 'replace') for sline in source]

lower_bound = max(0, lineno - context_lines)
upper_bound = lineno + context_lines

pre_context = source[lower_bound:lineno]
context_line = source[lineno]
post_context = source[lineno + 1:upper_bound]

return lower_bound, pre_context, context_line, post_context

def get_traceback_frames(self):
def explicit_or_implicit_cause(exc_value):
explicit = getattr(exc_value, '__cause__', None)
implicit = getattr(exc_value, '__context__', None)
return explicit or implicit

# Get the exception and all its causes
exceptions = []
exc_value = self.exc_value
while exc_value:
exceptions.append(exc_value)
exc_value = explicit_or_implicit_cause(exc_value)

frames = []
# No exceptions were supplied to ExceptionReporter
if not exceptions:
return frames

# In case there's just one exception (always in Python 2,
# sometimes in Python 3), take the traceback from self.tb (Python 2
# doesn't have a __traceback__ attribute on Exception)
exc_value = exceptions.pop()
tb = self.tb if six.PY2 or not exceptions else exc_value.__traceback__

while tb is not None:
# Support for __traceback_hide__ which is used by a few libraries
# to hide internal frames.
if tb.tb_frame.f_locals.get('__traceback_hide__'):
tb = tb.tb_next
continue
filename = tb.tb_frame.f_code.co_filename
function = tb.tb_frame.f_code.co_name
lineno = tb.tb_lineno - 1
loader = tb.tb_frame.f_globals.get('__loader__')
module_name = tb.tb_frame.f_globals.get('__name__') or ''
pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(
filename, lineno, 7, loader, module_name,
)
if pre_context_lineno is not None:
frames.append({
'exc_cause': explicit_or_implicit_cause(exc_value),
'exc_cause_explicit': getattr(exc_value, '__cause__', True),
'tb': tb,
'type': 'django' if module_name.startswith('django.') else 'user',
'filename': filename,
'function': function,
'lineno': lineno + 1,
'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame),
'id': id(tb),
'pre_context': pre_context,
'context_line': context_line,
'post_context': post_context,
'pre_context_lineno': pre_context_lineno + 1,
})

# If the traceback for current exception is consumed, try the
# other exception.
if six.PY2:
tb = tb.tb_next
elif not tb.tb_next and exceptions:
exc_value = exceptions.pop()
tb = exc_value.__traceback__
else:
tb = tb.tb_next

return frames

def format_exception(self):
"""
Return the same data as from traceback.format_exception.
"""
import traceback
frames = self.get_traceback_frames()
tb = [(f['filename'], f['lineno'], f['function'], f['context_line']) for f in frames]
list = ['Traceback (most recent call last):\n']
list += traceback.format_list(tb)
list += traceback.format_exception_only(self.exc_type, self.exc_value)
return list

def technical_404_response(request, exception):
"Create a technical 404 error response. The exception should be the Http404."
try:
error_url = exception.args[0]['path']
except (IndexError, TypeError, KeyError):
error_url = request.path_info[1:]  # Trim leading slash

try:
tried = exception.args[0]['tried']
except (IndexError, TypeError, KeyError):
tried = []
else:
if (not tried                           # empty URLconf
or (request.path == '/'
and len(tried) == 1             # default URLconf
and len(tried[0]) == 1
and getattr(tried[0][0], 'app_name', '') == getattr(tried[0][0], 'namespace', '') == 'admin')):
return default_urlconf(request)

urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
if isinstance(urlconf, types.ModuleType):
urlconf = urlconf.__name__

caller = ''
try:
resolver_match = resolve(request.path)
except Resolver404:
pass
else:
obj = resolver_match.func

if hasattr(obj, '__name__'):
caller = obj.__name__
elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'):
caller = obj.__class__.__name__

if hasattr(obj, '__module__'):
module = obj.__module__
caller = '%s.%s' % (module, caller)

t = DEBUG_ENGINE.from_string(TECHNICAL_404_TEMPLATE)
c = Context({
'urlconf': urlconf,
'root_urlconf': settings.ROOT_URLCONF,
'request_path': error_url,
'urlpatterns': tried,
'reason': force_bytes(exception, errors='replace'),
'request': request,
'settings': get_safe_settings(),
'raising_view_name': caller,
})
return HttpResponseNotFound(t.render(c), content_type='text/html')

def default_urlconf(request):
"Create an empty URLconf 404 error response."
t = DEBUG_ENGINE.from_string(DEFAULT_URLCONF_TEMPLATE)
c = Context({
"title": _("Welcome to Django"),
"heading": _("It worked!"),
"subheading": _("Congratulations on your first Django-powered page."),
"instructions": _("Of course, you haven't actually done any work yet. "
"Next, start your first app by running <code>python manage.py startapp [app_label]</code>."),
"explanation": _("You're seeing this message because you have <code>DEBUG = True</code> in your "
"Django settings file and you haven't configured any URLs. Get to work!"),
})

return HttpResponse(t.render(c), content_type='text/html')

#
# Templates are embedded in the file so that we know the error handler will
# always work even if the template loader is broken.
#

TECHNICAL_500_TEMPLATE = ("""
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE">
<title>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}"""
"""{% if request %} at {{ request.path_info|escape }}{% endif %}</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; }
h2 { margin-bottom:.8em; }
h2 span { font-size:80%; color:#666; font-weight:normal; }
h3 { margin:1em 0 .5em 0; }
h4 { margin:0 0 .5em 0; font-weight: normal; }
code, pre { font-size: 100%; white-space: pre-wrap; }
table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
tbody td, tbody th { vertical-align:top; padding:2px 3px; }
thead th {
padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
font-weight:normal; font-size:11px; border:1px solid #ddd;
}
tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
table.vars { margin:5px 0 2px 40px; }
table.vars td, table.req td { font-family:monospace; }
table td.code { width:100%; }
table td.code pre { overflow:hidden; }
table.source th { color:#666; }
table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
ul.traceback { list-style-type:none; color: #222; }
ul.traceback li.frame { padding-bottom:1em; color:#666; }
ul.traceback li.user { background-color:#e0e0e0; color:#000 }
div.context { padding:10px 0; overflow:hidden; }
div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
div.context ol li { font-family:monospace; white-space:pre; color:#777; cursor:pointer; padding-left: 2px; }
div.context ol li pre { display:inline; }
div.context ol.context-line li { color:#505050; background-color:#dfdfdf; padding: 3px 2px; }
div.context ol.context-line li span { position:absolute; right:32px; }
.user div.context ol.context-line li { background-color:#bbb; color:#000; }
.user div.context ol li { color:#666; }
div.commands { margin-left: 40px; }
div.commands a { color:#555; text-decoration:none; }
.user div.commands a { color: black; }
#summary { background: #ffc; }
#summary h2 { font-weight: normal; color: #666; }
#explanation { background:#eee; }
#template, #template-not-exist { background:#f6f6f6; }
#template-not-exist ul { margin: 0 0 10px 20px; }
#template-not-exist .postmortem-section { margin-bottom: 3px; }
#unicode-hint { background:#eee; }
#traceback { background:#eee; }
#requestinfo { background:#f6f6f6; padding-left:120px; }
#summary table { border:none; background:transparent; }
#requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
#requestinfo h3 { margin-bottom:-1em; }
.error { background: #ffc; }
.specific { color:#cc3300; font-weight:bold; }
h2 span.commands { font-size:.7em;}
span.commands a:link {color:#5E5694;}
pre.exception_value { font-family: sans-serif; color: #666; font-size: 1.5em; margin: 10px 0 10px 0; }
.append-bottom { margin-bottom: 10px; }
</style>
{% if not is_email %}
<script type="text/javascript">
//<!--
function getElementsByClassName(oElm, strTagName, strClassName){
// Written by Jonathan Snook, http://www.snook.ca/jon; Add-ons by Robert Nyman, http://www.robertnyman.com
var arrElements = (strTagName == "*" && document.all)? document.all :
oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName = strClassName.replace(/\-/g, "\\-");
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
var oElement;
for(var i=0; i<arrElements.length; i++){
oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}
function hideAll(elems) {
for (var e = 0; e < elems.length; e++) {
elems[e].style.display = 'none';
}
}
window.onload = function() {
hideAll(getElementsByClassName(document, 'table', 'vars'));
hideAll(getElementsByClassName(document, 'ol', 'pre-context'));
hideAll(getElementsByClassName(document, 'ol', 'post-context'));
hideAll(getElementsByClassName(document, 'div', 'pastebin'));
}
function toggle() {
for (var i = 0; i < arguments.length; i++) {
var e = document.getElementById(arguments[i]);
if (e) {
e.style.display = e.style.display == 'none' ? 'block': 'none';
}
}
return false;
}
function varToggle(link, id) {
toggle('v' + id);
var s = link.getElementsByTagName('span')[0];
var uarr = String.fromCharCode(0x25b6);
var darr = String.fromCharCode(0x25bc);
s.textContent = s.textContent == uarr ? darr : uarr;
return false;
}
function switchPastebinFriendly(link) {
s1 = "Switch to copy-and-paste view";
s2 = "Switch back to interactive view";
link.textContent = link.textContent.trim() == s1 ? s2: s1;
toggle('browserTraceback', 'pastebinTraceback');
return false;
}
//-->
</script>
{% endif %}
</head>
<body>
<div id="summary">
<h1>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}"""
"""{% if request %} at {{ request.path_info|escape }}{% endif %}</h1>
<pre class="exception_value">"""
"""{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}"""
"""</pre>
<table class="meta">
{% if request %}
<tr>
<th>Request Method:</th>
<td>{{ request.META.REQUEST_METHOD }}</td>
</tr>
<tr>
<th>Request URL:</th>
<td>{{ request.get_raw_uri|escape }}</td>
</tr>
{% endif %}
<tr>
<th>Django Version:</th>
<td>{{ django_version_info }}</td>
</tr>
{% if exception_type %}
<tr>
<th>Exception Type:</th>
<td>{{ exception_type }}</td>
</tr>
{% endif %}
{% if exception_type and exception_value %}
<tr>
<th>Exception Value:</th>
<td><pre>{{ exception_value|force_escape }}</pre></td>
</tr>
{% endif %}
{% if lastframe %}
<tr>
<th>Exception Location:</th>
<td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td>
</tr>
{% endif %}
<tr>
<th>Python Executable:</th>
<td>{{ sys_executable|escape }}</td>
</tr>
<tr>
<th>Python Version:</th>
<td>{{ sys_version_info }}</td>
</tr>
<tr>
<th>Python Path:</th>
<td><pre>{{ sys_path|pprint }}</pre></td>
</tr>
<tr>
<th>Server time:</th>
<td>{{server_time|date:"r"}}</td>
</tr>
</table>
</div>
{% if unicode_hint %}
<div id="unicode-hint">
<h2>Unicode error hint</h2>
<p>The string that could not be encoded/decoded was: <strong>{{ unicode_hint|force_escape }}</strong></p>
</div>
{% endif %}
{% if template_does_not_exist %}
<div id="template-not-exist">
<h2>Template-loader postmortem</h2>
{% if postmortem %}
<p class="append-bottom">Django tried loading these templates, in this order:</p>
{% for entry in postmortem %}
<p class="postmortem-section">Using engine <code>{{ entry.backend.name }}</code>:</p>
<ul>
{% if entry.tried %}
{% for attempt in entry.tried %}
<li><code>{{ attempt.0.loader_name }}</code>: {{ attempt.0.name }} ({{ attempt.1 }})</li>
{% endfor %}
{% else %}
<li>This engine did not provide a list of tried templates.</li>
{% endif %}
</ul>
{% endfor %}
{% else %}
<p>No templates were found because your 'TEMPLATES' setting is not configured.</p>
{% endif %}
</div>
{% endif %}
{% if template_info %}
<div id="template">
<h2>Error during template rendering</h2>
<p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p>
<h3>{{ template_info.message }}</h3>
<table class="source{% if template_info.top %} cut-top{% endif %}
{% if template_info.bottom != template_info.total %} cut-bottom{% endif %}">
{% for source_line in template_info.source_lines %}
{% if source_line.0 == template_info.line %}
<tr class="error"><th>{{ source_line.0 }}</th>
<td>{{ template_info.before }}"""
"""<span class="specific">{{ template_info.during }}</span>"""
"""{{ template_info.after }}</td>
</tr>
{% else %}
<tr><th>{{ source_line.0 }}</th>
<td>{{ source_line.1 }}</td></tr>
{% endif %}
{% endfor %}
</table>
</div>
{% endif %}
{% if frames %}
<div id="traceback">
<h2>Traceback <span class="commands">{% if not is_email %}<a href="#" onclick="return switchPastebinFriendly(this);">
Switch to copy-and-paste view</a></span>{% endif %}
</h2>
{% autoescape off %}
<div id="browserTraceback">
<ul class="traceback">
{% for frame in frames %}
{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}
<li><h3>
{% if frame.exc_cause_explicit %}
The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:
{% else %}
During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:
{% endif %}
</h3></li>
{% endif %}{% endifchanged %}
<li class="frame {{ frame.type }}">
<code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>

{% if frame.context_line %}
<div class="context" id="c{{ frame.id }}">
{% if frame.pre_context and not is_email %}
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">
{% for line in frame.pre_context %}
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ line|escape }}</pre></li>
{% endfor %}
</ol>
{% endif %}
<ol start="{{ frame.lineno }}" class="context-line">
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>
"""            """{{ frame.context_line|escape }}</pre>{% if not is_email %} <span>...</span>{% endif %}</li></ol>
{% if frame.post_context and not is_email  %}
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">
{% for line in frame.post_context %}
<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ line|escape }}</pre></li>
{% endfor %}
</ol>
{% endif %}
</div>
{% endif %}

{% if frame.vars %}
<div class="commands">
{% if is_email %}
<h2>Local Vars</h2>
{% else %}
<a href="#" onclick="return varToggle(this, '{{ frame.id }}')"><span>&#x25b6;</span> Local vars</a>
{% endif %}
</div>
<table class="vars" id="v{{ frame.id }}">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in frame.vars|dictsort:"0" %}
<tr>
<td>{{ var.0|force_escape }}</td>
<td class="code"><pre>{{ var.1 }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
{% endautoescape %}
<form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
{% if not is_email %}
<div id="pastebinTraceback" class="pastebin">
<input type="hidden" name="language" value="PythonConsole">
<input type="hidden" name="title"
value="{{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}">
<input type="hidden" name="source" value="Django Dpaste Agent">
<input type="hidden" name="poster" value="Django">
<textarea name="content" id="traceback_area" cols="140" rows="25">
Environment:

{% if request %}
Request Method: {{ request.META.REQUEST_METHOD }}
Request URL: {{ request.get_raw_uri|escape }}
{% endif %}
Django Version: {{ django_version_info }}
Python Version: {{ sys_version_info }}
Installed Applications:
{{ settings.INSTALLED_APPS|pprint }}
Installed Middleware:
{{ settings.MIDDLEWARE_CLASSES|pprint }}

{% if template_does_not_exist %}Template loader postmortem
{% if postmortem %}Django tried loading these templates, in this order:
{% for entry in postmortem %}
Using engine {{ entry.backend.name }}:
{% if entry.tried %}{% for attempt in entry.tried %}"""
"""    * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }})
{% endfor %}{% else %}    This engine did not provide a list of tried templates.
{% endif %}{% endfor %}
{% else %}No templates were found because your 'TEMPLATES' setting is not configured.
{% endif %}{% endif %}{% if template_info %}
Template error:
In template {{ template_info.name }}, error at line {{ template_info.line }}
{{ template_info.message }}"""
"{% for source_line in template_info.source_lines %}"
"{% if source_line.0 == template_info.line %}"
"   {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}"
"{% else %}"
"   {{ source_line.0 }} : {{ source_line.1 }}"
"""{% endif %}{% endfor %}{% endif %}

Traceback:{% for frame in frames %}
{% ifchanged frame.exc_cause %}{% if frame.exc_cause %}{% if frame.exc_cause_explicit %}
The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:
{% else %}
During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:
{% endif %}{% endif %}{% endifchanged %}
File "{{ frame.filename|escape }}" in {{ frame.function|escape }}
{% if frame.context_line %}  {{ frame.lineno }}. {{ frame.context_line|escape }}{% endif %}{% endfor %}

Exception Type: {{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}
Exception Value: {{ exception_value|force_escape }}
</textarea>
<br><br>
<input type="submit" value="Share this traceback on a public website">
</div>
</form>
</div>
{% endif %}
{% endif %}

<div id="requestinfo">
<h2>Request information</h2>

{% if request %}
<h3 id="get-info">GET</h3>
{% if request.GET %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in request.GET.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><pre>{{ var.1|pprint }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No GET data</p>
{% endif %}

<h3 id="post-info">POST</h3>
{% if filtered_POST %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in filtered_POST.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><pre>{{ var.1|pprint }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No POST data</p>
{% endif %}
<h3 id="files-info">FILES</h3>
{% if request.FILES %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in request.FILES.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><pre>{{ var.1|pprint }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No FILES data</p>
{% endif %}

<h3 id="cookie-info">COOKIES</h3>
{% if request.COOKIES %}
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in request.COOKIES.items %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><pre>{{ var.1|pprint }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No cookie data</p>
{% endif %}

<h3 id="meta-info">META</h3>
<table class="req">
<thead>
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in request.META.items|dictsort:"0" %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><pre>{{ var.1|pprint }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>Request data not supplied</p>
{% endif %}

<h3 id="settings-info">Settings</h3>
<h4>Using settings module <code>{{ settings.SETTINGS_MODULE }}</code></h4>
<table class="req">
<thead>
<tr>
<th>Setting</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{% for var in settings.items|dictsort:"0" %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><pre>{{ var.1|pprint }}</pre></td>
</tr>
{% endfor %}
</tbody>
</table>

</div>
{% if not is_email %}
<div id="explanation">
<p>
You're seeing this error because you have <code>DEBUG = True</code> in your
Django settings file. Change that to <code>False</code>, and Django will
display a standard page generated by the handler for this status code.
</p>
</div>
{% endif %}
</body>
</html>
""")

TECHNICAL_500_TEXT_TEMPLATE = (""""""
"""{% firstof exception_type 'Report' %}{% if request %} at {{ request.path_info }}{% endif %}
{% firstof exception_value 'No exception message supplied' %}
{% if request %}
Request Method: {{ request.META.REQUEST_METHOD }}
Request URL: {{ request.get_raw_uri }}{% endif %}
Django Version: {{ django_version_info }}
Python Executable: {{ sys_executable }}
Python Version: {{ sys_version_info }}
Python Path: {{ sys_path }}
Server time: {{server_time|date:"r"}}
Installed Applications:
{{ settings.INSTALLED_APPS|pprint }}
Installed Middleware:
{{ settings.MIDDLEWARE_CLASSES|pprint }}
{% if template_does_not_exist %}Template loader postmortem
{% if postmortem %}Django tried loading these templates, in this order:
{% for entry in postmortem %}
Using engine {{ entry.backend.name }}:
{% if entry.tried %}{% for attempt in entry.tried %}"""
"""    * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }})
{% endfor %}{% else %}    This engine did not provide a list of tried templates.
{% endif %}{% endfor %}
{% else %}No templates were found because your 'TEMPLATES' setting is not configured.
{% endif %}
{% endif %}{% if template_info %}
Template error:
In template {{ template_info.name }}, error at line {{ template_info.line }}
{{ template_info.message }}
{% for source_line in template_info.source_lines %}"""
"{% if source_line.0 == template_info.line %}"
"   {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}"
"{% else %}"
"   {{ source_line.0 }} : {{ source_line.1 }}"
"""{% endif %}{% endfor %}{% endif %}{% if frames %}

Traceback:"""
"{% for frame in frames %}"
"{% ifchanged frame.exc_cause %}"
"  {% if frame.exc_cause %}" """
{% if frame.exc_cause_explicit %}
The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:
{% else %}
During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:
{% endif %}
{% endif %}
{% endifchanged %}
File "{{ frame.filename }}" in {{ frame.function }}
{% if frame.context_line %}  {{ frame.lineno }}. {{ frame.context_line }}{% endif %}
{% endfor %}
{% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
{% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% endif %}{% endif %}
{% if request %}Request information:
GET:{% for k, v in request.GET.items %}
{{ k }} = {{ v|stringformat:"r" }}{% empty %} No GET data{% endfor %}

POST:{% for k, v in filtered_POST.items %}
{{ k }} = {{ v|stringformat:"r" }}{% empty %} No POST data{% endfor %}

FILES:{% for k, v in request.FILES.items %}
{{ k }} = {{ v|stringformat:"r" }}{% empty %} No FILES data{% endfor %}

COOKIES:{% for k, v in request.COOKIES.items %}
{{ k }} = {{ v|stringformat:"r" }}{% empty %} No cookie data{% endfor %}

META:{% for k, v in request.META.items|dictsort:"0" %}
{{ k }} = {{ v|stringformat:"r" }}{% endfor %}
{% else %}Request data not supplied
{% endif %}
Settings:
Using settings module {{ settings.SETTINGS_MODULE }}{% for k, v in settings.items|dictsort:"0" %}
{{ k }} = {{ v|stringformat:"r" }}{% endfor %}

{% if not is_email %}
You're seeing this error because you have DEBUG = True in your
Django settings file. Change that to False, and Django will
display a standard page generated by the handler for this status code.
{% endif %}
""")

TECHNICAL_404_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Page not found at {{ request.path_info|escape }}</title>
<meta name="robots" content="NONE,NOARCHIVE">
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; background:#eee; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; margin-bottom:.4em; }
h1 span { font-size:60%; color:#666; font-weight:normal; }
table { border:none; border-collapse: collapse; width:100%; }
td, th { vertical-align:top; padding:2px 3px; }
th { width:12em; text-align:right; color:#666; padding-right:.5em; }
#info { background:#f6f6f6; }
#info ol { margin: 0.5em 4em; }
#info ol li { font-family: monospace; }
#summary { background: #ffc; }
#explanation { background:#eee; border-bottom: 0px none; }
</style>
</head>
<body>
<div id="summary">
<h1>Page not found <span>(404)</span></h1>
<table class="meta">
<tr>
<th>Request Method:</th>
<td>{{ request.META.REQUEST_METHOD }}</td>
</tr>
<tr>
<th>Request URL:</th>
<td>{{ request.build_absolute_uri|escape }}</td>
</tr>
{% if raising_view_name %}
<tr>
<th>Raised by:</th>
<td>{{ raising_view_name }}</td>
</tr>
{% endif %}
</table>
</div>
<div id="info">
{% if urlpatterns %}
<p>
Using the URLconf defined in <code>{{ urlconf }}</code>,
Django tried these URL patterns, in this order:
</p>
<ol>
{% for pattern in urlpatterns %}
<li>
{% for pat in pattern %}
{{ pat.regex.pattern }}
{% if forloop.last and pat.name %}[name='{{ pat.name }}']{% endif %}
{% endfor %}
</li>
{% endfor %}
</ol>
<p>The current URL, <code>{{ request_path|escape }}</code>, didn't match any of these.</p>
{% else %}
<p>{{ reason }}</p>
{% endif %}
</div>

<div id="explanation">
<p>
You're seeing this error because you have <code>DEBUG = True</code> in
your Django settings file. Change that to <code>False</code>, and Django
will display a standard 404 page.
</p>
</div>
</body>
</html>
"""

DEFAULT_URLCONF_TEMPLATE = """
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE"><title>{{ title }}</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; }
h2 { margin-bottom:.8em; }
h2 span { font-size:80%; color:#666; font-weight:normal; }
h3 { margin:1em 0 .5em 0; }
h4 { margin:0 0 .5em 0; font-weight: normal; }
table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
tbody td, tbody th { vertical-align:top; padding:2px 3px; }
thead th {
padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
font-weight:normal; font-size:11px; border:1px solid #ddd;
}
tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
#summary { background: #e0ebff; }
#summary h2 { font-weight: normal; color: #666; }
#explanation { background:#eee; }
#instructions { background:#f6f6f6; }
#summary table { border:none; background:transparent; }
</style>
</head>

<body>
<div id="summary">
<h1>{{ heading }}</h1>
<h2>{{ subheading }}</h2>
</div>

<div id="instructions">
<p>
{{ instructions|safe }}
</p>
</div>

<div id="explanation">
<p>
{{ explanation|safe }}
</p>
</div>
</body></html>
"""

Source code for django.views.static

"""
Views and functions for serving static files. These are only to be used
during development, and SHOULD NOT be used in a production setting.
"""
from __future__ import unicode_literals

import mimetypes
import os
import posixpath
import re
import stat

from django.http import (
FileResponse, Http404, HttpResponse, HttpResponseNotModified,
HttpResponseRedirect,
)
from django.template import Context, Engine, TemplateDoesNotExist, loader
from django.utils.http import http_date, parse_http_date
from django.utils.six.moves.urllib.parse import unquote
from django.utils.translation import ugettext as _, ugettext_lazy

def serve(request, path, document_root=None, show_indexes=False):
"""
Serve static files below a given point in the directory structure.

To use, put a URL pattern such as::

from django.views.static import serve

url(r'^(?P<path>.*)$', serve, {'document_root': '/path/to/my/files/'})

in your URLconf. You must provide the ``document_root`` param. You may
also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
of the directory.  This index view will use the template hardcoded below,
but if you'd like to override it, you can create a template called
``static/directory_index.html``.
"""
path = posixpath.normpath(unquote(path))
path = path.lstrip('/')
newpath = ''
for part in path.split('/'):
if not part:
# Strip empty path components.
continue
drive, part = os.path.splitdrive(part)
head, part = os.path.split(part)
if part in (os.curdir, os.pardir):
# Strip '.' and '..' in path.
continue
newpath = os.path.join(newpath, part).replace('\\', '/')
if newpath and path != newpath:
return HttpResponseRedirect(newpath)
fullpath = os.path.join(document_root, newpath)
if os.path.isdir(fullpath):
if show_indexes:
return directory_index(newpath, fullpath)
raise Http404(_("Directory indexes are not allowed here."))
if not os.path.exists(fullpath):
raise Http404(_('"%(path)s" does not exist') % {'path': fullpath})
# Respect the If-Modified-Since header.
statobj = os.stat(fullpath)
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
statobj.st_mtime, statobj.st_size):
return HttpResponseNotModified()
content_type, encoding = mimetypes.guess_type(fullpath)
content_type = content_type or 'application/octet-stream'
response = FileResponse(open(fullpath, 'rb'), content_type=content_type)
response["Last-Modified"] = http_date(statobj.st_mtime)
if stat.S_ISREG(statobj.st_mode):
response["Content-Length"] = statobj.st_size
if encoding:
response["Content-Encoding"] = encoding
return response

DEFAULT_DIRECTORY_INDEX_TEMPLATE = """
{% load i18n %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en-us" />
<meta name="robots" content="NONE,NOARCHIVE" />
<title>{% blocktrans %}Index of {{ directory }}{% endblocktrans %}</title>
</head>
<body>
<h1>{% blocktrans %}Index of {{ directory }}{% endblocktrans %}</h1>
<ul>
{% if directory != "/" %}
<li><a href="../">../</a></li>
{% endif %}
{% for f in file_list %}
<li><a href="{{ f|urlencode }}">{{ f }}</a></li>
{% endfor %}
</ul>
</body>
</html>
"""
template_translatable = ugettext_lazy("Index of %(directory)s")

def directory_index(path, fullpath):
try:
t = loader.select_template([
'static/directory_index.html',
'static/directory_index',
])
except TemplateDoesNotExist:
t = Engine().from_string(DEFAULT_DIRECTORY_INDEX_TEMPLATE)
files = []
for f in os.listdir(fullpath):
if not f.startswith('.'):
if os.path.isdir(os.path.join(fullpath, f)):
f += '/'
files.append(f)
c = Context({
'directory': path + '/',
'file_list': files,
})
return HttpResponse(t.render(c))

def was_modified_since(header=None, mtime=0, size=0):
"""
Was something modified since the user last downloaded it?

header
This is the value of the If-Modified-Since header.  If this is None,
I'll just return True.

mtime
This is the modification time of the item we're talking about.

size
This is the size of the item we're talking about.
"""
try:
if header is None:
raise ValueError
matches = re.match(r"^([^;]+)(; length=([0-9]+))?$", header,
re.IGNORECASE)
header_mtime = parse_http_date(matches.group(1))
header_len = matches.group(3)
if header_len and int(header_len) != size:
raise ValueError
if int(mtime) > header_mtime:
raise ValueError
except (AttributeError, ValueError, OverflowError):
return True
return False

Source code for django.views.decorators.csrf

from functools import wraps

from django.middleware.csrf import CsrfViewMiddleware, get_token
from django.utils.decorators import available_attrs, decorator_from_middleware

csrf_protect = decorator_from_middleware(CsrfViewMiddleware)
csrf_protect.__name__ = "csrf_protect"
csrf_protect.__doc__ = """
This decorator adds CSRF protection in exactly the same way as
CsrfViewMiddleware, but it can be used on a per view basis.  Using both, or
using the decorator multiple times, is harmless and efficient.
"""

class _EnsureCsrfToken(CsrfViewMiddleware):
# We need this to behave just like the CsrfViewMiddleware, but not reject
# requests or log warnings.
def _reject(self, request, reason):
return None

requires_csrf_token = decorator_from_middleware(_EnsureCsrfToken)
requires_csrf_token.__name__ = 'requires_csrf_token'
requires_csrf_token.__doc__ = """
Use this decorator on views that need a correct csrf_token available to
RequestContext, but without the CSRF protection that csrf_protect
enforces.
"""

class _EnsureCsrfCookie(CsrfViewMiddleware):
def _reject(self, request, reason):
return None

def process_view(self, request, callback, callback_args, callback_kwargs):
retval = super(_EnsureCsrfCookie, self).process_view(request, callback, callback_args, callback_kwargs)
# Forces process_response to send the cookie
get_token(request)
return retval

ensure_csrf_cookie = decorator_from_middleware(_EnsureCsrfCookie)
ensure_csrf_cookie.__name__ = 'ensure_csrf_cookie'
ensure_csrf_cookie.__doc__ = """
Use this decorator to ensure that a view sets a CSRF cookie, whether or not it
uses the csrf_token template tag, or the CsrfViewMiddleware is used.
"""

[docs]def csrf_exempt(view_func):
"""
Marks a view function as being exempt from the CSRF view protection.
"""
# We could just do view_func.csrf_exempt = True, but decorators
# are nicer if they don't have side-effects, so we return a new
# function.
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
wrapped_view.csrf_exempt = True
return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)

Source code for django.views.decorators.debug

import functools

from django.http import HttpRequest

[docs]def sensitive_variables(*variables):
"""
Indicates which variables used in the decorated function are sensitive, so
that those variables can later be treated in a special way, for example
by hiding them when logging unhandled exceptions.

Two forms are accepted:

* with specified variable names:

@sensitive_variables('user', 'password', 'credit_card')
def my_function(user):
password = user.pass_word
credit_card = user.credit_card_number
...

* without any specified variable names, in which case it is assumed that
all variables are considered sensitive:

@sensitive_variables()
def my_function()
...
"""
def decorator(func):
@functools.wraps(func)
def sensitive_variables_wrapper(*func_args, **func_kwargs):
if variables:
sensitive_variables_wrapper.sensitive_variables = variables
else:
sensitive_variables_wrapper.sensitive_variables = '__ALL__'
return func(*func_args, **func_kwargs)
return sensitive_variables_wrapper
return decorator

[docs]def sensitive_post_parameters(*parameters):
"""
Indicates which POST parameters used in the decorated view are sensitive,
so that those parameters can later be treated in a special way, for example
by hiding them when logging unhandled exceptions.

Two forms are accepted:

* with specified parameters:

@sensitive_post_parameters('password', 'credit_card')
def my_view(request):
pw = request.POST['password']
cc = request.POST['credit_card']
...

* without any specified parameters, in which case it is assumed that
all parameters are considered sensitive:

@sensitive_post_parameters()
def my_view(request)
...
"""
def decorator(view):
@functools.wraps(view)
def sensitive_post_parameters_wrapper(request, *args, **kwargs):
assert isinstance(request, HttpRequest), (
"sensitive_post_parameters didn't receive an HttpRequest. "
"If you are decorating a classmethod, be sure to use "
"@method_decorator."
)
if parameters:
request.sensitive_post_parameters = parameters
else:
request.sensitive_post_parameters = '__ALL__'
return view(request, *args, **kwargs)
return sensitive_post_parameters_wrapper
return decorator

Source code for django.views.decorators.http

"""
Decorators for views based on HTTP headers.
"""

import logging
from calendar import timegm
from functools import wraps

from django.http import HttpResponseNotAllowed
from django.middleware.http import ConditionalGetMiddleware
from django.utils.cache import get_conditional_response
from django.utils.decorators import available_attrs, decorator_from_middleware
from django.utils.http import http_date, quote_etag

conditional_page = decorator_from_middleware(ConditionalGetMiddleware)

logger = logging.getLogger('django.request')

[docs]def require_http_methods(request_method_list):
"""
Decorator to make a view only accept particular request methods.  Usage::

@require_http_methods(["GET", "POST"])
def my_view(request):
# I can assume now that only GET or POST requests make it this far
# ...

Note that request methods should be in uppercase.
"""
def decorator(func):
@wraps(func, assigned=available_attrs(func))
def inner(request, *args, **kwargs):
if request.method not in request_method_list:
logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
extra={
'status_code': 405,
'request': request
}
)
return HttpResponseNotAllowed(request_method_list)
return func(request, *args, **kwargs)
return inner
return decorator

require_GET = require_http_methods(["GET"])
require_GET.__doc__ = "Decorator to require that a view only accepts the GET method."

require_POST = require_http_methods(["POST"])
require_POST.__doc__ = "Decorator to require that a view only accepts the POST method."

require_safe = require_http_methods(["GET", "HEAD"])
require_safe.__doc__ = "Decorator to require that a view only accepts safe methods: GET and HEAD."

[docs]def condition(etag_func=None, last_modified_func=None):
"""
Decorator to support conditional retrieval (or change) for a view
function.

The parameters are callables to compute the ETag and last modified time for
the requested resource, respectively. The callables are passed the same
parameters as the view itself. The Etag function should return a string (or
None if the resource doesn't exist), while the last_modified function
should return a datetime object (or None if the resource doesn't exist).

If both parameters are provided, all the preconditions must be met before
the view is processed.

This decorator will either pass control to the wrapped view function or
return an HTTP 304 response (unmodified) or 412 response (preconditions
failed), depending upon the request method.

Any behavior marked as "undefined" in the HTTP spec (e.g. If-none-match
plus If-modified-since headers) will result in the view function being
called.
"""
def decorator(func):
@wraps(func, assigned=available_attrs(func))
def inner(request, *args, **kwargs):
# Compute values (if any) for the requested resource.
def get_last_modified():
if last_modified_func:
dt = last_modified_func(request, *args, **kwargs)
if dt:
return timegm(dt.utctimetuple())

res_etag = etag_func(request, *args, **kwargs) if etag_func else None
res_last_modified = get_last_modified()

response = get_conditional_response(
request,
etag=res_etag,
last_modified=res_last_modified,
)

if response is None:
response = func(request, *args, **kwargs)

# Set relevant headers on the response if they don't already exist.
if res_last_modified and not response.has_header('Last-Modified'):
response['Last-Modified'] = http_date(res_last_modified)
if res_etag and not response.has_header('ETag'):
response['ETag'] = quote_etag(res_etag)

return response

return inner
return decorator

# Shortcut decorators for common cases based on ETag or Last-Modified only

[docs]def etag(etag_func):
return condition(etag_func=etag_func)

[docs]def last_modified(last_modified_func):
return condition(last_modified_func=last_modified_func)

Source code for django.views.decorators.cache

from functools import wraps

from django.middleware.cache import CacheMiddleware
from django.utils.cache import add_never_cache_headers, patch_cache_control
from django.utils.decorators import (
available_attrs, decorator_from_middleware_with_args,
)

def cache_page(*args, **kwargs):
"""
Decorator for views that tries getting the page from the cache and
populates the cache if the page isn't in the cache yet.

The cache is keyed by the URL and some data from the headers.
Additionally there is the key prefix that is used to distinguish different
cache areas in a multi-site setup. You could use the
get_current_site().domain, for example, as that is unique across a Django
project.

Additionally, all headers from the response's Vary header will be taken
into account on caching -- just like the middleware does.
"""
# We also add some asserts to give better error messages in case people are
# using other ways to call cache_page that no longer work.
if len(args) != 1 or callable(args[0]):
raise TypeError("cache_page has a single mandatory positional argument: timeout")
cache_timeout = args[0]
cache_alias = kwargs.pop('cache', None)
key_prefix = kwargs.pop('key_prefix', None)
if kwargs:
raise TypeError("cache_page has two optional keyword arguments: cache and key_prefix")

return decorator_from_middleware_with_args(CacheMiddleware)(
cache_timeout=cache_timeout, cache_alias=cache_alias, key_prefix=key_prefix
)

def cache_control(**kwargs):
def _cache_controller(viewfunc):
@wraps(viewfunc, assigned=available_attrs(viewfunc))
def _cache_controlled(request, *args, **kw):
response = viewfunc(request, *args, **kw)
patch_cache_control(response, **kwargs)
return response
return _cache_controlled
return _cache_controller

[docs]def never_cache(view_func):
"""
Decorator that adds headers to a response so that it will
never be cached.
"""
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view_func(request, *args, **kwargs):
response = view_func(request, *args, **kwargs)
add_never_cache_headers(response)
return response
return _wrapped_view_func

Source code for django.views.decorators.vary

from functools import wraps

from django.utils.cache import patch_vary_headers
from django.utils.decorators import available_attrs

[docs]def vary_on_headers(*headers):
"""
A view decorator that adds the specified headers to the Vary header of the
response. Usage:

@vary_on_headers('Cookie', 'Accept-language')
def index(request):
...

Note that the header names are not case-sensitive.
"""
def decorator(func):
@wraps(func, assigned=available_attrs(func))
def inner_func(*args, **kwargs):
response = func(*args, **kwargs)
patch_vary_headers(response, headers)
return response
return inner_func
return decorator

[docs]def vary_on_cookie(func):
"""
A view decorator that adds "Cookie" to the Vary header of a response. This
indicates that a page's contents depends on cookies. Usage:

@vary_on_cookie
def index(request):
...
"""
@wraps(func, assigned=available_attrs(func))
def inner_func(*args, **kwargs):
response = func(*args, **kwargs)
patch_vary_headers(response, ('Cookie',))
return response
return inner_func

Source code for django.views.generic.dates

from __future__ import unicode_literals

import datetime

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db import models
from django.http import Http404
from django.utils import timezone
from django.utils.encoding import force_str, force_text
from django.utils.functional import cached_property
from django.utils.translation import ugettext as _
from django.views.generic.base import View
from django.views.generic.detail import (
BaseDetailView, SingleObjectTemplateResponseMixin,
)
from django.views.generic.list import (
MultipleObjectMixin, MultipleObjectTemplateResponseMixin,
)

[docs]class YearMixin(object):
"""
Mixin for views manipulating year-based data.
"""
year_format = '%Y'
year = None

[docs]    def get_year_format(self):
"""
Get a year format string in strptime syntax to be used to parse the
year from url variables.
"""
return self.year_format

[docs]    def get_year(self):
"""
Return the year for which this view should display data.
"""
year = self.year
if year is None:
try:
year = self.kwargs['year']
except KeyError:
try:
year = self.request.GET['year']
except KeyError:
raise Http404(_("No year specified"))
return year

[docs]    def get_next_year(self, date):
"""
Get the next valid year.
"""
return _get_next_prev(self, date, is_previous=False, period='year')

[docs]    def get_previous_year(self, date):
"""
Get the previous valid year.
"""
return _get_next_prev(self, date, is_previous=True, period='year')

def _get_next_year(self, date):
"""
Return the start date of the next interval.

The interval is defined by start date <= item date < next start date.
"""
return date.replace(year=date.year + 1, month=1, day=1)

def _get_current_year(self, date):
"""
Return the start date of the current interval.
"""
return date.replace(month=1, day=1)

[docs]class MonthMixin(object):
"""
Mixin for views manipulating month-based data.
"""
month_format = '%b'
month = None

[docs]    def get_month_format(self):
"""
Get a month format string in strptime syntax to be used to parse the
month from url variables.
"""
return self.month_format

[docs]    def get_month(self):
"""
Return the month for which this view should display data.
"""
month = self.month
if month is None:
try:
month = self.kwargs['month']
except KeyError:
try:
month = self.request.GET['month']
except KeyError:
raise Http404(_("No month specified"))
return month

[docs]    def get_next_month(self, date):
"""
Get the next valid month.
"""
return _get_next_prev(self, date, is_previous=False, period='month')

[docs]    def get_previous_month(self, date):
"""
Get the previous valid month.
"""
return _get_next_prev(self, date, is_previous=True, period='month')

def _get_next_month(self, date):
"""
Return the start date of the next interval.

The interval is defined by start date <= item date < next start date.
"""
if date.month == 12:
return date.replace(year=date.year + 1, month=1, day=1)
else:
return date.replace(month=date.month + 1, day=1)

def _get_current_month(self, date):
"""
Return the start date of the previous interval.
"""
return date.replace(day=1)

[docs]class DayMixin(object):
"""
Mixin for views manipulating day-based data.
"""
day_format = '%d'
day = None

[docs]    def get_day_format(self):
"""
Get a day format string in strptime syntax to be used to parse the day
from url variables.
"""
return self.day_format

[docs]    def get_day(self):
"""
Return the day for which this view should display data.
"""
day = self.day
if day is None:
try:
day = self.kwargs['day']
except KeyError:
try:
day = self.request.GET['day']
except KeyError:
raise Http404(_("No day specified"))
return day

[docs]    def get_next_day(self, date):
"""
Get the next valid day.
"""
return _get_next_prev(self, date, is_previous=False, period='day')

[docs]    def get_previous_day(self, date):
"""
Get the previous valid day.
"""
return _get_next_prev(self, date, is_previous=True, period='day')

def _get_next_day(self, date):
"""
Return the start date of the next interval.

The interval is defined by start date <= item date < next start date.
"""
return date + datetime.timedelta(days=1)

def _get_current_day(self, date):
"""
Return the start date of the current interval.
"""
return date

[docs]class WeekMixin(object):
"""
Mixin for views manipulating week-based data.
"""
week_format = '%U'
week = None

[docs]    def get_week_format(self):
"""
Get a week format string in strptime syntax to be used to parse the
week from url variables.
"""
return self.week_format

[docs]    def get_week(self):
"""
Return the week for which this view should display data
"""
week = self.week
if week is None:
try:
week = self.kwargs['week']
except KeyError:
try:
week = self.request.GET['week']
except KeyError:
raise Http404(_("No week specified"))
return week

[docs]    def get_next_week(self, date):
"""
Get the next valid week.
"""
return _get_next_prev(self, date, is_previous=False, period='week')

def get_previous_week(self, date):
"""
Get the previous valid week.
"""
return _get_next_prev(self, date, is_previous=True, period='week')

def _get_next_week(self, date):
"""
Return the start date of the next interval.

The interval is defined by start date <= item date < next start date.
"""
return date + datetime.timedelta(days=7 - self._get_weekday(date))

def _get_current_week(self, date):
"""
Return the start date of the current interval.
"""
return date - datetime.timedelta(self._get_weekday(date))

def _get_weekday(self, date):
"""
Return the weekday for a given date.

The first day according to the week format is 0 and the last day is 6.
"""
week_format = self.get_week_format()
if week_format == '%W':                 # week starts on Monday
return date.weekday()
elif week_format == '%U':               # week starts on Sunday
return (date.weekday() + 1) % 7
else:
raise ValueError("unknown week format: %s" % week_format)

[docs]class DateMixin(object):
"""
Mixin class for views manipulating date-based data.
"""
date_field = None
allow_future = False

[docs]    def get_date_field(self):
"""
Get the name of the date field to be used to filter by.
"""
if self.date_field is None:
raise ImproperlyConfigured("%s.date_field is required." % self.__class__.__name__)
return self.date_field

[docs]    def get_allow_future(self):
"""
Returns `True` if the view should be allowed to display objects from
the future.
"""
return self.allow_future

# Note: the following three methods only work in subclasses that also
# inherit SingleObjectMixin or MultipleObjectMixin.

@cached_property
def uses_datetime_field(self):
"""
Return `True` if the date field is a `DateTimeField` and `False`
if it's a `DateField`.
"""
model = self.get_queryset().model if self.model is None else self.model
field = model._meta.get_field(self.get_date_field())
return isinstance(field, models.DateTimeField)

def _make_date_lookup_arg(self, value):
"""
Convert a date into a datetime when the date field is a DateTimeField.

When time zone support is enabled, `date` is assumed to be in the
current time zone, so that displayed items are consistent with the URL.
"""
if self.uses_datetime_field:
value = datetime.datetime.combine(value, datetime.time.min)
if settings.USE_TZ:
value = timezone.make_aware(value, timezone.get_current_timezone())
return value

def _make_single_date_lookup(self, date):
"""
Get the lookup kwargs for filtering on a single date.

If the date field is a DateTimeField, we can't just filter on
date_field=date because that doesn't take the time into account.
"""
date_field = self.get_date_field()
if self.uses_datetime_field:
since = self._make_date_lookup_arg(date)
until = self._make_date_lookup_arg(date + datetime.timedelta(days=1))
return {
'%s__gte' % date_field: since,
'%s__lt' % date_field: until,
}
else:
# Skip self._make_date_lookup_arg, it's a no-op in this branch.
return {date_field: date}

[docs]class BaseDateListView(MultipleObjectMixin, DateMixin, View):
"""
Abstract base class for date-based views displaying a list of objects.
"""
allow_empty = False
date_list_period = 'year'

def get(self, request, *args, **kwargs):
self.date_list, self.object_list, extra_context = self.get_dated_items()
context = self.get_context_data(object_list=self.object_list,
date_list=self.date_list)
context.update(extra_context)
return self.render_to_response(context)

[docs]    def get_dated_items(self):
"""
Obtain the list of dates and items.
"""
raise NotImplementedError('A DateView must provide an implementation of get_dated_items()')

def get_ordering(self):
"""
Returns the field or fields to use for ordering the queryset; uses the
date field by default.
"""
return '-%s' % self.get_date_field() if self.ordering is None else self.ordering

[docs]    def get_dated_queryset(self, **lookup):
"""
Get a queryset properly filtered according to `allow_future` and any
extra lookup kwargs.
"""
qs = self.get_queryset().filter(**lookup)
date_field = self.get_date_field()
allow_future = self.get_allow_future()
allow_empty = self.get_allow_empty()
paginate_by = self.get_paginate_by(qs)

if not allow_future:
now = timezone.now() if self.uses_datetime_field else timezone_today()
qs = qs.filter(**{'%s__lte' % date_field: now})

if not allow_empty:
# When pagination is enabled, it's better to do a cheap query
# than to load the unpaginated queryset in memory.
is_empty = len(qs) == 0 if paginate_by is None else not qs.exists()
if is_empty:
raise Http404(_("No %(verbose_name_plural)s available") % {
'verbose_name_plural': force_text(qs.model._meta.verbose_name_plural)
})

return qs

[docs]    def get_date_list_period(self):
"""
Get the aggregation period for the list of dates: 'year', 'month', or 'day'.
"""
return self.date_list_period

[docs]    def get_date_list(self, queryset, date_type=None, ordering='ASC'):
"""
Get a date list by calling `queryset.dates/datetimes()`, checking
along the way for empty lists that aren't allowed.
"""
date_field = self.get_date_field()
allow_empty = self.get_allow_empty()
if date_type is None:
date_type = self.get_date_list_period()

if self.uses_datetime_field:
date_list = queryset.datetimes(date_field, date_type, ordering)
else:
date_list = queryset.dates(date_field, date_type, ordering)
if date_list is not None and not date_list and not allow_empty:
name = force_text(queryset.model._meta.verbose_name_plural)
raise Http404(_("No %(verbose_name_plural)s available") %
{'verbose_name_plural': name})

return date_list

[docs]class BaseArchiveIndexView(BaseDateListView):
"""
Base class for archives of date-based items.

Requires a response mixin.
"""
context_object_name = 'latest'

def get_dated_items(self):
"""
Return (date_list, items, extra_context) for this request.
"""
qs = self.get_dated_queryset()
date_list = self.get_date_list(qs, ordering='DESC')

if not date_list:
qs = qs.none()

return (date_list, qs, {})

[docs]class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView):
"""
Top-level archive of date-based items.
"""
template_name_suffix = '_archive'

[docs]class BaseYearArchiveView(YearMixin, BaseDateListView):
"""
List of objects published in a given year.
"""
date_list_period = 'month'
make_object_list = False

def get_dated_items(self):
"""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year()

date_field = self.get_date_field()
date = _date_from_string(year, self.get_year_format())

since = self._make_date_lookup_arg(date)
until = self._make_date_lookup_arg(self._get_next_year(date))
lookup_kwargs = {
'%s__gte' % date_field: since,
'%s__lt' % date_field: until,
}

qs = self.get_dated_queryset(**lookup_kwargs)
date_list = self.get_date_list(qs)

if not self.get_make_object_list():
# We need this to be a queryset since parent classes introspect it
# to find information about the model.
qs = qs.none()

return (date_list, qs, {
'year': date,
'next_year': self.get_next_year(date),
'previous_year': self.get_previous_year(date),
})

def get_make_object_list(self):
"""
Return `True` if this view should contain the full list of objects in
the given year.
"""
return self.make_object_list

[docs]class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView):
"""
List of objects published in a given year.
"""
template_name_suffix = '_archive_year'

[docs]class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView):
"""
List of objects published in a given month.
"""
date_list_period = 'day'

def get_dated_items(self):
"""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year()
month = self.get_month()

date_field = self.get_date_field()
date = _date_from_string(year, self.get_year_format(),
month, self.get_month_format())

since = self._make_date_lookup_arg(date)
until = self._make_date_lookup_arg(self._get_next_month(date))
lookup_kwargs = {
'%s__gte' % date_field: since,
'%s__lt' % date_field: until,
}

qs = self.get_dated_queryset(**lookup_kwargs)
date_list = self.get_date_list(qs)

return (date_list, qs, {
'month': date,
'next_month': self.get_next_month(date),
'previous_month': self.get_previous_month(date),
})

[docs]class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView):
"""
List of objects published in a given month.
"""
template_name_suffix = '_archive_month'

[docs]class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
"""
List of objects published in a given week.
"""

def get_dated_items(self):
"""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year()
week = self.get_week()

date_field = self.get_date_field()
week_format = self.get_week_format()
week_start = {
'%W': '1',
'%U': '0',
}[week_format]
date = _date_from_string(year, self.get_year_format(),
week_start, '%w',
week, week_format)

since = self._make_date_lookup_arg(date)
until = self._make_date_lookup_arg(self._get_next_week(date))
lookup_kwargs = {
'%s__gte' % date_field: since,
'%s__lt' % date_field: until,
}

qs = self.get_dated_queryset(**lookup_kwargs)

return (None, qs, {
'week': date,
'next_week': self.get_next_week(date),
'previous_week': self.get_previous_week(date),
})

[docs]class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
"""
List of objects published in a given week.
"""
template_name_suffix = '_archive_week'

[docs]class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
"""
List of objects published on a given day.
"""
def get_dated_items(self):
"""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year()
month = self.get_month()
day = self.get_day()

date = _date_from_string(year, self.get_year_format(),
month, self.get_month_format(),
day, self.get_day_format())

return self._get_dated_items(date)

def _get_dated_items(self, date):
"""
Do the actual heavy lifting of getting the dated items; this accepts a
date object so that TodayArchiveView can be trivial.
"""
lookup_kwargs = self._make_single_date_lookup(date)
qs = self.get_dated_queryset(**lookup_kwargs)

return (None, qs, {
'day': date,
'previous_day': self.get_previous_day(date),
'next_day': self.get_next_day(date),
'previous_month': self.get_previous_month(date),
'next_month': self.get_next_month(date)
})

[docs]class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView):
"""
List of objects published on a given day.
"""
template_name_suffix = "_archive_day"

[docs]class BaseTodayArchiveView(BaseDayArchiveView):
"""
List of objects published today.
"""

def get_dated_items(self):
"""
Return (date_list, items, extra_context) for this request.
"""
return self._get_dated_items(datetime.date.today())

[docs]class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView):
"""
List of objects published today.
"""
template_name_suffix = "_archive_day"

[docs]class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView):
"""
Detail view of a single object on a single date; this differs from the
standard DetailView by accepting a year/month/day in the URL.
"""
def get_object(self, queryset=None):
"""
Get the object this request displays.
"""
year = self.get_year()
month = self.get_month()
day = self.get_day()
date = _date_from_string(year, self.get_year_format(),
month, self.get_month_format(),
day, self.get_day_format())

# Use a custom queryset if provided
qs = self.get_queryset() if queryset is None else queryset

if not self.get_allow_future() and date > datetime.date.today():
raise Http404(_(
"Future %(verbose_name_plural)s not available because "
"%(class_name)s.allow_future is False.") % {
'verbose_name_plural': qs.model._meta.verbose_name_plural,
'class_name': self.__class__.__name__,
},
)

# Filter down a queryset from self.queryset using the date from the
# URL. This'll get passed as the queryset to DetailView.get_object,
# which'll handle the 404
lookup_kwargs = self._make_single_date_lookup(date)
qs = qs.filter(**lookup_kwargs)

return super(BaseDetailView, self).get_object(queryset=qs)

[docs]class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView):
"""
Detail view of a single object on a single date; this differs from the
standard DetailView by accepting a year/month/day in the URL.
"""
template_name_suffix = '_detail'

def _date_from_string(year, year_format, month='', month_format='', day='', day_format='', delim='__'):
"""
Helper: get a datetime.date object given a format string and a year,
month, and day (only year is mandatory). Raise a 404 for an invalid date.
"""
format = delim.join((year_format, month_format, day_format))
datestr = delim.join((year, month, day))
try:
return datetime.datetime.strptime(force_str(datestr), format).date()
except ValueError:
raise Http404(_("Invalid date string '%(datestr)s' given format '%(format)s'") % {
'datestr': datestr,
'format': format,
})

def _get_next_prev(generic_view, date, is_previous, period):
"""
Helper: Get the next or the previous valid date. The idea is to allow
links on month/day views to never be 404s by never providing a date
that'll be invalid for the given view.

This is a bit complicated since it handles different intervals of time,
hence the coupling to generic_view.

However in essence the logic comes down to:

* If allow_empty and allow_future are both true, this is easy: just
return the naive result (just the next/previous day/week/month,
regardless of object existence.)

* If allow_empty is true, allow_future is false, and the naive result
isn't in the future, then return it; otherwise return None.

* If allow_empty is false and allow_future is true, return the next
date *that contains a valid object*, even if it's in the future. If
there are no next objects, return None.

* If allow_empty is false and allow_future is false, return the next
date that contains a valid object. If that date is in the future, or
if there are no next objects, return None.
"""
date_field = generic_view.get_date_field()
allow_empty = generic_view.get_allow_empty()
allow_future = generic_view.get_allow_future()

get_current = getattr(generic_view, '_get_current_%s' % period)
get_next = getattr(generic_view, '_get_next_%s' % period)

# Bounds of the current interval
start, end = get_current(date), get_next(date)

# If allow_empty is True, the naive result will be valid
if allow_empty:
if is_previous:
result = get_current(start - datetime.timedelta(days=1))
else:
result = end

if allow_future or result <= timezone_today():
return result
else:
return None

# Otherwise, we'll need to go to the database to look for an object
# whose date_field is at least (greater than/less than) the given
# naive result
else:
# Construct a lookup and an ordering depending on whether we're doing
# a previous date or a next date lookup.
if is_previous:
lookup = {'%s__lt' % date_field: generic_view._make_date_lookup_arg(start)}
ordering = '-%s' % date_field
else:
lookup = {'%s__gte' % date_field: generic_view._make_date_lookup_arg(end)}
ordering = date_field

# Filter out objects in the future if appropriate.
if not allow_future:
# Fortunately, to match the implementation of allow_future,
# we need __lte, which doesn't conflict with __lt above.
if generic_view.uses_datetime_field:
now = timezone.now()
else:
now = timezone_today()
lookup['%s__lte' % date_field] = now

qs = generic_view.get_queryset().filter(**lookup).order_by(ordering)

# Snag the first object from the queryset; if it doesn't exist that
# means there's no next/previous link available.
try:
result = getattr(qs[0], date_field)
except IndexError:
return None

# Convert datetimes to dates in the current time zone.
if generic_view.uses_datetime_field:
if settings.USE_TZ:
result = timezone.localtime(result)
result = result.date()

# Return the first day of the period.
return get_current(result)

def timezone_today():
"""
Return the current date in the current time zone.
"""
if settings.USE_TZ:
return timezone.localtime(timezone.now()).date()
else:
return datetime.date.today()

Source code for django.test.utils

import logging
import re
import sys
import time
import warnings
from contextlib import contextmanager
from functools import wraps
from unittest import skipIf, skipUnless
from xml.dom.minidom import Node, parseString

from django.apps import apps
from django.conf import UserSettingsHolder, settings
from django.core import mail
from django.core.signals import request_started
from django.core.urlresolvers import get_script_prefix, set_script_prefix
from django.db import reset_queries
from django.http import request
from django.template import Template
from django.test.signals import setting_changed, template_rendered
from django.utils import six
from django.utils.decorators import ContextDecorator
from django.utils.encoding import force_str
from django.utils.translation import deactivate

try:
import jinja2
except ImportError:
jinja2 = None

__all__ = (
'Approximate', 'ContextList', 'isolate_lru_cache', 'get_runner',
'modify_settings', 'override_settings',
'requires_tz_support',
'setup_test_environment', 'teardown_test_environment',
)

TZ_SUPPORT = hasattr(time, 'tzset')

class Approximate(object):
def __init__(self, val, places=7):
self.val = val
self.places = places

def __repr__(self):
return repr(self.val)

def __eq__(self, other):
if self.val == other:
return True
return round(abs(self.val - other), self.places) == 0

class ContextList(list):
"""A wrapper that provides direct key access to context items contained
in a list of context objects.
"""
def __getitem__(self, key):
if isinstance(key, six.string_types):
for subcontext in self:
if key in subcontext:
return subcontext[key]
raise KeyError(key)
else:
return super(ContextList, self).__getitem__(key)

def __contains__(self, key):
try:
self[key]
except KeyError:
return False
return True

def keys(self):
"""
Flattened keys of subcontexts.
"""
keys = set()
for subcontext in self:
for dict in subcontext:
keys |= set(dict.keys())
return keys

def instrumented_test_render(self, context):
"""
An instrumented Template render method, providing a signal
that can be intercepted by the test system Client
"""
template_rendered.send(sender=self, template=self, context=context)
return self.nodelist.render(context)

[docs]def setup_test_environment():
"""Perform any global pre-test setup. This involves:

- Installing the instrumented test renderer
- Set the email backend to the locmem email backend.
- Setting the active locale to match the LANGUAGE_CODE setting.
"""
Template._original_render = Template._render
Template._render = instrumented_test_render

# Storing previous values in the settings module itself is problematic.
# Store them in arbitrary (but related) modules instead. See #20636.

mail._original_email_backend = settings.EMAIL_BACKEND
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'

request._original_allowed_hosts = settings.ALLOWED_HOSTS
settings.ALLOWED_HOSTS = ['*']

mail.outbox = []

deactivate()

[docs]def teardown_test_environment():
"""Perform any global post-test teardown. This involves:

- Restoring the original test renderer
- Restoring the email sending functions
"""
Template._render = Template._original_render
del Template._original_render

settings.EMAIL_BACKEND = mail._original_email_backend
del mail._original_email_backend

settings.ALLOWED_HOSTS = request._original_allowed_hosts
del request._original_allowed_hosts

del mail.outbox

def get_runner(settings, test_runner_class=None):
if not test_runner_class:
test_runner_class = settings.TEST_RUNNER

test_path = test_runner_class.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
test_module_name = '.'.join(test_path[:-1])
else:
test_module_name = '.'
test_module = __import__(test_module_name, {}, {}, force_str(test_path[-1]))
test_runner = getattr(test_module, test_path[-1])
return test_runner

[docs]class override_settings(object):
"""
Acts as either a decorator, or a context manager. If it's a decorator it
takes a function and returns a wrapped function. If it's a contextmanager
it's used with the ``with`` statement. In either event entering/exiting
are called before and after, respectively, the function/block is executed.
"""
def __init__(self, **kwargs):
self.options = kwargs

def __enter__(self):
self.enable()

def __exit__(self, exc_type, exc_value, traceback):
self.disable()

def __call__(self, test_func):
from django.test import SimpleTestCase
if isinstance(test_func, type):
if not issubclass(test_func, SimpleTestCase):
raise Exception(
"Only subclasses of Django SimpleTestCase can be decorated "
"with override_settings")
self.save_options(test_func)
return test_func
else:
@wraps(test_func)
def inner(*args, **kwargs):
with self:
return test_func(*args, **kwargs)
return inner

def save_options(self, test_func):
if test_func._overridden_settings is None:
test_func._overridden_settings = self.options
else:
# Duplicate dict to prevent subclasses from altering their parent.
test_func._overridden_settings = dict(
test_func._overridden_settings, **self.options)

def enable(self):
# Keep this code at the beginning to leave the settings unchanged
# in case it raises an exception because INSTALLED_APPS is invalid.
if 'INSTALLED_APPS' in self.options:
try:
apps.set_installed_apps(self.options['INSTALLED_APPS'])
except Exception:
apps.unset_installed_apps()
raise
override = UserSettingsHolder(settings._wrapped)
for key, new_value in self.options.items():
setattr(override, key, new_value)
self.wrapped = settings._wrapped
settings._wrapped = override
for key, new_value in self.options.items():
setting_changed.send(sender=settings._wrapped.__class__,
setting=key, value=new_value, enter=True)

def disable(self):
if 'INSTALLED_APPS' in self.options:
apps.unset_installed_apps()
settings._wrapped = self.wrapped
del self.wrapped
for key in self.options:
new_value = getattr(settings, key, None)
setting_changed.send(sender=settings._wrapped.__class__,
setting=key, value=new_value, enter=False)

[docs]class modify_settings(override_settings):
"""
Like override_settings, but makes it possible to append, prepend or remove
items instead of redefining the entire list.
"""
def __init__(self, *args, **kwargs):
if args:
# Hack used when instantiating from SimpleTestCase.setUpClass.
assert not kwargs
self.operations = args[0]
else:
assert not args
self.operations = list(kwargs.items())

def save_options(self, test_func):
if test_func._modified_settings is None:
test_func._modified_settings = self.operations
else:
# Duplicate list to prevent subclasses from altering their parent.
test_func._modified_settings = list(
test_func._modified_settings) + self.operations

def enable(self):
self.options = {}
for name, operations in self.operations:
try:
# When called from SimpleTestCase.setUpClass, values may be
# overridden several times; cumulate changes.
value = self.options[name]
except KeyError:
value = list(getattr(settings, name, []))
for action, items in operations.items():
# items my be a single value or an iterable.
if isinstance(items, six.string_types):
items = [items]
if action == 'append':
value = value + [item for item in items if item not in value]
elif action == 'prepend':
value = [item for item in items if item not in value] + value
elif action == 'remove':
value = [item for item in value if item not in items]
else:
raise ValueError("Unsupported action: %s" % action)
self.options[name] = value
super(modify_settings, self).enable()

def override_system_checks(new_checks, deployment_checks=None):
""" Acts as a decorator. Overrides list of registered system checks.
Useful when you override `INSTALLED_APPS`, e.g. if you exclude `auth` app,
you also need to exclude its system checks. """

from django.core.checks.registry import registry

def outer(test_func):
@wraps(test_func)
def inner(*args, **kwargs):
old_checks = registry.registered_checks
registry.registered_checks = new_checks
old_deployment_checks = registry.deployment_checks
if deployment_checks is not None:
registry.deployment_checks = deployment_checks
try:
return test_func(*args, **kwargs)
finally:
registry.registered_checks = old_checks
registry.deployment_checks = old_deployment_checks
return inner
return outer

def compare_xml(want, got):
"""Tries to do a 'xml-comparison' of want and got.  Plain string
comparison doesn't always work because, for example, attribute
ordering should not be important. Comment nodes are not considered in the
comparison.

Based on https://github.com/lxml/lxml/blob/master/src/lxml/doctestcompare.py
"""
_norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')

def norm_whitespace(v):
return _norm_whitespace_re.sub(' ', v)

def child_text(element):
return ''.join(c.data for c in element.childNodes
if c.nodeType == Node.TEXT_NODE)

def children(element):
return [c for c in element.childNodes
if c.nodeType == Node.ELEMENT_NODE]

def norm_child_text(element):
return norm_whitespace(child_text(element))

def attrs_dict(element):
return dict(element.attributes.items())

def check_element(want_element, got_element):
if want_element.tagName != got_element.tagName:
return False
if norm_child_text(want_element) != norm_child_text(got_element):
return False
if attrs_dict(want_element) != attrs_dict(got_element):
return False
want_children = children(want_element)
got_children = children(got_element)
if len(want_children) != len(got_children):
return False
for want, got in zip(want_children, got_children):
if not check_element(want, got):
return False
return True

def first_node(document):
for node in document.childNodes:
if node.nodeType != Node.COMMENT_NODE:
return node

want, got = strip_quotes(want, got)
want = want.replace('\\n', '\n')
got = got.replace('\\n', '\n')

# If the string is not a complete xml document, we may need to add a
# root element. This allow us to compare fragments, like "<foo/><bar/>"
if not want.startswith('<?xml'):
wrapper = '<root>%s</root>'
want = wrapper % want
got = wrapper % got

# Parse the want and got strings, and compare the parsings.
want_root = first_node(parseString(want))
got_root = first_node(parseString(got))

return check_element(want_root, got_root)

def strip_quotes(want, got):
"""
Strip quotes of doctests output values:

>>> strip_quotes("'foo'")
"foo"
>>> strip_quotes('"foo"')
"foo"
"""
def is_quoted_string(s):
s = s.strip()
return (len(s) >= 2
and s[0] == s[-1]
and s[0] in ('"', "'"))

def is_quoted_unicode(s):
s = s.strip()
return (len(s) >= 3
and s[0] == 'u'
and s[1] == s[-1]
and s[1] in ('"', "'"))

if is_quoted_string(want) and is_quoted_string(got):
want = want.strip()[1:-1]
got = got.strip()[1:-1]
elif is_quoted_unicode(want) and is_quoted_unicode(got):
want = want.strip()[2:-1]
got = got.strip()[2:-1]
return want, got

def str_prefix(s):
return s % {'_': '' if six.PY3 else 'u'}

class CaptureQueriesContext(object):
"""
Context manager that captures queries executed by the specified connection.
"""
def __init__(self, connection):
self.connection = connection

def __iter__(self):
return iter(self.captured_queries)

def __getitem__(self, index):
return self.captured_queries[index]

def __len__(self):
return len(self.captured_queries)

@property
def captured_queries(self):
return self.connection.queries[self.initial_queries:self.final_queries]

def __enter__(self):
self.force_debug_cursor = self.connection.force_debug_cursor
self.connection.force_debug_cursor = True
self.initial_queries = len(self.connection.queries_log)
self.final_queries = None
request_started.disconnect(reset_queries)
return self

def __exit__(self, exc_type, exc_value, traceback):
self.connection.force_debug_cursor = self.force_debug_cursor
request_started.connect(reset_queries)
if exc_type is not None:
return
self.final_queries = len(self.connection.queries_log)

class ignore_warnings(object):
def __init__(self, **kwargs):
self.ignore_kwargs = kwargs
if 'message' in self.ignore_kwargs or 'module' in self.ignore_kwargs:
self.filter_func = warnings.filterwarnings
else:
self.filter_func = warnings.simplefilter

def __call__(self, decorated):
if isinstance(decorated, type):
# A class is decorated
saved_setUp = decorated.setUp
saved_tearDown = decorated.tearDown

def setUp(inner_self):
self.catch_warnings = warnings.catch_warnings()
self.catch_warnings.__enter__()
self.filter_func('ignore', **self.ignore_kwargs)
saved_setUp(inner_self)

def tearDown(inner_self):
saved_tearDown(inner_self)
self.catch_warnings.__exit__(*sys.exc_info())

decorated.setUp = setUp
decorated.tearDown = tearDown
return decorated
else:
@wraps(decorated)
def inner(*args, **kwargs):
with warnings.catch_warnings():
self.filter_func('ignore', **self.ignore_kwargs)
return decorated(*args, **kwargs)
return inner

@contextmanager
def patch_logger(logger_name, log_level):
"""
Context manager that takes a named logger and the logging level
and provides a simple mock-like list of messages received
"""
calls = []

def replacement(msg, *args, **kwargs):
calls.append(msg % args)
logger = logging.getLogger(logger_name)
orig = getattr(logger, log_level)
setattr(logger, log_level, replacement)
try:
yield calls
finally:
setattr(logger, log_level, orig)

# On OSes that don't provide tzset (Windows), we can't set the timezone
# in which the program runs. As a consequence, we must skip tests that
# don't enforce a specific timezone (with timezone.override or equivalent),
# or attempt to interpret naive datetimes in the default timezone.

requires_tz_support = skipUnless(TZ_SUPPORT,
"This test relies on the ability to run a program in an arbitrary "
"time zone, but your operating system isn't able to do that.")

@contextmanager
def extend_sys_path(*paths):
"""Context manager to temporarily add paths to sys.path."""
_orig_sys_path = sys.path[:]
sys.path.extend(paths)
try:
yield
finally:
sys.path = _orig_sys_path

@contextmanager
def isolate_lru_cache(lru_cache_object):
"""Clear the cache of an LRU cache object on entering and exiting."""
lru_cache_object.cache_clear()
try:
yield
finally:
lru_cache_object.cache_clear()

@contextmanager
def captured_output(stream_name):
"""Return a context manager used by captured_stdout/stdin/stderr
that temporarily replaces the sys stream *stream_name* with a StringIO.

Note: This function and the following ``captured_std*`` are copied
from CPython's ``test.support`` module."""
orig_stdout = getattr(sys, stream_name)
setattr(sys, stream_name, six.StringIO())
try:
yield getattr(sys, stream_name)
finally:
setattr(sys, stream_name, orig_stdout)

def captured_stdout():
"""Capture the output of sys.stdout:

with captured_stdout() as stdout:
print("hello")
self.assertEqual(stdout.getvalue(), "hello\n")
"""
return captured_output("stdout")

def captured_stderr():
"""Capture the output of sys.stderr:

with captured_stderr() as stderr:
print("hello", file=sys.stderr)
self.assertEqual(stderr.getvalue(), "hello\n")
"""
return captured_output("stderr")

def captured_stdin():
"""Capture the input to sys.stdin:

with captured_stdin() as stdin:
stdin.write('hello\n')
stdin.seek(0)
# call test code that consumes from sys.stdin
captured = input()
self.assertEqual(captured, "hello")
"""
return captured_output("stdin")

def reset_warning_registry():
"""
Clear warning registry for all modules. This is required in some tests
because of a bug in Python that prevents warnings.simplefilter("always")
from always making warnings appear: http://bugs.python.org/issue4180

The bug was fixed in Python 3.4.2.
"""
key = "__warningregistry__"
for mod in sys.modules.values():
if hasattr(mod, key):
getattr(mod, key).clear()

@contextmanager
def freeze_time(t):
"""
Context manager to temporarily freeze time.time(). This temporarily
modifies the time function of the time module. Modules which import the
time function directly (e.g. `from time import time`) won't be affected
This isn't meant as a public API, but helps reduce some repetitive code in
Django's test suite.
"""
_real_time = time.time
time.time = lambda: t
try:
yield
finally:
time.time = _real_time

def require_jinja2(test_func):
"""
Decorator to enable a Jinja2 template engine in addition to the regular
Django template engine for a test or skip it if Jinja2 isn't available.
"""
test_func = skipIf(jinja2 is None, "this test requires jinja2")(test_func)
test_func = override_settings(TEMPLATES=[{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
}, {
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'APP_DIRS': True,
'OPTIONS': {'keep_trailing_newline': True},
}])(test_func)
return test_func

class ScriptPrefix(ContextDecorator):
def __enter__(self):
set_script_prefix(self.prefix)

def __exit__(self, exc_type, exc_val, traceback):
set_script_prefix(self.old_prefix)

def __init__(self, prefix):
self.prefix = prefix
self.old_prefix = get_script_prefix()

def override_script_prefix(prefix):
"""
Decorator or context manager to temporary override the script prefix.
"""
return ScriptPrefix(prefix)

class LoggingCaptureMixin(object):
"""
Capture the output from the 'django' logger and store it on the class's
logger_output attribute.
"""
def setUp(self):
self.logger = logging.getLogger('django')
self.old_stream = self.logger.handlers[0].stream
self.logger_output = six.StringIO()
self.logger.handlers[0].stream = self.logger_output

def tearDown(self):
self.logger.handlers[0].stream = self.old_stream

Source code for django.test.testcases

from __future__ import unicode_literals

import difflib
import errno
import json
import os
import posixpath
import socket
import sys
import threading
import unittest
import warnings
from collections import Counter
from contextlib import contextmanager
from copy import copy
from functools import wraps
from unittest.util import safe_repr

from django.apps import apps
from django.conf import settings
from django.core import mail
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.core.files import locks
from django.core.handlers.wsgi import WSGIHandler, get_path_info
from django.core.management import call_command
from django.core.management.color import no_style
from django.core.management.sql import emit_post_migrate_signal
from django.core.servers.basehttp import WSGIRequestHandler, WSGIServer
from django.core.urlresolvers import clear_url_caches, set_urlconf
from django.db import DEFAULT_DB_ALIAS, connection, connections, transaction
from django.forms.fields import CharField
from django.http import QueryDict
from django.test.client import Client
from django.test.html import HTMLParseError, parse_html
from django.test.signals import setting_changed, template_rendered
from django.test.utils import (
CaptureQueriesContext, ContextList, compare_xml, modify_settings,
override_settings,
)
from django.utils import six
from django.utils.decorators import classproperty
from django.utils.deprecation import (
RemovedInDjango20Warning, RemovedInDjango110Warning,
)
from django.utils.encoding import force_text
from django.utils.six.moves.urllib.parse import (
unquote, urljoin, urlparse, urlsplit, urlunsplit,
)
from django.utils.six.moves.urllib.request import url2pathname
from django.views.static import serve

__all__ = ('TestCase', 'TransactionTestCase',
'SimpleTestCase', 'skipIfDBFeature', 'skipUnlessDBFeature')

def to_list(value):
"""
Puts value into a list if it's not already one.
Returns an empty list if value is None.
"""
if value is None:
value = []
elif not isinstance(value, list):
value = [value]
return value

def assert_and_parse_html(self, html, user_msg, msg):
try:
dom = parse_html(html)
except HTMLParseError as e:
standardMsg = '%s\n%s' % (msg, e.msg)
self.fail(self._formatMessage(user_msg, standardMsg))
return dom

class _AssertNumQueriesContext(CaptureQueriesContext):
def __init__(self, test_case, num, connection):
self.test_case = test_case
self.num = num
super(_AssertNumQueriesContext, self).__init__(connection)

def __exit__(self, exc_type, exc_value, traceback):
super(_AssertNumQueriesContext, self).__exit__(exc_type, exc_value, traceback)
if exc_type is not None:
return
executed = len(self)
self.test_case.assertEqual(
executed, self.num,
"%d queries executed, %d expected\nCaptured queries were:\n%s" % (
executed, self.num,
'\n'.join(
query['sql'] for query in self.captured_queries
)
)
)

class _AssertTemplateUsedContext(object):
def __init__(self, test_case, template_name):
self.test_case = test_case
self.template_name = template_name
self.rendered_templates = []
self.rendered_template_names = []
self.context = ContextList()

def on_template_render(self, sender, signal, template, context, **kwargs):
self.rendered_templates.append(template)
self.rendered_template_names.append(template.name)
self.context.append(copy(context))

def test(self):
return self.template_name in self.rendered_template_names

def message(self):
return '%s was not rendered.' % self.template_name

def __enter__(self):
template_rendered.connect(self.on_template_render)
return self

def __exit__(self, exc_type, exc_value, traceback):
template_rendered.disconnect(self.on_template_render)
if exc_type is not None:
return

if not self.test():
message = self.message()
if len(self.rendered_templates) == 0:
message += ' No template was rendered.'
else:
message += ' Following templates were rendered: %s' % (
', '.join(self.rendered_template_names))
self.test_case.fail(message)

class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext):
def test(self):
return self.template_name not in self.rendered_template_names

def message(self):
return '%s was rendered.' % self.template_name

class _CursorFailure(object):
def __init__(self, cls_name, wrapped):
self.cls_name = cls_name
self.wrapped = wrapped

def __call__(self):
raise AssertionError(
"Database queries aren't allowed in SimpleTestCase. "
"Either use TestCase or TransactionTestCase to ensure proper test isolation or "
"set %s.allow_database_queries to True to silence this failure." % self.cls_name
)

[docs]class SimpleTestCase(unittest.TestCase):

# The class we'll use for the test client self.client.
# Can be overridden in derived classes.
client_class = Client
_overridden_settings = None
_modified_settings = None

# Tests shouldn't be allowed to query the database since
# this base class doesn't enforce any isolation.
allow_database_queries = False

@classmethod
def setUpClass(cls):
super(SimpleTestCase, cls).setUpClass()
if cls._overridden_settings:
cls._cls_overridden_context = override_settings(**cls._overridden_settings)
cls._cls_overridden_context.enable()
if cls._modified_settings:
cls._cls_modified_context = modify_settings(cls._modified_settings)
cls._cls_modified_context.enable()
if not cls.allow_database_queries:
for alias in connections:
connection = connections[alias]
connection.cursor = _CursorFailure(cls.__name__, connection.cursor)

@classmethod
def tearDownClass(cls):
if not cls.allow_database_queries:
for alias in connections:
connection = connections[alias]
connection.cursor = connection.cursor.wrapped
if hasattr(cls, '_cls_modified_context'):
cls._cls_modified_context.disable()
delattr(cls, '_cls_modified_context')
if hasattr(cls, '_cls_overridden_context'):
cls._cls_overridden_context.disable()
delattr(cls, '_cls_overridden_context')
super(SimpleTestCase, cls).tearDownClass()

def __call__(self, result=None):
"""
Wrapper around default __call__ method to perform common Django test
set up. This means that user-defined Test Cases aren't required to
include a call to super().setUp().
"""
testMethod = getattr(self, self._testMethodName)
skipped = (getattr(self.__class__, "__unittest_skip__", False) or
getattr(testMethod, "__unittest_skip__", False))

if not skipped:
try:
self._pre_setup()
except Exception:
result.addError(self, sys.exc_info())
return
super(SimpleTestCase, self).__call__(result)
if not skipped:
try:
self._post_teardown()
except Exception:
result.addError(self, sys.exc_info())
return

def _pre_setup(self):
"""Performs any pre-test setup. This includes:

* Creating a test client.
* If the class has a 'urls' attribute, replace ROOT_URLCONF with it.
* Clearing the mail test outbox.
"""
self.client = self.client_class()
self._urlconf_setup()
mail.outbox = []

def _urlconf_setup(self):
if hasattr(self, 'urls'):
warnings.warn(
"SimpleTestCase.urls is deprecated and will be removed in "
"Django 1.10. Use @override_settings(ROOT_URLCONF=...) "
"in %s instead." % self.__class__.__name__,
RemovedInDjango110Warning, stacklevel=2)
set_urlconf(None)
self._old_root_urlconf = settings.ROOT_URLCONF
settings.ROOT_URLCONF = self.urls
clear_url_caches()

def _post_teardown(self):
"""Performs any post-test things. This includes:

* Putting back the original ROOT_URLCONF if it was changed.
"""
self._urlconf_teardown()

def _urlconf_teardown(self):
if hasattr(self, '_old_root_urlconf'):
set_urlconf(None)
settings.ROOT_URLCONF = self._old_root_urlconf
clear_url_caches()

[docs]    def settings(self, **kwargs):
"""
A context manager that temporarily sets a setting and reverts to the original value when exiting the context.
"""
return override_settings(**kwargs)

[docs]    def modify_settings(self, **kwargs):
"""
A context manager that temporarily applies changes a list setting and
reverts back to the original value when exiting the context.
"""
return modify_settings(**kwargs)

[docs]    def assertRedirects(self, response, expected_url, status_code=302,
target_status_code=200, host=None, msg_prefix='',
fetch_redirect_response=True):
"""Asserts that a response redirected to a specific URL, and that the
redirect URL can be loaded.

Note that assertRedirects won't work for external links since it uses
TestClient to do a request (use fetch_redirect_response=False to check
such links without fetching them).
"""
if host is not None:
warnings.warn(
"The host argument is deprecated and no longer used by assertRedirects",
RemovedInDjango20Warning, stacklevel=2
)

if msg_prefix:
msg_prefix += ": "

if hasattr(response, 'redirect_chain'):
# The request was a followed redirect
self.assertTrue(len(response.redirect_chain) > 0,
msg_prefix + "Response didn't redirect as expected: Response"
" code was %d (expected %d)" %
(response.status_code, status_code))

self.assertEqual(response.redirect_chain[0][1], status_code,
msg_prefix + "Initial response didn't redirect as expected:"
" Response code was %d (expected %d)" %
(response.redirect_chain[0][1], status_code))

url, status_code = response.redirect_chain[-1]
scheme, netloc, path, query, fragment = urlsplit(url)

self.assertEqual(response.status_code, target_status_code,
msg_prefix + "Response didn't redirect as expected: Final"
" Response code was %d (expected %d)" %
(response.status_code, target_status_code))

else:
# Not a followed redirect
self.assertEqual(response.status_code, status_code,
msg_prefix + "Response didn't redirect as expected: Response"
" code was %d (expected %d)" %
(response.status_code, status_code))

url = response.url
scheme, netloc, path, query, fragment = urlsplit(url)

# Prepend the request path to handle relative path redirects.
if not path.startswith('/'):
url = urljoin(response.request['PATH_INFO'], url)
path = urljoin(response.request['PATH_INFO'], path)

if fetch_redirect_response:
redirect_response = response.client.get(path, QueryDict(query),
secure=(scheme == 'https'))

# Get the redirection page, using the same client that was used
# to obtain the original response.
self.assertEqual(redirect_response.status_code, target_status_code,
msg_prefix + "Couldn't retrieve redirection page '%s':"
" response code was %d (expected %d)" %
(path, redirect_response.status_code, target_status_code))

if url != expected_url:
# For temporary backwards compatibility, try to compare with a relative url
e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url)
relative_url = urlunsplit(('', '', e_path, e_query, e_fragment))
if url == relative_url:
warnings.warn(
"assertRedirects had to strip the scheme and domain from the "
"expected URL, as it was always added automatically to URLs "
"before Django 1.9. Please update your expected URLs by "
"removing the scheme and domain.",
RemovedInDjango20Warning, stacklevel=2)
expected_url = relative_url

self.assertEqual(url, expected_url,
msg_prefix + "Response redirected to '%s', expected '%s'" %
(url, expected_url))

def _assert_contains(self, response, text, status_code, msg_prefix, html):
# If the response supports deferred rendering and hasn't been rendered
# yet, then ensure that it does get rendered before proceeding further.
if (hasattr(response, 'render') and callable(response.render)
and not response.is_rendered):
response.render()

if msg_prefix:
msg_prefix += ": "

self.assertEqual(response.status_code, status_code,
msg_prefix + "Couldn't retrieve content: Response code was %d"
" (expected %d)" % (response.status_code, status_code))

if response.streaming:
content = b''.join(response.streaming_content)
else:
content = response.content
if not isinstance(text, bytes) or html:
text = force_text(text, encoding=response.charset)
content = content.decode(response.charset)
text_repr = "'%s'" % text
else:
text_repr = repr(text)
if html:
content = assert_and_parse_html(self, content, None,
"Response's content is not valid HTML:")
text = assert_and_parse_html(self, text, None,
"Second argument is not valid HTML:")
real_count = content.count(text)
return (text_repr, real_count, msg_prefix)

[docs]    def assertContains(self, response, text, count=None, status_code=200,
msg_prefix='', html=False):
"""
Asserts that a response indicates that some content was retrieved
successfully, (i.e., the HTTP status code was as expected), and that
``text`` occurs ``count`` times in the content of the response.
If ``count`` is None, the count doesn't matter - the assertion is true
if the text occurs at least once in the response.
"""
text_repr, real_count, msg_prefix = self._assert_contains(
response, text, status_code, msg_prefix, html)

if count is not None:
self.assertEqual(real_count, count,
msg_prefix + "Found %d instances of %s in response"
" (expected %d)" % (real_count, text_repr, count))
else:
self.assertTrue(real_count != 0,
msg_prefix + "Couldn't find %s in response" % text_repr)

[docs]    def assertNotContains(self, response, text, status_code=200,
msg_prefix='', html=False):
"""
Asserts that a response indicates that some content was retrieved
successfully, (i.e., the HTTP status code was as expected), and that
``text`` doesn't occurs in the content of the response.
"""
text_repr, real_count, msg_prefix = self._assert_contains(
response, text, status_code, msg_prefix, html)

self.assertEqual(real_count, 0,
msg_prefix + "Response should not contain %s" % text_repr)

[docs]    def assertFormError(self, response, form, field, errors, msg_prefix=''):
"""
Asserts that a form used to render the response has a specific field
error.
"""
if msg_prefix:
msg_prefix += ": "

# Put context(s) into a list to simplify processing.
contexts = to_list(response.context)
if not contexts:
self.fail(msg_prefix + "Response did not use any contexts to "
"render the response")

# Put error(s) into a list to simplify processing.
errors = to_list(errors)

# Search all contexts for the error.
found_form = False
for i, context in enumerate(contexts):
if form not in context:
continue
found_form = True
for err in errors:
if field:
if field in context[form].errors:
field_errors = context[form].errors[field]
self.assertTrue(err in field_errors,
msg_prefix + "The field '%s' on form '%s' in"
" context %d does not contain the error '%s'"
" (actual errors: %s)" %
(field, form, i, err, repr(field_errors)))
elif field in context[form].fields:
self.fail(msg_prefix + "The field '%s' on form '%s'"
" in context %d contains no errors" %
(field, form, i))
else:
self.fail(msg_prefix + "The form '%s' in context %d"
" does not contain the field '%s'" %
(form, i, field))
else:
non_field_errors = context[form].non_field_errors()
self.assertTrue(err in non_field_errors,
msg_prefix + "The form '%s' in context %d does not"
" contain the non-field error '%s'"
" (actual errors: %s)" %
(form, i, err, non_field_errors))
if not found_form:
self.fail(msg_prefix + "The form '%s' was not used to render the"
" response" % form)

[docs]    def assertFormsetError(self, response, formset, form_index, field, errors,
msg_prefix=''):
"""
Asserts that a formset used to render the response has a specific error.

For field errors, specify the ``form_index`` and the ``field``.
For non-field errors, specify the ``form_index`` and the ``field`` as
None.
For non-form errors, specify ``form_index`` as None and the ``field``
as None.
"""
# Add punctuation to msg_prefix
if msg_prefix:
msg_prefix += ": "

# Put context(s) into a list to simplify processing.
contexts = to_list(response.context)
if not contexts:
self.fail(msg_prefix + 'Response did not use any contexts to '
'render the response')

# Put error(s) into a list to simplify processing.
errors = to_list(errors)

# Search all contexts for the error.
found_formset = False
for i, context in enumerate(contexts):
if formset not in context:
continue
found_formset = True
for err in errors:
if field is not None:
if field in context[formset].forms[form_index].errors:
field_errors = context[formset].forms[form_index].errors[field]
self.assertTrue(err in field_errors,
msg_prefix + "The field '%s' on formset '%s', "
"form %d in context %d does not contain the "
"error '%s' (actual errors: %s)" %
(field, formset, form_index, i, err,
repr(field_errors)))
elif field in context[formset].forms[form_index].fields:
self.fail(msg_prefix + "The field '%s' "
"on formset '%s', form %d in "
"context %d contains no errors" %
(field, formset, form_index, i))
else:
self.fail(msg_prefix + "The formset '%s', form %d in "
"context %d does not contain the field '%s'" %
(formset, form_index, i, field))
elif form_index is not None:
non_field_errors = context[formset].forms[form_index].non_field_errors()
self.assertFalse(len(non_field_errors) == 0,
msg_prefix + "The formset '%s', form %d in "
"context %d does not contain any non-field "
"errors." % (formset, form_index, i))
self.assertTrue(err in non_field_errors,
msg_prefix + "The formset '%s', form %d "
"in context %d does not contain the "
"non-field error '%s' "
"(actual errors: %s)" %
(formset, form_index, i, err,
repr(non_field_errors)))
else:
non_form_errors = context[formset].non_form_errors()
self.assertFalse(len(non_form_errors) == 0,
msg_prefix + "The formset '%s' in "
"context %d does not contain any "
"non-form errors." % (formset, i))
self.assertTrue(err in non_form_errors,
msg_prefix + "The formset '%s' in context "
"%d does not contain the "
"non-form error '%s' (actual errors: %s)" %
(formset, i, err, repr(non_form_errors)))
if not found_formset:
self.fail(msg_prefix + "The formset '%s' was not used to render "
"the response" % formset)

def _assert_template_used(self, response, template_name, msg_prefix):

if response is None and template_name is None:
raise TypeError('response and/or template_name argument must be provided')

if msg_prefix:
msg_prefix += ": "

if template_name is not None and response is not None and not hasattr(response, 'templates'):
raise ValueError(
"assertTemplateUsed() and assertTemplateNotUsed() are only "
"usable on responses fetched using the Django test Client."
)

if not hasattr(response, 'templates') or (response is None and template_name):
if response:
template_name = response
response = None
# use this template with context manager
return template_name, None, msg_prefix

template_names = [t.name for t in response.templates if t.name is not
None]
return None, template_names, msg_prefix

[docs]    def assertTemplateUsed(self, response=None, template_name=None, msg_prefix='', count=None):
"""
Asserts that the template with the provided name was used in rendering
the response. Also usable as context manager.
"""
context_mgr_template, template_names, msg_prefix = self._assert_template_used(
response, template_name, msg_prefix)

if context_mgr_template:
# Use assertTemplateUsed as context manager.
return _AssertTemplateUsedContext(self, context_mgr_template)

if not template_names:
self.fail(msg_prefix + "No templates used to render the response")
self.assertTrue(template_name in template_names,
msg_prefix + "Template '%s' was not a template used to render"
" the response. Actual template(s) used: %s" %
(template_name, ', '.join(template_names)))

if count is not None:
self.assertEqual(template_names.count(template_name), count,
msg_prefix + "Template '%s' was expected to be rendered %d "
"time(s) but was actually rendered %d time(s)." %
(template_name, count, template_names.count(template_name)))

[docs]    def assertTemplateNotUsed(self, response=None, template_name=None, msg_prefix=''):
"""
Asserts that the template with the provided name was NOT used in
rendering the response. Also usable as context manager.
"""

context_mgr_template, template_names, msg_prefix = self._assert_template_used(
response, template_name, msg_prefix)

if context_mgr_template:
# Use assertTemplateNotUsed as context manager.
return _AssertTemplateNotUsedContext(self, context_mgr_template)

self.assertFalse(template_name in template_names,
msg_prefix + "Template '%s' was used unexpectedly in rendering"
" the response" % template_name)

@contextmanager
def _assert_raises_message_cm(self, expected_exception, expected_message):
with self.assertRaises(expected_exception) as cm:
yield cm
self.assertIn(expected_message, str(cm.exception))

[docs]    def assertRaisesMessage(self, expected_exception, expected_message, *args, **kwargs):
"""
Asserts that expected_message is found in the the message of a raised
exception.

Args:
expected_exception: Exception class expected to be raised.
expected_message: expected error message string value.
args: Function to be called and extra positional args.
kwargs: Extra kwargs.
"""
# callable_obj was a documented kwarg in Django 1.8 and older.
callable_obj = kwargs.pop('callable_obj', None)
if callable_obj:
warnings.warn(
'The callable_obj kwarg is deprecated. Pass the callable '
'as a positional argument instead.', RemovedInDjango20Warning
)
elif len(args):
callable_obj = args[0]
args = args[1:]

cm = self._assert_raises_message_cm(expected_exception, expected_message)
# Assertion used in context manager fashion.
if callable_obj is None:
return cm
# Assertion was passed a callable.
with cm:
callable_obj(*args, **kwargs)

[docs]    def assertFieldOutput(self, fieldclass, valid, invalid, field_args=None,
field_kwargs=None, empty_value=''):
"""
Asserts that a form field behaves correctly with various inputs.

Args:
fieldclass: the class of the field to be tested.
valid: a dictionary mapping valid inputs to their expected
cleaned values.
invalid: a dictionary mapping invalid inputs to one or more
raised error messages.
field_args: the args passed to instantiate the field
field_kwargs: the kwargs passed to instantiate the field
empty_value: the expected clean output for inputs in empty_values
"""
if field_args is None:
field_args = []
if field_kwargs is None:
field_kwargs = {}
required = fieldclass(*field_args, **field_kwargs)
optional = fieldclass(*field_args,
**dict(field_kwargs, required=False))
# test valid inputs
for input, output in valid.items():
self.assertEqual(required.clean(input), output)
self.assertEqual(optional.clean(input), output)
# test invalid inputs
for input, errors in invalid.items():
with self.assertRaises(ValidationError) as context_manager:
required.clean(input)
self.assertEqual(context_manager.exception.messages, errors)

with self.assertRaises(ValidationError) as context_manager:
optional.clean(input)
self.assertEqual(context_manager.exception.messages, errors)
# test required inputs
error_required = [force_text(required.error_messages['required'])]
for e in required.empty_values:
with self.assertRaises(ValidationError) as context_manager:
required.clean(e)
self.assertEqual(context_manager.exception.messages,
error_required)
self.assertEqual(optional.clean(e), empty_value)
# test that max_length and min_length are always accepted
if issubclass(fieldclass, CharField):
field_kwargs.update({'min_length': 2, 'max_length': 20})
self.assertIsInstance(fieldclass(*field_args, **field_kwargs),
fieldclass)

[docs]    def assertHTMLEqual(self, html1, html2, msg=None):
"""
Asserts that two HTML snippets are semantically the same.
Whitespace in most cases is ignored, and attribute ordering is not
significant. The passed-in arguments must be valid HTML.
"""
dom1 = assert_and_parse_html(self, html1, msg,
'First argument is not valid HTML:')
dom2 = assert_and_parse_html(self, html2, msg,
'Second argument is not valid HTML:')

if dom1 != dom2:
standardMsg = '%s != %s' % (
safe_repr(dom1, True), safe_repr(dom2, True))
diff = ('\n' + '\n'.join(difflib.ndiff(
six.text_type(dom1).splitlines(),
six.text_type(dom2).splitlines())))
standardMsg = self._truncateMessage(standardMsg, diff)
self.fail(self._formatMessage(msg, standardMsg))

[docs]    def assertHTMLNotEqual(self, html1, html2, msg=None):
"""Asserts that two HTML snippets are not semantically equivalent."""
dom1 = assert_and_parse_html(self, html1, msg,
'First argument is not valid HTML:')
dom2 = assert_and_parse_html(self, html2, msg,
'Second argument is not valid HTML:')

if dom1 == dom2:
standardMsg = '%s == %s' % (
safe_repr(dom1, True), safe_repr(dom2, True))
self.fail(self._formatMessage(msg, standardMsg))

[docs]    def assertInHTML(self, needle, haystack, count=None, msg_prefix=''):
needle = assert_and_parse_html(self, needle, None,
'First argument is not valid HTML:')
haystack = assert_and_parse_html(self, haystack, None,
'Second argument is not valid HTML:')
real_count = haystack.count(needle)
if count is not None:
self.assertEqual(real_count, count,
msg_prefix + "Found %d instances of '%s' in response"
" (expected %d)" % (real_count, needle, count))
else:
self.assertTrue(real_count != 0,
msg_prefix + "Couldn't find '%s' in response" % needle)

[docs]    def assertJSONEqual(self, raw, expected_data, msg=None):
"""
Asserts that the JSON fragments raw and expected_data are equal.
Usual JSON non-significant whitespace rules apply as the heavyweight
is delegated to the json library.
"""
try:
data = json.loads(raw)
except ValueError:
self.fail("First argument is not valid JSON: %r" % raw)
if isinstance(expected_data, six.string_types):
try:
expected_data = json.loads(expected_data)
except ValueError:
self.fail("Second argument is not valid JSON: %r" % expected_data)
self.assertEqual(data, expected_data, msg=msg)

[docs]    def assertJSONNotEqual(self, raw, expected_data, msg=None):
"""
Asserts that the JSON fragments raw and expected_data are not equal.
Usual JSON non-significant whitespace rules apply as the heavyweight
is delegated to the json library.
"""
try:
data = json.loads(raw)
except ValueError:
self.fail("First argument is not valid JSON: %r" % raw)
if isinstance(expected_data, six.string_types):
try:
expected_data = json.loads(expected_data)
except ValueError:
self.fail("Second argument is not valid JSON: %r" % expected_data)
self.assertNotEqual(data, expected_data, msg=msg)

[docs]    def assertXMLEqual(self, xml1, xml2, msg=None):
"""
Asserts that two XML snippets are semantically the same.
Whitespace in most cases is ignored, and attribute ordering is not
significant. The passed-in arguments must be valid XML.
"""
try:
result = compare_xml(xml1, xml2)
except Exception as e:
standardMsg = 'First or second argument is not valid XML\n%s' % e
self.fail(self._formatMessage(msg, standardMsg))
else:
if not result:
standardMsg = '%s != %s' % (safe_repr(xml1, True), safe_repr(xml2, True))
diff = ('\n' + '\n'.join(
difflib.ndiff(
six.text_type(xml1).splitlines(),
six.text_type(xml2).splitlines(),
)
))
standardMsg = self._truncateMessage(standardMsg, diff)
self.fail(self._formatMessage(msg, standardMsg))

[docs]    def assertXMLNotEqual(self, xml1, xml2, msg=None):
"""
Asserts that two XML snippets are not semantically equivalent.
Whitespace in most cases is ignored, and attribute ordering is not
significant. The passed-in arguments must be valid XML.
"""
try:
result = compare_xml(xml1, xml2)
except Exception as e:
standardMsg = 'First or second argument is not valid XML\n%s' % e
self.fail(self._formatMessage(msg, standardMsg))
else:
if result:
standardMsg = '%s == %s' % (safe_repr(xml1, True), safe_repr(xml2, True))
self.fail(self._formatMessage(msg, standardMsg))

[docs]class TransactionTestCase(SimpleTestCase):

# Subclasses can ask for resetting of auto increment sequence before each
# test case
reset_sequences = False

# Subclasses can enable only a subset of apps for faster tests
available_apps = None

# Subclasses can define fixtures which will be automatically installed.
fixtures = None

# If transactions aren't available, Django will serialize the database
# contents into a fixture during setup and flush and reload them
# during teardown (as flush does not restore data from migrations).
# This can be slow; this flag allows enabling on a per-case basis.
serialized_rollback = False

# Since tests will be wrapped in a transaction, or serialized if they
# are not available, we allow queries to be run.
allow_database_queries = True

def _pre_setup(self):
"""Performs any pre-test setup. This includes:

* If the class has an 'available_apps' attribute, restricting the app
registry to these applications, then firing post_migrate -- it must
run with the correct set of applications for the test case.
* If the class has a 'fixtures' attribute, installing these fixtures.
"""
super(TransactionTestCase, self)._pre_setup()
if self.available_apps is not None:
apps.set_available_apps(self.available_apps)
setting_changed.send(sender=settings._wrapped.__class__,
setting='INSTALLED_APPS',
value=self.available_apps,
enter=True)
for db_name in self._databases_names(include_mirrors=False):
emit_post_migrate_signal(verbosity=0, interactive=False, db=db_name)
try:
self._fixture_setup()
except Exception:
if self.available_apps is not None:
apps.unset_available_apps()
setting_changed.send(sender=settings._wrapped.__class__,
setting='INSTALLED_APPS',
value=settings.INSTALLED_APPS,
enter=False)

raise

@classmethod
def _databases_names(cls, include_mirrors=True):
# If the test case has a multi_db=True flag, act on all databases,
# including mirrors or not. Otherwise, just on the default DB.
if getattr(cls, 'multi_db', False):
return [alias for alias in connections
if include_mirrors or not connections[alias].settings_dict['TEST']['MIRROR']]
else:
return [DEFAULT_DB_ALIAS]

def _reset_sequences(self, db_name):
conn = connections[db_name]
if conn.features.supports_sequence_reset:
sql_list = conn.ops.sequence_reset_by_name_sql(
no_style(), conn.introspection.sequence_list())
if sql_list:
with transaction.atomic(using=db_name):
cursor = conn.cursor()
for sql in sql_list:
cursor.execute(sql)

def _fixture_setup(self):
for db_name in self._databases_names(include_mirrors=False):
# Reset sequences
if self.reset_sequences:
self._reset_sequences(db_name)

# If we need to provide replica initial data from migrated apps,
# then do so.
if self.serialized_rollback and hasattr(connections[db_name], "_test_serialized_contents"):
if self.available_apps is not None:
apps.unset_available_apps()
connections[db_name].creation.deserialize_db_from_string(
connections[db_name]._test_serialized_contents
)
if self.available_apps is not None:
apps.set_available_apps(self.available_apps)

if self.fixtures:
# We have to use this slightly awkward syntax due to the fact
# that we're using *args and **kwargs together.
call_command('loaddata', *self.fixtures,
**{'verbosity': 0, 'database': db_name})

def _should_reload_connections(self):
return True

def _post_teardown(self):
"""Performs any post-test things. This includes:

* Flushing the contents of the database, to leave a clean slate. If
the class has an 'available_apps' attribute, post_migrate isn't fired.
* Force-closing the connection, so the next test gets a clean cursor.
"""
try:
self._fixture_teardown()
super(TransactionTestCase, self)._post_teardown()
if self._should_reload_connections():
# Some DB cursors include SQL statements as part of cursor
# creation. If you have a test that does a rollback, the effect
# of these statements is lost, which can affect the operation of
# tests (e.g., losing a timezone setting causing objects to be
# created with the wrong time). To make sure this doesn't
# happen, get a clean connection at the start of every test.
for conn in connections.all():
conn.close()
finally:
if self.available_apps is not None:
apps.unset_available_apps()
setting_changed.send(sender=settings._wrapped.__class__,
setting='INSTALLED_APPS',
value=settings.INSTALLED_APPS,
enter=False)

def _fixture_teardown(self):
# Allow TRUNCATE ... CASCADE and don't emit the post_migrate signal
# when flushing only a subset of the apps
for db_name in self._databases_names(include_mirrors=False):
# Flush the database
inhibit_post_migrate = (
self.available_apps is not None
or (
# Inhibit the post_migrate signal when using serialized
# rollback to avoid trying to recreate the serialized data.
self.serialized_rollback and
hasattr(connections[db_name], '_test_serialized_contents')
)
)
call_command('flush', verbosity=0, interactive=False,
database=db_name, reset_sequences=False,
allow_cascade=self.available_apps is not None,
inhibit_post_migrate=inhibit_post_migrate)

[docs]    def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True, msg=None):
items = six.moves.map(transform, qs)
if not ordered:
return self.assertEqual(Counter(items), Counter(values), msg=msg)
values = list(values)
# For example qs.iterator() could be passed as qs, but it does not
# have 'ordered' attribute.
if len(values) > 1 and hasattr(qs, 'ordered') and not qs.ordered:
raise ValueError("Trying to compare non-ordered queryset "
"against more than one ordered values")
return self.assertEqual(list(items), values, msg=msg)

[docs]    def assertNumQueries(self, num, func=None, *args, **kwargs):
using = kwargs.pop("using", DEFAULT_DB_ALIAS)
conn = connections[using]

context = _AssertNumQueriesContext(self, num, conn)
if func is None:
return context

with context:
func(*args, **kwargs)

def connections_support_transactions():
"""
Returns True if all connections support transactions.
"""
return all(conn.features.supports_transactions
for conn in connections.all())

[docs]class TestCase(TransactionTestCase):
"""
Similar to TransactionTestCase, but uses `transaction.atomic()` to achieve
test isolation.

In most situations, TestCase should be preferred to TransactionTestCase as
it allows faster execution. However, there are some situations where using
TransactionTestCase might be necessary (e.g. testing some transactional
behavior).

On database backends with no transaction support, TestCase behaves as
TransactionTestCase.
"""
@classmethod
def _enter_atomics(cls):
"""Helper method to open atomic blocks for multiple databases"""
atomics = {}
for db_name in cls._databases_names():
atomics[db_name] = transaction.atomic(using=db_name)
atomics[db_name].__enter__()
return atomics

@classmethod
def _rollback_atomics(cls, atomics):
"""Rollback atomic blocks opened through the previous method"""
for db_name in reversed(cls._databases_names()):
transaction.set_rollback(True, using=db_name)
atomics[db_name].__exit__(None, None, None)

@classmethod
def setUpClass(cls):
super(TestCase, cls).setUpClass()
if not connections_support_transactions():
return
cls.cls_atomics = cls._enter_atomics()

if cls.fixtures:
for db_name in cls._databases_names(include_mirrors=False):
try:
call_command('loaddata', *cls.fixtures, **{
'verbosity': 0,
'commit': False,
'database': db_name,
})
except Exception:
cls._rollback_atomics(cls.cls_atomics)
raise
try:
cls.setUpTestData()
except Exception:
cls._rollback_atomics(cls.cls_atomics)
raise

@classmethod
def tearDownClass(cls):
if connections_support_transactions():
cls._rollback_atomics(cls.cls_atomics)
for conn in connections.all():
conn.close()
super(TestCase, cls).tearDownClass()

@classmethod

[docs]    def setUpTestData(cls):
"""Load initial data for the TestCase"""
pass

def _should_reload_connections(self):
if connections_support_transactions():
return False
return super(TestCase, self)._should_reload_connections()

def _fixture_setup(self):
if not connections_support_transactions():
# If the backend does not support transactions, we should reload
# class data before each test
self.setUpTestData()
return super(TestCase, self)._fixture_setup()

assert not self.reset_sequences, 'reset_sequences cannot be used on TestCase instances'
self.atomics = self._enter_atomics()

def _fixture_teardown(self):
if not connections_support_transactions():
return super(TestCase, self)._fixture_teardown()
self._rollback_atomics(self.atomics)

class CheckCondition(object):
"""Descriptor class for deferred condition checking"""
def __init__(self, cond_func):
self.cond_func = cond_func

def __get__(self, obj, objtype):
return self.cond_func()

def _deferredSkip(condition, reason):
def decorator(test_func):
if not (isinstance(test_func, type) and
issubclass(test_func, unittest.TestCase)):
@wraps(test_func)
def skip_wrapper(*args, **kwargs):
if condition():
raise unittest.SkipTest(reason)
return test_func(*args, **kwargs)
test_item = skip_wrapper
else:
# Assume a class is decorated
test_item = test_func
test_item.__unittest_skip__ = CheckCondition(condition)
test_item.__unittest_skip_why__ = reason
return test_item
return decorator

[docs]def skipIfDBFeature(*features):
"""
Skip a test if a database has at least one of the named features.
"""
return _deferredSkip(
lambda: any(getattr(connection.features, feature, False) for feature in features),
"Database has feature(s) %s" % ", ".join(features)
)

[docs]def skipUnlessDBFeature(*features):
"""
Skip a test unless a database has all the named features.
"""
return _deferredSkip(
lambda: not all(getattr(connection.features, feature, False) for feature in features),
"Database doesn't support feature(s): %s" % ", ".join(features)
)

def skipUnlessAnyDBFeature(*features):
"""
Skip a test unless a database has any of the named features.
"""
return _deferredSkip(
lambda: not any(getattr(connection.features, feature, False) for feature in features),
"Database doesn't support any of the feature(s): %s" % ", ".join(features)
)

class QuietWSGIRequestHandler(WSGIRequestHandler):
"""
Just a regular WSGIRequestHandler except it doesn't log to the standard
output any of the requests received, so as to not clutter the output for
the tests' results.
"""

def log_message(*args):
pass

class FSFilesHandler(WSGIHandler):
"""
WSGI middleware that intercepts calls to a directory, as defined by one of
the *_ROOT settings, and serves those files, publishing them under *_URL.
"""
def __init__(self, application):
self.application = application
self.base_url = urlparse(self.get_base_url())
super(FSFilesHandler, self).__init__()

def _should_handle(self, path):
"""
Checks if the path should be handled. Ignores the path if:

* the host is provided as part of the base_url
* the request's path isn't under the media path (or equal)
"""
return path.startswith(self.base_url[2]) and not self.base_url[1]

def file_path(self, url):
"""
Returns the relative path to the file on disk for the given URL.
"""
relative_url = url[len(self.base_url[2]):]
return url2pathname(relative_url)

def get_response(self, request):
from django.http import Http404

if self._should_handle(request.path):
try:
return self.serve(request)
except Http404:
pass
return super(FSFilesHandler, self).get_response(request)

def serve(self, request):
os_rel_path = self.file_path(request.path)
os_rel_path = posixpath.normpath(unquote(os_rel_path))
# Emulate behavior of django.contrib.staticfiles.views.serve() when it
# invokes staticfiles' finders functionality.
# TODO: Modify if/when that internal API is refactored
final_rel_path = os_rel_path.replace('\\', '/').lstrip('/')
return serve(request, final_rel_path, document_root=self.get_base_dir())

def __call__(self, environ, start_response):
if not self._should_handle(get_path_info(environ)):
return self.application(environ, start_response)
return super(FSFilesHandler, self).__call__(environ, start_response)

class _StaticFilesHandler(FSFilesHandler):
"""
Handler for serving static files. A private class that is meant to be used
solely as a convenience by LiveServerThread.
"""

def get_base_dir(self):
return settings.STATIC_ROOT

def get_base_url(self):
return settings.STATIC_URL

class _MediaFilesHandler(FSFilesHandler):
"""
Handler for serving the media files. A private class that is meant to be
used solely as a convenience by LiveServerThread.
"""

def get_base_dir(self):
return settings.MEDIA_ROOT

def get_base_url(self):
return settings.MEDIA_URL

class LiveServerThread(threading.Thread):
"""
Thread for running a live http server while the tests are running.
"""

def __init__(self, host, possible_ports, static_handler, connections_override=None):
self.host = host
self.port = None
self.possible_ports = possible_ports
self.is_ready = threading.Event()
self.error = None
self.static_handler = static_handler
self.connections_override = connections_override
super(LiveServerThread, self).__init__()

def run(self):
"""
Sets up the live server and databases, and then loops over handling
http requests.
"""
if self.connections_override:
# Override this thread's database connections with the ones
# provided by the main thread.
for alias, conn in self.connections_override.items():
connections[alias] = conn
try:
# Create the handler for serving static and media files
handler = self.static_handler(_MediaFilesHandler(WSGIHandler()))

# Go through the list of possible ports, hoping that we can find
# one that is free to use for the WSGI server.
for index, port in enumerate(self.possible_ports):
try:
self.httpd = self._create_server(port)
except socket.error as e:
if (index + 1 < len(self.possible_ports) and
e.errno == errno.EADDRINUSE):
# This port is already in use, so we go on and try with
# the next one in the list.
continue
else:
# Either none of the given ports are free or the error
# is something else than "Address already in use". So
# we let that error bubble up to the main thread.
raise
else:
# A free port was found.
self.port = port
break

self.httpd.set_app(handler)
self.is_ready.set()
self.httpd.serve_forever()
except Exception as e:
self.error = e
self.is_ready.set()

def _create_server(self, port):
return WSGIServer((self.host, port), QuietWSGIRequestHandler)

def terminate(self):
if hasattr(self, 'httpd'):
# Stop the WSGI server
self.httpd.shutdown()
self.httpd.server_close()

[docs]class LiveServerTestCase(TransactionTestCase):
"""
Does basically the same as TransactionTestCase but also launches a live
http server in a separate thread so that the tests may use another testing
framework, such as Selenium for example, instead of the built-in dummy
client.
Note that it inherits from TransactionTestCase instead of TestCase because
the threads do not share the same transactions (unless if using in-memory
sqlite) and each thread needs to commit all their transactions so that the
other thread can see the changes.
"""

static_handler = _StaticFilesHandler

@classproperty
def live_server_url(cls):
return 'http://%s:%s' % (
cls.server_thread.host, cls.server_thread.port)

@classmethod
def setUpClass(cls):
super(LiveServerTestCase, cls).setUpClass()
connections_override = {}
for conn in connections.all():
# If using in-memory sqlite databases, pass the connections to
# the server thread.
if conn.vendor == 'sqlite' and conn.is_in_memory_db(conn.settings_dict['NAME']):
# Explicitly enable thread-shareability for this connection
conn.allow_thread_sharing = True
connections_override[conn.alias] = conn

# Launch the live server's thread
specified_address = os.environ.get(
'DJANGO_LIVE_TEST_SERVER_ADDRESS', 'localhost:8081-8179')

# The specified ports may be of the form '8000-8010,8080,9200-9300'
# i.e. a comma-separated list of ports or ranges of ports, so we break
# it down into a detailed list of all possible ports.
possible_ports = []
try:
host, port_ranges = specified_address.split(':')
for port_range in port_ranges.split(','):
# A port range can be of either form: '8000' or '8000-8010'.
extremes = list(map(int, port_range.split('-')))
assert len(extremes) in [1, 2]
if len(extremes) == 1:
# Port range of the form '8000'
possible_ports.append(extremes[0])
else:
# Port range of the form '8000-8010'
for port in range(extremes[0], extremes[1] + 1):
possible_ports.append(port)
except Exception:
msg = 'Invalid address ("%s") for live server.' % specified_address
six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg), sys.exc_info()[2])
cls.server_thread = cls._create_server_thread(host, possible_ports, connections_override)
cls.server_thread.daemon = True
cls.server_thread.start()

# Wait for the live server to be ready
cls.server_thread.is_ready.wait()
if cls.server_thread.error:
# Clean up behind ourselves, since tearDownClass won't get called in
# case of errors.
cls._tearDownClassInternal()
raise cls.server_thread.error

@classmethod
def _create_server_thread(cls, host, possible_ports, connections_override):
return LiveServerThread(
host,
possible_ports,
cls.static_handler,
connections_override=connections_override,
)

@classmethod
def _tearDownClassInternal(cls):
# There may not be a 'server_thread' attribute if setUpClass() for some
# reasons has raised an exception.
if hasattr(cls, 'server_thread'):
# Terminate the live server's thread
cls.server_thread.terminate()
cls.server_thread.join()

# Restore sqlite in-memory database connections' non-shareability
for conn in connections.all():
if conn.vendor == 'sqlite' and conn.is_in_memory_db(conn.settings_dict['NAME']):
conn.allow_thread_sharing = False

@classmethod
def tearDownClass(cls):
cls._tearDownClassInternal()
super(LiveServerTestCase, cls).tearDownClass()

class SerializeMixin(object):
"""
Mixin to enforce serialization of TestCases that share a common resource.

Define a common 'lockfile' for each set of TestCases to serialize. This
file must exist on the filesystem.

Place it early in the MRO in order to isolate setUpClass / tearDownClass.
"""

lockfile = None

@classmethod
def setUpClass(cls):
if cls.lockfile is None:
raise ValueError(
"{}.lockfile isn't set. Set it to a unique value "
"in the base class.".format(cls.__name__))
cls._lockfile = open(cls.lockfile)
locks.lock(cls._lockfile, locks.LOCK_EX)
super(SerializeMixin, cls).setUpClass()

@classmethod
def tearDownClass(cls):
super(SerializeMixin, cls).tearDownClass()
cls._lockfile.close()

Source code for django.test.client

from __future__ import unicode_literals

import json
import mimetypes
import os
import re
import sys
from copy import copy
from importlib import import_module
from io import BytesIO

from django.apps import apps
from django.conf import settings
from django.core import urlresolvers
from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import ISO_8859_1, UTF_8, WSGIRequest
from django.core.signals import (
got_request_exception, request_finished, request_started,
)
from django.db import close_old_connections
from django.http import HttpRequest, QueryDict, SimpleCookie
from django.template import TemplateDoesNotExist
from django.test import signals
from django.test.utils import ContextList
from django.utils import six
from django.utils.encoding import force_bytes, force_str, uri_to_iri
from django.utils.functional import SimpleLazyObject, curry
from django.utils.http import urlencode
from django.utils.itercompat import is_iterable
from django.utils.six.moves.urllib.parse import urljoin, urlparse, urlsplit

__all__ = ('Client', 'RedirectCycleError', 'RequestFactory', 'encode_file', 'encode_multipart')

BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
CONTENT_TYPE_RE = re.compile('.*; charset=([\w\d-]+);?')

class RedirectCycleError(Exception):
"""
The test client has been asked to follow a redirect loop.
"""
def __init__(self, message, last_response):
super(RedirectCycleError, self).__init__(message)
self.last_response = last_response
self.redirect_chain = last_response.redirect_chain

class FakePayload(object):
"""
A wrapper around BytesIO that restricts what can be read since data from
the network can't be seeked and cannot be read outside of its content
length. This makes sure that views can't do anything under the test client
that wouldn't work in Real Life.
"""
def __init__(self, content=None):
self.__content = BytesIO()
self.__len = 0
self.read_started = False
if content is not None:
self.write(content)

def __len__(self):
return self.__len

def read(self, num_bytes=None):
if not self.read_started:
self.__content.seek(0)
self.read_started = True
if num_bytes is None:
num_bytes = self.__len or 0
assert self.__len >= num_bytes, "Cannot read more than the available bytes from the HTTP incoming data."
content = self.__content.read(num_bytes)
self.__len -= num_bytes
return content

def write(self, content):
if self.read_started:
raise ValueError("Unable to write a payload after he's been read")
content = force_bytes(content)
self.__content.write(content)
self.__len += len(content)

def closing_iterator_wrapper(iterable, close):
try:
for item in iterable:
yield item
finally:
request_finished.disconnect(close_old_connections)
close()                                 # will fire request_finished
request_finished.connect(close_old_connections)

class ClientHandler(BaseHandler):
"""
A HTTP Handler that can be used for testing purposes. Uses the WSGI
interface to compose requests, but returns the raw HttpResponse object with
the originating WSGIRequest attached to its ``wsgi_request`` attribute.
"""
def __init__(self, enforce_csrf_checks=True, *args, **kwargs):
self.enforce_csrf_checks = enforce_csrf_checks
super(ClientHandler, self).__init__(*args, **kwargs)

def __call__(self, environ):
# Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available.
if self._request_middleware is None:
self.load_middleware()

request_started.disconnect(close_old_connections)
request_started.send(sender=self.__class__, environ=environ)
request_started.connect(close_old_connections)
request = WSGIRequest(environ)
# sneaky little hack so that we can easily get round
# CsrfViewMiddleware.  This makes life easier, and is probably
# required for backwards compatibility with external tests against
# admin views.
request._dont_enforce_csrf_checks = not self.enforce_csrf_checks

# Request goes through middleware.
response = self.get_response(request)
# Attach the originating request to the response so that it could be
# later retrieved.
response.wsgi_request = request

# We're emulating a WSGI server; we must call the close method
# on completion.
if response.streaming:
response.streaming_content = closing_iterator_wrapper(
response.streaming_content, response.close)
else:
request_finished.disconnect(close_old_connections)
response.close()                    # will fire request_finished
request_finished.connect(close_old_connections)

return response

def store_rendered_templates(store, signal, sender, template, context, **kwargs):
"""
Stores templates and contexts that are rendered.

The context is copied so that it is an accurate representation at the time
of rendering.
"""
store.setdefault('templates', []).append(template)
store.setdefault('context', ContextList()).append(copy(context))

def encode_multipart(boundary, data):
"""
Encodes multipart POST data from a dictionary of form values.

The key will be used as the form data name; the value will be transmitted
as content. If the value is a file, the contents of the file will be sent
as an application/octet-stream; otherwise, str(value) will be sent.
"""
lines = []
to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)

# Not by any means perfect, but good enough for our purposes.
is_file = lambda thing: hasattr(thing, "read") and callable(thing.read)

# Each bit of the multipart form data could be either a form value or a
# file, or a *list* of form values and/or files. Remember that HTTP field
# names can be duplicated!
for (key, value) in data.items():
if is_file(value):
lines.extend(encode_file(boundary, key, value))
elif not isinstance(value, six.string_types) and is_iterable(value):
for item in value:
if is_file(item):
lines.extend(encode_file(boundary, key, item))
else:
lines.extend(to_bytes(val) for val in [
'--%s' % boundary,
'Content-Disposition: form-data; name="%s"' % key,
'',
item
])
else:
lines.extend(to_bytes(val) for val in [
'--%s' % boundary,
'Content-Disposition: form-data; name="%s"' % key,
'',
value
])

lines.extend([
to_bytes('--%s--' % boundary),
b'',
])
return b'\r\n'.join(lines)

def encode_file(boundary, key, file):
to_bytes = lambda s: force_bytes(s, settings.DEFAULT_CHARSET)
filename = os.path.basename(file.name) if hasattr(file, 'name') else ''
if hasattr(file, 'content_type'):
content_type = file.content_type
elif filename:
content_type = mimetypes.guess_type(filename)[0]
else:
content_type = None

if content_type is None:
content_type = 'application/octet-stream'
if not filename:
filename = key
return [
to_bytes('--%s' % boundary),
to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"'
% (key, filename)),
to_bytes('Content-Type: %s' % content_type),
b'',
to_bytes(file.read())
]

[docs]class RequestFactory(object):
"""
Class that lets you create mock Request objects for use in testing.

Usage:

rf = RequestFactory()
get_request = rf.get('/hello/')
post_request = rf.post('/submit/', {'foo': 'bar'})

Once you have a request object you can pass it to any view function,
just as if that view had been hooked up using a URLconf.
"""
def __init__(self, **defaults):
self.defaults = defaults
self.cookies = SimpleCookie()
self.errors = BytesIO()

def _base_environ(self, **request):
"""
The base environment for a request.
"""
# This is a minimal valid WSGI environ dictionary, plus:
# - HTTP_COOKIE: for cookie support,
# - REMOTE_ADDR: often useful, see #8551.
# See http://www.python.org/dev/peps/pep-3333/#environ-variables
environ = {
'HTTP_COOKIE': self.cookies.output(header='', sep='; '),
'PATH_INFO': str('/'),
'REMOTE_ADDR': str('127.0.0.1'),
'REQUEST_METHOD': str('GET'),
'SCRIPT_NAME': str(''),
'SERVER_NAME': str('testserver'),
'SERVER_PORT': str('80'),
'SERVER_PROTOCOL': str('HTTP/1.1'),
'wsgi.version': (1, 0),
'wsgi.url_scheme': str('http'),
'wsgi.input': FakePayload(b''),
'wsgi.errors': self.errors,
'wsgi.multiprocess': True,
'wsgi.multithread': False,
'wsgi.run_once': False,
}
environ.update(self.defaults)
environ.update(request)
return environ

def request(self, **request):
"Construct a generic request object."
return WSGIRequest(self._base_environ(**request))

def _encode_data(self, data, content_type):
if content_type is MULTIPART_CONTENT:
return encode_multipart(BOUNDARY, data)
else:
# Encode the content so that the byte representation is correct.
match = CONTENT_TYPE_RE.match(content_type)
if match:
charset = match.group(1)
else:
charset = settings.DEFAULT_CHARSET
return force_bytes(data, encoding=charset)

def _get_path(self, parsed):
path = force_str(parsed[2])
# If there are parameters, add them
if parsed[3]:
path += str(";") + force_str(parsed[3])
path = uri_to_iri(path).encode(UTF_8)
# Under Python 3, non-ASCII values in the WSGI environ are arbitrarily
# decoded with ISO-8859-1. We replicate this behavior here.
# Refs comment in `get_bytes_from_wsgi()`.
return path.decode(ISO_8859_1) if six.PY3 else path

def get(self, path, data=None, secure=False, **extra):
"Construct a GET request."

data = {} if data is None else data
r = {
'QUERY_STRING': urlencode(data, doseq=True),
}
r.update(extra)
return self.generic('GET', path, secure=secure, **r)

def post(self, path, data=None, content_type=MULTIPART_CONTENT,
secure=False, **extra):
"Construct a POST request."

data = {} if data is None else data
post_data = self._encode_data(data, content_type)

return self.generic('POST', path, post_data, content_type,
secure=secure, **extra)

def head(self, path, data=None, secure=False, **extra):
"Construct a HEAD request."

data = {} if data is None else data
r = {
'QUERY_STRING': urlencode(data, doseq=True),
}
r.update(extra)
return self.generic('HEAD', path, secure=secure, **r)

def trace(self, path, secure=False, **extra):
"Construct a TRACE request."
return self.generic('TRACE', path, secure=secure, **extra)

def options(self, path, data='', content_type='application/octet-stream',
secure=False, **extra):
"Construct an OPTIONS request."
return self.generic('OPTIONS', path, data, content_type,
secure=secure, **extra)

def put(self, path, data='', content_type='application/octet-stream',
secure=False, **extra):
"Construct a PUT request."
return self.generic('PUT', path, data, content_type,
secure=secure, **extra)

def patch(self, path, data='', content_type='application/octet-stream',
secure=False, **extra):
"Construct a PATCH request."
return self.generic('PATCH', path, data, content_type,
secure=secure, **extra)

def delete(self, path, data='', content_type='application/octet-stream',
secure=False, **extra):
"Construct a DELETE request."
return self.generic('DELETE', path, data, content_type,
secure=secure, **extra)

def generic(self, method, path, data='',
content_type='application/octet-stream', secure=False,
**extra):
"""Constructs an arbitrary HTTP request."""
parsed = urlparse(force_str(path))
data = force_bytes(data, settings.DEFAULT_CHARSET)
r = {
'PATH_INFO': self._get_path(parsed),
'REQUEST_METHOD': str(method),
'SERVER_PORT': str('443') if secure else str('80'),
'wsgi.url_scheme': str('https') if secure else str('http'),
}
if data:
r.update({
'CONTENT_LENGTH': len(data),
'CONTENT_TYPE': str(content_type),
'wsgi.input': FakePayload(data),
})
r.update(extra)
# If QUERY_STRING is absent or empty, we want to extract it from the URL.
if not r.get('QUERY_STRING'):
query_string = force_bytes(parsed[4])
# WSGI requires latin-1 encoded strings. See get_path_info().
if six.PY3:
query_string = query_string.decode('iso-8859-1')
r['QUERY_STRING'] = query_string
return self.request(**r)

[docs]class Client(RequestFactory):
"""
A class that can act as a client for testing purposes.

It allows the user to compose GET and POST requests, and
obtain the response that the server gave to those requests.
The server Response objects are annotated with the details
of the contexts and templates that were rendered during the
process of serving the request.

Client objects are stateful - they will retain cookie (and
thus session) details for the lifetime of the Client instance.

This is not intended as a replacement for Twill/Selenium or
the like - it is here to allow testing against the
contexts and templates produced by a view, rather than the
HTML rendered to the end-user.
"""
def __init__(self, enforce_csrf_checks=False, **defaults):
super(Client, self).__init__(**defaults)
self.handler = ClientHandler(enforce_csrf_checks)
self.exc_info = None

def store_exc_info(self, **kwargs):
"""
Stores exceptions when they are generated by a view.
"""
self.exc_info = sys.exc_info()

def _session(self):
"""
Obtains the current session variables.
"""
if apps.is_installed('django.contrib.sessions'):
engine = import_module(settings.SESSION_ENGINE)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
if cookie:
return engine.SessionStore(cookie.value)
else:
s = engine.SessionStore()
s.save()
self.cookies[settings.SESSION_COOKIE_NAME] = s.session_key
return s
return {}
session = property(_session)

def request(self, **request):
"""
The master request method. Composes the environment dictionary
and passes to the handler, returning the result of the handler.
Assumes defaults for the query environment, which can be overridden
using the arguments to the request.
"""
environ = self._base_environ(**request)

# Curry a data dictionary into an instance of the template renderer
# callback function.
data = {}
on_template_render = curry(store_rendered_templates, data)
signal_uid = "template-render-%s" % id(request)
signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid)
# Capture exceptions created by the handler.
exception_uid = "request-exception-%s" % id(request)
got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid)
try:
try:
response = self.handler(environ)
except TemplateDoesNotExist as e:
# If the view raises an exception, Django will attempt to show
# the 500.html template. If that template is not available,
# we should ignore the error in favor of re-raising the
# underlying exception that caused the 500 error. Any other
# template found to be missing during view error handling
# should be reported as-is.
if e.args != ('500.html',):
raise

# Look for a signalled exception, clear the current context
# exception data, then re-raise the signalled exception.
# Also make sure that the signalled exception is cleared from
# the local cache!
if self.exc_info:
exc_info = self.exc_info
self.exc_info = None
six.reraise(*exc_info)

# Save the client and request that stimulated the response.
response.client = self
response.request = request

# Add any rendered template detail to the response.
response.templates = data.get("templates", [])
response.context = data.get("context")

response.json = curry(self._parse_json, response)

# Attach the ResolverMatch instance to the response
response.resolver_match = SimpleLazyObject(
lambda: urlresolvers.resolve(request['PATH_INFO']))

# Flatten a single context. Not really necessary anymore thanks to
# the __getattr__ flattening in ContextList, but has some edge-case
# backwards-compatibility implications.
if response.context and len(response.context) == 1:
response.context = response.context[0]

# Update persistent cookie data.
if response.cookies:
self.cookies.update(response.cookies)

return response
finally:
signals.template_rendered.disconnect(dispatch_uid=signal_uid)
got_request_exception.disconnect(dispatch_uid=exception_uid)

[docs]    def get(self, path, data=None, follow=False, secure=False, **extra):
"""
Requests a response from the server using GET.
"""
response = super(Client, self).get(path, data=data, secure=secure,
**extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def post(self, path, data=None, content_type=MULTIPART_CONTENT,
follow=False, secure=False, **extra):
"""
Requests a response from the server using POST.
"""
response = super(Client, self).post(path, data=data,
content_type=content_type,
secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def head(self, path, data=None, follow=False, secure=False, **extra):
"""
Request a response from the server using HEAD.
"""
response = super(Client, self).head(path, data=data, secure=secure,
**extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def options(self, path, data='', content_type='application/octet-stream',
follow=False, secure=False, **extra):
"""
Request a response from the server using OPTIONS.
"""
response = super(Client, self).options(path, data=data,
content_type=content_type,
secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def put(self, path, data='', content_type='application/octet-stream',
follow=False, secure=False, **extra):
"""
Send a resource to the server using PUT.
"""
response = super(Client, self).put(path, data=data,
content_type=content_type,
secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def patch(self, path, data='', content_type='application/octet-stream',
follow=False, secure=False, **extra):
"""
Send a resource to the server using PATCH.
"""
response = super(Client, self).patch(path, data=data,
content_type=content_type,
secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def delete(self, path, data='', content_type='application/octet-stream',
follow=False, secure=False, **extra):
"""
Send a DELETE request to the server.
"""
response = super(Client, self).delete(path, data=data,
content_type=content_type,
secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def trace(self, path, data='', follow=False, secure=False, **extra):
"""
Send a TRACE request to the server.
"""
response = super(Client, self).trace(path, data=data, secure=secure, **extra)
if follow:
response = self._handle_redirects(response, **extra)
return response

[docs]    def login(self, **credentials):
"""
Sets the Factory to appear as if it has successfully logged into a site.

Returns True if login is possible; False if the provided credentials
are incorrect, or the user is inactive, or if the sessions framework is
not available.
"""
from django.contrib.auth import authenticate
user = authenticate(**credentials)
if (user and user.is_active and
apps.is_installed('django.contrib.sessions')):
self._login(user)
return True
else:
return False

[docs]    def force_login(self, user, backend=None):
if backend is None:
backend = settings.AUTHENTICATION_BACKENDS[0]
user.backend = backend
self._login(user)

def _login(self, user):
from django.contrib.auth import login
engine = import_module(settings.SESSION_ENGINE)

# Create a fake request to store login details.
request = HttpRequest()

if self.session:
request.session = self.session
else:
request.session = engine.SessionStore()
login(request, user)

# Save the session values.
request.session.save()

# Set the cookie to represent the session.
session_cookie = settings.SESSION_COOKIE_NAME
self.cookies[session_cookie] = request.session.session_key
cookie_data = {
'max-age': None,
'path': '/',
'domain': settings.SESSION_COOKIE_DOMAIN,
'secure': settings.SESSION_COOKIE_SECURE or None,
'expires': None,
}
self.cookies[session_cookie].update(cookie_data)

[docs]    def logout(self):
"""
Removes the authenticated user's cookies and session object.

Causes the authenticated user to be logged out.
"""
from django.contrib.auth import get_user, logout

request = HttpRequest()
engine = import_module(settings.SESSION_ENGINE)
if self.session:
request.session = self.session
request.user = get_user(request)
else:
request.session = engine.SessionStore()
logout(request)
self.cookies = SimpleCookie()

def _parse_json(self, response, **extra):
if 'application/json' not in response.get('Content-Type'):
raise ValueError(
'Content-Type header is "{0}", not "application/json"'
.format(response.get('Content-Type'))
)
return json.loads(response.content.decode(), **extra)

def _handle_redirects(self, response, **extra):
"Follows any redirects by requesting responses from the server using GET."

response.redirect_chain = []
while response.status_code in (301, 302, 303, 307):
response_url = response.url
redirect_chain = response.redirect_chain
redirect_chain.append((response_url, response.status_code))

url = urlsplit(response_url)
if url.scheme:
extra['wsgi.url_scheme'] = url.scheme
if url.hostname:
extra['SERVER_NAME'] = url.hostname
if url.port:
extra['SERVER_PORT'] = str(url.port)

# Prepend the request path to handle relative path redirects
path = url.path
if not path.startswith('/'):
path = urljoin(response.request['PATH_INFO'], path)

response = self.get(path, QueryDict(url.query), follow=False, **extra)
response.redirect_chain = redirect_chain

if redirect_chain[-1] in redirect_chain[:-1]:
# Check that we're not redirecting to somewhere we've already
# been to, to prevent loops.
raise RedirectCycleError("Redirect loop detected.", last_response=response)
if len(redirect_chain) > 20:
# Such a lengthy chain likely also means a loop, but one with
# a growing path, changing view, or changing query argument;
# 20 is the value of "network.http.redirection-limit" from Firefox.
raise RedirectCycleError("Too many redirects.", last_response=response)

return response

Source code for django.test.runner

import collections
import ctypes
import itertools
import logging
import multiprocessing
import os
import pickle
import textwrap
import unittest
from importlib import import_module

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db import DEFAULT_DB_ALIAS, connections
from django.test import SimpleTestCase, TestCase
from django.test.utils import setup_test_environment, teardown_test_environment
from django.utils.datastructures import OrderedSet
from django.utils.six import StringIO

try:
import tblib.pickling_support
except ImportError:
tblib = None

class DebugSQLTextTestResult(unittest.TextTestResult):
def __init__(self, stream, descriptions, verbosity):
self.logger = logging.getLogger('django.db.backends')
self.logger.setLevel(logging.DEBUG)
super(DebugSQLTextTestResult, self).__init__(stream, descriptions, verbosity)

def startTest(self, test):
self.debug_sql_stream = StringIO()
self.handler = logging.StreamHandler(self.debug_sql_stream)
self.logger.addHandler(self.handler)
super(DebugSQLTextTestResult, self).startTest(test)

def stopTest(self, test):
super(DebugSQLTextTestResult, self).stopTest(test)
self.logger.removeHandler(self.handler)
if self.showAll:
self.debug_sql_stream.seek(0)
self.stream.write(self.debug_sql_stream.read())
self.stream.writeln(self.separator2)

def addError(self, test, err):
super(DebugSQLTextTestResult, self).addError(test, err)
self.debug_sql_stream.seek(0)
self.errors[-1] = self.errors[-1] + (self.debug_sql_stream.read(),)

def addFailure(self, test, err):
super(DebugSQLTextTestResult, self).addFailure(test, err)
self.debug_sql_stream.seek(0)
self.failures[-1] = self.failures[-1] + (self.debug_sql_stream.read(),)

def printErrorList(self, flavour, errors):
for test, err, sql_debug in errors:
self.stream.writeln(self.separator1)
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
self.stream.writeln(self.separator2)
self.stream.writeln("%s" % err)
self.stream.writeln(self.separator2)
self.stream.writeln("%s" % sql_debug)

class RemoteTestResult(object):
"""
Record information about which tests have succeeded and which have failed.

The sole purpose of this class is to record events in the child processes
so they can be replayed in the master process. As a consequence it doesn't
inherit unittest.TestResult and doesn't attempt to implement all its API.

The implementation matches the unpythonic coding style of unittest2.
"""

def __init__(self):
self.events = []
self.failfast = False
self.shouldStop = False
self.testsRun = 0

@property
def test_index(self):
return self.testsRun - 1

def check_picklable(self, test, err):
# Ensure that sys.exc_info() tuples are picklable. This displays a
# clear multiprocessing.pool.RemoteTraceback generated in the child
# process instead of a multiprocessing.pool.MaybeEncodingError, making
# the root cause easier to figure out for users who aren't familiar
# with the multiprocessing module. Since we're in a forked process,
# our best chance to communicate with them is to print to stdout.
try:
pickle.dumps(err)
except Exception as exc:
original_exc_txt = repr(err[1])
original_exc_txt = textwrap.fill(original_exc_txt, 75, initial_indent='    ', subsequent_indent='    ')
pickle_exc_txt = repr(exc)
pickle_exc_txt = textwrap.fill(pickle_exc_txt, 75, initial_indent='    ', subsequent_indent='    ')
if tblib is None:
print("""

{} failed:

{}

Unfortunately, tracebacks cannot be pickled, making it impossible for the
parallel test runner to handle this exception cleanly.

In order to see the traceback, you should install tblib:

pip install tblib
""".format(test, original_exc_txt))
else:
print("""

{} failed:

{}

Unfortunately, the exception it raised cannot be pickled, making it impossible
for the parallel test runner to handle it cleanly.

Here's the error encountered while trying to pickle the exception:

{}

You should re-run this test without the --parallel option to reproduce the
failure and get a correct traceback.
""".format(test, original_exc_txt, pickle_exc_txt))
raise

def stop_if_failfast(self):
if self.failfast:
self.stop()

def stop(self):
self.shouldStop = True

def startTestRun(self):
self.events.append(('startTestRun',))

def stopTestRun(self):
self.events.append(('stopTestRun',))

def startTest(self, test):
self.testsRun += 1
self.events.append(('startTest', self.test_index))

def stopTest(self, test):
self.events.append(('stopTest', self.test_index))

def addError(self, test, err):
self.check_picklable(test, err)
self.events.append(('addError', self.test_index, err))
self.stop_if_failfast()

def addFailure(self, test, err):
self.check_picklable(test, err)
self.events.append(('addFailure', self.test_index, err))
self.stop_if_failfast()

def addSubTest(self, test, subtest, err):
raise NotImplementedError("subtests aren't supported at this time")

def addSuccess(self, test):
self.events.append(('addSuccess', self.test_index))

def addSkip(self, test, reason):
self.events.append(('addSkip', self.test_index, reason))

def addExpectedFailure(self, test, err):
# If tblib isn't installed, pickling the traceback will always fail.
# However we don't want tblib to be required for running the tests
# when they pass or fail as expected. Drop the traceback when an
# expected failure occurs.
if tblib is None:
err = err[0], err[1], None
self.check_picklable(test, err)
self.events.append(('addExpectedFailure', self.test_index, err))

def addUnexpectedSuccess(self, test):
self.events.append(('addUnexpectedSuccess', self.test_index))
self.stop_if_failfast()

class RemoteTestRunner(object):
"""
Run tests and record everything but don't display anything.

The implementation matches the unpythonic coding style of unittest2.
"""

resultclass = RemoteTestResult

def __init__(self, failfast=False, resultclass=None):
self.failfast = failfast
if resultclass is not None:
self.resultclass = resultclass

def run(self, test):
result = self.resultclass()
unittest.registerResult(result)
result.failfast = self.failfast
test(result)
return result

def default_test_processes():
"""
Default number of test processes when using the --parallel option.
"""
# The current implementation of the parallel test runner requires
# multiprocessing to start subprocesses with fork().
# On Python 3.4+: if multiprocessing.get_start_method() != 'fork':
if not hasattr(os, 'fork'):
return 1
try:
return int(os.environ['DJANGO_TEST_PROCESSES'])
except KeyError:
return multiprocessing.cpu_count()

_worker_id = 0

def _init_worker(counter):
"""
Switch to databases dedicated to this worker.

This helper lives at module-level because of the multiprocessing module's
requirements.
"""

global _worker_id

with counter.get_lock():
counter.value += 1
_worker_id = counter.value

for alias in connections:
connection = connections[alias]
settings_dict = connection.creation.get_test_db_clone_settings(_worker_id)
# connection.settings_dict must be updated in place for changes to be
# reflected in django.db.connections. If the following line assigned
# connection.settings_dict = settings_dict, new threads would connect
# to the default database instead of the appropriate clone.
connection.settings_dict.update(settings_dict)
connection.close()

def _run_subsuite(args):
"""
Run a suite of tests with a RemoteTestRunner and return a RemoteTestResult.

This helper lives at module-level and its arguments are wrapped in a tuple
because of the multiprocessing module's requirements.
"""
subsuite_index, subsuite, failfast = args
runner = RemoteTestRunner(failfast=failfast)
result = runner.run(subsuite)
return subsuite_index, result.events

class ParallelTestSuite(unittest.TestSuite):
"""
Run a series of tests in parallel in several processes.

While the unittest module's documentation implies that orchestrating the
execution of tests is the responsibility of the test runner, in practice,
it appears that TestRunner classes are more concerned with formatting and
displaying test results.

Since there are fewer use cases for customizing TestSuite than TestRunner,
implementing parallelization at the level of the TestSuite improves
interoperability with existing custom test runners. A single instance of a
test runner can still collect results from all tests without being aware
that they have been run in parallel.
"""

# In case someone wants to modify these in a subclass.
init_worker = _init_worker
run_subsuite = _run_subsuite

def __init__(self, suite, processes, failfast=False):
self.subsuites = partition_suite_by_case(suite)
self.processes = processes
self.failfast = failfast
super(ParallelTestSuite, self).__init__()

def run(self, result):
"""
Distribute test cases across workers.

Return an identifier of each test case with its result in order to use
imap_unordered to show results as soon as they're available.

To minimize pickling errors when getting results from workers:

- pass back numeric indexes in self.subsuites instead of tests
- make tracebacks picklable with tblib, if available

Even with tblib, errors may still occur for dynamically created
exception classes such Model.DoesNotExist which cannot be unpickled.
"""
if tblib is not None:
tblib.pickling_support.install()

counter = multiprocessing.Value(ctypes.c_int, 0)
pool = multiprocessing.Pool(
processes=self.processes,
initializer=self.init_worker.__func__,
initargs=[counter])
args = [
(index, subsuite, self.failfast)
for index, subsuite in enumerate(self.subsuites)
]
test_results = pool.imap_unordered(self.run_subsuite.__func__, args)

while True:
if result.shouldStop:
pool.terminate()
break

try:
subsuite_index, events = test_results.next(timeout=0.1)
except multiprocessing.TimeoutError:
continue
except StopIteration:
pool.close()
break

tests = list(self.subsuites[subsuite_index])
for event in events:
event_name = event[0]
handler = getattr(result, event_name, None)
if handler is None:
continue
test = tests[event[1]]
args = event[2:]
handler(test, *args)

pool.join()

return result

[docs]class DiscoverRunner(object):
"""
A Django test runner that uses unittest2 test discovery.
"""

test_suite = unittest.TestSuite
parallel_test_suite = ParallelTestSuite
test_runner = unittest.TextTestRunner
test_loader = unittest.defaultTestLoader
reorder_by = (TestCase, SimpleTestCase)

def __init__(self, pattern=None, top_level=None, verbosity=1,
interactive=True, failfast=False, keepdb=False,
reverse=False, debug_sql=False, parallel=0,
**kwargs):

self.pattern = pattern
self.top_level = top_level

self.verbosity = verbosity
self.interactive = interactive
self.failfast = failfast
self.keepdb = keepdb
self.reverse = reverse
self.debug_sql = debug_sql
self.parallel = parallel

@classmethod

[docs]    def add_arguments(cls, parser):
parser.add_argument('-t', '--top-level-directory',
action='store', dest='top_level', default=None,
help='Top level of project for unittest discovery.')
parser.add_argument('-p', '--pattern', action='store', dest='pattern',
default="test*.py",
help='The test matching pattern. Defaults to test*.py.')
parser.add_argument('-k', '--keepdb', action='store_true', dest='keepdb',
default=False,
help='Preserves the test DB between runs.')
parser.add_argument('-r', '--reverse', action='store_true', dest='reverse',
default=False,
help='Reverses test cases order.')
parser.add_argument('-d', '--debug-sql', action='store_true', dest='debug_sql',
default=False,
help='Prints logged SQL queries on failure.')
parser.add_argument(
'--parallel', dest='parallel', nargs='?', default=1, type=int,
const=default_test_processes(), metavar='N',
help='Run tests using up to N parallel processes.')

[docs]    def setup_test_environment(self, **kwargs):
setup_test_environment()
settings.DEBUG = False
unittest.installHandler()

[docs]    def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
suite = self.test_suite()
test_labels = test_labels or ['.']
extra_tests = extra_tests or []

discover_kwargs = {}
if self.pattern is not None:
discover_kwargs['pattern'] = self.pattern
if self.top_level is not None:
discover_kwargs['top_level_dir'] = self.top_level

for label in test_labels:
kwargs = discover_kwargs.copy()
tests = None

label_as_path = os.path.abspath(label)

# if a module, or "module.ClassName[.method_name]", just run those
if not os.path.exists(label_as_path):
tests = self.test_loader.loadTestsFromName(label)
elif os.path.isdir(label_as_path) and not self.top_level:
# Try to be a bit smarter than unittest about finding the
# default top-level for a given directory path, to avoid
# breaking relative imports. (Unittest's default is to set
# top-level equal to the path, which means relative imports
# will result in "Attempted relative import in non-package.").

# We'd be happy to skip this and require dotted module paths
# (which don't cause this problem) instead of file paths (which
# do), but in the case of a directory in the cwd, which would
# be equally valid if considered as a top-level module or as a
# directory path, unittest unfortunately prefers the latter.

top_level = label_as_path
while True:
init_py = os.path.join(top_level, '__init__.py')
if os.path.exists(init_py):
try_next = os.path.dirname(top_level)
if try_next == top_level:
# __init__.py all the way down? give up.
break
top_level = try_next
continue
break
kwargs['top_level_dir'] = top_level

if not (tests and tests.countTestCases()) and is_discoverable(label):
# Try discovery if path is a package or directory
tests = self.test_loader.discover(start_dir=label, **kwargs)

# Make unittest forget the top-level dir it calculated from this
# run, to support running tests from two different top-levels.
self.test_loader._top_level_dir = None

suite.addTests(tests)

for test in extra_tests:
suite.addTest(test)

suite = reorder_suite(suite, self.reorder_by, self.reverse)

if self.parallel > 1:
parallel_suite = self.parallel_test_suite(suite, self.parallel, self.failfast)

# Since tests are distributed across processes on a per-TestCase
# basis, there's no need for more processes than TestCases.
parallel_units = len(parallel_suite.subsuites)
if self.parallel > parallel_units:
self.parallel = parallel_units

# If there's only one TestCase, parallelization isn't needed.
if self.parallel > 1:
suite = parallel_suite

return suite

[docs]    def setup_databases(self, **kwargs):
return setup_databases(
self.verbosity, self.interactive, self.keepdb, self.debug_sql,
self.parallel, **kwargs
)

def get_resultclass(self):
return DebugSQLTextTestResult if self.debug_sql else None

[docs]    def run_suite(self, suite, **kwargs):
resultclass = self.get_resultclass()
return self.test_runner(
verbosity=self.verbosity,
failfast=self.failfast,
resultclass=resultclass,
).run(suite)

[docs]    def teardown_databases(self, old_config, **kwargs):
"""
Destroys all the non-mirror databases.
"""
for connection, old_name, destroy in old_config:
if destroy:
if self.parallel > 1:
for index in range(self.parallel):
connection.creation.destroy_test_db(
number=index + 1,
verbosity=self.verbosity,
keepdb=self.keepdb,
)
connection.creation.destroy_test_db(old_name, self.verbosity, self.keepdb)

[docs]    def teardown_test_environment(self, **kwargs):
unittest.removeHandler()
teardown_test_environment()

[docs]    def suite_result(self, suite, result, **kwargs):
return len(result.failures) + len(result.errors)

[docs]    def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""
Run the unit tests for all the test labels in the provided list.

Test labels should be dotted Python paths to test modules, test
classes, or test methods.

A list of 'extra' tests may also be provided; these tests
will be added to the test suite.

Returns the number of tests that failed.
"""
self.setup_test_environment()
suite = self.build_suite(test_labels, extra_tests)
old_config = self.setup_databases()
result = self.run_suite(suite)
self.teardown_databases(old_config)
self.teardown_test_environment()
return self.suite_result(suite, result)

def is_discoverable(label):
"""
Check if a test label points to a python package or file directory.

Relative labels like "." and ".." are seen as directories.
"""
try:
mod = import_module(label)
except (ImportError, TypeError):
pass
else:
return hasattr(mod, '__path__')

return os.path.isdir(os.path.abspath(label))

def dependency_ordered(test_databases, dependencies):
"""
Reorder test_databases into an order that honors the dependencies
described in TEST[DEPENDENCIES].
"""
ordered_test_databases = []
resolved_databases = set()

# Maps db signature to dependencies of all it's aliases
dependencies_map = {}

# sanity check - no DB can depend on its own alias
for sig, (_, aliases) in test_databases:
all_deps = set()
for alias in aliases:
all_deps.update(dependencies.get(alias, []))
if not all_deps.isdisjoint(aliases):
raise ImproperlyConfigured(
"Circular dependency: databases %r depend on each other, "
"but are aliases." % aliases)
dependencies_map[sig] = all_deps

while test_databases:
changed = False
deferred = []

# Try to find a DB that has all it's dependencies met
for signature, (db_name, aliases) in test_databases:
if dependencies_map[signature].issubset(resolved_databases):
resolved_databases.update(aliases)
ordered_test_databases.append((signature, (db_name, aliases)))
changed = True
else:
deferred.append((signature, (db_name, aliases)))

if not changed:
raise ImproperlyConfigured(
"Circular dependency in TEST[DEPENDENCIES]")
test_databases = deferred
return ordered_test_databases

def reorder_suite(suite, classes, reverse=False):
"""
Reorders a test suite by test type.

`classes` is a sequence of types

All tests of type classes[0] are placed first, then tests of type
classes[1], etc. Tests with no match in classes are placed last.

If `reverse` is True, tests within classes are sorted in opposite order,
but test classes are not reversed.
"""
class_count = len(classes)
suite_class = type(suite)
bins = [OrderedSet() for i in range(class_count + 1)]
partition_suite_by_type(suite, classes, bins, reverse=reverse)
reordered_suite = suite_class()
for i in range(class_count + 1):
reordered_suite.addTests(bins[i])
return reordered_suite

def partition_suite_by_type(suite, classes, bins, reverse=False):
"""
Partitions a test suite by test type. Also prevents duplicated tests.

classes is a sequence of types
bins is a sequence of TestSuites, one more than classes
reverse changes the ordering of tests within bins

Tests of type classes[i] are added to bins[i],
tests with no match found in classes are place in bins[-1]
"""
suite_class = type(suite)
if reverse:
suite = reversed(tuple(suite))
for test in suite:
if isinstance(test, suite_class):
partition_suite_by_type(test, classes, bins, reverse=reverse)
else:
for i in range(len(classes)):
if isinstance(test, classes[i]):
bins[i].add(test)
break
else:
bins[-1].add(test)

def partition_suite_by_case(suite):
"""
Partitions a test suite by test case, preserving the order of tests.
"""
groups = []
suite_class = type(suite)
for test_type, test_group in itertools.groupby(suite, type):
if issubclass(test_type, unittest.TestCase):
groups.append(suite_class(test_group))
else:
for item in test_group:
groups.extend(partition_suite_by_case(item))
return groups

def get_unique_databases_and_mirrors():
"""
Figure out which databases actually need to be created.

Deduplicate entries in DATABASES that correspond the same database or are
configured as test mirrors.

Return two values:
- test_databases: ordered mapping of signatures to (name, list of aliases)
where all aliases share the same underlying database.
- mirrored_aliases: mapping of mirror aliases to original aliases.
"""
mirrored_aliases = {}
test_databases = {}
dependencies = {}
default_sig = connections[DEFAULT_DB_ALIAS].creation.test_db_signature()

for alias in connections:
connection = connections[alias]
test_settings = connection.settings_dict['TEST']

if test_settings['MIRROR']:
# If the database is marked as a test mirror, save the alias.
mirrored_aliases[alias] = test_settings['MIRROR']
else:
# Store a tuple with DB parameters that uniquely identify it.
# If we have two aliases with the same values for that tuple,
# we only need to create the test database once.
item = test_databases.setdefault(
connection.creation.test_db_signature(),
(connection.settings_dict['NAME'], set())
)
item[1].add(alias)

if 'DEPENDENCIES' in test_settings:
dependencies[alias] = test_settings['DEPENDENCIES']
else:
if alias != DEFAULT_DB_ALIAS and connection.creation.test_db_signature() != default_sig:
dependencies[alias] = test_settings.get('DEPENDENCIES', [DEFAULT_DB_ALIAS])

test_databases = dependency_ordered(test_databases.items(), dependencies)
test_databases = collections.OrderedDict(test_databases)
return test_databases, mirrored_aliases

def setup_databases(verbosity, interactive, keepdb=False, debug_sql=False, parallel=0, **kwargs):
"""
Creates the test databases.
"""
test_databases, mirrored_aliases = get_unique_databases_and_mirrors()

old_names = []

for signature, (db_name, aliases) in test_databases.items():
first_alias = None
for alias in aliases:
connection = connections[alias]
old_names.append((connection, db_name, first_alias is None))

# Actually create the database for the first connection
if first_alias is None:
first_alias = alias
connection.creation.create_test_db(
verbosity=verbosity,
autoclobber=not interactive,
keepdb=keepdb,
serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE", True),
)
if parallel > 1:
for index in range(parallel):
connection.creation.clone_test_db(
number=index + 1,
verbosity=verbosity,
keepdb=keepdb,
)
# Configure all other connections as mirrors of the first one
else:
connections[alias].creation.set_as_test_mirror(
connections[first_alias].settings_dict)

# Configure the test mirrors.
for alias, mirror_alias in mirrored_aliases.items():
connections[alias].creation.set_as_test_mirror(
connections[mirror_alias].settings_dict)

if debug_sql:
for alias in connections:
connections[alias].force_debug_cursor = True

return old_names

Source code for django.http.request

from __future__ import unicode_literals

import copy
import re
import sys
from io import BytesIO
from itertools import chain

from django.conf import settings
from django.core import signing
from django.core.exceptions import DisallowedHost, ImproperlyConfigured
from django.core.files import uploadhandler
from django.http.multipartparser import MultiPartParser, MultiPartParserError
from django.utils import six
from django.utils.datastructures import ImmutableList, MultiValueDict
from django.utils.encoding import (
escape_uri_path, force_bytes, force_str, force_text, iri_to_uri,
)
from django.utils.http import is_same_domain
from django.utils.six.moves.urllib.parse import (
parse_qsl, quote, urlencode, urljoin, urlsplit,
)

RAISE_ERROR = object()
host_validation_re = re.compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9:]+\])(:\d+)?$")

[docs]class UnreadablePostError(IOError):
pass

class RawPostDataException(Exception):
"""
You cannot access raw_post_data from a request that has
multipart/* POST data if it has been accessed via POST,
FILES, etc..
"""
pass

[docs]class HttpRequest(object):
"""A basic HTTP request."""

# The encoding used in GET/POST dicts. None means use default setting.
_encoding = None
_upload_handlers = []

def __init__(self):
# WARNING: The `WSGIRequest` subclass doesn't call `super`.
# Any variable assignment made here should also happen in
# `WSGIRequest.__init__()`.

self.GET = QueryDict(mutable=True)
self.POST = QueryDict(mutable=True)
self.COOKIES = {}
self.META = {}
self.FILES = MultiValueDict()

self.path = ''
self.path_info = ''
self.method = None
self.resolver_match = None
self._post_parse_error = False

def __repr__(self):
if self.method is None or not self.get_full_path():
return force_str('<%s>' % self.__class__.__name__)
return force_str(
'<%s: %s %r>' % (self.__class__.__name__, self.method, force_str(self.get_full_path()))
)

def _get_raw_host(self):
"""
Return the HTTP host using the environment or request headers. Skip
allowed hosts protection, so may return an insecure host.
"""
# We try three options, in order of decreasing preference.
if settings.USE_X_FORWARDED_HOST and (
'HTTP_X_FORWARDED_HOST' in self.META):
host = self.META['HTTP_X_FORWARDED_HOST']
elif 'HTTP_HOST' in self.META:
host = self.META['HTTP_HOST']
else:
# Reconstruct the host using the algorithm from PEP 333.
host = self.META['SERVER_NAME']
server_port = self.get_port()
if server_port != ('443' if self.is_secure() else '80'):
host = '%s:%s' % (host, server_port)
return host

[docs]    def get_host(self):
"""Return the HTTP host using the environment or request headers."""
host = self._get_raw_host()

# There is no hostname validation when DEBUG=True
if settings.DEBUG:
return host

domain, port = split_domain_port(host)
if domain and validate_host(domain, settings.ALLOWED_HOSTS):
return host
else:
msg = "Invalid HTTP_HOST header: %r." % host
if domain:
msg += " You may need to add %r to ALLOWED_HOSTS." % domain
else:
msg += " The domain name provided is not valid according to RFC 1034/1035."
raise DisallowedHost(msg)

[docs]    def get_port(self):
"""Return the port number for the request as a string."""
if settings.USE_X_FORWARDED_PORT and 'HTTP_X_FORWARDED_PORT' in self.META:
port = self.META['HTTP_X_FORWARDED_PORT']
else:
port = self.META['SERVER_PORT']
return str(port)

[docs]    def get_full_path(self, force_append_slash=False):
# RFC 3986 requires query string arguments to be in the ASCII range.
# Rather than crash if this doesn't happen, we encode defensively.
return '%s%s%s' % (
escape_uri_path(self.path),
'/' if force_append_slash and not self.path.endswith('/') else '',
('?' + iri_to_uri(self.META.get('QUERY_STRING', ''))) if self.META.get('QUERY_STRING', '') else ''
)

[docs]    def get_signed_cookie(self, key, default=RAISE_ERROR, salt='', max_age=None):
"""
Attempts to return a signed cookie. If the signature fails or the
cookie has expired, raises an exception... unless you provide the
default argument in which case that value will be returned instead.
"""
try:
cookie_value = self.COOKIES[key]
except KeyError:
if default is not RAISE_ERROR:
return default
else:
raise
try:
value = signing.get_cookie_signer(salt=key + salt).unsign(
cookie_value, max_age=max_age)
except signing.BadSignature:
if default is not RAISE_ERROR:
return default
else:
raise
return value

def get_raw_uri(self):
"""
Return an absolute URI from variables available in this request. Skip
allowed hosts protection, so may return insecure URI.
"""
return '{scheme}://{host}{path}'.format(
scheme=self.scheme,
host=self._get_raw_host(),
path=self.get_full_path(),
)

[docs]    def build_absolute_uri(self, location=None):
"""
Builds an absolute URI from the location and the variables available in
this request. If no ``location`` is specified, the absolute URI is
built on ``request.get_full_path()``. Anyway, if the location is
absolute, it is simply converted to an RFC 3987 compliant URI and
returned and if location is relative or is scheme-relative (i.e.,
``//example.com/``), it is urljoined to a base URL constructed from the
request variables.
"""
if location is None:
# Make it an absolute url (but schemeless and domainless) for the
# edge case that the path starts with '//'.
location = '//%s' % self.get_full_path()
bits = urlsplit(location)
if not (bits.scheme and bits.netloc):
current_uri = '{scheme}://{host}{path}'.format(scheme=self.scheme,
host=self.get_host(),
path=self.path)
# Join the constructed URL with the provided location, which will
# allow the provided ``location`` to apply query strings to the
# base path as well as override the host, if it begins with //
location = urljoin(current_uri, location)
return iri_to_uri(location)

def _get_scheme(self):
"""
Hook for subclasses like WSGIRequest to implement. Returns 'http' by
default.
"""
return 'http'

@property
def scheme(self):
if settings.SECURE_PROXY_SSL_HEADER:
try:
header, value = settings.SECURE_PROXY_SSL_HEADER
except ValueError:
raise ImproperlyConfigured(
'The SECURE_PROXY_SSL_HEADER setting must be a tuple containing two values.'
)
if self.META.get(header) == value:
return 'https'
return self._get_scheme()

[docs]    def is_secure(self):
return self.scheme == 'https'

[docs]    def is_ajax(self):
return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

@property
def encoding(self):
return self._encoding

@encoding.setter
def encoding(self, val):
"""
Sets the encoding used for GET/POST accesses. If the GET or POST
dictionary has already been created, it is removed and recreated on the
next access (so that it is decoded correctly).
"""
self._encoding = val
if hasattr(self, '_get'):
del self._get
if hasattr(self, '_post'):
del self._post

def _initialize_handlers(self):
self._upload_handlers = [uploadhandler.load_handler(handler, self)
for handler in settings.FILE_UPLOAD_HANDLERS]

@property
def upload_handlers(self):
if not self._upload_handlers:
# If there are no upload handlers defined, initialize them from settings.
self._initialize_handlers()
return self._upload_handlers

@upload_handlers.setter
def upload_handlers(self, upload_handlers):
if hasattr(self, '_files'):
raise AttributeError("You cannot set the upload handlers after the upload has been processed.")
self._upload_handlers = upload_handlers

def parse_file_upload(self, META, post_data):
"""Returns a tuple of (POST QueryDict, FILES MultiValueDict)."""
self.upload_handlers = ImmutableList(
self.upload_handlers,
warning="You cannot alter upload handlers after the upload has been processed."
)
parser = MultiPartParser(META, post_data, self.upload_handlers, self.encoding)
return parser.parse()

@property
def body(self):
if not hasattr(self, '_body'):
if self._read_started:
raise RawPostDataException("You cannot access body after reading from request's data stream")
try:
self._body = self.read()
except IOError as e:
six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])
self._stream = BytesIO(self._body)
return self._body

def _mark_post_parse_error(self):
self._post = QueryDict('')
self._files = MultiValueDict()
self._post_parse_error = True

def _load_post_and_files(self):
"""Populate self._post and self._files if the content-type is a form type"""
if self.method != 'POST':
self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
return
if self._read_started and not hasattr(self, '_body'):
self._mark_post_parse_error()
return

if self.META.get('CONTENT_TYPE', '').startswith('multipart/form-data'):
if hasattr(self, '_body'):
# Use already read data
data = BytesIO(self._body)
else:
data = self
try:
self._post, self._files = self.parse_file_upload(self.META, data)
except MultiPartParserError:
# An error occurred while parsing POST data. Since when
# formatting the error the request handler might access
# self.POST, set self._post and self._file to prevent
# attempts to parse POST data again.
# Mark that an error occurred. This allows self.__repr__ to
# be explicit about it instead of simply representing an
# empty POST
self._mark_post_parse_error()
raise
elif self.META.get('CONTENT_TYPE', '').startswith('application/x-www-form-urlencoded'):
self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
else:
self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()

def close(self):
if hasattr(self, '_files'):
for f in chain.from_iterable(l[1] for l in self._files.lists()):
f.close()

# File-like and iterator interface.
#
# Expects self._stream to be set to an appropriate source of bytes by
# a corresponding request subclass (e.g. WSGIRequest).
# Also when request data has already been read by request.POST or
# request.body, self._stream points to a BytesIO instance
# containing that data.

[docs]    def read(self, *args, **kwargs):
self._read_started = True
try:
return self._stream.read(*args, **kwargs)
except IOError as e:
six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])

[docs]    def readline(self, *args, **kwargs):
self._read_started = True
try:
return self._stream.readline(*args, **kwargs)
except IOError as e:
six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])

[docs]    def xreadlines(self):
while True:
buf = self.readline()
if not buf:
break
yield buf

__iter__ = xreadlines

[docs]    def readlines(self):
return list(iter(self))

[docs]class QueryDict(MultiValueDict):
"""
A specialized MultiValueDict which represents a query string.

A QueryDict can be used to represent GET or POST data. It subclasses
MultiValueDict since keys in such data can be repeated, for instance
in the data from a form with a <select multiple> field.

By default QueryDicts are immutable, though the copy() method
will always return a mutable copy.

Both keys and values set on this class are converted from the given encoding
(DEFAULT_CHARSET by default) to unicode.
"""

# These are both reset in __init__, but is specified here at the class
# level so that unpickling will have valid values
_mutable = True
_encoding = None

[docs]    def __init__(self, query_string=None, mutable=False, encoding=None):
super(QueryDict, self).__init__()
if not encoding:
encoding = settings.DEFAULT_CHARSET
self.encoding = encoding
if six.PY3:
if isinstance(query_string, bytes):
# query_string normally contains URL-encoded data, a subset of ASCII.
try:
query_string = query_string.decode(encoding)
except UnicodeDecodeError:
# ... but some user agents are misbehaving :-(
query_string = query_string.decode('iso-8859-1')
for key, value in parse_qsl(query_string or '',
keep_blank_values=True,
encoding=encoding):
self.appendlist(key, value)
else:
for key, value in parse_qsl(query_string or '',
keep_blank_values=True):
try:
value = value.decode(encoding)
except UnicodeDecodeError:
value = value.decode('iso-8859-1')
self.appendlist(force_text(key, encoding, errors='replace'),
value)
self._mutable = mutable

@property
def encoding(self):
if self._encoding is None:
self._encoding = settings.DEFAULT_CHARSET
return self._encoding

@encoding.setter
def encoding(self, value):
self._encoding = value

def _assert_mutable(self):
if not self._mutable:
raise AttributeError("This QueryDict instance is immutable")

[docs]    def __setitem__(self, key, value):
self._assert_mutable()
key = bytes_to_text(key, self.encoding)
value = bytes_to_text(value, self.encoding)
super(QueryDict, self).__setitem__(key, value)

def __delitem__(self, key):
self._assert_mutable()
super(QueryDict, self).__delitem__(key)

def __copy__(self):
result = self.__class__('', mutable=True, encoding=self.encoding)
for key, value in six.iterlists(self):
result.setlist(key, value)
return result

def __deepcopy__(self, memo):
result = self.__class__('', mutable=True, encoding=self.encoding)
memo[id(self)] = result
for key, value in six.iterlists(self):
result.setlist(copy.deepcopy(key, memo), copy.deepcopy(value, memo))
return result

[docs]    def setlist(self, key, list_):
self._assert_mutable()
key = bytes_to_text(key, self.encoding)
list_ = [bytes_to_text(elt, self.encoding) for elt in list_]
super(QueryDict, self).setlist(key, list_)

[docs]    def setlistdefault(self, key, default_list=None):
self._assert_mutable()
return super(QueryDict, self).setlistdefault(key, default_list)

[docs]    def appendlist(self, key, value):
self._assert_mutable()
key = bytes_to_text(key, self.encoding)
value = bytes_to_text(value, self.encoding)
super(QueryDict, self).appendlist(key, value)

[docs]    def pop(self, key, *args):
self._assert_mutable()
return super(QueryDict, self).pop(key, *args)

[docs]    def popitem(self):
self._assert_mutable()
return super(QueryDict, self).popitem()

def clear(self):
self._assert_mutable()
super(QueryDict, self).clear()

[docs]    def setdefault(self, key, default=None):
self._assert_mutable()
key = bytes_to_text(key, self.encoding)
default = bytes_to_text(default, self.encoding)
return super(QueryDict, self).setdefault(key, default)

[docs]    def copy(self):
"""Returns a mutable copy of this object."""
return self.__deepcopy__({})

[docs]    def urlencode(self, safe=None):
"""
Returns an encoded string of all query string arguments.

:arg safe: Used to specify characters which do not require quoting, for
example::

>>> q = QueryDict('', mutable=True)
>>> q['next'] = '/a&b/'
>>> q.urlencode()
'next=%2Fa%26b%2F'
>>> q.urlencode(safe='/')
'next=/a%26b/'
"""
output = []
if safe:
safe = force_bytes(safe, self.encoding)
encode = lambda k, v: '%s=%s' % ((quote(k, safe), quote(v, safe)))
else:
encode = lambda k, v: urlencode({k: v})
for k, list_ in self.lists():
k = force_bytes(k, self.encoding)
output.extend(encode(k, force_bytes(v, self.encoding))
for v in list_)
return '&'.join(output)

# It's neither necessary nor appropriate to use
# django.utils.encoding.smart_text for parsing URLs and form inputs. Thus,
# this slightly more restricted function, used by QueryDict.
def bytes_to_text(s, encoding):
"""
Converts basestring objects to unicode, using the given encoding. Illegally
encoded input characters are replaced with Unicode "unknown" codepoint
(\ufffd).

Returns any non-basestring objects without change.
"""
if isinstance(s, bytes):
return six.text_type(s, encoding, 'replace')
else:
return s

def split_domain_port(host):
"""
Return a (domain, port) tuple from a given host.

Returned domain is lower-cased. If the host is invalid, the domain will be
empty.
"""
host = host.lower()

if not host_validation_re.match(host):
return '', ''

if host[-1] == ']':
# It's an IPv6 address without a port.
return host, ''
bits = host.rsplit(':', 1)
if len(bits) == 2:
return tuple(bits)
return bits[0], ''

def validate_host(host, allowed_hosts):
"""
Validate the given host for this site.

Check that the host looks valid and matches a host or host pattern in the
given list of ``allowed_hosts``. Any pattern beginning with a period
matches a domain and all its subdomains (e.g. ``.example.com`` matches
``example.com`` and any subdomain), ``*`` matches anything, and anything
else must match exactly.

Note: This function assumes that the given host is lower-cased and has
already had the port, if any, stripped off.

Return ``True`` for a valid host, ``False`` otherwise.
"""
host = host[:-1] if host.endswith('.') else host

for pattern in allowed_hosts:
if pattern == '*' or is_same_domain(host, pattern):
return True

return False

Source code for django.http.response

from __future__ import unicode_literals

import datetime
import json
import re
import sys
import time
from email.header import Header

from django.conf import settings
from django.core import signals, signing
from django.core.exceptions import DisallowedRedirect
from django.core.serializers.json import DjangoJSONEncoder
from django.http.cookie import SimpleCookie
from django.utils import six, timezone
from django.utils.encoding import (
force_bytes, force_str, force_text, iri_to_uri,
)
from django.utils.http import cookie_date
from django.utils.six.moves import map
from django.utils.six.moves.http_client import responses
from django.utils.six.moves.urllib.parse import urlparse

_charset_from_content_type_re = re.compile(r';\s*charset=(?P<charset>[^\s;]+)', re.I)

class BadHeaderError(ValueError):
pass

class HttpResponseBase(six.Iterator):
"""
An HTTP response base class with dictionary-accessed headers.

This class doesn't handle content. It should not be used directly.
Use the HttpResponse and StreamingHttpResponse subclasses instead.
"""

status_code = 200

def __init__(self, content_type=None, status=None, reason=None, charset=None):
# _headers is a mapping of the lower-case name to the original case of
# the header (required for working with legacy systems) and the header
# value. Both the name of the header and its value are ASCII strings.
self._headers = {}
self._closable_objects = []
# This parameter is set by the handler. It's necessary to preserve the
# historical behavior of request_finished.
self._handler_class = None
self.cookies = SimpleCookie()
self.closed = False
if status is not None:
self.status_code = status
self._reason_phrase = reason
self._charset = charset
if content_type is None:
content_type = '%s; charset=%s' % (settings.DEFAULT_CONTENT_TYPE,
self.charset)
self['Content-Type'] = content_type

@property
def reason_phrase(self):
if self._reason_phrase is not None:
return self._reason_phrase
# Leave self._reason_phrase unset in order to use the default
# reason phrase for status code.
return responses.get(self.status_code, 'Unknown Status Code')

@reason_phrase.setter
def reason_phrase(self, value):
self._reason_phrase = value

@property
def charset(self):
if self._charset is not None:
return self._charset
content_type = self.get('Content-Type', '')
matched = _charset_from_content_type_re.search(content_type)
if matched:
# Extract the charset and strip its double quotes
return matched.group('charset').replace('"', '')
return settings.DEFAULT_CHARSET

@charset.setter
def charset(self, value):
self._charset = value

def serialize_headers(self):
"""HTTP headers as a bytestring."""
def to_bytes(val, encoding):
return val if isinstance(val, bytes) else val.encode(encoding)

headers = [
(b': '.join([to_bytes(key, 'ascii'), to_bytes(value, 'latin-1')]))
for key, value in self._headers.values()
]
return b'\r\n'.join(headers)

if six.PY3:
__bytes__ = serialize_headers
else:
__str__ = serialize_headers

def _convert_to_charset(self, value, charset, mime_encode=False):
"""Converts headers key/value to ascii/latin-1 native strings.

`charset` must be 'ascii' or 'latin-1'. If `mime_encode` is True and
`value` can't be represented in the given charset, MIME-encoding
is applied.
"""
if not isinstance(value, (bytes, six.text_type)):
value = str(value)
if ((isinstance(value, bytes) and (b'\n' in value or b'\r' in value)) or
isinstance(value, six.text_type) and ('\n' in value or '\r' in value)):
raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
try:
if six.PY3:
if isinstance(value, str):
# Ensure string is valid in given charset
value.encode(charset)
else:
# Convert bytestring using given charset
value = value.decode(charset)
else:
if isinstance(value, str):
# Ensure string is valid in given charset
value.decode(charset)
else:
# Convert unicode string to given charset
value = value.encode(charset)
except UnicodeError as e:
if mime_encode:
# Wrapping in str() is a workaround for #12422 under Python 2.
value = str(Header(value, 'utf-8', maxlinelen=sys.maxsize).encode())
else:
e.reason += ', HTTP response headers must be in %s format' % charset
raise
return value

def __setitem__(self, header, value):
header = self._convert_to_charset(header, 'ascii')
value = self._convert_to_charset(value, 'latin-1', mime_encode=True)
self._headers[header.lower()] = (header, value)

def __delitem__(self, header):
try:
del self._headers[header.lower()]
except KeyError:
pass

def __getitem__(self, header):
return self._headers[header.lower()][1]

def has_header(self, header):
"""Case-insensitive check for a header."""
return header.lower() in self._headers

__contains__ = has_header

def items(self):
return self._headers.values()

def get(self, header, alternate=None):
return self._headers.get(header.lower(), (None, alternate))[1]

def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False):
"""
Sets a cookie.

``expires`` can be:
- a string in the correct format,
- a naive ``datetime.datetime`` object in UTC,
- an aware ``datetime.datetime`` object in any time zone.
If it is a ``datetime.datetime`` object then ``max_age`` will be calculated.
"""
value = force_str(value)
self.cookies[key] = value
if expires is not None:
if isinstance(expires, datetime.datetime):
if timezone.is_aware(expires):
expires = timezone.make_naive(expires, timezone.utc)
delta = expires - expires.utcnow()
# Add one second so the date matches exactly (a fraction of
# time gets lost between converting to a timedelta and
# then the date string).
delta = delta + datetime.timedelta(seconds=1)
# Just set max_age - the max_age logic will set expires.
expires = None
max_age = max(0, delta.days * 86400 + delta.seconds)
else:
self.cookies[key]['expires'] = expires
if max_age is not None:
self.cookies[key]['max-age'] = max_age
# IE requires expires, so set it if hasn't been already.
if not expires:
self.cookies[key]['expires'] = cookie_date(time.time() +
max_age)
if path is not None:
self.cookies[key]['path'] = path
if domain is not None:
self.cookies[key]['domain'] = domain
if secure:
self.cookies[key]['secure'] = True
if httponly:
self.cookies[key]['httponly'] = True

def setdefault(self, key, value):
"""Sets a header unless it has already been set."""
if key not in self:
self[key] = value

def set_signed_cookie(self, key, value, salt='', **kwargs):
value = signing.get_cookie_signer(salt=key + salt).sign(value)
return self.set_cookie(key, value, **kwargs)

def delete_cookie(self, key, path='/', domain=None):
self.set_cookie(key, max_age=0, path=path, domain=domain,
expires='Thu, 01-Jan-1970 00:00:00 GMT')

# Common methods used by subclasses

def make_bytes(self, value):
"""Turn a value into a bytestring encoded in the output charset."""
# Per PEP 3333, this response body must be bytes. To avoid returning
# an instance of a subclass, this function returns `bytes(value)`.
# This doesn't make a copy when `value` already contains bytes.

# Handle string types -- we can't rely on force_bytes here because:
# - under Python 3 it attempts str conversion first
# - when self._charset != 'utf-8' it re-encodes the content
if isinstance(value, bytes):
return bytes(value)
if isinstance(value, six.text_type):
return bytes(value.encode(self.charset))

# Handle non-string types (#16494)
return force_bytes(value, self.charset)

# These methods partially implement the file-like object interface.
# See https://docs.python.org/3/library/io.html#io.IOBase

# The WSGI server must call this method upon completion of the request.
# See http://blog.dscpl.com.au/2012/10/obligations-for-calling-close-on.html
def close(self):
for closable in self._closable_objects:
try:
closable.close()
except Exception:
pass
self.closed = True
signals.request_finished.send(sender=self._handler_class)

def write(self, content):
raise IOError("This %s instance is not writable" % self.__class__.__name__)

def flush(self):
pass

def tell(self):
raise IOError("This %s instance cannot tell its position" % self.__class__.__name__)

# These methods partially implement a stream-like object interface.
# See https://docs.python.org/library/io.html#io.IOBase

def writable(self):
return False

def writelines(self, lines):
raise IOError("This %s instance is not writable" % self.__class__.__name__)

[docs]class HttpResponse(HttpResponseBase):
"""
An HTTP response class with a string as content.

This content that can be read, appended to or replaced.
"""

streaming = False

[docs]    def __init__(self, content=b'', *args, **kwargs):
super(HttpResponse, self).__init__(*args, **kwargs)
# Content is a bytestring. See the `content` property methods.
self.content = content

def __repr__(self):
return '<%(cls)s status_code=%(status_code)d, "%(content_type)s">' % {
'cls': self.__class__.__name__,
'status_code': self.status_code,
'content_type': self['Content-Type'],
}

def serialize(self):
"""Full HTTP message, including headers, as a bytestring."""
return self.serialize_headers() + b'\r\n\r\n' + self.content

if six.PY3:
__bytes__ = serialize
else:
__str__ = serialize

@property
def content(self):
return b''.join(self._container)

@content.setter
def content(self, value):
# Consume iterators upon assignment to allow repeated iteration.
if hasattr(value, '__iter__') and not isinstance(value, (bytes, six.string_types)):
if hasattr(value, 'close'):
self._closable_objects.append(value)
value = b''.join(self.make_bytes(chunk) for chunk in value)
else:
value = self.make_bytes(value)
# Create a list of properly encoded bytestrings to support write().
self._container = [value]

def __iter__(self):
return iter(self._container)

[docs]    def write(self, content):
self._container.append(self.make_bytes(content))

[docs]    def tell(self):
return len(self.content)

[docs]    def getvalue(self):
return self.content

[docs]    def writable(self):
return True

[docs]    def writelines(self, lines):
for line in lines:
self.write(line)

[docs]class StreamingHttpResponse(HttpResponseBase):
"""
A streaming HTTP response class with an iterator as content.

This should only be iterated once, when the response is streamed to the
client. However, it can be appended to or replaced with a new iterator
that wraps the original content (or yields entirely new content).
"""

streaming = True

def __init__(self, streaming_content=(), *args, **kwargs):
super(StreamingHttpResponse, self).__init__(*args, **kwargs)
# `streaming_content` should be an iterable of bytestrings.
# See the `streaming_content` property methods.
self.streaming_content = streaming_content

@property
def content(self):
raise AttributeError("This %s instance has no `content` attribute. "
"Use `streaming_content` instead." % self.__class__.__name__)

@property
def streaming_content(self):
return map(self.make_bytes, self._iterator)

@streaming_content.setter
def streaming_content(self, value):
self._set_streaming_content(value)

def _set_streaming_content(self, value):
# Ensure we can never iterate on "value" more than once.
self._iterator = iter(value)
if hasattr(value, 'close'):
self._closable_objects.append(value)

def __iter__(self):
return self.streaming_content

def getvalue(self):
return b''.join(self.streaming_content)

[docs]class FileResponse(StreamingHttpResponse):
"""
A streaming HTTP response class optimized for files.
"""
block_size = 4096

def _set_streaming_content(self, value):
if hasattr(value, 'read'):
self.file_to_stream = value
filelike = value
if hasattr(filelike, 'close'):
self._closable_objects.append(filelike)
value = iter(lambda: filelike.read(self.block_size), b'')
else:
self.file_to_stream = None
super(FileResponse, self)._set_streaming_content(value)

class HttpResponseRedirectBase(HttpResponse):
allowed_schemes = ['http', 'https', 'ftp']

def __init__(self, redirect_to, *args, **kwargs):
parsed = urlparse(force_text(redirect_to))
if parsed.scheme and parsed.scheme not in self.allowed_schemes:
raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)
super(HttpResponseRedirectBase, self).__init__(*args, **kwargs)
self['Location'] = iri_to_uri(redirect_to)

url = property(lambda self: self['Location'])

def __repr__(self):
return '<%(cls)s status_code=%(status_code)d, "%(content_type)s", url="%(url)s">' % {
'cls': self.__class__.__name__,
'status_code': self.status_code,
'content_type': self['Content-Type'],
'url': self.url,
}

[docs]class HttpResponseRedirect(HttpResponseRedirectBase):
status_code = 302

[docs]class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
status_code = 301

[docs]class HttpResponseNotModified(HttpResponse):
status_code = 304

def __init__(self, *args, **kwargs):
super(HttpResponseNotModified, self).__init__(*args, **kwargs)
del self['content-type']

@HttpResponse.content.setter
def content(self, value):
if value:
raise AttributeError("You cannot set content to a 304 (Not Modified) response")
self._container = []

[docs]class HttpResponseBadRequest(HttpResponse):
status_code = 400

[docs]class HttpResponseNotFound(HttpResponse):
status_code = 404

[docs]class HttpResponseForbidden(HttpResponse):
status_code = 403

[docs]class HttpResponseNotAllowed(HttpResponse):
status_code = 405

def __init__(self, permitted_methods, *args, **kwargs):
super(HttpResponseNotAllowed, self).__init__(*args, **kwargs)
self['Allow'] = ', '.join(permitted_methods)

def __repr__(self):
return '<%(cls)s [%(methods)s] status_code=%(status_code)d, "%(content_type)s">' % {
'cls': self.__class__.__name__,
'status_code': self.status_code,
'content_type': self['Content-Type'],
'methods': self['Allow'],
}

[docs]class HttpResponseGone(HttpResponse):
status_code = 410

[docs]class HttpResponseServerError(HttpResponse):
status_code = 500

class Http404(Exception):
pass

[docs]class JsonResponse(HttpResponse):
"""
An HTTP response class that consumes data to be serialized to JSON.

:param data: Data to be dumped into json. By default only ``dict`` objects
are allowed to be passed due to a security flaw before EcmaScript 5. See
the ``safe`` parameter for more information.
:param encoder: Should be an json encoder class. Defaults to
``django.core.serializers.json.DjangoJSONEncoder``.
:param safe: Controls if only ``dict`` objects may be serialized. Defaults
to ``True``.
:param json_dumps_params: A dictionary of kwargs passed to json.dumps().
"""

def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if safe and not isinstance(data, dict):
raise TypeError('In order to allow non-dict objects to be '
'serialized set the safe parameter to False')
if json_dumps_params is None:
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params)
super(JsonResponse, self).__init__(content=data, **kwargs)

Source code for django.db.utils

import inspect
import os
import pkgutil
import warnings
from importlib import import_module
from threading import local

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import six
from django.utils._os import npath, upath
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.functional import cached_property
from django.utils.module_loading import import_string

DEFAULT_DB_ALIAS = 'default'
DJANGO_VERSION_PICKLE_KEY = '_django_version'

[docs]class Error(Exception if six.PY3 else StandardError):  # NOQA: StandardError undefined on PY3
pass

[docs]class InterfaceError(Error):
pass

[docs]class DatabaseError(Error):
pass

[docs]class DataError(DatabaseError):
pass

[docs]class OperationalError(DatabaseError):
pass

[docs]class IntegrityError(DatabaseError):
pass

[docs]class InternalError(DatabaseError):
pass

[docs]class ProgrammingError(DatabaseError):
pass

[docs]class NotSupportedError(DatabaseError):
pass

class DatabaseErrorWrapper(object):
"""
Context manager and decorator that re-throws backend-specific database
exceptions using Django's common wrappers.
"""

def __init__(self, wrapper):
"""
wrapper is a database wrapper.

It must have a Database attribute defining PEP-249 exceptions.
"""
self.wrapper = wrapper

def __enter__(self):
pass

def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
return
for dj_exc_type in (
DataError,
OperationalError,
IntegrityError,
InternalError,
ProgrammingError,
NotSupportedError,
DatabaseError,
InterfaceError,
Error,
):
db_exc_type = getattr(self.wrapper.Database, dj_exc_type.__name__)
if issubclass(exc_type, db_exc_type):
dj_exc_value = dj_exc_type(*exc_value.args)
dj_exc_value.__cause__ = exc_value
# Only set the 'errors_occurred' flag for errors that may make
# the connection unusable.
if dj_exc_type not in (DataError, IntegrityError):
self.wrapper.errors_occurred = True
six.reraise(dj_exc_type, dj_exc_value, traceback)

def __call__(self, func):
# Note that we are intentionally not using @wraps here for performance
# reasons. Refs #21109.
def inner(*args, **kwargs):
with self:
return func(*args, **kwargs)
return inner

def load_backend(backend_name):
"""
Return a database backend's "base" module given a fully qualified database
backend name, or raise an error if it doesn't exist.
"""
# This backend was renamed in Django 1.9.
if backend_name == 'django.db.backends.postgresql_psycopg2':
backend_name = 'django.db.backends.postgresql'

try:
return import_module('%s.base' % backend_name)
except ImportError as e_user:
# The database backend wasn't found. Display a helpful error message
# listing all possible (built-in) database backends.
backend_dir = os.path.join(os.path.dirname(upath(__file__)), 'backends')
try:
builtin_backends = [
name for _, name, ispkg in pkgutil.iter_modules([npath(backend_dir)])
if ispkg and name not in {'base', 'dummy', 'postgresql_psycopg2'}
]
except EnvironmentError:
builtin_backends = []
if backend_name not in ['django.db.backends.%s' % b for b in
builtin_backends]:
backend_reprs = map(repr, sorted(builtin_backends))
error_msg = ("%r isn't an available database backend.\n"
"Try using 'django.db.backends.XXX', where XXX "
"is one of:\n    %s\nError was: %s" %
(backend_name, ", ".join(backend_reprs), e_user))
raise ImproperlyConfigured(error_msg)
else:
# If there's some other error, this must be an error in Django
raise

class ConnectionDoesNotExist(Exception):
pass

class ConnectionHandler(object):
def __init__(self, databases=None):
"""
databases is an optional dictionary of database definitions (structured
like settings.DATABASES).
"""
self._databases = databases
self._connections = local()

@cached_property
def databases(self):
if self._databases is None:
self._databases = settings.DATABASES
if self._databases == {}:
self._databases = {
DEFAULT_DB_ALIAS: {
'ENGINE': 'django.db.backends.dummy',
},
}
if self._databases[DEFAULT_DB_ALIAS] == {}:
self._databases[DEFAULT_DB_ALIAS]['ENGINE'] = 'django.db.backends.dummy'

if DEFAULT_DB_ALIAS not in self._databases:
raise ImproperlyConfigured("You must define a '%s' database" % DEFAULT_DB_ALIAS)
return self._databases

def ensure_defaults(self, alias):
"""
Puts the defaults into the settings dictionary for a given connection
where no settings is provided.
"""
try:
conn = self.databases[alias]
except KeyError:
raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias)

conn.setdefault('ATOMIC_REQUESTS', False)
conn.setdefault('AUTOCOMMIT', True)
conn.setdefault('ENGINE', 'django.db.backends.dummy')
if conn['ENGINE'] == 'django.db.backends.' or not conn['ENGINE']:
conn['ENGINE'] = 'django.db.backends.dummy'
conn.setdefault('CONN_MAX_AGE', 0)
conn.setdefault('OPTIONS', {})
conn.setdefault('TIME_ZONE', None)
for setting in ['NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']:
conn.setdefault(setting, '')

def prepare_test_settings(self, alias):
"""
Makes sure the test settings are available in the 'TEST' sub-dictionary.
"""
try:
conn = self.databases[alias]
except KeyError:
raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias)

test_settings = conn.setdefault('TEST', {})
for key in ['CHARSET', 'COLLATION', 'NAME', 'MIRROR']:
test_settings.setdefault(key, None)

def __getitem__(self, alias):
if hasattr(self._connections, alias):
return getattr(self._connections, alias)

self.ensure_defaults(alias)
self.prepare_test_settings(alias)
db = self.databases[alias]
backend = load_backend(db['ENGINE'])
conn = backend.DatabaseWrapper(db, alias)
setattr(self._connections, alias, conn)
return conn

def __setitem__(self, key, value):
setattr(self._connections, key, value)

def __delitem__(self, key):
delattr(self._connections, key)

def __iter__(self):
return iter(self.databases)

def all(self):
return [self[alias] for alias in self]

def close_all(self):
for alias in self:
try:
connection = getattr(self._connections, alias)
except AttributeError:
continue
connection.close()

class ConnectionRouter(object):
def __init__(self, routers=None):
"""
If routers is not specified, will default to settings.DATABASE_ROUTERS.
"""
self._routers = routers

@cached_property
def routers(self):
if self._routers is None:
self._routers = settings.DATABASE_ROUTERS
routers = []
for r in self._routers:
if isinstance(r, six.string_types):
router = import_string(r)()
else:
router = r
routers.append(router)
return routers

def _router_func(action):
def _route_db(self, model, **hints):
chosen_db = None
for router in self.routers:
try:
method = getattr(router, action)
except AttributeError:
# If the router doesn't have a method, skip to the next one.
pass
else:
chosen_db = method(model, **hints)
if chosen_db:
return chosen_db
instance = hints.get('instance')
if instance is not None and instance._state.db:
return instance._state.db
return DEFAULT_DB_ALIAS
return _route_db

db_for_read = _router_func('db_for_read')
db_for_write = _router_func('db_for_write')

def allow_relation(self, obj1, obj2, **hints):
for router in self.routers:
try:
method = router.allow_relation
except AttributeError:
# If the router doesn't have a method, skip to the next one.
pass
else:
allow = method(obj1, obj2, **hints)
if allow is not None:
return allow
return obj1._state.db == obj2._state.db

def allow_migrate(self, db, app_label, **hints):
for router in self.routers:
try:
method = router.allow_migrate
except AttributeError:
# If the router doesn't have a method, skip to the next one.
continue

if six.PY3:
sig = inspect.signature(router.allow_migrate)
has_deprecated_signature = not any(
p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()
)
else:
argspec = inspect.getargspec(router.allow_migrate)
has_deprecated_signature = len(argspec.args) == 3 and not argspec.keywords

if has_deprecated_signature:
warnings.warn(
"The signature of allow_migrate has changed from "
"allow_migrate(self, db, model) to "
"allow_migrate(self, db, app_label, model_name=None, **hints). "
"Support for the old signature will be removed in Django 1.10.",
RemovedInDjango110Warning)
model = hints.get('model')
allow = None if model is None else method(db, model)
else:
allow = method(db, app_label, **hints)

if allow is not None:
return allow
return True

def allow_migrate_model(self, db, model):
return self.allow_migrate(
db,
model._meta.app_label,
model_name=model._meta.model_name,
model=model,
)

def get_migratable_models(self, app_config, db, include_auto_created=False):
"""
Return app models allowed to be synchronized on provided db.
"""
models = app_config.get_models(include_auto_created=include_auto_created)
return [model for model in models if self.allow_migrate_model(db, model)]

Source code for django.db.transaction

from django.db import (
DEFAULT_DB_ALIAS, DatabaseError, Error, ProgrammingError, connections,
)
from django.utils.decorators import ContextDecorator

[docs]class TransactionManagementError(ProgrammingError):
"""
This exception is thrown when transaction management is used improperly.
"""
pass

def get_connection(using=None):
"""
Get a database connection by name, or the default database connection
if no name is provided. This is a private API.
"""
if using is None:
using = DEFAULT_DB_ALIAS
return connections[using]

[docs]def get_autocommit(using=None):
"""
Get the autocommit status of the connection.
"""
return get_connection(using).get_autocommit()

[docs]def set_autocommit(autocommit, using=None):
"""
Set the autocommit status of the connection.
"""
return get_connection(using).set_autocommit(autocommit)

[docs]def commit(using=None):
"""
Commits a transaction.
"""
get_connection(using).commit()

[docs]def rollback(using=None):
"""
Rolls back a transaction.
"""
get_connection(using).rollback()

[docs]def savepoint(using=None):
"""
Creates a savepoint (if supported and required by the backend) inside the
current transaction. Returns an identifier for the savepoint that will be
used for the subsequent rollback or commit.
"""
return get_connection(using).savepoint()

[docs]def savepoint_rollback(sid, using=None):
"""
Rolls back the most recent savepoint (if one exists). Does nothing if
savepoints are not supported.
"""
get_connection(using).savepoint_rollback(sid)

[docs]def savepoint_commit(sid, using=None):
"""
Commits the most recent savepoint (if one exists). Does nothing if
savepoints are not supported.
"""
get_connection(using).savepoint_commit(sid)

[docs]def clean_savepoints(using=None):
"""
Resets the counter used to generate unique savepoint ids in this thread.
"""
get_connection(using).clean_savepoints()

[docs]def get_rollback(using=None):
"""
Gets the "needs rollback" flag -- for *advanced use* only.
"""
return get_connection(using).get_rollback()

[docs]def set_rollback(rollback, using=None):
"""
Sets or unsets the "needs rollback" flag -- for *advanced use* only.

When `rollback` is `True`, it triggers a rollback when exiting the
innermost enclosing atomic block that has `savepoint=True` (that's the
default). Use this to force a rollback without raising an exception.

When `rollback` is `False`, it prevents such a rollback. Use this only
after rolling back to a known-good state! Otherwise, you break the atomic
block and data corruption may occur.
"""
return get_connection(using).set_rollback(rollback)

[docs]def on_commit(func, using=None):
"""
Register `func` to be called when the current transaction is committed.
If the current transaction is rolled back, `func` will not be called.
"""
get_connection(using).on_commit(func)

#################################
# Decorators / context managers #
#################################

class Atomic(ContextDecorator):
"""
This class guarantees the atomic execution of a given block.

An instance can be used either as a decorator or as a context manager.

When it's used as a decorator, __call__ wraps the execution of the
decorated function in the instance itself, used as a context manager.

When it's used as a context manager, __enter__ creates a transaction or a
savepoint, depending on whether a transaction is already in progress, and
__exit__ commits the transaction or releases the savepoint on normal exit,
and rolls back the transaction or to the savepoint on exceptions.

It's possible to disable the creation of savepoints if the goal is to
ensure that some code runs within a transaction without creating overhead.

A stack of savepoints identifiers is maintained as an attribute of the
connection. None denotes the absence of a savepoint.

This allows reentrancy even if the same AtomicWrapper is reused. For
example, it's possible to define `oa = @atomic('other')` and use `@oa` or
`with oa:` multiple times.

Since database connections are thread-local, this is thread-safe.

This is a private API.
"""

def __init__(self, using, savepoint):
self.using = using
self.savepoint = savepoint

def __enter__(self):
connection = get_connection(self.using)

if not connection.in_atomic_block:
# Reset state when entering an outermost atomic block.
connection.commit_on_exit = True
connection.needs_rollback = False
if not connection.get_autocommit():
# Some database adapters (namely sqlite3) don't handle
# transactions and savepoints properly when autocommit is off.
# Turning autocommit back on isn't an option; it would trigger
# a premature commit. Give up if that happens.
if connection.features.autocommits_when_autocommit_is_off:
raise TransactionManagementError(
"Your database backend doesn't behave properly when "
"autocommit is off. Turn it on before using 'atomic'.")
# Pretend we're already in an atomic block to bypass the code
# that disables autocommit to enter a transaction, and make a
# note to deal with this case in __exit__.
connection.in_atomic_block = True
connection.commit_on_exit = False

if connection.in_atomic_block:
# We're already in a transaction; create a savepoint, unless we
# were told not to or we're already waiting for a rollback. The
# second condition avoids creating useless savepoints and prevents
# overwriting needs_rollback until the rollback is performed.
if self.savepoint and not connection.needs_rollback:
sid = connection.savepoint()
connection.savepoint_ids.append(sid)
else:
connection.savepoint_ids.append(None)
else:
connection.set_autocommit(False, force_begin_transaction_with_broken_autocommit=True)
connection.in_atomic_block = True

def __exit__(self, exc_type, exc_value, traceback):
connection = get_connection(self.using)

if connection.savepoint_ids:
sid = connection.savepoint_ids.pop()
else:
# Prematurely unset this flag to allow using commit or rollback.
connection.in_atomic_block = False

try:
if connection.closed_in_transaction:
# The database will perform a rollback by itself.
# Wait until we exit the outermost block.
pass

elif exc_type is None and not connection.needs_rollback:
if connection.in_atomic_block:
# Release savepoint if there is one
if sid is not None:
try:
connection.savepoint_commit(sid)
except DatabaseError:
try:
connection.savepoint_rollback(sid)
# The savepoint won't be reused. Release it to
# minimize overhead for the database server.
connection.savepoint_commit(sid)
except Error:
# If rolling back to a savepoint fails, mark for
# rollback at a higher level and avoid shadowing
# the original exception.
connection.needs_rollback = True
raise
else:
# Commit transaction
try:
connection.commit()
except DatabaseError:
try:
connection.rollback()
except Error:
# An error during rollback means that something
# went wrong with the connection. Drop it.
connection.close()
raise
else:
# This flag will be set to True again if there isn't a savepoint
# allowing to perform the rollback at this level.
connection.needs_rollback = False
if connection.in_atomic_block:
# Roll back to savepoint if there is one, mark for rollback
# otherwise.
if sid is None:
connection.needs_rollback = True
else:
try:
connection.savepoint_rollback(sid)
# The savepoint won't be reused. Release it to
# minimize overhead for the database server.
connection.savepoint_commit(sid)
except Error:
# If rolling back to a savepoint fails, mark for
# rollback at a higher level and avoid shadowing
# the original exception.
connection.needs_rollback = True
else:
# Roll back transaction
try:
connection.rollback()
except Error:
# An error during rollback means that something
# went wrong with the connection. Drop it.
connection.close()

finally:
# Outermost block exit when autocommit was enabled.
if not connection.in_atomic_block:
if connection.closed_in_transaction:
connection.connection = None
else:
connection.set_autocommit(True)
# Outermost block exit when autocommit was disabled.
elif not connection.savepoint_ids and not connection.commit_on_exit:
if connection.closed_in_transaction:
connection.connection = None
else:
connection.in_atomic_block = False

[docs]def atomic(using=None, savepoint=True):
# Bare decorator: @atomic -- although the first argument is called
# `using`, it's actually the function being decorated.
if callable(using):
return Atomic(DEFAULT_DB_ALIAS, savepoint)(using)
# Decorator: @atomic(...) or context manager: with atomic(...): ...
else:
return Atomic(using, savepoint)

def _non_atomic_requests(view, using):
try:
view._non_atomic_requests.add(using)
except AttributeError:
view._non_atomic_requests = {using}
return view

[docs]def non_atomic_requests(using=None):
if callable(using):
return _non_atomic_requests(using, DEFAULT_DB_ALIAS)
else:
if using is None:
using = DEFAULT_DB_ALIAS
return lambda view: _non_atomic_requests(view, using)

Source code for django.db.models.lookups

from copy import copy

from django.conf import settings
from django.db.models.expressions import Func, Value
from django.db.models.fields import (
DateField, DateTimeField, Field, IntegerField, TimeField,
)
from django.db.models.query_utils import RegisterLookupMixin
from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.six.moves import range

[docs]class Lookup(object):
lookup_name = None

def __init__(self, lhs, rhs):
self.lhs, self.rhs = lhs, rhs
self.rhs = self.get_prep_lookup()
if hasattr(self.lhs, 'get_bilateral_transforms'):
bilateral_transforms = self.lhs.get_bilateral_transforms()
else:
bilateral_transforms = []
if bilateral_transforms:
# We should warn the user as soon as possible if he is trying to apply
# a bilateral transformation on a nested QuerySet: that won't work.
# We need to import QuerySet here so as to avoid circular
from django.db.models.query import QuerySet
if isinstance(rhs, QuerySet):
raise NotImplementedError("Bilateral transformations on nested querysets are not supported.")
self.bilateral_transforms = bilateral_transforms

def apply_bilateral_transforms(self, value):
for transform in self.bilateral_transforms:
value = transform(value)
return value

def batch_process_rhs(self, compiler, connection, rhs=None):
if rhs is None:
rhs = self.rhs
if self.bilateral_transforms:
sqls, sqls_params = [], []
for p in rhs:
value = Value(p, output_field=self.lhs.output_field)
value = self.apply_bilateral_transforms(value)
value = value.resolve_expression(compiler.query)
sql, sql_params = compiler.compile(value)
sqls.append(sql)
sqls_params.extend(sql_params)
else:
params = self.lhs.output_field.get_db_prep_lookup(
self.lookup_name, rhs, connection, prepared=True)
sqls, sqls_params = ['%s'] * len(params), params
return sqls, sqls_params

def get_prep_lookup(self):
return self.lhs.output_field.get_prep_lookup(self.lookup_name, self.rhs)

def get_db_prep_lookup(self, value, connection):
return (
'%s', self.lhs.output_field.get_db_prep_lookup(
self.lookup_name, value, connection, prepared=True))

[docs]    def process_lhs(self, compiler, connection, lhs=None):
lhs = lhs or self.lhs
return compiler.compile(lhs)

[docs]    def process_rhs(self, compiler, connection):
value = self.rhs
if self.bilateral_transforms:
if self.rhs_is_direct_value():
# Do not call get_db_prep_lookup here as the value will be
# transformed before being used for lookup
value = Value(value, output_field=self.lhs.output_field)
value = self.apply_bilateral_transforms(value)
value = value.resolve_expression(compiler.query)
# Due to historical reasons there are a couple of different
# ways to produce sql here. get_compiler is likely a Query
# instance, _as_sql QuerySet and as_sql just something with
# as_sql. Finally the value can of course be just plain
# Python value.
if hasattr(value, 'get_compiler'):
value = value.get_compiler(connection=connection)
if hasattr(value, 'as_sql'):
sql, params = compiler.compile(value)
return '(' + sql + ')', params
if hasattr(value, '_as_sql'):
sql, params = value._as_sql(connection=connection)
return '(' + sql + ')', params
else:
return self.get_db_prep_lookup(value, connection)

def rhs_is_direct_value(self):
return not(
hasattr(self.rhs, 'as_sql') or
hasattr(self.rhs, '_as_sql') or
hasattr(self.rhs, 'get_compiler'))

def relabeled_clone(self, relabels):
new = copy(self)
new.lhs = new.lhs.relabeled_clone(relabels)
if hasattr(new.rhs, 'relabeled_clone'):
new.rhs = new.rhs.relabeled_clone(relabels)
return new

def get_group_by_cols(self):
cols = self.lhs.get_group_by_cols()
if hasattr(self.rhs, 'get_group_by_cols'):
cols.extend(self.rhs.get_group_by_cols())
return cols

def as_sql(self, compiler, connection):
raise NotImplementedError

@cached_property
def contains_aggregate(self):
return self.lhs.contains_aggregate or getattr(self.rhs, 'contains_aggregate', False)

[docs]class Transform(RegisterLookupMixin, Func):
"""
RegisterLookupMixin() is first so that get_lookup() and get_transform()
first examine self and then check output_field.
"""
bilateral = False

def __init__(self, expression, **extra):
# Restrict Transform to allow only a single expression.
super(Transform, self).__init__(expression, **extra)

@property
def lhs(self):
return self.get_source_expressions()[0]

def get_bilateral_transforms(self):
if hasattr(self.lhs, 'get_bilateral_transforms'):
bilateral_transforms = self.lhs.get_bilateral_transforms()
else:
bilateral_transforms = []
if self.bilateral:
bilateral_transforms.append(self.__class__)
return bilateral_transforms

class BuiltinLookup(Lookup):
def process_lhs(self, compiler, connection, lhs=None):
lhs_sql, params = super(BuiltinLookup, self).process_lhs(
compiler, connection, lhs)
field_internal_type = self.lhs.output_field.get_internal_type()
db_type = self.lhs.output_field.db_type(connection=connection)
lhs_sql = connection.ops.field_cast_sql(
db_type, field_internal_type) % lhs_sql
lhs_sql = connection.ops.lookup_cast(self.lookup_name, field_internal_type) % lhs_sql
return lhs_sql, list(params)

def as_sql(self, compiler, connection):
lhs_sql, params = self.process_lhs(compiler, connection)
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
params.extend(rhs_params)
rhs_sql = self.get_rhs_op(connection, rhs_sql)
return '%s %s' % (lhs_sql, rhs_sql), params

def get_rhs_op(self, connection, rhs):
return connection.operators[self.lookup_name] % rhs

class Exact(BuiltinLookup):
lookup_name = 'exact'
Field.register_lookup(Exact)

class IExact(BuiltinLookup):
lookup_name = 'iexact'

def process_rhs(self, qn, connection):
rhs, params = super(IExact, self).process_rhs(qn, connection)
if params:
params[0] = connection.ops.prep_for_iexact_query(params[0])
return rhs, params

Field.register_lookup(IExact)

class GreaterThan(BuiltinLookup):
lookup_name = 'gt'
Field.register_lookup(GreaterThan)

class GreaterThanOrEqual(BuiltinLookup):
lookup_name = 'gte'
Field.register_lookup(GreaterThanOrEqual)

class LessThan(BuiltinLookup):
lookup_name = 'lt'
Field.register_lookup(LessThan)

class LessThanOrEqual(BuiltinLookup):
lookup_name = 'lte'
Field.register_lookup(LessThanOrEqual)

class In(BuiltinLookup):
lookup_name = 'in'

def process_rhs(self, compiler, connection):
if self.rhs_is_direct_value():
# rhs should be an iterable, we use batch_process_rhs
# to prepare/transform those values
rhs = list(self.rhs)
if not rhs:
from django.db.models.sql.datastructures import EmptyResultSet
raise EmptyResultSet
sqls, sqls_params = self.batch_process_rhs(compiler, connection, rhs)
placeholder = '(' + ', '.join(sqls) + ')'
return (placeholder, sqls_params)
else:
return super(In, self).process_rhs(compiler, connection)

def get_rhs_op(self, connection, rhs):
return 'IN %s' % rhs

def as_sql(self, compiler, connection):
max_in_list_size = connection.ops.max_in_list_size()
if self.rhs_is_direct_value() and max_in_list_size and len(self.rhs) > max_in_list_size:
return self.split_parameter_list_as_sql(compiler, connection)
return super(In, self).as_sql(compiler, connection)

def split_parameter_list_as_sql(self, compiler, connection):
# This is a special case for databases which limit the number of
# elements which can appear in an 'IN' clause.
max_in_list_size = connection.ops.max_in_list_size()
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.batch_process_rhs(compiler, connection)
in_clause_elements = ['(']
params = []
for offset in range(0, len(rhs_params), max_in_list_size):
if offset > 0:
in_clause_elements.append(' OR ')
in_clause_elements.append('%s IN (' % lhs)
params.extend(lhs_params)
sqls = rhs[offset: offset + max_in_list_size]
sqls_params = rhs_params[offset: offset + max_in_list_size]
param_group = ', '.join(sqls)
in_clause_elements.append(param_group)
in_clause_elements.append(')')
params.extend(sqls_params)
in_clause_elements.append(')')
return ''.join(in_clause_elements), params
Field.register_lookup(In)

class PatternLookup(BuiltinLookup):

def get_rhs_op(self, connection, rhs):
# Assume we are in startswith. We need to produce SQL like:
#     col LIKE %s, ['thevalue%']
# For python values we can (and should) do that directly in Python,
# but if the value is for example reference to other column, then
# we need to add the % pattern match to the lookup by something like
#     col LIKE othercol || '%%'
# So, for Python values we don't need any special pattern, but for
# SQL reference values or SQL transformations we need the correct
# pattern added.
if (hasattr(self.rhs, 'get_compiler') or hasattr(self.rhs, 'as_sql')
or hasattr(self.rhs, '_as_sql') or self.bilateral_transforms):
pattern = connection.pattern_ops[self.lookup_name].format(connection.pattern_esc)
return pattern.format(rhs)
else:
return super(PatternLookup, self).get_rhs_op(connection, rhs)

class Contains(PatternLookup):
lookup_name = 'contains'

def process_rhs(self, qn, connection):
rhs, params = super(Contains, self).process_rhs(qn, connection)
if params and not self.bilateral_transforms:
params[0] = "%%%s%%" % connection.ops.prep_for_like_query(params[0])
return rhs, params
Field.register_lookup(Contains)

class IContains(Contains):
lookup_name = 'icontains'
Field.register_lookup(IContains)

class StartsWith(PatternLookup):
lookup_name = 'startswith'

def process_rhs(self, qn, connection):
rhs, params = super(StartsWith, self).process_rhs(qn, connection)
if params and not self.bilateral_transforms:
params[0] = "%s%%" % connection.ops.prep_for_like_query(params[0])
return rhs, params
Field.register_lookup(StartsWith)

class IStartsWith(PatternLookup):
lookup_name = 'istartswith'

def process_rhs(self, qn, connection):
rhs, params = super(IStartsWith, self).process_rhs(qn, connection)
if params and not self.bilateral_transforms:
params[0] = "%s%%" % connection.ops.prep_for_like_query(params[0])
return rhs, params
Field.register_lookup(IStartsWith)

class EndsWith(PatternLookup):
lookup_name = 'endswith'

def process_rhs(self, qn, connection):
rhs, params = super(EndsWith, self).process_rhs(qn, connection)
if params and not self.bilateral_transforms:
params[0] = "%%%s" % connection.ops.prep_for_like_query(params[0])
return rhs, params
Field.register_lookup(EndsWith)

class IEndsWith(PatternLookup):
lookup_name = 'iendswith'

def process_rhs(self, qn, connection):
rhs, params = super(IEndsWith, self).process_rhs(qn, connection)
if params and not self.bilateral_transforms:
params[0] = "%%%s" % connection.ops.prep_for_like_query(params[0])
return rhs, params
Field.register_lookup(IEndsWith)

class Between(BuiltinLookup):
def get_rhs_op(self, connection, rhs):
return "BETWEEN %s AND %s" % (rhs, rhs)

class Range(BuiltinLookup):
lookup_name = 'range'

def get_rhs_op(self, connection, rhs):
return "BETWEEN %s AND %s" % (rhs[0], rhs[1])

def process_rhs(self, compiler, connection):
if self.rhs_is_direct_value():
# rhs should be an iterable of 2 values, we use batch_process_rhs
# to prepare/transform those values
return self.batch_process_rhs(compiler, connection)
else:
return super(Range, self).process_rhs(compiler, connection)
Field.register_lookup(Range)

class IsNull(BuiltinLookup):
lookup_name = 'isnull'

def as_sql(self, compiler, connection):
sql, params = compiler.compile(self.lhs)
if self.rhs:
return "%s IS NULL" % sql, params
else:
return "%s IS NOT NULL" % sql, params
Field.register_lookup(IsNull)

class Search(BuiltinLookup):
lookup_name = 'search'

def as_sql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
sql_template = connection.ops.fulltext_search_sql(field_name=lhs)
return sql_template, lhs_params + rhs_params
Field.register_lookup(Search)

class Regex(BuiltinLookup):
lookup_name = 'regex'

def as_sql(self, compiler, connection):
if self.lookup_name in connection.operators:
return super(Regex, self).as_sql(compiler, connection)
else:
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
sql_template = connection.ops.regex_lookup(self.lookup_name)
return sql_template % (lhs, rhs), lhs_params + rhs_params
Field.register_lookup(Regex)

class IRegex(Regex):
lookup_name = 'iregex'
Field.register_lookup(IRegex)

class DateTimeDateTransform(Transform):
lookup_name = 'date'

@cached_property
def output_field(self):
return DateField()

def as_sql(self, compiler, connection):
lhs, lhs_params = compiler.compile(self.lhs)
tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None
sql, tz_params = connection.ops.datetime_cast_date_sql(lhs, tzname)
lhs_params.extend(tz_params)
return sql, lhs_params

class DateTransform(Transform):
def as_sql(self, compiler, connection):
sql, params = compiler.compile(self.lhs)
lhs_output_field = self.lhs.output_field
if isinstance(lhs_output_field, DateTimeField):
tzname = timezone.get_current_timezone_name() if settings.USE_TZ else None
sql, tz_params = connection.ops.datetime_extract_sql(self.lookup_name, sql, tzname)
params.extend(tz_params)
elif isinstance(lhs_output_field, DateField):
sql = connection.ops.date_extract_sql(self.lookup_name, sql)
elif isinstance(lhs_output_field, TimeField):
sql = connection.ops.time_extract_sql(self.lookup_name, sql)
else:
raise ValueError('DateTransform only valid on Date/Time/DateTimeFields')
return sql, params

@cached_property
def output_field(self):
return IntegerField()

class YearTransform(DateTransform):
lookup_name = 'year'

class YearLookup(Lookup):
def year_lookup_bounds(self, connection, year):
output_field = self.lhs.lhs.output_field
if isinstance(output_field, DateTimeField):
bounds = connection.ops.year_lookup_bounds_for_datetime_field(year)
else:
bounds = connection.ops.year_lookup_bounds_for_date_field(year)
return bounds

@YearTransform.register_lookup
class YearExact(YearLookup):
lookup_name = 'exact'

def as_sql(self, compiler, connection):
# We will need to skip the extract part and instead go
# directly with the originating field, that is self.lhs.lhs.
lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs)
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
bounds = self.year_lookup_bounds(connection, rhs_params[0])
params.extend(bounds)
return '%s BETWEEN %%s AND %%s' % lhs_sql, params

class YearComparisonLookup(YearLookup):
def as_sql(self, compiler, connection):
# We will need to skip the extract part and instead go
# directly with the originating field, that is self.lhs.lhs.
lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs)
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
rhs_sql = self.get_rhs_op(connection, rhs_sql)
start, finish = self.year_lookup_bounds(connection, rhs_params[0])
params.append(self.get_bound(start, finish))
return '%s %s' % (lhs_sql, rhs_sql), params

def get_rhs_op(self, connection, rhs):
return connection.operators[self.lookup_name] % rhs

def get_bound(self):
raise NotImplementedError(
'subclasses of YearComparisonLookup must provide a get_bound() method'
)

@YearTransform.register_lookup
class YearGt(YearComparisonLookup):
lookup_name = 'gt'

def get_bound(self, start, finish):
return finish

@YearTransform.register_lookup
class YearGte(YearComparisonLookup):
lookup_name = 'gte'

def get_bound(self, start, finish):
return start

@YearTransform.register_lookup
class YearLt(YearComparisonLookup):
lookup_name = 'lt'

def get_bound(self, start, finish):
return start

@YearTransform.register_lookup
class YearLte(YearComparisonLookup):
lookup_name = 'lte'

def get_bound(self, start, finish):
return finish

class MonthTransform(DateTransform):
lookup_name = 'month'

class DayTransform(DateTransform):
lookup_name = 'day'

class WeekDayTransform(DateTransform):
lookup_name = 'week_day'

class HourTransform(DateTransform):
lookup_name = 'hour'

class MinuteTransform(DateTransform):
lookup_name = 'minute'

class SecondTransform(DateTransform):
lookup_name = 'second'

DateField.register_lookup(YearTransform)
DateField.register_lookup(MonthTransform)
DateField.register_lookup(DayTransform)
DateField.register_lookup(WeekDayTransform)

TimeField.register_lookup(HourTransform)
TimeField.register_lookup(MinuteTransform)
TimeField.register_lookup(SecondTransform)

DateTimeField.register_lookup(DateTimeDateTransform)
DateTimeField.register_lookup(YearTransform)
DateTimeField.register_lookup(MonthTransform)
DateTimeField.register_lookup(DayTransform)
DateTimeField.register_lookup(WeekDayTransform)
DateTimeField.register_lookup(HourTransform)
DateTimeField.register_lookup(MinuteTransform)
DateTimeField.register_lookup(SecondTransform)

Source code for django.db.models.fields

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import collections
import copy
import datetime
import decimal
import math
import uuid
import warnings
from base64 import b64decode, b64encode
from functools import total_ordering

from django import forms
from django.apps import apps
from django.conf import settings
from django.core import checks, exceptions, validators
# When the _meta object was formalized, this exception was moved to
# django.core.exceptions. It is retained here for backwards compatibility
# purposes.
from django.core.exceptions import FieldDoesNotExist  # NOQA
from django.db import connection, connections, router
from django.db.models.query_utils import QueryWrapper, RegisterLookupMixin
from django.utils import six, timezone
from django.utils.datastructures import DictWrapper
from django.utils.dateparse import (
parse_date, parse_datetime, parse_duration, parse_time,
)
from django.utils.deprecation import (
RemovedInDjango20Warning, warn_about_renamed_method,
)
from django.utils.duration import duration_string
from django.utils.encoding import (
force_bytes, force_text, python_2_unicode_compatible, smart_text,
)
from django.utils.functional import Promise, cached_property, curry
from django.utils.ipv6 import clean_ipv6_address
from django.utils.itercompat import is_iterable
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _

# Avoid "TypeError: Item in ``from list'' not a string" -- unicode_literals
# makes these strings unicode
__all__ = [str(x) for x in (
'AutoField', 'BLANK_CHOICE_DASH', 'BigIntegerField', 'BinaryField',
'BooleanField', 'CharField', 'CommaSeparatedIntegerField', 'DateField',
'DateTimeField', 'DecimalField', 'DurationField', 'EmailField', 'Empty',
'Field', 'FieldDoesNotExist', 'FilePathField', 'FloatField',
'GenericIPAddressField', 'IPAddressField', 'IntegerField', 'NOT_PROVIDED',
'NullBooleanField', 'PositiveIntegerField', 'PositiveSmallIntegerField',
'SlugField', 'SmallIntegerField', 'TextField', 'TimeField', 'URLField',
'UUIDField',
)]

class Empty(object):
pass

class NOT_PROVIDED:
pass

# The values to use for "blank" in SelectFields. Will be appended to the start
# of most "choices" lists.
BLANK_CHOICE_DASH = [("", "---------")]

def _load_field(app_label, model_name, field_name):
return apps.get_model(app_label, model_name)._meta.get_field(field_name)

# A guide to Field parameters:
#
#   * name:      The name of the field specified in the model.
#   * attname:   The attribute to use on the model object. This is the same as
#                "name", except in the case of ForeignKeys, where "_id" is
#                appended.
#   * db_column: The db_column specified in the model (or None).
#   * column:    The database column for this field. This is the same as
#                "attname", except if db_column is specified.
#
# Code that introspects values, or does other dynamic things, should use
# attname. For example, this gets the primary key value of object "obj":
#
#     getattr(obj, opts.pk.attname)

def _empty(of_cls):
new = Empty()
new.__class__ = of_cls
return new

@total_ordering
@python_2_unicode_compatible

[docs]class Field(RegisterLookupMixin):
"""Base class for all field types"""

# Designates whether empty strings fundamentally are allowed at the
# database level.
empty_strings_allowed = True
empty_values = list(validators.EMPTY_VALUES)

# These track each time a Field instance is created. Used to retain order.
# The auto_creation_counter is used for fields that Django implicitly
# creates, creation_counter is used for all user-specified fields.
creation_counter = 0
auto_creation_counter = -1
default_validators = []  # Default set of validators
default_error_messages = {
'invalid_choice': _('Value %(value)r is not a valid choice.'),
'null': _('This field cannot be null.'),
'blank': _('This field cannot be blank.'),
'unique': _('%(model_name)s with this %(field_label)s '
'already exists.'),
# Translators: The 'lookup_type' is one of 'date', 'year' or 'month'.
# Eg: "Title must be unique for pub_date year"
'unique_for_date': _("%(field_label)s must be unique for "
"%(date_field_label)s %(lookup_type)s."),
}
system_check_deprecated_details = None
system_check_removed_details = None

# Field flags
hidden = False

many_to_many = None
many_to_one = None
one_to_many = None
one_to_one = None
related_model = None

# Generic field type description, usually overridden by subclasses
def _description(self):
return _('Field of type: %(field_type)s') % {
'field_type': self.__class__.__name__
}
description = property(_description)

def __init__(self, verbose_name=None, name=None, primary_key=False,
max_length=None, unique=False, blank=False, null=False,
db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
serialize=True, unique_for_date=None, unique_for_month=None,
unique_for_year=None, choices=None, help_text='', db_column=None,
db_tablespace=None, auto_created=False, validators=[],
error_messages=None):
self.name = name
self.verbose_name = verbose_name  # May be set by set_attributes_from_name
self._verbose_name = verbose_name  # Store original for deconstruction
self.primary_key = primary_key
self.max_length, self._unique = max_length, unique
self.blank, self.null = blank, null
self.remote_field = rel
self.is_relation = self.remote_field is not None
self.default = default
self.editable = editable
self.serialize = serialize
self.unique_for_date = unique_for_date
self.unique_for_month = unique_for_month
self.unique_for_year = unique_for_year
if isinstance(choices, collections.Iterator):
choices = list(choices)
self.choices = choices or []
self.help_text = help_text
self.db_index = db_index
self.db_column = db_column
self.db_tablespace = db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
self.auto_created = auto_created

# Adjust the appropriate creation counter, and save our local copy.
if auto_created:
self.creation_counter = Field.auto_creation_counter
Field.auto_creation_counter -= 1
else:
self.creation_counter = Field.creation_counter
Field.creation_counter += 1

self._validators = validators  # Store for deconstruction later

messages = {}
for c in reversed(self.__class__.__mro__):
messages.update(getattr(c, 'default_error_messages', {}))
messages.update(error_messages or {})
self._error_messages = error_messages  # Store for deconstruction later
self.error_messages = messages

def __str__(self):
""" Return "app_label.model_label.field_name". """
model = self.model
app = model._meta.app_label
return '%s.%s.%s' % (app, model._meta.object_name, self.name)

def __repr__(self):
"""
Displays the module, class and name of the field.
"""
path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__)
name = getattr(self, 'name', None)
if name is not None:
return '<%s: %s>' % (path, name)
return '<%s>' % path

def check(self, **kwargs):
errors = []
errors.extend(self._check_field_name())
errors.extend(self._check_choices())
errors.extend(self._check_db_index())
errors.extend(self._check_null_allowed_for_primary_keys())
errors.extend(self._check_backend_specific_checks(**kwargs))
errors.extend(self._check_deprecation_details())
return errors

def _check_field_name(self):
""" Check if field name is valid, i.e. 1) does not end with an
underscore, 2) does not contain "__" and 3) is not "pk". """

if self.name.endswith('_'):
return [
checks.Error(
'Field names must not end with an underscore.',
hint=None,
obj=self,
id='fields.E001',
)
]
elif '__' in self.name:
return [
checks.Error(
'Field names must not contain "__".',
hint=None,
obj=self,
id='fields.E002',
)
]
elif self.name == 'pk':
return [
checks.Error(
"'pk' is a reserved word that cannot be used as a field name.",
hint=None,
obj=self,
id='fields.E003',
)
]
else:
return []

@property
def rel(self):
warnings.warn(
"Usage of field.rel has been deprecated. Use field.remote_field instead.",
RemovedInDjango20Warning, 2)
return self.remote_field

def _check_choices(self):
if self.choices:
if (isinstance(self.choices, six.string_types) or
not is_iterable(self.choices)):
return [
checks.Error(
"'choices' must be an iterable (e.g., a list or tuple).",
hint=None,
obj=self,
id='fields.E004',
)
]
elif any(isinstance(choice, six.string_types) or
not is_iterable(choice) or len(choice) != 2
for choice in self.choices):
return [
checks.Error(
("'choices' must be an iterable containing "
"(actual value, human readable name) tuples."),
hint=None,
obj=self,
id='fields.E005',
)
]
else:
return []
else:
return []

def _check_db_index(self):
if self.db_index not in (None, True, False):
return [
checks.Error(
"'db_index' must be None, True or False.",
hint=None,
obj=self,
id='fields.E006',
)
]
else:
return []

def _check_null_allowed_for_primary_keys(self):
if (self.primary_key and self.null and
not connection.features.interprets_empty_strings_as_nulls):
# We cannot reliably check this for backends like Oracle which
# consider NULL and '' to be equal (and thus set up
# character-based fields a little differently).
return [
checks.Error(
'Primary keys must not have null=True.',
hint=('Set null=False on the field, or '
'remove primary_key=True argument.'),
obj=self,
id='fields.E007',
)
]
else:
return []

def _check_backend_specific_checks(self, **kwargs):
app_label = self.model._meta.app_label
for db in connections:
if router.allow_migrate(db, app_label, model=self.model):
return connections[db].validation.check_field(self, **kwargs)
return []

def _check_deprecation_details(self):
if self.system_check_removed_details is not None:
return [
checks.Error(
self.system_check_removed_details.get(
'msg',
'%s has been removed except for support in historical '
'migrations.' % self.__class__.__name__
),
hint=self.system_check_removed_details.get('hint'),
obj=self,
id=self.system_check_removed_details.get('id', 'fields.EXXX'),
)
]
elif self.system_check_deprecated_details is not None:
return [
checks.Warning(
self.system_check_deprecated_details.get(
'msg',
'%s has been deprecated.' % self.__class__.__name__
),
hint=self.system_check_deprecated_details.get('hint'),
obj=self,
id=self.system_check_deprecated_details.get('id', 'fields.WXXX'),
)
]
return []

def get_col(self, alias, output_field=None):
if output_field is None:
output_field = self
if alias != self.model._meta.db_table or output_field != self:
from django.db.models.expressions import Col
return Col(alias, self, output_field)
else:
return self.cached_col

@cached_property
def cached_col(self):
from django.db.models.expressions import Col
return Col(self.model._meta.db_table, self)

def select_format(self, compiler, sql, params):
"""
Custom format for select clauses. For example, GIS columns need to be
selected as AsText(table.col) on MySQL as the table.col data can't be used
by Django.
"""
return sql, params

[docs]    def deconstruct(self):
"""
Returns enough information to recreate the field as a 4-tuple:

* The name of the field on the model, if contribute_to_class has been run
* The import path of the field, including the class: django.db.models.IntegerField
This should be the most portable version, so less specific may be better.
* A list of positional arguments
* A dict of keyword arguments

Note that the positional or keyword arguments must contain values of the
following types (including inner values of collection types):

* None, bool, str, unicode, int, long, float, complex, set, frozenset, list, tuple, dict
* UUID
* datetime.datetime (naive), datetime.date
* top-level classes, top-level functions - will be referenced by their full import path
* Storage instances - these have their own deconstruct() method

This is because the values here must be serialized into a text format
(possibly new Python code, possibly JSON) and these are the only types
with encoding handlers defined.

There's no need to return the exact way the field was instantiated this time,
just ensure that the resulting field is the same - prefer keyword arguments
over positional ones, and omit parameters with their default values.
"""
# Short-form way of fetching all the default parameters
keywords = {}
possibles = {
"verbose_name": None,
"primary_key": False,
"max_length": None,
"unique": False,
"blank": False,
"null": False,
"db_index": False,
"default": NOT_PROVIDED,
"editable": True,
"serialize": True,
"unique_for_date": None,
"unique_for_month": None,
"unique_for_year": None,
"choices": [],
"help_text": '',
"db_column": None,
"db_tablespace": settings.DEFAULT_INDEX_TABLESPACE,
"auto_created": False,
"validators": [],
"error_messages": None,
}
attr_overrides = {
"unique": "_unique",
"error_messages": "_error_messages",
"validators": "_validators",
"verbose_name": "_verbose_name",
}
equals_comparison = {"choices", "validators", "db_tablespace"}
for name, default in possibles.items():
value = getattr(self, attr_overrides.get(name, name))
# Unroll anything iterable for choices into a concrete list
if name == "choices" and isinstance(value, collections.Iterable):
value = list(value)
# Do correct kind of comparison
if name in equals_comparison:
if value != default:
keywords[name] = value
else:
if value is not default:
keywords[name] = value
# Work out path - we shorten it for known Django core fields
path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
if path.startswith("django.db.models.fields.related"):
path = path.replace("django.db.models.fields.related", "django.db.models")
if path.startswith("django.db.models.fields.files"):
path = path.replace("django.db.models.fields.files", "django.db.models")
if path.startswith("django.db.models.fields.proxy"):
path = path.replace("django.db.models.fields.proxy", "django.db.models")
if path.startswith("django.db.models.fields"):
path = path.replace("django.db.models.fields", "django.db.models")
# Return basic info - other fields should override this.
return (
force_text(self.name, strings_only=True),
path,
[],
keywords,
)

def clone(self):
"""
Uses deconstruct() to clone a new copy of this Field.
Will not preserve any class attachments/attribute names.
"""
name, path, args, kwargs = self.deconstruct()
return self.__class__(*args, **kwargs)

def __eq__(self, other):
# Needed for @total_ordering
if isinstance(other, Field):
return self.creation_counter == other.creation_counter
return NotImplemented

def __lt__(self, other):
# This is needed because bisect does not take a comparison function.
if isinstance(other, Field):
return self.creation_counter < other.creation_counter
return NotImplemented

def __hash__(self):
return hash(self.creation_counter)

def __deepcopy__(self, memodict):
# We don't have to deepcopy very much here, since most things are not
# intended to be altered after initial creation.
obj = copy.copy(self)
if self.remote_field:
obj.remote_field = copy.copy(self.remote_field)
if hasattr(self.remote_field, 'field') and self.remote_field.field is self:
obj.remote_field.field = obj
memodict[id(self)] = obj
return obj

def __copy__(self):
# We need to avoid hitting __reduce__, so define this
# slightly weird copy construct.
obj = Empty()
obj.__class__ = self.__class__
obj.__dict__ = self.__dict__.copy()
return obj

def __reduce__(self):
"""
Pickling should return the model._meta.fields instance of the field,
not a new copy of that field. So, we use the app registry to load the
model and then the field back.
"""
if not hasattr(self, 'model'):
# Fields are sometimes used without attaching them to models (for
# example in aggregation). In this case give back a plain field
# instance. The code below will create a new empty instance of
# class self.__class__, then update its dict with self.__dict__
# values - so, this is very close to normal pickle.
return _empty, (self.__class__,), self.__dict__
if self.model._deferred:
# Deferred model will not be found from the app registry. This
# could be fixed by reconstructing the deferred model on unpickle.
raise RuntimeError("Fields of deferred models can't be reduced")
return _load_field, (self.model._meta.app_label, self.model._meta.object_name,
self.name)

def get_pk_value_on_save(self, instance):
"""
Hook to generate new PK values on save. This method is called when
saving instances with no primary key value set. If this method returns
something else than None, then the returned value is used when saving
the new instance.
"""
if self.default:
return self.get_default()
return None

[docs]    def to_python(self, value):
"""
Converts the input value into the expected Python data type, raising
django.core.exceptions.ValidationError if the data can't be converted.
Returns the converted value. Subclasses should override this.
"""
return value

@cached_property
def validators(self):
# Some validators can't be created at field initialization time.
# This method provides a way to delay their creation until required.
return self.default_validators + self._validators

def run_validators(self, value):
if value in self.empty_values:
return

errors = []
for v in self.validators:
try:
v(value)
except exceptions.ValidationError as e:
if hasattr(e, 'code') and e.code in self.error_messages:
e.message = self.error_messages[e.code]
errors.extend(e.error_list)

if errors:
raise exceptions.ValidationError(errors)

def validate(self, value, model_instance):
"""
Validates value and throws ValidationError. Subclasses should override
this to provide validation logic.
"""
if not self.editable:
# Skip validation for non-editable fields.
return

if self.choices and value not in self.empty_values:
for option_key, option_value in self.choices:
if isinstance(option_value, (list, tuple)):
# This is an optgroup, so look inside the group for
# options.
for optgroup_key, optgroup_value in option_value:
if value == optgroup_key:
return
elif value == option_key:
return
raise exceptions.ValidationError(
self.error_messages['invalid_choice'],
code='invalid_choice',
params={'value': value},
)

if value is None and not self.null:
raise exceptions.ValidationError(self.error_messages['null'], code='null')

if not self.blank and value in self.empty_values:
raise exceptions.ValidationError(self.error_messages['blank'], code='blank')

def clean(self, value, model_instance):
"""
Convert the value's type and run validation. Validation errors
from to_python and validate are propagated. The correct value is
returned if no error is raised.
"""
value = self.to_python(value)
self.validate(value, model_instance)
self.run_validators(value)
return value

[docs]    def db_type(self, connection):
"""
Returns the database column data type for this field, for the provided
connection.
"""
# The default implementation of this method looks at the
# backend-specific data_types dictionary, looking up the field by its
# "internal type".
#
# A Field class can implement the get_internal_type() method to specify
# which *preexisting* Django Field class it's most similar to -- i.e.,
# a custom field might be represented by a TEXT column type, which is
# the same as the TextField Django field type, which means the custom
# field's get_internal_type() returns 'TextField'.
#
# But the limitation of the get_internal_type() / data_types approach
# is that it cannot handle database column types that aren't already
# mapped to one of the built-in Django field types. In this case, you
# can implement db_type() instead of get_internal_type() to specify
# exactly which wacky database column type you want to use.
data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
try:
return connection.data_types[self.get_internal_type()] % data
except KeyError:
return None

def db_parameters(self, connection):
"""
Extension of db_type(), providing a range of different return
values (type, checks).
This will look at db_type(), allowing custom model fields to override it.
"""
data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
type_string = self.db_type(connection)
try:
check_string = connection.data_type_check_constraints[self.get_internal_type()] % data
except KeyError:
check_string = None
return {
"type": type_string,
"check": check_string,
}

def db_type_suffix(self, connection):
return connection.data_types_suffix.get(self.get_internal_type())

def get_db_converters(self, connection):
if hasattr(self, 'from_db_value'):
return [self.from_db_value]
return []

@property
def unique(self):
return self._unique or self.primary_key

def set_attributes_from_name(self, name):
if not self.name:
self.name = name
self.attname, self.column = self.get_attname_column()
self.concrete = self.column is not None
if self.verbose_name is None and self.name:
self.verbose_name = self.name.replace('_', ' ')

def contribute_to_class(self, cls, name, virtual_only=False):
self.set_attributes_from_name(name)
self.model = cls
if virtual_only:
cls._meta.add_field(self, virtual=True)
else:
cls._meta.add_field(self)
if self.choices:
setattr(cls, 'get_%s_display' % self.name,
curry(cls._get_FIELD_display, field=self))

def get_filter_kwargs_for_object(self, obj):
"""
Return a dict that when passed as kwargs to self.model.filter(), would
yield all instances having the same value for this field as obj has.
"""
return {self.name: getattr(obj, self.attname)}

def get_attname(self):
return self.name

def get_attname_column(self):
attname = self.get_attname()
column = self.db_column or attname
return attname, column

def get_cache_name(self):
return '_%s_cache' % self.name

[docs]    def get_internal_type(self):
return self.__class__.__name__

[docs]    def pre_save(self, model_instance, add):
"""
Returns field's value just before saving.
"""
return getattr(model_instance, self.attname)

[docs]    def get_prep_value(self, value):
"""
Perform preliminary non-db specific value checks and conversions.
"""
if isinstance(value, Promise):
value = value._proxy____cast()
return value

[docs]    def get_db_prep_value(self, value, connection, prepared=False):
"""Returns field's value prepared for interacting with the database
backend.

Used by the default implementations of ``get_db_prep_save``and
`get_db_prep_lookup```
"""
if not prepared:
value = self.get_prep_value(value)
return value

[docs]    def get_db_prep_save(self, value, connection):
"""
Returns field's value prepared for saving into a database.
"""
return self.get_db_prep_value(value, connection=connection,
prepared=False)

[docs]    def get_prep_lookup(self, lookup_type, value):
"""
Perform preliminary non-db specific lookup checks and conversions
"""
if hasattr(value, '_prepare'):
return value._prepare(self)

if lookup_type in {
'iexact', 'contains', 'icontains',
'startswith', 'istartswith', 'endswith', 'iendswith',
'isnull', 'search', 'regex', 'iregex',
}:
return value
elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
return self.get_prep_value(value)
elif lookup_type in ('range', 'in'):
return [self.get_prep_value(v) for v in value]
return self.get_prep_value(value)

[docs]    def get_db_prep_lookup(self, lookup_type, value, connection,
prepared=False):
"""
Returns field's value prepared for database lookup.
"""
if not prepared:
value = self.get_prep_lookup(lookup_type, value)
prepared = True
if hasattr(value, 'get_compiler'):
value = value.get_compiler(connection=connection)
if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'):
# If the value has a relabeled_clone method it means the
# value will be handled later on.
if hasattr(value, 'relabeled_clone'):
return value
if hasattr(value, 'as_sql'):
sql, params = value.as_sql()
else:
sql, params = value._as_sql(connection=connection)
return QueryWrapper(('(%s)' % sql), params)

if lookup_type in ('search', 'regex', 'iregex', 'contains',
'icontains', 'iexact', 'startswith', 'endswith',
'istartswith', 'iendswith'):
return [value]
elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
return [self.get_db_prep_value(value, connection=connection,
prepared=prepared)]
elif lookup_type in ('range', 'in'):
return [self.get_db_prep_value(v, connection=connection,
prepared=prepared) for v in value]
elif lookup_type == 'isnull':
return []
else:
return [value]

def has_default(self):
"""
Returns a boolean of whether this field has a default value.
"""
return self.default is not NOT_PROVIDED

def get_default(self):
"""
Returns the default value for this field.
"""
if self.has_default():
if callable(self.default):
return self.default()
return self.default
if (not self.empty_strings_allowed or (self.null and
not connection.features.interprets_empty_strings_as_nulls)):
return None
return ""

def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH, limit_choices_to=None):
"""Returns choices with a default blank choices included, for use
as SelectField choices for this field."""
blank_defined = False
choices = list(self.choices) if self.choices else []
named_groups = choices and isinstance(choices[0][1], (list, tuple))
if not named_groups:
for choice, __ in choices:
if choice in ('', None):
blank_defined = True
break

first_choice = (blank_choice if include_blank and
not blank_defined else [])
if self.choices:
return first_choice + choices
rel_model = self.remote_field.model
limit_choices_to = limit_choices_to or self.get_limit_choices_to()
if hasattr(self.remote_field, 'get_related_field'):
lst = [(getattr(x, self.remote_field.get_related_field().attname),
smart_text(x))
for x in rel_model._default_manager.complex_filter(
limit_choices_to)]
else:
lst = [(x._get_pk_val(), smart_text(x))
for x in rel_model._default_manager.complex_filter(
limit_choices_to)]
return first_choice + lst

def get_choices_default(self):
return self.get_choices()

@warn_about_renamed_method(
'Field', '_get_val_from_obj', 'value_from_object',
RemovedInDjango20Warning
)
def _get_val_from_obj(self, obj):
if obj is not None:
return getattr(obj, self.attname)
else:
return self.get_default()

[docs]    def value_to_string(self, obj):
"""
Returns a string value of this field from the passed obj.
This is used by the serialization framework.
"""
return smart_text(self.value_from_object(obj))

def _get_flatchoices(self):
"""Flattened version of choices tuple."""
flat = []
for choice, value in self.choices:
if isinstance(value, (list, tuple)):
flat.extend(value)
else:
flat.append((choice, value))
return flat
flatchoices = property(_get_flatchoices)

def save_form_data(self, instance, data):
setattr(instance, self.name, data)

[docs]    def formfield(self, form_class=None, choices_form_class=None, **kwargs):
"""
Returns a django.forms.Field instance for this database Field.
"""
defaults = {'required': not self.blank,
'label': capfirst(self.verbose_name),
'help_text': self.help_text}
if self.has_default():
if callable(self.default):
defaults['initial'] = self.default
defaults['show_hidden_initial'] = True
else:
defaults['initial'] = self.get_default()
if self.choices:
# Fields with choices get special treatment.
include_blank = (self.blank or
not (self.has_default() or 'initial' in kwargs))
defaults['choices'] = self.get_choices(include_blank=include_blank)
defaults['coerce'] = self.to_python
if self.null:
defaults['empty_value'] = None
if choices_form_class is not None:
form_class = choices_form_class
else:
form_class = forms.TypedChoiceField
# Many of the subclass-specific formfield arguments (min_value,
# max_value) don't apply for choice fields, so be sure to only pass
# the values that TypedChoiceField will understand.
for k in list(kwargs):
if k not in ('coerce', 'empty_value', 'choices', 'required',
'widget', 'label', 'initial', 'help_text',
'error_messages', 'show_hidden_initial'):
del kwargs[k]
defaults.update(kwargs)
if form_class is None:
form_class = forms.CharField
return form_class(**defaults)

def value_from_object(self, obj):
"""
Returns the value of this field in the given model instance.
"""
return getattr(obj, self.attname)

[docs]class AutoField(Field):
description = _("Integer")

empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be an integer."),
}

def __init__(self, *args, **kwargs):
kwargs['blank'] = True
super(AutoField, self).__init__(*args, **kwargs)

def check(self, **kwargs):
errors = super(AutoField, self).check(**kwargs)
errors.extend(self._check_primary_key())
return errors

def _check_primary_key(self):
if not self.primary_key:
return [
checks.Error(
'AutoFields must set primary_key=True.',
hint=None,
obj=self,
id='fields.E100',
),
]
else:
return []

def deconstruct(self):
name, path, args, kwargs = super(AutoField, self).deconstruct()
del kwargs['blank']
kwargs['primary_key'] = True
return name, path, args, kwargs

def get_internal_type(self):
return "AutoField"

def to_python(self, value):
if value is None:
return value
try:
return int(value)
except (TypeError, ValueError):
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def validate(self, value, model_instance):
pass

def get_db_prep_value(self, value, connection, prepared=False):
if not prepared:
value = self.get_prep_value(value)
value = connection.ops.validate_autopk_value(value)
return value

def get_prep_value(self, value):
value = super(AutoField, self).get_prep_value(value)
if value is None:
return None
return int(value)

def contribute_to_class(self, cls, name, **kwargs):
assert not cls._meta.has_auto_field, \
"A model can't have more than one AutoField."
super(AutoField, self).contribute_to_class(cls, name, **kwargs)
cls._meta.has_auto_field = True
cls._meta.auto_field = self

def formfield(self, **kwargs):
return None

[docs]class BooleanField(Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be either True or False."),
}
description = _("Boolean (Either True or False)")

def __init__(self, *args, **kwargs):
kwargs['blank'] = True
super(BooleanField, self).__init__(*args, **kwargs)

def check(self, **kwargs):
errors = super(BooleanField, self).check(**kwargs)
errors.extend(self._check_null(**kwargs))
return errors

def _check_null(self, **kwargs):
if getattr(self, 'null', False):
return [
checks.Error(
'BooleanFields do not accept null values.',
hint='Use a NullBooleanField instead.',
obj=self,
id='fields.E110',
)
]
else:
return []

def deconstruct(self):
name, path, args, kwargs = super(BooleanField, self).deconstruct()
del kwargs['blank']
return name, path, args, kwargs

def get_internal_type(self):
return "BooleanField"

def to_python(self, value):
if value in (True, False):
# if value is 1 or 0 than it's equal to True or False, but we want
# to return a true bool for semantic reasons.
return bool(value)
if value in ('t', 'True', '1'):
return True
if value in ('f', 'False', '0'):
return False
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def get_prep_lookup(self, lookup_type, value):
# Special-case handling for filters coming from a Web request (e.g. the
# admin interface). Only works for scalar values (not lists). If you're
# passing in a list, you might as well make things the right type when
# constructing the list.
if value in ('1', '0'):
value = bool(int(value))
return super(BooleanField, self).get_prep_lookup(lookup_type, value)

def get_prep_value(self, value):
value = super(BooleanField, self).get_prep_value(value)
if value is None:
return None
return bool(value)

def formfield(self, **kwargs):
# Unlike most fields, BooleanField figures out include_blank from
# self.null instead of self.blank.
if self.choices:
include_blank = not (self.has_default() or 'initial' in kwargs)
defaults = {'choices': self.get_choices(include_blank=include_blank)}
else:
defaults = {'form_class': forms.BooleanField}
defaults.update(kwargs)
return super(BooleanField, self).formfield(**defaults)

[docs]class CharField(Field):
description = _("String (up to %(max_length)s)")

def __init__(self, *args, **kwargs):
super(CharField, self).__init__(*args, **kwargs)
self.validators.append(validators.MaxLengthValidator(self.max_length))

def check(self, **kwargs):
errors = super(CharField, self).check(**kwargs)
errors.extend(self._check_max_length_attribute(**kwargs))
return errors

def _check_max_length_attribute(self, **kwargs):
if self.max_length is None:
return [
checks.Error(
"CharFields must define a 'max_length' attribute.",
hint=None,
obj=self,
id='fields.E120',
)
]
elif not isinstance(self.max_length, six.integer_types) or self.max_length <= 0:
return [
checks.Error(
"'max_length' must be a positive integer.",
hint=None,
obj=self,
id='fields.E121',
)
]
else:
return []

def get_internal_type(self):
return "CharField"

def to_python(self, value):
if isinstance(value, six.string_types) or value is None:
return value
return smart_text(value)

def get_prep_value(self, value):
value = super(CharField, self).get_prep_value(value)
return self.to_python(value)

def formfield(self, **kwargs):
# Passing max_length to forms.CharField means that the value's length
# will be validated twice. This is considered acceptable since we want
# the value in the form field (to pass into widget for example).
defaults = {'max_length': self.max_length}
defaults.update(kwargs)
return super(CharField, self).formfield(**defaults)

[docs]class CommaSeparatedIntegerField(CharField):
default_validators = [validators.validate_comma_separated_integer_list]
description = _("Comma-separated integers")

def formfield(self, **kwargs):
defaults = {
'error_messages': {
'invalid': _('Enter only digits separated by commas.'),
}
}
defaults.update(kwargs)
return super(CommaSeparatedIntegerField, self).formfield(**defaults)

class DateTimeCheckMixin(object):

def check(self, **kwargs):
errors = super(DateTimeCheckMixin, self).check(**kwargs)
errors.extend(self._check_mutually_exclusive_options())
errors.extend(self._check_fix_default_value())
return errors

def _check_mutually_exclusive_options(self):
# auto_now, auto_now_add, and default are mutually exclusive
# options. The use of more than one of these options together
# will trigger an Error
mutually_exclusive_options = [self.auto_now_add, self.auto_now,
self.has_default()]
enabled_options = [option not in (None, False)
for option in mutually_exclusive_options].count(True)
if enabled_options > 1:
return [
checks.Error(
"The options auto_now, auto_now_add, and default "
"are mutually exclusive. Only one of these options "
"may be present.",
hint=None,
obj=self,
id='fields.E160',
)
]
else:
return []

def _check_fix_default_value(self):
return []

[docs]class DateField(DateTimeCheckMixin, Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value has an invalid date format. It must be "
"in YYYY-MM-DD format."),
'invalid_date': _("'%(value)s' value has the correct format (YYYY-MM-DD) "
"but it is an invalid date."),
}
description = _("Date (without time)")

def __init__(self, verbose_name=None, name=None, auto_now=False,
auto_now_add=False, **kwargs):
self.auto_now, self.auto_now_add = auto_now, auto_now_add
if auto_now or auto_now_add:
kwargs['editable'] = False
kwargs['blank'] = True
super(DateField, self).__init__(verbose_name, name, **kwargs)

def _check_fix_default_value(self):
"""
Adds a warning to the checks framework stating, that using an actual
date or datetime value is probably wrong; it's only being evaluated on
server start-up.

For details see ticket #21905
"""
if not self.has_default():
return []

now = timezone.now()
if not timezone.is_naive(now):
now = timezone.make_naive(now, timezone.utc)
value = self.default
if isinstance(value, datetime.datetime):
if not timezone.is_naive(value):
value = timezone.make_naive(value, timezone.utc)
value = value.date()
elif isinstance(value, datetime.date):
# Nothing to do, as dates don't have tz information
pass
else:
# No explicit date / datetime value -- no checks necessary
return []
offset = datetime.timedelta(days=1)
lower = (now - offset).date()
upper = (now + offset).date()
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint='It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`',
obj=self,
id='fields.W161',
)
]

return []

def deconstruct(self):
name, path, args, kwargs = super(DateField, self).deconstruct()
if self.auto_now:
kwargs['auto_now'] = True
if self.auto_now_add:
kwargs['auto_now_add'] = True
if self.auto_now or self.auto_now_add:
del kwargs['editable']
del kwargs['blank']
return name, path, args, kwargs

def get_internal_type(self):
return "DateField"

def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.datetime):
if settings.USE_TZ and timezone.is_aware(value):
# Convert aware datetimes to the default time zone
# before casting them to dates (#17742).
default_timezone = timezone.get_default_timezone()
value = timezone.make_naive(value, default_timezone)
return value.date()
if isinstance(value, datetime.date):
return value

try:
parsed = parse_date(value)
if parsed is not None:
return parsed
except ValueError:
raise exceptions.ValidationError(
self.error_messages['invalid_date'],
code='invalid_date',
params={'value': value},
)

raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def pre_save(self, model_instance, add):
if self.auto_now or (self.auto_now_add and add):
value = datetime.date.today()
setattr(model_instance, self.attname, value)
return value
else:
return super(DateField, self).pre_save(model_instance, add)

def contribute_to_class(self, cls, name, **kwargs):
super(DateField, self).contribute_to_class(cls, name, **kwargs)
if not self.null:
setattr(cls, 'get_next_by_%s' % self.name,
curry(cls._get_next_or_previous_by_FIELD, field=self,
is_next=True))
setattr(cls, 'get_previous_by_%s' % self.name,
curry(cls._get_next_or_previous_by_FIELD, field=self,
is_next=False))

def get_prep_value(self, value):
value = super(DateField, self).get_prep_value(value)
return self.to_python(value)

def get_db_prep_value(self, value, connection, prepared=False):
# Casts dates into the format expected by the backend
if not prepared:
value = self.get_prep_value(value)
return connection.ops.adapt_datefield_value(value)

def value_to_string(self, obj):
val = self.value_from_object(obj)
return '' if val is None else val.isoformat()

def formfield(self, **kwargs):
defaults = {'form_class': forms.DateField}
defaults.update(kwargs)
return super(DateField, self).formfield(**defaults)

[docs]class DateTimeField(DateField):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value has an invalid format. It must be in "
"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format."),
'invalid_date': _("'%(value)s' value has the correct format "
"(YYYY-MM-DD) but it is an invalid date."),
'invalid_datetime': _("'%(value)s' value has the correct format "
"(YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) "
"but it is an invalid date/time."),
}
description = _("Date (with time)")

# __init__ is inherited from DateField

def _check_fix_default_value(self):
"""
Adds a warning to the checks framework stating, that using an actual
date or datetime value is probably wrong; it's only being evaluated on
server start-up.

For details see ticket #21905
"""
if not self.has_default():
return []

now = timezone.now()
if not timezone.is_naive(now):
now = timezone.make_naive(now, timezone.utc)
value = self.default
if isinstance(value, datetime.datetime):
second_offset = datetime.timedelta(seconds=10)
lower = now - second_offset
upper = now + second_offset
if timezone.is_aware(value):
value = timezone.make_naive(value, timezone.utc)
elif isinstance(value, datetime.date):
second_offset = datetime.timedelta(seconds=10)
lower = now - second_offset
lower = datetime.datetime(lower.year, lower.month, lower.day)
upper = now + second_offset
upper = datetime.datetime(upper.year, upper.month, upper.day)
value = datetime.datetime(value.year, value.month, value.day)
else:
# No explicit date / datetime value -- no checks necessary
return []
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint='It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`',
obj=self,
id='fields.W161',
)
]

return []

def get_internal_type(self):
return "DateTimeField"

def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.datetime):
return value
if isinstance(value, datetime.date):
value = datetime.datetime(value.year, value.month, value.day)
if settings.USE_TZ:
# For backwards compatibility, interpret naive datetimes in
# local time. This won't work during DST change, but we can't
# do much about it, so we let the exceptions percolate up the
# call stack.
warnings.warn("DateTimeField %s.%s received a naive datetime "
"(%s) while time zone support is active." %
(self.model.__name__, self.name, value),
RuntimeWarning)
default_timezone = timezone.get_default_timezone()
value = timezone.make_aware(value, default_timezone)
return value

try:
parsed = parse_datetime(value)
if parsed is not None:
return parsed
except ValueError:
raise exceptions.ValidationError(
self.error_messages['invalid_datetime'],
code='invalid_datetime',
params={'value': value},
)

try:
parsed = parse_date(value)
if parsed is not None:
return datetime.datetime(parsed.year, parsed.month, parsed.day)
except ValueError:
raise exceptions.ValidationError(
self.error_messages['invalid_date'],
code='invalid_date',
params={'value': value},
)

raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def pre_save(self, model_instance, add):
if self.auto_now or (self.auto_now_add and add):
value = timezone.now()
setattr(model_instance, self.attname, value)
return value
else:
return super(DateTimeField, self).pre_save(model_instance, add)

# contribute_to_class is inherited from DateField, it registers
# get_next_by_FOO and get_prev_by_FOO

# get_prep_lookup is inherited from DateField

def get_prep_value(self, value):
value = super(DateTimeField, self).get_prep_value(value)
value = self.to_python(value)
if value is not None and settings.USE_TZ and timezone.is_naive(value):
# For backwards compatibility, interpret naive datetimes in local
# time. This won't work during DST change, but we can't do much
# about it, so we let the exceptions percolate up the call stack.
try:
name = '%s.%s' % (self.model.__name__, self.name)
except AttributeError:
name = '(unbound)'
warnings.warn("DateTimeField %s received a naive datetime (%s)"
" while time zone support is active." %
(name, value),
RuntimeWarning)
default_timezone = timezone.get_default_timezone()
value = timezone.make_aware(value, default_timezone)
return value

def get_db_prep_value(self, value, connection, prepared=False):
# Casts datetimes into the format expected by the backend
if not prepared:
value = self.get_prep_value(value)
return connection.ops.adapt_datetimefield_value(value)

def value_to_string(self, obj):
val = self.value_from_object(obj)
return '' if val is None else val.isoformat()

def formfield(self, **kwargs):
defaults = {'form_class': forms.DateTimeField}
defaults.update(kwargs)
return super(DateTimeField, self).formfield(**defaults)

[docs]class DecimalField(Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be a decimal number."),
}
description = _("Decimal number")

def __init__(self, verbose_name=None, name=None, max_digits=None,
decimal_places=None, **kwargs):
self.max_digits, self.decimal_places = max_digits, decimal_places
super(DecimalField, self).__init__(verbose_name, name, **kwargs)

def check(self, **kwargs):
errors = super(DecimalField, self).check(**kwargs)

digits_errors = self._check_decimal_places()
digits_errors.extend(self._check_max_digits())
if not digits_errors:
errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
else:
errors.extend(digits_errors)
return errors

def _check_decimal_places(self):
try:
decimal_places = int(self.decimal_places)
if decimal_places < 0:
raise ValueError()
except TypeError:
return [
checks.Error(
"DecimalFields must define a 'decimal_places' attribute.",
hint=None,
obj=self,
id='fields.E130',
)
]
except ValueError:
return [
checks.Error(
"'decimal_places' must be a non-negative integer.",
hint=None,
obj=self,
id='fields.E131',
)
]
else:
return []

def _check_max_digits(self):
try:
max_digits = int(self.max_digits)
if max_digits <= 0:
raise ValueError()
except TypeError:
return [
checks.Error(
"DecimalFields must define a 'max_digits' attribute.",
hint=None,
obj=self,
id='fields.E132',
)
]
except ValueError:
return [
checks.Error(
"'max_digits' must be a positive integer.",
hint=None,
obj=self,
id='fields.E133',
)
]
else:
return []

def _check_decimal_places_and_max_digits(self, **kwargs):
if int(self.decimal_places) > int(self.max_digits):
return [
checks.Error(
"'max_digits' must be greater or equal to 'decimal_places'.",
hint=None,
obj=self,
id='fields.E134',
)
]
return []

@cached_property
def validators(self):
return super(DecimalField, self).validators + [
validators.DecimalValidator(self.max_digits, self.decimal_places)
]

def deconstruct(self):
name, path, args, kwargs = super(DecimalField, self).deconstruct()
if self.max_digits is not None:
kwargs['max_digits'] = self.max_digits
if self.decimal_places is not None:
kwargs['decimal_places'] = self.decimal_places
return name, path, args, kwargs

def get_internal_type(self):
return "DecimalField"

def to_python(self, value):
if value is None:
return value
try:
return decimal.Decimal(value)
except decimal.InvalidOperation:
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def _format(self, value):
if isinstance(value, six.string_types):
return value
else:
return self.format_number(value)

def format_number(self, value):
"""
Formats a number into a string with the requisite number of digits and
decimal places.
"""
# Method moved to django.db.backends.utils.
#
# It is preserved because it is used by the oracle backend
# (django.db.backends.oracle.query), and also for
# backwards-compatibility with any external code which may have used
# this method.
from django.db.backends import utils
return utils.format_number(value, self.max_digits, self.decimal_places)

def get_db_prep_save(self, value, connection):
return connection.ops.adapt_decimalfield_value(self.to_python(value),
self.max_digits, self.decimal_places)

def get_prep_value(self, value):
value = super(DecimalField, self).get_prep_value(value)
return self.to_python(value)

def formfield(self, **kwargs):
defaults = {
'max_digits': self.max_digits,
'decimal_places': self.decimal_places,
'form_class': forms.DecimalField,
}
defaults.update(kwargs)
return super(DecimalField, self).formfield(**defaults)

[docs]class DurationField(Field):
"""Stores timedelta objects.

Uses interval on postgres, INVERAL DAY TO SECOND on Oracle, and bigint of
microseconds on other databases.
"""
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value has an invalid format. It must be in "
"[DD] [HH:[MM:]]ss[.uuuuuu] format.")
}
description = _("Duration")

def get_internal_type(self):
return "DurationField"

def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.timedelta):
return value
try:
parsed = parse_duration(value)
except ValueError:
pass
else:
if parsed is not None:
return parsed

raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def get_db_prep_value(self, value, connection, prepared=False):
if connection.features.has_native_duration_field:
return value
if value is None:
return None
# Discard any fractional microseconds due to floating point arithmetic.
return int(round(value.total_seconds() * 1000000))

def get_db_converters(self, connection):
converters = []
if not connection.features.has_native_duration_field:
converters.append(connection.ops.convert_durationfield_value)
return converters + super(DurationField, self).get_db_converters(connection)

def value_to_string(self, obj):
val = self.value_from_object(obj)
return '' if val is None else duration_string(val)

def formfield(self, **kwargs):
defaults = {
'form_class': forms.DurationField,
}
defaults.update(kwargs)
return super(DurationField, self).formfield(**defaults)

[docs]class EmailField(CharField):
default_validators = [validators.validate_email]
description = _("Email address")

def __init__(self, *args, **kwargs):
# max_length=254 to be compliant with RFCs 3696 and 5321
kwargs['max_length'] = kwargs.get('max_length', 254)
super(EmailField, self).__init__(*args, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(EmailField, self).deconstruct()
# We do not exclude max_length if it matches default as we want to change
# the default in future.
return name, path, args, kwargs

def formfield(self, **kwargs):
# As with CharField, this will cause email validation to be performed
# twice.
defaults = {
'form_class': forms.EmailField,
}
defaults.update(kwargs)
return super(EmailField, self).formfield(**defaults)

[docs]class FilePathField(Field):
description = _("File path")

def __init__(self, verbose_name=None, name=None, path='', match=None,
recursive=False, allow_files=True, allow_folders=False, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
self.allow_files, self.allow_folders = allow_files, allow_folders
kwargs['max_length'] = kwargs.get('max_length', 100)
super(FilePathField, self).__init__(verbose_name, name, **kwargs)

def check(self, **kwargs):
errors = super(FilePathField, self).check(**kwargs)
errors.extend(self._check_allowing_files_or_folders(**kwargs))
return errors

def _check_allowing_files_or_folders(self, **kwargs):
if not self.allow_files and not self.allow_folders:
return [
checks.Error(
"FilePathFields must have either 'allow_files' or 'allow_folders' set to True.",
hint=None,
obj=self,
id='fields.E140',
)
]
return []

def deconstruct(self):
name, path, args, kwargs = super(FilePathField, self).deconstruct()
if self.path != '':
kwargs['path'] = self.path
if self.match is not None:
kwargs['match'] = self.match
if self.recursive is not False:
kwargs['recursive'] = self.recursive
if self.allow_files is not True:
kwargs['allow_files'] = self.allow_files
if self.allow_folders is not False:
kwargs['allow_folders'] = self.allow_folders
if kwargs.get("max_length") == 100:
del kwargs["max_length"]
return name, path, args, kwargs

def get_prep_value(self, value):
value = super(FilePathField, self).get_prep_value(value)
if value is None:
return None
return six.text_type(value)

def formfield(self, **kwargs):
defaults = {
'path': self.path,
'match': self.match,
'recursive': self.recursive,
'form_class': forms.FilePathField,
'allow_files': self.allow_files,
'allow_folders': self.allow_folders,
}
defaults.update(kwargs)
return super(FilePathField, self).formfield(**defaults)

def get_internal_type(self):
return "FilePathField"

[docs]class FloatField(Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be a float."),
}
description = _("Floating point number")

def get_prep_value(self, value):
value = super(FloatField, self).get_prep_value(value)
if value is None:
return None
return float(value)

def get_internal_type(self):
return "FloatField"

def to_python(self, value):
if value is None:
return value
try:
return float(value)
except (TypeError, ValueError):
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def formfield(self, **kwargs):
defaults = {'form_class': forms.FloatField}
defaults.update(kwargs)
return super(FloatField, self).formfield(**defaults)

[docs]class IntegerField(Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be an integer."),
}
description = _("Integer")

def check(self, **kwargs):
errors = super(IntegerField, self).check(**kwargs)
errors.extend(self._check_max_length_warning())
return errors

def _check_max_length_warning(self):
if self.max_length is not None:
return [
checks.Warning(
"'max_length' is ignored when used with IntegerField",
hint="Remove 'max_length' from field",
obj=self,
id='fields.W122',
)
]
return []

@cached_property
def validators(self):
# These validators can't be added at field initialization time since
# they're based on values retrieved from `connection`.
range_validators = []
internal_type = self.get_internal_type()
min_value, max_value = connection.ops.integer_field_range(internal_type)
if min_value is not None:
range_validators.append(validators.MinValueValidator(min_value))
if max_value is not None:
range_validators.append(validators.MaxValueValidator(max_value))
return super(IntegerField, self).validators + range_validators

def get_prep_value(self, value):
value = super(IntegerField, self).get_prep_value(value)
if value is None:
return None
return int(value)

def get_prep_lookup(self, lookup_type, value):
if ((lookup_type == 'gte' or lookup_type == 'lt')
and isinstance(value, float)):
value = math.ceil(value)
return super(IntegerField, self).get_prep_lookup(lookup_type, value)

def get_internal_type(self):
return "IntegerField"

def to_python(self, value):
if value is None:
return value
try:
return int(value)
except (TypeError, ValueError):
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def formfield(self, **kwargs):
defaults = {'form_class': forms.IntegerField}
defaults.update(kwargs)
return super(IntegerField, self).formfield(**defaults)

[docs]class BigIntegerField(IntegerField):
empty_strings_allowed = False
description = _("Big (8 byte) integer")
MAX_BIGINT = 9223372036854775807

def get_internal_type(self):
return "BigIntegerField"

def formfield(self, **kwargs):
defaults = {'min_value': -BigIntegerField.MAX_BIGINT - 1,
'max_value': BigIntegerField.MAX_BIGINT}
defaults.update(kwargs)
return super(BigIntegerField, self).formfield(**defaults)

class IPAddressField(Field):
empty_strings_allowed = False
description = _("IPv4 address")
system_check_removed_details = {
'msg': (
'IPAddressField has been removed except for support in '
'historical migrations.'
),
'hint': 'Use GenericIPAddressField instead.',
'id': 'fields.E900',
}

def __init__(self, *args, **kwargs):
kwargs['max_length'] = 15
super(IPAddressField, self).__init__(*args, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(IPAddressField, self).deconstruct()
del kwargs['max_length']
return name, path, args, kwargs

def get_prep_value(self, value):
value = super(IPAddressField, self).get_prep_value(value)
if value is None:
return None
return six.text_type(value)

def get_internal_type(self):
return "IPAddressField"

[docs]class GenericIPAddressField(Field):
empty_strings_allowed = False
description = _("IP address")
default_error_messages = {}

def __init__(self, verbose_name=None, name=None, protocol='both',
unpack_ipv4=False, *args, **kwargs):
self.unpack_ipv4 = unpack_ipv4
self.protocol = protocol
self.default_validators, invalid_error_message = \
validators.ip_address_validators(protocol, unpack_ipv4)
self.default_error_messages['invalid'] = invalid_error_message
kwargs['max_length'] = 39
super(GenericIPAddressField, self).__init__(verbose_name, name, *args,
**kwargs)

def check(self, **kwargs):
errors = super(GenericIPAddressField, self).check(**kwargs)
errors.extend(self._check_blank_and_null_values(**kwargs))
return errors

def _check_blank_and_null_values(self, **kwargs):
if not getattr(self, 'null', False) and getattr(self, 'blank', False):
return [
checks.Error(
('GenericIPAddressFields cannot have blank=True if null=False, '
'as blank values are stored as nulls.'),
hint=None,
obj=self,
id='fields.E150',
)
]
return []

def deconstruct(self):
name, path, args, kwargs = super(GenericIPAddressField, self).deconstruct()
if self.unpack_ipv4 is not False:
kwargs['unpack_ipv4'] = self.unpack_ipv4
if self.protocol != "both":
kwargs['protocol'] = self.protocol
if kwargs.get("max_length") == 39:
del kwargs['max_length']
return name, path, args, kwargs

def get_internal_type(self):
return "GenericIPAddressField"

def to_python(self, value):
if value is None:
return None
if not isinstance(value, six.string_types):
value = force_text(value)
value = value.strip()
if ':' in value:
return clean_ipv6_address(value,
self.unpack_ipv4, self.error_messages['invalid'])
return value

def get_db_prep_value(self, value, connection, prepared=False):
if not prepared:
value = self.get_prep_value(value)
return connection.ops.adapt_ipaddressfield_value(value)

def get_prep_value(self, value):
value = super(GenericIPAddressField, self).get_prep_value(value)
if value is None:
return None
if value and ':' in value:
try:
return clean_ipv6_address(value, self.unpack_ipv4)
except exceptions.ValidationError:
pass
return six.text_type(value)

def formfield(self, **kwargs):
defaults = {
'protocol': self.protocol,
'form_class': forms.GenericIPAddressField,
}
defaults.update(kwargs)
return super(GenericIPAddressField, self).formfield(**defaults)

[docs]class NullBooleanField(Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value must be either None, True or False."),
}
description = _("Boolean (Either True, False or None)")

def __init__(self, *args, **kwargs):
kwargs['null'] = True
kwargs['blank'] = True
super(NullBooleanField, self).__init__(*args, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(NullBooleanField, self).deconstruct()
del kwargs['null']
del kwargs['blank']
return name, path, args, kwargs

def get_internal_type(self):
return "NullBooleanField"

def to_python(self, value):
if value is None:
return None
if value in (True, False):
return bool(value)
if value in ('None',):
return None
if value in ('t', 'True', '1'):
return True
if value in ('f', 'False', '0'):
return False
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def get_prep_lookup(self, lookup_type, value):
# Special-case handling for filters coming from a Web request (e.g. the
# admin interface). Only works for scalar values (not lists). If you're
# passing in a list, you might as well make things the right type when
# constructing the list.
if value in ('1', '0'):
value = bool(int(value))
return super(NullBooleanField, self).get_prep_lookup(lookup_type,
value)

def get_prep_value(self, value):
value = super(NullBooleanField, self).get_prep_value(value)
if value is None:
return None
return bool(value)

def formfield(self, **kwargs):
defaults = {
'form_class': forms.NullBooleanField,
'required': not self.blank,
'label': capfirst(self.verbose_name),
'help_text': self.help_text}
defaults.update(kwargs)
return super(NullBooleanField, self).formfield(**defaults)

[docs]class PositiveIntegerField(IntegerField):
description = _("Positive integer")

def get_internal_type(self):
return "PositiveIntegerField"

def formfield(self, **kwargs):
defaults = {'min_value': 0}
defaults.update(kwargs)
return super(PositiveIntegerField, self).formfield(**defaults)

[docs]class PositiveSmallIntegerField(IntegerField):
description = _("Positive small integer")

def get_internal_type(self):
return "PositiveSmallIntegerField"

def formfield(self, **kwargs):
defaults = {'min_value': 0}
defaults.update(kwargs)
return super(PositiveSmallIntegerField, self).formfield(**defaults)

[docs]class SlugField(CharField):
default_validators = [validators.validate_slug]
description = _("Slug (up to %(max_length)s)")

def __init__(self, *args, **kwargs):
kwargs['max_length'] = kwargs.get('max_length', 50)
# Set db_index=True unless it's been set manually.
if 'db_index' not in kwargs:
kwargs['db_index'] = True
self.allow_unicode = kwargs.pop('allow_unicode', False)
if self.allow_unicode:
self.default_validators = [validators.validate_unicode_slug]
super(SlugField, self).__init__(*args, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(SlugField, self).deconstruct()
if kwargs.get("max_length") == 50:
del kwargs['max_length']
if self.db_index is False:
kwargs['db_index'] = False
else:
del kwargs['db_index']
if self.allow_unicode is not False:
kwargs['allow_unicode'] = self.allow_unicode
return name, path, args, kwargs

def get_internal_type(self):
return "SlugField"

def formfield(self, **kwargs):
defaults = {'form_class': forms.SlugField, 'allow_unicode': self.allow_unicode}
defaults.update(kwargs)
return super(SlugField, self).formfield(**defaults)

[docs]class SmallIntegerField(IntegerField):
description = _("Small integer")

def get_internal_type(self):
return "SmallIntegerField"

[docs]class TextField(Field):
description = _("Text")

def get_internal_type(self):
return "TextField"

def to_python(self, value):
if isinstance(value, six.string_types) or value is None:
return value
return smart_text(value)

def get_prep_value(self, value):
value = super(TextField, self).get_prep_value(value)
return self.to_python(value)

def formfield(self, **kwargs):
# Passing max_length to forms.CharField means that the value's length
# will be validated twice. This is considered acceptable since we want
# the value in the form field (to pass into widget for example).
defaults = {'max_length': self.max_length, 'widget': forms.Textarea}
defaults.update(kwargs)
return super(TextField, self).formfield(**defaults)

[docs]class TimeField(DateTimeCheckMixin, Field):
empty_strings_allowed = False
default_error_messages = {
'invalid': _("'%(value)s' value has an invalid format. It must be in "
"HH:MM[:ss[.uuuuuu]] format."),
'invalid_time': _("'%(value)s' value has the correct format "
"(HH:MM[:ss[.uuuuuu]]) but it is an invalid time."),
}
description = _("Time")

def __init__(self, verbose_name=None, name=None, auto_now=False,
auto_now_add=False, **kwargs):
self.auto_now, self.auto_now_add = auto_now, auto_now_add
if auto_now or auto_now_add:
kwargs['editable'] = False
kwargs['blank'] = True
super(TimeField, self).__init__(verbose_name, name, **kwargs)

def _check_fix_default_value(self):
"""
Adds a warning to the checks framework stating, that using an actual
time or datetime value is probably wrong; it's only being evaluated on
server start-up.

For details see ticket #21905
"""
if not self.has_default():
return []

now = timezone.now()
if not timezone.is_naive(now):
now = timezone.make_naive(now, timezone.utc)
value = self.default
if isinstance(value, datetime.datetime):
second_offset = datetime.timedelta(seconds=10)
lower = now - second_offset
upper = now + second_offset
if timezone.is_aware(value):
value = timezone.make_naive(value, timezone.utc)
elif isinstance(value, datetime.time):
second_offset = datetime.timedelta(seconds=10)
lower = now - second_offset
upper = now + second_offset
value = datetime.datetime.combine(now.date(), value)
if timezone.is_aware(value):
value = timezone.make_naive(value, timezone.utc).time()
else:
# No explicit time / datetime value -- no checks necessary
return []
if lower <= value <= upper:
return [
checks.Warning(
'Fixed default value provided.',
hint='It seems you set a fixed date / time / datetime '
'value as default for this field. This may not be '
'what you want. If you want to have the current date '
'as default, use `django.utils.timezone.now`',
obj=self,
id='fields.W161',
)
]

return []

def deconstruct(self):
name, path, args, kwargs = super(TimeField, self).deconstruct()
if self.auto_now is not False:
kwargs["auto_now"] = self.auto_now
if self.auto_now_add is not False:
kwargs["auto_now_add"] = self.auto_now_add
if self.auto_now or self.auto_now_add:
del kwargs['blank']
del kwargs['editable']
return name, path, args, kwargs

def get_internal_type(self):
return "TimeField"

def to_python(self, value):
if value is None:
return None
if isinstance(value, datetime.time):
return value
if isinstance(value, datetime.datetime):
# Not usually a good idea to pass in a datetime here (it loses
# information), but this can be a side-effect of interacting with a
# database backend (e.g. Oracle), so we'll be accommodating.
return value.time()

try:
parsed = parse_time(value)
if parsed is not None:
return parsed
except ValueError:
raise exceptions.ValidationError(
self.error_messages['invalid_time'],
code='invalid_time',
params={'value': value},
)

raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)

def pre_save(self, model_instance, add):
if self.auto_now or (self.auto_now_add and add):
value = datetime.datetime.now().time()
setattr(model_instance, self.attname, value)
return value
else:
return super(TimeField, self).pre_save(model_instance, add)

def get_prep_value(self, value):
value = super(TimeField, self).get_prep_value(value)
return self.to_python(value)

def get_db_prep_value(self, value, connection, prepared=False):
# Casts times into the format expected by the backend
if not prepared:
value = self.get_prep_value(value)
return connection.ops.adapt_timefield_value(value)

def value_to_string(self, obj):
val = self.value_from_object(obj)
return '' if val is None else val.isoformat()

def formfield(self, **kwargs):
defaults = {'form_class': forms.TimeField}
defaults.update(kwargs)
return super(TimeField, self).formfield(**defaults)

[docs]class URLField(CharField):
default_validators = [validators.URLValidator()]
description = _("URL")

def __init__(self, verbose_name=None, name=None, **kwargs):
kwargs['max_length'] = kwargs.get('max_length', 200)
super(URLField, self).__init__(verbose_name, name, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(URLField, self).deconstruct()
if kwargs.get("max_length") == 200:
del kwargs['max_length']
return name, path, args, kwargs

def formfield(self, **kwargs):
# As with CharField, this will cause URL validation to be performed
# twice.
defaults = {
'form_class': forms.URLField,
}
defaults.update(kwargs)
return super(URLField, self).formfield(**defaults)

[docs]class BinaryField(Field):
description = _("Raw binary data")
empty_values = [None, b'']

def __init__(self, *args, **kwargs):
kwargs['editable'] = False
super(BinaryField, self).__init__(*args, **kwargs)
if self.max_length is not None:
self.validators.append(validators.MaxLengthValidator(self.max_length))

def deconstruct(self):
name, path, args, kwargs = super(BinaryField, self).deconstruct()
del kwargs['editable']
return name, path, args, kwargs

def get_internal_type(self):
return "BinaryField"

def get_default(self):
if self.has_default() and not callable(self.default):
return self.default
default = super(BinaryField, self).get_default()
if default == '':
return b''
return default

def get_db_prep_value(self, value, connection, prepared=False):
value = super(BinaryField, self).get_db_prep_value(value, connection, prepared)
if value is not None:
return connection.Database.Binary(value)
return value

def value_to_string(self, obj):
"""Binary data is serialized as base64"""
return b64encode(force_bytes(self.value_from_object(obj))).decode('ascii')

def to_python(self, value):
# If it's a string, it should be base64-encoded data
if isinstance(value, six.text_type):
return six.memoryview(b64decode(force_bytes(value)))
return value

[docs]class UUIDField(Field):
default_error_messages = {
'invalid': _("'%(value)s' is not a valid UUID."),
}
description = 'Universally unique identifier'
empty_strings_allowed = False

def __init__(self, verbose_name=None, **kwargs):
kwargs['max_length'] = 32
super(UUIDField, self).__init__(verbose_name, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(UUIDField, self).deconstruct()
del kwargs['max_length']
return name, path, args, kwargs

def get_internal_type(self):
return "UUIDField"

def get_db_prep_value(self, value, connection, prepared=False):
if value is None:
return None
if not isinstance(value, uuid.UUID):
try:
value = uuid.UUID(value)
except AttributeError:
raise TypeError(self.error_messages['invalid'] % {'value': value})

if connection.features.has_native_uuid_field:
return value
return value.hex

def to_python(self, value):
if value and not isinstance(value, uuid.UUID):
try:
return uuid.UUID(value)
except ValueError:
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)
return value

def formfield(self, **kwargs):
defaults = {
'form_class': forms.UUIDField,
}
defaults.update(kwargs)
return super(UUIDField, self).formfield(**defaults)

Source code for django.db.models.base

from __future__ import unicode_literals

import copy
import inspect
import warnings
from itertools import chain

from django.apps import apps
from django.conf import settings
from django.core import checks
from django.core.exceptions import (
NON_FIELD_ERRORS, FieldDoesNotExist, FieldError, MultipleObjectsReturned,
ObjectDoesNotExist, ValidationError,
)
from django.db import (
DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY, DatabaseError, connections,
router, transaction,
)
from django.db.models import signals
from django.db.models.constants import LOOKUP_SEP
from django.db.models.deletion import CASCADE, Collector
from django.db.models.fields import AutoField
from django.db.models.fields.related import (
ForeignObjectRel, ManyToOneRel, OneToOneField, lazy_related_operation,
resolve_relation,
)
from django.db.models.manager import ensure_default_manager
from django.db.models.options import Options
from django.db.models.query import Q
from django.db.models.query_utils import (
DeferredAttribute, deferred_class_factory,
)
from django.db.models.utils import make_model_tuple
from django.utils import six
from django.utils.encoding import force_str, force_text
from django.utils.functional import curry
from django.utils.six.moves import zip
from django.utils.text import capfirst, get_text_list
from django.utils.translation import ugettext_lazy as _
from django.utils.version import get_version

def subclass_exception(name, parents, module, attached_to=None):
"""
Create exception subclass. Used by ModelBase below.

If 'attached_to' is supplied, the exception will be created in a way that
allows it to be pickled, assuming the returned exception class will be added
as an attribute to the 'attached_to' class.
"""
class_dict = {'__module__': module}
if attached_to is not None:
def __reduce__(self):
# Exceptions are special - they've got state that isn't
# in self.__dict__. We assume it is all in self.args.
return (unpickle_inner_exception, (attached_to, name), self.args)

def __setstate__(self, args):
self.args = args

class_dict['__reduce__'] = __reduce__
class_dict['__setstate__'] = __setstate__

return type(name, parents, class_dict)

class ModelBase(type):
"""
Metaclass for all models.
"""
def __new__(cls, name, bases, attrs):
super_new = super(ModelBase, cls).__new__

# Also ensure initialization is only performed for subclasses of Model
# (excluding Model class itself).
parents = [b for b in bases if isinstance(b, ModelBase)]
if not parents:
return super_new(cls, name, bases, attrs)

# Create the class.
module = attrs.pop('__module__')
new_class = super_new(cls, name, bases, {'__module__': module})
attr_meta = attrs.pop('Meta', None)
abstract = getattr(attr_meta, 'abstract', False)
if not attr_meta:
meta = getattr(new_class, 'Meta', None)
else:
meta = attr_meta
base_meta = getattr(new_class, '_meta', None)

app_label = None

# Look for an application configuration to attach the model to.
app_config = apps.get_containing_app_config(module)

if getattr(meta, 'app_label', None) is None:
if app_config is None:
if not abstract:
raise RuntimeError(
"Model class %s.%s doesn't declare an explicit "
"app_label and isn't in an application in "
"INSTALLED_APPS." % (module, name)
)

else:
app_label = app_config.label

new_class.add_to_class('_meta', Options(meta, app_label))
if not abstract:
new_class.add_to_class(
'DoesNotExist',
subclass_exception(
str('DoesNotExist'),
tuple(
x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract
) or (ObjectDoesNotExist,),
module,
attached_to=new_class))
new_class.add_to_class(
'MultipleObjectsReturned',
subclass_exception(
str('MultipleObjectsReturned'),
tuple(
x.MultipleObjectsReturned for x in parents if hasattr(x, '_meta') and not x._meta.abstract
) or (MultipleObjectsReturned,),
module,
attached_to=new_class))
if base_meta and not base_meta.abstract:
# Non-abstract child classes inherit some attributes from their
# non-abstract parent (unless an ABC comes before it in the
# method resolution order).
if not hasattr(meta, 'ordering'):
new_class._meta.ordering = base_meta.ordering
if not hasattr(meta, 'get_latest_by'):
new_class._meta.get_latest_by = base_meta.get_latest_by

is_proxy = new_class._meta.proxy

# If the model is a proxy, ensure that the base class
# hasn't been swapped out.
if is_proxy and base_meta and base_meta.swapped:
raise TypeError("%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped))

if getattr(new_class, '_default_manager', None):
if not is_proxy:
# Multi-table inheritance doesn't inherit default manager from
# parents.
new_class._default_manager = None
new_class._base_manager = None
else:
# Proxy classes do inherit parent's default manager, if none is
# set explicitly.
new_class._default_manager = new_class._default_manager._copy_to_model(new_class)
new_class._base_manager = new_class._base_manager._copy_to_model(new_class)

# Add all attributes to the class.
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)

# All the fields of any type declared on this model
new_fields = chain(
new_class._meta.local_fields,
new_class._meta.local_many_to_many,
new_class._meta.virtual_fields
)
field_names = {f.name for f in new_fields}

# Basic setup for proxy models.
if is_proxy:
base = None
for parent in [kls for kls in parents if hasattr(kls, '_meta')]:
if parent._meta.abstract:
if parent._meta.fields:
raise TypeError(
"Abstract base class containing model fields not "
"permitted for proxy model '%s'." % name
)
else:
continue
if base is not None:
raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name)
else:
base = parent
if base is None:
raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
new_class._meta.setup_proxy(base)
new_class._meta.concrete_model = base._meta.concrete_model
base._meta.concrete_model._meta.proxied_children.append(new_class._meta)
else:
new_class._meta.concrete_model = new_class

# Collect the parent links for multi-table inheritance.
parent_links = {}
for base in reversed([new_class] + parents):
# Conceptually equivalent to `if base is Model`.
if not hasattr(base, '_meta'):
continue
# Skip concrete parent classes.
if base != new_class and not base._meta.abstract:
continue
# Locate OneToOneField instances.
for field in base._meta.local_fields:
if isinstance(field, OneToOneField):
related = resolve_relation(new_class, field.remote_field.model)
parent_links[make_model_tuple(related)] = field
# Do the appropriate setup for any model parents.
for base in parents:
original_base = base
if not hasattr(base, '_meta'):
# Things without _meta aren't functional models, so they're
# uninteresting parents.
continue

parent_fields = base._meta.local_fields + base._meta.local_many_to_many
# Check for clashes between locally declared fields and those
# on the base classes (we cannot handle shadowed fields at the
# moment).
for field in parent_fields:
if field.name in field_names:
raise FieldError(
'Local field %r in class %r clashes '
'with field of similar name from '
'base class %r' % (field.name, name, base.__name__)
)
if not base._meta.abstract:
# Concrete classes...
base = base._meta.concrete_model
base_key = make_model_tuple(base)
if base_key in parent_links:
field = parent_links[base_key]
elif not is_proxy:
attr_name = '%s_ptr' % base._meta.model_name
field = OneToOneField(
base,
on_delete=CASCADE,
name=attr_name,
auto_created=True,
parent_link=True,
)
# Only add the ptr field if it's not already present;
# e.g. migrations will already have it specified
if not hasattr(new_class, attr_name):
new_class.add_to_class(attr_name, field)
else:
field = None
new_class._meta.parents[base] = field
else:
base_parents = base._meta.parents.copy()

# .. and abstract ones.
for field in parent_fields:
new_field = copy.deepcopy(field)
new_class.add_to_class(field.name, new_field)
# Replace parent links defined on this base by the new
# field as it will be appropriately resolved if required.
if field.one_to_one:
for parent, parent_link in base_parents.items():
if field == parent_link:
base_parents[parent] = new_field

# Pass any non-abstract parent classes onto child.
new_class._meta.parents.update(base_parents)

# Inherit managers from the abstract base classes.
new_class.copy_managers(base._meta.abstract_managers)

# Proxy models inherit the non-abstract managers from their base,
# unless they have redefined any of them.
if is_proxy:
new_class.copy_managers(original_base._meta.concrete_managers)

# Inherit virtual fields (like GenericForeignKey) from the parent
# class
for field in base._meta.virtual_fields:
if base._meta.abstract and field.name in field_names:
raise FieldError(
'Local field %r in class %r clashes '
'with field of similar name from '
'abstract base class %r' % (field.name, name, base.__name__)
)
new_class.add_to_class(field.name, copy.deepcopy(field))

if abstract:
# Abstract base models can't be instantiated and don't appear in
# the list of models for an app. We do the final setup for them a
# little differently from normal models.
attr_meta.abstract = False
new_class.Meta = attr_meta
return new_class

new_class._prepare()
new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
return new_class

def copy_managers(cls, base_managers):
# This is in-place sorting of an Options attribute, but that's fine.
base_managers.sort()
for _, mgr_name, manager in base_managers:  # NOQA (redefinition of _)
val = getattr(cls, mgr_name, None)
if not val or val is manager:
new_manager = manager._copy_to_model(cls)
cls.add_to_class(mgr_name, new_manager)

def add_to_class(cls, name, value):
# We should call the contribute_to_class method only if it's bound
if not inspect.isclass(value) and hasattr(value, 'contribute_to_class'):
value.contribute_to_class(cls, name)
else:
setattr(cls, name, value)

def _prepare(cls):
"""
Creates some methods once self._meta has been populated.
"""
opts = cls._meta
opts._prepare(cls)

if opts.order_with_respect_to:
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)

# Defer creating accessors on the foreign class until it has been
# created and registered. If remote_field is None, we're ordering
# with respect to a GenericForeignKey and don't know what the
# foreign class is - we'll add those accessors later in
# contribute_to_class().
if opts.order_with_respect_to.remote_field:
wrt = opts.order_with_respect_to
remote = wrt.remote_field.model
lazy_related_operation(make_foreign_order_accessors, cls, remote)

# Give the class a docstring -- its definition.
if cls.__doc__ is None:
cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join(f.name for f in opts.fields))

get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get(opts.label_lower)
if get_absolute_url_override:
setattr(cls, 'get_absolute_url', get_absolute_url_override)

ensure_default_manager(cls)
signals.class_prepared.send(sender=cls)

class ModelState(object):
"""
A class for storing instance state
"""
def __init__(self, db=None):
self.db = db
# If true, uniqueness validation checks will consider this a new, as-yet-unsaved object.
# Necessary for correct validation of new instances of objects with explicit (non-auto) PKs.
# This impacts validation only; it has no effect on the actual save.
self.adding = True

[docs]class Model(six.with_metaclass(ModelBase)):
_deferred = False

def __init__(self, *args, **kwargs):
signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs)

# Set up the storage for instance state
self._state = ModelState()

# There is a rather weird disparity here; if kwargs, it's set, then args
# overrides it. It should be one or the other; don't duplicate the work
# The reason for the kwargs check is that standard iterator passes in by
# args, and instantiation for iteration is 33% faster.
args_len = len(args)
if args_len > len(self._meta.concrete_fields):
# Daft, but matches old exception sans the err msg.
raise IndexError("Number of args exceeds number of fields")

if not kwargs:
fields_iter = iter(self._meta.concrete_fields)
# The ordering of the zip calls matter - zip throws StopIteration
# when an iter throws it. So if the first iter throws it, the second
# is *not* consumed. We rely on this, so don't change the order
# without changing the logic.
for val, field in zip(args, fields_iter):
setattr(self, field.attname, val)
else:
# Slower, kwargs-ready version.
fields_iter = iter(self._meta.fields)
for val, field in zip(args, fields_iter):
setattr(self, field.attname, val)
kwargs.pop(field.name, None)
# Maintain compatibility with existing calls.
if isinstance(field.remote_field, ManyToOneRel):
kwargs.pop(field.attname, None)

# Now we're left with the unprocessed fields that *must* come from
# keywords, or default.

for field in fields_iter:
is_related_object = False
# This slightly odd construct is so that we can access any
# data-descriptor object (DeferredAttribute) without triggering its
# __get__ method.
if (field.attname not in kwargs and
(isinstance(self.__class__.__dict__.get(field.attname), DeferredAttribute)
or field.column is None)):
# This field will be populated on request.
continue
if kwargs:
if isinstance(field.remote_field, ForeignObjectRel):
try:
# Assume object instance was passed in.
rel_obj = kwargs.pop(field.name)
is_related_object = True
except KeyError:
try:
# Object instance wasn't passed in -- must be an ID.
val = kwargs.pop(field.attname)
except KeyError:
val = field.get_default()
else:
# Object instance was passed in. Special case: You can
# pass in "None" for related objects if it's allowed.
if rel_obj is None and field.null:
val = None
else:
try:
val = kwargs.pop(field.attname)
except KeyError:
# This is done with an exception rather than the
# default argument on pop because we don't want
# get_default() to be evaluated, and then not used.
# Refs #12057.
val = field.get_default()
else:
val = field.get_default()

if is_related_object:
# If we are passed a related instance, set it using the
# field.name instead of field.attname (e.g. "user" instead of
# "user_id") so that the object gets properly cached (and type
# checked) by the RelatedObjectDescriptor.
setattr(self, field.name, rel_obj)
else:
setattr(self, field.attname, val)

if kwargs:
for prop in list(kwargs):
try:
if isinstance(getattr(self.__class__, prop), property):
setattr(self, prop, kwargs.pop(prop))
except AttributeError:
pass
if kwargs:
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
super(Model, self).__init__()
signals.post_init.send(sender=self.__class__, instance=self)

@classmethod

[docs]    def from_db(cls, db, field_names, values):
if cls._deferred:
new = cls(**dict(zip(field_names, values)))
else:
new = cls(*values)
new._state.adding = False
new._state.db = db
return new

def __repr__(self):
try:
u = six.text_type(self)
except (UnicodeEncodeError, UnicodeDecodeError):
u = '[Bad Unicode data]'
return force_str('<%s: %s>' % (self.__class__.__name__, u))

[docs]    def __str__(self):
if six.PY2 and hasattr(self, '__unicode__'):
return force_text(self).encode('utf-8')
return str('%s object' % self.__class__.__name__)

[docs]    def __eq__(self, other):
if not isinstance(other, Model):
return False
if self._meta.concrete_model != other._meta.concrete_model:
return False
my_pk = self._get_pk_val()
if my_pk is None:
return self is other
return my_pk == other._get_pk_val()

def __ne__(self, other):
return not self.__eq__(other)

[docs]    def __hash__(self):
if self._get_pk_val() is None:
raise TypeError("Model instances without primary key value are unhashable")
return hash(self._get_pk_val())

def __reduce__(self):
"""
Provides pickling support. Normally, this just dispatches to Python's
standard handling. However, for models with deferred field loading, we
need to do things manually, as they're dynamically created classes and
only module-level classes can be pickled by the default path.
"""
data = self.__dict__
data[DJANGO_VERSION_PICKLE_KEY] = get_version()
if not self._deferred:
class_id = self._meta.app_label, self._meta.object_name
return model_unpickle, (class_id, [], simple_class_factory), data
defers = []
for field in self._meta.fields:
if isinstance(self.__class__.__dict__.get(field.attname),
DeferredAttribute):
defers.append(field.attname)
model = self._meta.proxy_for_model
class_id = model._meta.app_label, model._meta.object_name
return (model_unpickle, (class_id, defers, deferred_class_factory), data)

def __setstate__(self, state):
msg = None
pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY)
if pickled_version:
current_version = get_version()
if current_version != pickled_version:
msg = ("Pickled model instance's Django version %s does"
" not match the current version %s."
% (pickled_version, current_version))
else:
msg = "Pickled model instance's Django version is not specified."

if msg:
warnings.warn(msg, RuntimeWarning, stacklevel=2)

self.__dict__.update(state)

def _get_pk_val(self, meta=None):
if not meta:
meta = self._meta
return getattr(self, meta.pk.attname)

def _set_pk_val(self, value):
return setattr(self, self._meta.pk.attname, value)

pk = property(_get_pk_val, _set_pk_val)

[docs]    def get_deferred_fields(self):
"""
Returns a set containing names of deferred fields for this instance.
"""
return {
f.attname for f in self._meta.concrete_fields
if isinstance(self.__class__.__dict__.get(f.attname), DeferredAttribute)
}

[docs]    def refresh_from_db(self, using=None, fields=None, **kwargs):
"""
Reloads field values from the database.

By default, the reloading happens from the database this instance was
loaded from, or by the read router if this instance wasn't loaded from
any database. The using parameter will override the default.

Fields can be used to specify which fields to reload. The fields
should be an iterable of field attnames. If fields is None, then
all non-deferred fields are reloaded.

When accessing deferred fields of an instance, the deferred loading
of the field will call this method.
"""
if fields is not None:
if len(fields) == 0:
return
if any(LOOKUP_SEP in f for f in fields):
raise ValueError(
'Found "%s" in fields argument. Relations and transforms '
'are not allowed in fields.' % LOOKUP_SEP)

db = using if using is not None else self._state.db
if self._deferred:
non_deferred_model = self._meta.proxy_for_model
else:
non_deferred_model = self.__class__
db_instance_qs = non_deferred_model._default_manager.using(db).filter(pk=self.pk)

# Use provided fields, if not set then reload all non-deferred fields.
if fields is not None:
fields = list(fields)
db_instance_qs = db_instance_qs.only(*fields)
elif self._deferred:
deferred_fields = self.get_deferred_fields()
fields = [f.attname for f in self._meta.concrete_fields
if f.attname not in deferred_fields]
db_instance_qs = db_instance_qs.only(*fields)

db_instance = db_instance_qs.get()
non_loaded_fields = db_instance.get_deferred_fields()
for field in self._meta.concrete_fields:
if field.attname in non_loaded_fields:
# This field wasn't refreshed - skip ahead.
continue
setattr(self, field.attname, getattr(db_instance, field.attname))
# Throw away stale foreign key references.
if field.is_relation and field.get_cache_name() in self.__dict__:
rel_instance = getattr(self, field.get_cache_name())
local_val = getattr(db_instance, field.attname)
related_val = None if rel_instance is None else getattr(rel_instance, field.target_field.attname)
if local_val != related_val or (local_val is None and related_val is None):
del self.__dict__[field.get_cache_name()]
self._state.db = db_instance._state.db

def serializable_value(self, field_name):
"""
Returns the value of the field name for this instance. If the field is
a foreign key, returns the id value, instead of the object. If there's
no Field object with this name on the model, the model attribute's
value is returned directly.

Used to serialize a field's value (in the serializer, or form output,
for example). Normally, you would just access the attribute directly
and not use this method.
"""
try:
field = self._meta.get_field(field_name)
except FieldDoesNotExist:
return getattr(self, field_name)
return getattr(self, field.attname)

[docs]    def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
"""
Saves the current instance. Override this in a subclass if you want to
control the saving process.

The 'force_insert' and 'force_update' parameters can be used to insist
that the "save" must be an SQL insert or update (or equivalent for
non-SQL backends), respectively. Normally, they should not be set.
"""
# Ensure that a model instance without a PK hasn't been assigned to
# a ForeignKey or OneToOneField on this model. If the field is
# nullable, allowing the save() would result in silent data loss.
for field in self._meta.concrete_fields:
if field.is_relation:
# If the related field isn't cached, then an instance hasn't
# been assigned and there's no need to worry about this check.
try:
getattr(self, field.get_cache_name())
except AttributeError:
continue
obj = getattr(self, field.name, None)
# A pk may have been assigned manually to a model instance not
# saved to the database (or auto-generated in a case like
# UUIDField), but we allow the save to proceed and rely on the
# database to raise an IntegrityError if applicable. If
# constraints aren't supported by the database, there's the
# unavoidable risk of data corruption.
if obj and obj.pk is None:
# Remove the object from a related instance cache.
if not field.remote_field.multiple:
delattr(obj, field.remote_field.get_cache_name())
raise ValueError(
"save() prohibited to prevent data loss due to "
"unsaved related object '%s'." % field.name
)

using = using or router.db_for_write(self.__class__, instance=self)
if force_insert and (force_update or update_fields):
raise ValueError("Cannot force both insert and updating in model saving.")

if update_fields is not None:
# If update_fields is empty, skip the save. We do also check for
# no-op saves later on for inheritance cases. This bailout is
# still needed for skipping signal sending.
if len(update_fields) == 0:
return

update_fields = frozenset(update_fields)
field_names = set()

for field in self._meta.fields:
if not field.primary_key:
field_names.add(field.name)

if field.name != field.attname:
field_names.add(field.attname)

non_model_fields = update_fields.difference(field_names)

if non_model_fields:
raise ValueError("The following fields do not exist in this "
"model or are m2m fields: %s"
% ', '.join(non_model_fields))

# If saving to the same database, and this model is deferred, then
# automatically do a "update_fields" save on the loaded fields.
elif not force_insert and self._deferred and using == self._state.db:
field_names = set()
for field in self._meta.concrete_fields:
if not field.primary_key and not hasattr(field, 'through'):
field_names.add(field.attname)
deferred_fields = [
f.attname for f in self._meta.fields
if (f.attname not in self.__dict__ and
isinstance(self.__class__.__dict__[f.attname], DeferredAttribute))
]

loaded_fields = field_names.difference(deferred_fields)
if loaded_fields:
update_fields = frozenset(loaded_fields)

self.save_base(using=using, force_insert=force_insert,
force_update=force_update, update_fields=update_fields)

save.alters_data = True

def save_base(self, raw=False, force_insert=False,
force_update=False, using=None, update_fields=None):
"""
Handles the parts of saving which should be done only once per save,
yet need to be done in raw saves, too. This includes some sanity
checks and signal sending.

The 'raw' argument is telling save_base not to save any parent
models and not to do any changes to the values before save. This
is used by fixture loading.
"""
using = using or router.db_for_write(self.__class__, instance=self)
assert not (force_insert and (force_update or update_fields))
assert update_fields is None or len(update_fields) > 0
cls = origin = self.__class__
# Skip proxies, but keep the origin as the proxy model.
if cls._meta.proxy:
cls = cls._meta.concrete_model
meta = cls._meta
if not meta.auto_created:
signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using,
update_fields=update_fields)
with transaction.atomic(using=using, savepoint=False):
if not raw:
self._save_parents(cls, using, update_fields)
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
# Store the database on which the object was saved
self._state.db = using
# Once saved, this is no longer a to-be-added instance.
self._state.adding = False

# Signal that the save is complete
if not meta.auto_created:
signals.post_save.send(sender=origin, instance=self, created=(not updated),
update_fields=update_fields, raw=raw, using=using)

save_base.alters_data = True

def _save_parents(self, cls, using, update_fields):
"""
Saves all the parents of cls using values from self.
"""
meta = cls._meta
for parent, field in meta.parents.items():
# Make sure the link fields are synced between parent and self.
if (field and getattr(self, parent._meta.pk.attname) is None
and getattr(self, field.attname) is not None):
setattr(self, parent._meta.pk.attname, getattr(self, field.attname))
self._save_parents(cls=parent, using=using, update_fields=update_fields)
self._save_table(cls=parent, using=using, update_fields=update_fields)
# Set the parent's PK value to self.
if field:
setattr(self, field.attname, self._get_pk_val(parent._meta))
# Since we didn't have an instance of the parent handy set
# attname directly, bypassing the descriptor. Invalidate
# the related object cache, in case it's been accidentally
# populated. A fresh instance will be re-built from the
# database if necessary.
cache_name = field.get_cache_name()
if hasattr(self, cache_name):
delattr(self, cache_name)

def _save_table(self, raw=False, cls=None, force_insert=False,
force_update=False, using=None, update_fields=None):
"""
Does the heavy-lifting involved in saving. Updates or inserts the data
for a single table.
"""
meta = cls._meta
non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]

if update_fields:
non_pks = [f for f in non_pks
if f.name in update_fields or f.attname in update_fields]

pk_val = self._get_pk_val(meta)
if pk_val is None:
pk_val = meta.pk.get_pk_value_on_save(self)
setattr(self, meta.pk.attname, pk_val)
pk_set = pk_val is not None
if not pk_set and (force_update or update_fields):
raise ValueError("Cannot force an update in save() with no primary key.")
updated = False
# If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
if pk_set and not force_insert:
base_qs = cls._base_manager.using(using)
values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
for f in non_pks]
forced_update = update_fields or force_update
updated = self._do_update(base_qs, using, pk_val, values, update_fields,
forced_update)
if force_update and not updated:
raise DatabaseError("Forced update did not affect any rows.")
if update_fields and not updated:
raise DatabaseError("Save with update_fields did not affect any rows.")
if not updated:
if meta.order_with_respect_to:
# If this is a model with an order_with_respect_to
# autopopulate the _order field
field = meta.order_with_respect_to
filter_args = field.get_filter_kwargs_for_object(self)
order_value = cls._base_manager.using(using).filter(**filter_args).count()
self._order = order_value

fields = meta.local_concrete_fields
if not pk_set:
fields = [f for f in fields if not isinstance(f, AutoField)]

update_pk = bool(meta.has_auto_field and not pk_set)
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
if update_pk:
setattr(self, meta.pk.attname, result)
return updated

def _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update):
"""
This method will try to update the model. If the model was updated (in
the sense that an update query was done and a matching row was found
from the DB) the method will return True.
"""
filtered = base_qs.filter(pk=pk_val)
if not values:
# We can end up here when saving a model in inheritance chain where
# update_fields doesn't target any field in current model. In that
# case we just say the update succeeded. Another case ending up here
# is a model with just PK - in that case check that the PK still
# exists.
return update_fields is not None or filtered.exists()
if self._meta.select_on_save and not forced_update:
if filtered.exists():
# It may happen that the object is deleted from the DB right after
# this check, causing the subsequent UPDATE to return zero matching
# rows. The same result can occur in some rare cases when the
# database returns zero despite the UPDATE being executed
# successfully (a row is matched and updated). In order to
# distinguish these two cases, the object's existence in the
# database is again checked for if the UPDATE query returns 0.
return filtered._update(values) > 0 or filtered.exists()
else:
return False
return filtered._update(values) > 0

def _do_insert(self, manager, using, fields, update_pk, raw):
"""
Do an INSERT. If update_pk is defined then this method should return
the new pk for the model.
"""
return manager._insert([self], fields=fields, return_id=update_pk,
using=using, raw=raw)

[docs]    def delete(self, using=None, keep_parents=False):
using = using or router.db_for_write(self.__class__, instance=self)
assert self._get_pk_val() is not None, (
"%s object can't be deleted because its %s attribute is set to None." %
(self._meta.object_name, self._meta.pk.attname)
)

collector = Collector(using=using)
collector.collect([self], keep_parents=keep_parents)
return collector.delete()

delete.alters_data = True

def _get_FIELD_display(self, field):
value = getattr(self, field.attname)
return force_text(dict(field.flatchoices).get(value, value), strings_only=True)

def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
if not self.pk:
raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
op = 'gt' if is_next else 'lt'
order = '' if is_next else '-'
param = force_text(getattr(self, field.attname))
q = Q(**{'%s__%s' % (field.name, op): param})
q = q | Q(**{field.name: param, 'pk__%s' % op: self.pk})
qs = self.__class__._default_manager.using(self._state.db).filter(**kwargs).filter(q).order_by(
'%s%s' % (order, field.name), '%spk' % order
)
try:
return qs[0]
except IndexError:
raise self.DoesNotExist("%s matching query does not exist." % self.__class__._meta.object_name)

def _get_next_or_previous_in_order(self, is_next):
cachename = "__%s_order_cache" % is_next
if not hasattr(self, cachename):
op = 'gt' if is_next else 'lt'
order = '_order' if is_next else '-_order'
order_field = self._meta.order_with_respect_to
filter_args = order_field.get_filter_kwargs_for_object(self)
obj = self._default_manager.filter(**filter_args).filter(**{
'_order__%s' % op: self._default_manager.values('_order').filter(**{
self._meta.pk.name: self.pk
})
}).order_by(order)[:1].get()
setattr(self, cachename, obj)
return getattr(self, cachename)

def prepare_database_save(self, field):
if self.pk is None:
raise ValueError("Unsaved model instance %r cannot be used in an ORM query." % self)
return getattr(self, field.remote_field.get_related_field().attname)

[docs]    def clean(self):
"""
Hook for doing any extra model-wide validation after clean() has been
called on every field by self.clean_fields. Any ValidationError raised
by this method will not be associated with a particular field; it will
have a special-case association with the field defined by NON_FIELD_ERRORS.
"""
pass

[docs]    def validate_unique(self, exclude=None):
"""
Checks unique constraints on the model and raises ``ValidationError``
if any failed.
"""
unique_checks, date_checks = self._get_unique_checks(exclude=exclude)

errors = self._perform_unique_checks(unique_checks)
date_errors = self._perform_date_checks(date_checks)

for k, v in date_errors.items():
errors.setdefault(k, []).extend(v)

if errors:
raise ValidationError(errors)

def _get_unique_checks(self, exclude=None):
"""
Gather a list of checks to perform. Since validate_unique could be
called from a ModelForm, some fields may have been excluded; we can't
perform a unique check on a model that is missing fields involved
in that check.
Fields that did not validate should also be excluded, but they need
to be passed in via the exclude argument.
"""
if exclude is None:
exclude = []
unique_checks = []

unique_togethers = [(self.__class__, self._meta.unique_together)]
for parent_class in self._meta.get_parent_list():
if parent_class._meta.unique_together:
unique_togethers.append((parent_class, parent_class._meta.unique_together))

for model_class, unique_together in unique_togethers:
for check in unique_together:
for name in check:
# If this is an excluded field, don't add this check.
if name in exclude:
break
else:
unique_checks.append((model_class, tuple(check)))

# These are checks for the unique_for_<date/year/month>.
date_checks = []

# Gather a list of checks for fields declared as unique and add them to
# the list of checks.

fields_with_class = [(self.__class__, self._meta.local_fields)]
for parent_class in self._meta.get_parent_list():
fields_with_class.append((parent_class, parent_class._meta.local_fields))

for model_class, fields in fields_with_class:
for f in fields:
name = f.name
if name in exclude:
continue
if f.unique:
unique_checks.append((model_class, (name,)))
if f.unique_for_date and f.unique_for_date not in exclude:
date_checks.append((model_class, 'date', name, f.unique_for_date))
if f.unique_for_year and f.unique_for_year not in exclude:
date_checks.append((model_class, 'year', name, f.unique_for_year))
if f.unique_for_month and f.unique_for_month not in exclude:
date_checks.append((model_class, 'month', name, f.unique_for_month))
return unique_checks, date_checks

def _perform_unique_checks(self, unique_checks):
errors = {}

for model_class, unique_check in unique_checks:
# Try to look up an existing object with the same values as this
# object's values for all the unique field.

lookup_kwargs = {}
for field_name in unique_check:
f = self._meta.get_field(field_name)
lookup_value = getattr(self, f.attname)
if lookup_value is None:
# no value, skip the lookup
continue
if f.primary_key and not self._state.adding:
# no need to check for unique primary key when editing
continue
lookup_kwargs[str(field_name)] = lookup_value

# some fields were skipped, no reason to do the check
if len(unique_check) != len(lookup_kwargs):
continue

qs = model_class._default_manager.filter(**lookup_kwargs)

# Exclude the current object from the query if we are editing an
# instance (as opposed to creating a new one)
# Note that we need to use the pk as defined by model_class, not
# self.pk. These can be different fields because model inheritance
# allows single model to have effectively multiple primary keys.
# Refs #17615.
model_class_pk = self._get_pk_val(model_class._meta)
if not self._state.adding and model_class_pk is not None:
qs = qs.exclude(pk=model_class_pk)
if qs.exists():
if len(unique_check) == 1:
key = unique_check[0]
else:
key = NON_FIELD_ERRORS
errors.setdefault(key, []).append(self.unique_error_message(model_class, unique_check))

return errors

def _perform_date_checks(self, date_checks):
errors = {}
for model_class, lookup_type, field, unique_for in date_checks:
lookup_kwargs = {}
# there's a ticket to add a date lookup, we can remove this special
# case if that makes it's way in
date = getattr(self, unique_for)
if date is None:
continue
if lookup_type == 'date':
lookup_kwargs['%s__day' % unique_for] = date.day
lookup_kwargs['%s__month' % unique_for] = date.month
lookup_kwargs['%s__year' % unique_for] = date.year
else:
lookup_kwargs['%s__%s' % (unique_for, lookup_type)] = getattr(date, lookup_type)
lookup_kwargs[field] = getattr(self, field)

qs = model_class._default_manager.filter(**lookup_kwargs)
# Exclude the current object from the query if we are editing an
# instance (as opposed to creating a new one)
if not self._state.adding and self.pk is not None:
qs = qs.exclude(pk=self.pk)

if qs.exists():
errors.setdefault(field, []).append(
self.date_error_message(lookup_type, field, unique_for)
)
return errors

def date_error_message(self, lookup_type, field_name, unique_for):
opts = self._meta
field = opts.get_field(field_name)
return ValidationError(
message=field.error_messages['unique_for_date'],
code='unique_for_date',
params={
'model': self,
'model_name': six.text_type(capfirst(opts.verbose_name)),
'lookup_type': lookup_type,
'field': field_name,
'field_label': six.text_type(capfirst(field.verbose_name)),
'date_field': unique_for,
'date_field_label': six.text_type(capfirst(opts.get_field(unique_for).verbose_name)),
}
)

def unique_error_message(self, model_class, unique_check):
opts = model_class._meta

params = {
'model': self,
'model_class': model_class,
'model_name': six.text_type(capfirst(opts.verbose_name)),
'unique_check': unique_check,
}

# A unique field
if len(unique_check) == 1:
field = opts.get_field(unique_check[0])
params['field_label'] = six.text_type(capfirst(field.verbose_name))
return ValidationError(
message=field.error_messages['unique'],
code='unique',
params=params,
)

# unique_together
else:
field_labels = [capfirst(opts.get_field(f).verbose_name) for f in unique_check]
params['field_labels'] = six.text_type(get_text_list(field_labels, _('and')))
return ValidationError(
message=_("%(model_name)s with this %(field_labels)s already exists."),
code='unique_together',
params=params,
)

[docs]    def full_clean(self, exclude=None, validate_unique=True):
"""
Calls clean_fields, clean, and validate_unique, on the model,
and raises a ``ValidationError`` for any errors that occurred.
"""
errors = {}
if exclude is None:
exclude = []
else:
exclude = list(exclude)

try:
self.clean_fields(exclude=exclude)
except ValidationError as e:
errors = e.update_error_dict(errors)

# Form.clean() is run even if other validation fails, so do the
# same with Model.clean() for consistency.
try:
self.clean()
except ValidationError as e:
errors = e.update_error_dict(errors)

# Run unique checks, but only for fields that passed validation.
if validate_unique:
for name in errors.keys():
if name != NON_FIELD_ERRORS and name not in exclude:
exclude.append(name)
try:
self.validate_unique(exclude=exclude)
except ValidationError as e:
errors = e.update_error_dict(errors)

if errors:
raise ValidationError(errors)

[docs]    def clean_fields(self, exclude=None):
"""
Cleans all fields and raises a ValidationError containing a dict
of all validation errors if any occur.
"""
if exclude is None:
exclude = []

errors = {}
for f in self._meta.fields:
if f.name in exclude:
continue
# Skip validation for empty fields with blank=True. The developer
# is responsible for making sure they have a valid value.
raw_value = getattr(self, f.attname)
if f.blank and raw_value in f.empty_values:
continue
try:
setattr(self, f.attname, f.clean(raw_value, self))
except ValidationError as e:
errors[f.name] = e.error_list

if errors:
raise ValidationError(errors)

@classmethod
def check(cls, **kwargs):
errors = []
errors.extend(cls._check_swappable())
errors.extend(cls._check_model())
errors.extend(cls._check_managers(**kwargs))
if not cls._meta.swapped:
errors.extend(cls._check_fields(**kwargs))
errors.extend(cls._check_m2m_through_same_relationship())
errors.extend(cls._check_long_column_names())
clash_errors = cls._check_id_field() + cls._check_field_name_clashes()
errors.extend(clash_errors)
# If there are field name clashes, hide consequent column name
# clashes.
if not clash_errors:
errors.extend(cls._check_column_name_clashes())
errors.extend(cls._check_index_together())
errors.extend(cls._check_unique_together())
errors.extend(cls._check_ordering())

return errors

@classmethod
def _check_swappable(cls):
""" Check if the swapped model exists. """

errors = []
if cls._meta.swapped:
try:
apps.get_model(cls._meta.swapped)
except ValueError:
errors.append(
checks.Error(
"'%s' is not of the form 'app_label.app_name'." % cls._meta.swappable,
hint=None,
obj=None,
id='models.E001',
)
)
except LookupError:
app_label, model_name = cls._meta.swapped.split('.')
errors.append(
checks.Error(
"'%s' references '%s.%s', which has not been "
"installed, or is abstract." % (
cls._meta.swappable, app_label, model_name
),
hint=None,
obj=None,
id='models.E002',
)
)
return errors

@classmethod
def _check_model(cls):
errors = []
if cls._meta.proxy:
if cls._meta.local_fields or cls._meta.local_many_to_many:
errors.append(
checks.Error(
"Proxy model '%s' contains model fields." % cls.__name__,
hint=None,
obj=None,
id='models.E017',
)
)
return errors

@classmethod
def _check_managers(cls, **kwargs):
""" Perform all manager checks. """

errors = []
for __, manager, __ in cls._meta.managers:
errors.extend(manager.check(**kwargs))
return errors

@classmethod
def _check_fields(cls, **kwargs):
""" Perform all field checks. """

errors = []
for field in cls._meta.local_fields:
errors.extend(field.check(**kwargs))
for field in cls._meta.local_many_to_many:
errors.extend(field.check(from_model=cls, **kwargs))
return errors

@classmethod
def _check_m2m_through_same_relationship(cls):
""" Check if no relationship model is used by more than one m2m field.
"""

errors = []
seen_intermediary_signatures = []

fields = cls._meta.local_many_to_many

# Skip when the target model wasn't found.
fields = (f for f in fields if isinstance(f.remote_field.model, ModelBase))

# Skip when the relationship model wasn't found.
fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase))

for f in fields:
signature = (f.remote_field.model, cls, f.remote_field.through)
if signature in seen_intermediary_signatures:
errors.append(
checks.Error(
"The model has two many-to-many relations through "
"the intermediate model '%s'." % f.remote_field.through._meta.label,
hint=None,
obj=cls,
id='models.E003',
)
)
else:
seen_intermediary_signatures.append(signature)
return errors

@classmethod
def _check_id_field(cls):
""" Check if `id` field is a primary key. """

fields = list(f for f in cls._meta.local_fields
if f.name == 'id' and f != cls._meta.pk)
# fields is empty or consists of the invalid "id" field
if fields and not fields[0].primary_key and cls._meta.pk.name == 'id':
return [
checks.Error(
"'id' can only be used as a field name if the field also "
"sets 'primary_key=True'.",
hint=None,
obj=cls,
id='models.E004',
)
]
else:
return []

@classmethod
def _check_field_name_clashes(cls):
""" Ref #17673. """

errors = []
used_fields = {}  # name or attname -> field

# Check that multi-inheritance doesn't cause field name shadowing.
for parent in cls._meta.get_parent_list():
for f in parent._meta.local_fields:
clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
if clash:
errors.append(
checks.Error(
"The field '%s' from parent model "
"'%s' clashes with the field '%s' "
"from parent model '%s'." % (
clash.name, clash.model._meta,
f.name, f.model._meta
),
hint=None,
obj=cls,
id='models.E005',
)
)
used_fields[f.name] = f
used_fields[f.attname] = f

# Check that fields defined in the model don't clash with fields from
# parents, including auto-generated fields like multi-table inheritance
# child accessors.
for parent in cls._meta.get_parent_list():
for f in parent._meta.get_fields():
if f not in used_fields:
used_fields[f.name] = f

for f in cls._meta.local_fields:
clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
# Note that we may detect clash between user-defined non-unique
# field "id" and automatically added unique field "id", both
# defined at the same model. This special case is considered in
# _check_id_field and here we ignore it.
id_conflict = (f.name == "id" and
clash and clash.name == "id" and clash.model == cls)
if clash and not id_conflict:
errors.append(
checks.Error(
"The field '%s' clashes with the field '%s' "
"from model '%s'." % (
f.name, clash.name, clash.model._meta
),
hint=None,
obj=f,
id='models.E006',
)
)
used_fields[f.name] = f
used_fields[f.attname] = f

return errors

@classmethod
def _check_column_name_clashes(cls):
# Store a list of column names which have already been used by other fields.
used_column_names = []
errors = []

for f in cls._meta.local_fields:
_, column_name = f.get_attname_column()

# Ensure the column name is not already in use.
if column_name and column_name in used_column_names:
errors.append(
checks.Error(
"Field '%s' has column name '%s' that is used by "
"another field." % (f.name, column_name),
hint="Specify a 'db_column' for the field.",
obj=cls,
id='models.E007'
)
)
else:
used_column_names.append(column_name)

return errors

@classmethod
def _check_index_together(cls):
""" Check the value of "index_together" option. """
if not isinstance(cls._meta.index_together, (tuple, list)):
return [
checks.Error(
"'index_together' must be a list or tuple.",
hint=None,
obj=cls,
id='models.E008',
)
]

elif any(not isinstance(fields, (tuple, list))
for fields in cls._meta.index_together):
return [
checks.Error(
"All 'index_together' elements must be lists or tuples.",
hint=None,
obj=cls,
id='models.E009',
)
]

else:
errors = []
for fields in cls._meta.index_together:
errors.extend(cls._check_local_fields(fields, "index_together"))
return errors

@classmethod
def _check_unique_together(cls):
""" Check the value of "unique_together" option. """
if not isinstance(cls._meta.unique_together, (tuple, list)):
return [
checks.Error(
"'unique_together' must be a list or tuple.",
hint=None,
obj=cls,
id='models.E010',
)
]

elif any(not isinstance(fields, (tuple, list))
for fields in cls._meta.unique_together):
return [
checks.Error(
"All 'unique_together' elements must be lists or tuples.",
hint=None,
obj=cls,
id='models.E011',
)
]

else:
errors = []
for fields in cls._meta.unique_together:
errors.extend(cls._check_local_fields(fields, "unique_together"))
return errors

@classmethod
def _check_local_fields(cls, fields, option):
from django.db import models

# In order to avoid hitting the relation tree prematurely, we use our
# own fields_map instead of using get_field()
forward_fields_map = {
field.name: field for field in cls._meta._get_fields(reverse=False)
}

errors = []
for field_name in fields:
try:
field = forward_fields_map[field_name]
except KeyError:
errors.append(
checks.Error(
"'%s' refers to the non-existent field '%s'." % (
option, field_name,
),
hint=None,
obj=cls,
id='models.E012',
)
)
else:
if isinstance(field.remote_field, models.ManyToManyRel):
errors.append(
checks.Error(
"'%s' refers to a ManyToManyField '%s', but "
"ManyToManyFields are not permitted in '%s'." % (
option, field_name, option,
),
hint=None,
obj=cls,
id='models.E013',
)
)
elif field not in cls._meta.local_fields:
errors.append(
checks.Error(
("'%s' refers to field '%s' which is not local "
"to model '%s'.") % (
option, field_name, cls._meta.object_name,
),
hint=("This issue may be caused by multi-table "
"inheritance."),
obj=cls,
id='models.E016',
)
)
return errors

@classmethod
def _check_ordering(cls):
""" Check "ordering" option -- is it a list of strings and do all fields
exist? """
if cls._meta._ordering_clash:
return [
checks.Error(
"'ordering' and 'order_with_respect_to' cannot be used together.",
hint=None,
obj=cls,
id='models.E021',
),
]

if cls._meta.order_with_respect_to or not cls._meta.ordering:
return []

if not isinstance(cls._meta.ordering, (list, tuple)):
return [
checks.Error(
("'ordering' must be a tuple or list "
"(even if you want to order by only one field)."),
hint=None,
obj=cls,
id='models.E014',
)
]

errors = []
fields = cls._meta.ordering

# Skip '?' fields.
fields = (f for f in fields if f != '?')

# Convert "-field" to "field".
fields = ((f[1:] if f.startswith('-') else f) for f in fields)

# Skip ordering in the format field1__field2 (FIXME: checking
# this format would be nice, but it's a little fiddly).
fields = (f for f in fields if '__' not in f)

# Skip ordering on pk. This is always a valid order_by field
# but is an alias and therefore won't be found by opts.get_field.
fields = {f for f in fields if f != 'pk'}

# Check for invalid or non-existent fields in ordering.
invalid_fields = []

# Any field name that is not present in field_names does not exist.
# Also, ordering by m2m fields is not allowed.
opts = cls._meta
valid_fields = set(chain.from_iterable(
(f.name, f.attname) if not (f.auto_created and not f.concrete) else (f.field.related_query_name(),)
for f in chain(opts.fields, opts.related_objects)
))

invalid_fields.extend(fields - valid_fields)

for invalid_field in invalid_fields:
errors.append(
checks.Error(
"'ordering' refers to the non-existent field '%s'." % invalid_field,
hint=None,
obj=cls,
id='models.E015',
)
)
return errors

@classmethod
def _check_long_column_names(cls):
"""
Check that any auto-generated column names are shorter than the limits
for each database in which the model will be created.
"""
errors = []
allowed_len = None
db_alias = None

# Find the minimum max allowed length among all specified db_aliases.
for db in settings.DATABASES.keys():
# skip databases where the model won't be created
if not router.allow_migrate_model(db, cls):
continue
connection = connections[db]
max_name_length = connection.ops.max_name_length()
if max_name_length is None or connection.features.truncates_names:
continue
else:
if allowed_len is None:
allowed_len = max_name_length
db_alias = db
elif max_name_length < allowed_len:
allowed_len = max_name_length
db_alias = db

if allowed_len is None:
return errors

for f in cls._meta.local_fields:
_, column_name = f.get_attname_column()

# Check if auto-generated name for the field is too long
# for the database.
if (f.db_column is None and column_name is not None
and len(column_name) > allowed_len):
errors.append(
checks.Error(
'Autogenerated column name too long for field "%s". '
'Maximum length is "%s" for database "%s".'
% (column_name, allowed_len, db_alias),
hint="Set the column name manually using 'db_column'.",
obj=cls,
id='models.E018',
)
)

for f in cls._meta.local_many_to_many:
# Check if auto-generated name for the M2M field is too long
# for the database.
for m2m in f.remote_field.through._meta.local_fields:
_, rel_name = m2m.get_attname_column()
if (m2m.db_column is None and rel_name is not None
and len(rel_name) > allowed_len):
errors.append(
checks.Error(
'Autogenerated column name too long for M2M field '
'"%s". Maximum length is "%s" for database "%s".'
% (rel_name, allowed_len, db_alias),
hint=("Use 'through' to create a separate model "
"for M2M and then set column_name using "
"'db_column'."),
obj=cls,
id='models.E019',
)
)

return errors

############################################
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
############################################

# ORDERING METHODS #########################

def method_set_order(ordered_obj, self, id_list, using=None):
if using is None:
using = DEFAULT_DB_ALIAS
order_wrt = ordered_obj._meta.order_with_respect_to
filter_args = order_wrt.get_forward_related_filter(self)
# FIXME: It would be nice if there was an "update many" version of update
# for situations like this.
with transaction.atomic(using=using, savepoint=False):
for i, j in enumerate(id_list):
ordered_obj.objects.filter(pk=j, **filter_args).update(_order=i)

def method_get_order(ordered_obj, self):
order_wrt = ordered_obj._meta.order_with_respect_to
filter_args = order_wrt.get_forward_related_filter(self)
pk_name = ordered_obj._meta.pk.name
return ordered_obj.objects.filter(**filter_args).values_list(pk_name, flat=True)

def make_foreign_order_accessors(model, related_model):
setattr(
related_model,
'get_%s_order' % model.__name__.lower(),
curry(method_get_order, model)
)
setattr(
related_model,
'set_%s_order' % model.__name__.lower(),
curry(method_set_order, model)
)

########
# MISC #
########

def simple_class_factory(model, attrs):
"""
Needed for dynamic classes.
"""
return model

def model_unpickle(model_id, attrs, factory):
"""
Used to unpickle Model subclasses with deferred fields.
"""
if isinstance(model_id, tuple):
if not apps.ready:
apps.populate(settings.INSTALLED_APPS)
model = apps.get_model(*model_id)
else:
# Backwards compat - the model was cached directly in earlier versions.
model = model_id
cls = factory(model, attrs)
return cls.__new__(cls)
model_unpickle.__safe_for_unpickle__ = True

def unpickle_inner_exception(klass, exception_name):
# Get the exception class from the class it is attached to:
exception = getattr(klass, exception_name)
return exception.__new__(exception)

Source code for django.db.models.aggregates

"""
Classes to represent the definitions of aggregate functions.
"""
from django.core.exceptions import FieldError
from django.db.models.expressions import Func, Star
from django.db.models.fields import FloatField, IntegerField

__all__ = [
'Aggregate', 'Avg', 'Count', 'Max', 'Min', 'StdDev', 'Sum', 'Variance',
]

[docs]class Aggregate(Func):
contains_aggregate = True
name = None

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
# Aggregates are not allowed in UPDATE queries, so ignore for_save
c = super(Aggregate, self).resolve_expression(query, allow_joins, reuse, summarize)
if not summarize:
expressions = c.get_source_expressions()
for index, expr in enumerate(expressions):
if expr.contains_aggregate:
before_resolved = self.get_source_expressions()[index]
name = before_resolved.name if hasattr(before_resolved, 'name') else repr(before_resolved)
raise FieldError("Cannot compute %s('%s'): '%s' is an aggregate" % (c.name, name, name))
c._patch_aggregate(query)  # backward-compatibility support
return c

@property
def default_alias(self):
expressions = self.get_source_expressions()
if len(expressions) == 1 and hasattr(expressions[0], 'name'):
return '%s__%s' % (expressions[0].name, self.name.lower())
raise TypeError("Complex expressions require an alias")

def get_group_by_cols(self):
return []

def _patch_aggregate(self, query):
"""
Helper method for patching 3rd party aggregates that do not yet support
the new way of subclassing. This method will be removed in Django 1.10.

add_to_query(query, alias, col, source, is_summary) will be defined on
legacy aggregates which, in turn, instantiates the SQL implementation of
the aggregate. In all the cases found, the general implementation of
add_to_query looks like:

def add_to_query(self, query, alias, col, source, is_summary):
klass = SQLImplementationAggregate
aggregate = klass(col, source=source, is_summary=is_summary, **self.extra)
query.aggregates[alias] = aggregate

By supplying a known alias, we can get the SQLAggregate out of the
aggregates dict, and use the sql_function and sql_template attributes
to patch *this* aggregate.
"""
if not hasattr(self, 'add_to_query') or self.function is not None:
return

placeholder_alias = "_XXXXXXXX_"
self.add_to_query(query, placeholder_alias, None, None, None)
sql_aggregate = query.aggregates.pop(placeholder_alias)
if 'sql_function' not in self.extra and hasattr(sql_aggregate, 'sql_function'):
self.extra['function'] = sql_aggregate.sql_function

if hasattr(sql_aggregate, 'sql_template'):
self.extra['template'] = sql_aggregate.sql_template

[docs]class Avg(Aggregate):
function = 'AVG'
name = 'Avg'

def __init__(self, expression, **extra):
output_field = extra.pop('output_field', FloatField())
super(Avg, self).__init__(expression, output_field=output_field, **extra)

def as_oracle(self, compiler, connection):
if self.output_field.get_internal_type() == 'DurationField':
expression = self.get_source_expressions()[0]
from django.db.backends.oracle.functions import IntervalToSeconds, SecondsToInterval
return compiler.compile(
SecondsToInterval(Avg(IntervalToSeconds(expression)))
)
return super(Avg, self).as_sql(compiler, connection)

[docs]class Count(Aggregate):
function = 'COUNT'
name = 'Count'
template = '%(function)s(%(distinct)s%(expressions)s)'

def __init__(self, expression, distinct=False, **extra):
if expression == '*':
expression = Star()
super(Count, self).__init__(
expression, distinct='DISTINCT ' if distinct else '', output_field=IntegerField(), **extra)

def __repr__(self):
return "{}({}, distinct={})".format(
self.__class__.__name__,
self.arg_joiner.join(str(arg) for arg in self.source_expressions),
'False' if self.extra['distinct'] == '' else 'True',
)

def convert_value(self, value, expression, connection, context):
if value is None:
return 0
return int(value)

[docs]class Max(Aggregate):
function = 'MAX'
name = 'Max'

[docs]class Min(Aggregate):
function = 'MIN'
name = 'Min'

[docs]class StdDev(Aggregate):
name = 'StdDev'

def __init__(self, expression, sample=False, **extra):
self.function = 'STDDEV_SAMP' if sample else 'STDDEV_POP'
super(StdDev, self).__init__(expression, output_field=FloatField(), **extra)

def __repr__(self):
return "{}({}, sample={})".format(
self.__class__.__name__,
self.arg_joiner.join(str(arg) for arg in self.source_expressions),
'False' if self.function == 'STDDEV_POP' else 'True',
)

def convert_value(self, value, expression, connection, context):
if value is None:
return value
return float(value)

[docs]class Sum(Aggregate):
function = 'SUM'
name = 'Sum'

def as_oracle(self, compiler, connection):
if self.output_field.get_internal_type() == 'DurationField':
expression = self.get_source_expressions()[0]
from django.db.backends.oracle.functions import IntervalToSeconds, SecondsToInterval
return compiler.compile(
SecondsToInterval(Sum(IntervalToSeconds(expression)))
)
return super(Sum, self).as_sql(compiler, connection)

[docs]class Variance(Aggregate):
name = 'Variance'

def __init__(self, expression, sample=False, **extra):
self.function = 'VAR_SAMP' if sample else 'VAR_POP'
super(Variance, self).__init__(expression, output_field=FloatField(), **extra)

def __repr__(self):
return "{}({}, sample={})".format(
self.__class__.__name__,
self.arg_joiner.join(str(arg) for arg in self.source_expressions),
'False' if self.function == 'VAR_POP' else 'True',
)

def convert_value(self, value, expression, connection, context):
if value is None:
return value
return float(value)

Source code for django.db.models.query_utils

"""
Various data structures used in query construction.

Factored out from django.db.models.query to avoid making the main module very
large and/or so that they can be used by other modules without getting into
circular import difficulties.
"""
from __future__ import unicode_literals

import inspect
from collections import namedtuple

from django.core.exceptions import FieldDoesNotExist
from django.db.backends import utils
from django.db.models.constants import LOOKUP_SEP
from django.utils import tree

# PathInfo is used when converting lookups (fk__somecol). The contents
# describe the relation in Model terms (model Options and Fields for both
# sides of the relation. The join_field is the field backing the relation.
PathInfo = namedtuple('PathInfo', 'from_opts to_opts target_fields join_field m2m direct')

class InvalidQuery(Exception):
"""
The query passed to raw isn't a safe query to use with raw.
"""
pass

class QueryWrapper(object):
"""
A type that indicates the contents are an SQL fragment and the associate
parameters. Can be used to pass opaque data to a where-clause, for example.
"""
contains_aggregate = False

def __init__(self, sql, params):
self.data = sql, list(params)

def as_sql(self, compiler=None, connection=None):
return self.data

[docs]class Q(tree.Node):
"""
Encapsulates filters as objects that can then be combined logically (using
`&` and `|`).
"""
# Connection types
AND = 'AND'
OR = 'OR'
default = AND

def __init__(self, *args, **kwargs):
super(Q, self).__init__(children=list(args) + list(kwargs.items()))

def _combine(self, other, conn):
if not isinstance(other, Q):
raise TypeError(other)
obj = type(self)()
obj.connector = conn
obj.add(self, conn)
obj.add(other, conn)
return obj

def __or__(self, other):
return self._combine(other, self.OR)

def __and__(self, other):
return self._combine(other, self.AND)

def __invert__(self):
obj = type(self)()
obj.add(self, self.AND)
obj.negate()
return obj

def clone(self):
clone = self.__class__._new_instance(
children=[], connector=self.connector, negated=self.negated)
for child in self.children:
if hasattr(child, 'clone'):
clone.children.append(child.clone())
else:
clone.children.append(child)
return clone

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
# We must promote any new joins to left outer joins so that when Q is
# used as an expression, rows aren't filtered due to joins.
clause, joins = query._add_q(self, reuse, allow_joins=allow_joins, split_subq=False)
query.promote_joins(joins)
return clause

@classmethod
def _refs_aggregate(cls, obj, existing_aggregates):
if not isinstance(obj, tree.Node):
aggregate, aggregate_lookups = refs_aggregate(obj[0].split(LOOKUP_SEP), existing_aggregates)
if not aggregate and hasattr(obj[1], 'refs_aggregate'):
return obj[1].refs_aggregate(existing_aggregates)
return aggregate, aggregate_lookups
for c in obj.children:
aggregate, aggregate_lookups = cls._refs_aggregate(c, existing_aggregates)
if aggregate:
return aggregate, aggregate_lookups
return False, ()

def refs_aggregate(self, existing_aggregates):
if not existing_aggregates:
return False

return self._refs_aggregate(self, existing_aggregates)

class DeferredAttribute(object):
"""
A wrapper for a deferred-loading field. When the value is read from this
object the first time, the query is executed.
"""
def __init__(self, field_name, model):
self.field_name = field_name

def __get__(self, instance, owner):
"""
Retrieves and caches the value from the datastore on the first lookup.
Returns the cached value.
"""
non_deferred_model = instance._meta.proxy_for_model
opts = non_deferred_model._meta

assert instance is not None
data = instance.__dict__
if data.get(self.field_name, self) is self:
# self.field_name is the attname of the field, but only() takes the
# actual name, so we need to translate it here.
try:
f = opts.get_field(self.field_name)
except FieldDoesNotExist:
f = [f for f in opts.fields if f.attname == self.field_name][0]
name = f.name
# Let's see if the field is part of the parent chain. If so we
# might be able to reuse the already loaded value. Refs #18343.
val = self._check_parent_chain(instance, name)
if val is None:
instance.refresh_from_db(fields=[self.field_name])
val = getattr(instance, self.field_name)
data[self.field_name] = val
return data[self.field_name]

def __set__(self, instance, value):
"""
Deferred loading attributes can be set normally (which means there will
never be a database lookup involved.
"""
instance.__dict__[self.field_name] = value

def _check_parent_chain(self, instance, name):
"""
Check if the field value can be fetched from a parent field already
loaded in the instance. This can be done if the to-be fetched
field is a primary key field.
"""
opts = instance._meta
f = opts.get_field(name)
link_field = opts.get_ancestor_link(f.model)
if f.primary_key and f != link_field:
return getattr(instance, link_field.attname)
return None

class RegisterLookupMixin(object):
def _get_lookup(self, lookup_name):
try:
return self.class_lookups[lookup_name]
except KeyError:
# To allow for inheritance, check parent class' class_lookups.
for parent in inspect.getmro(self.__class__):
if 'class_lookups' not in parent.__dict__:
continue
if lookup_name in parent.class_lookups:
return parent.class_lookups[lookup_name]
except AttributeError:
# This class didn't have any class_lookups
pass
return None

def get_lookup(self, lookup_name):
from django.db.models.lookups import Lookup
found = self._get_lookup(lookup_name)
if found is None and hasattr(self, 'output_field'):
return self.output_field.get_lookup(lookup_name)
if found is not None and not issubclass(found, Lookup):
return None
return found

def get_transform(self, lookup_name):
from django.db.models.lookups import Transform
found = self._get_lookup(lookup_name)
if found is None and hasattr(self, 'output_field'):
return self.output_field.get_transform(lookup_name)
if found is not None and not issubclass(found, Transform):
return None
return found

@classmethod
def register_lookup(cls, lookup, lookup_name=None):
if lookup_name is None:
lookup_name = lookup.lookup_name
if 'class_lookups' not in cls.__dict__:
cls.class_lookups = {}
cls.class_lookups[lookup_name] = lookup
return lookup

@classmethod
def _unregister_lookup(cls, lookup, lookup_name=None):
"""
Remove given lookup from cls lookups. For use in tests only as it's
not thread-safe.
"""
if lookup_name is None:
lookup_name = lookup.lookup_name
del cls.class_lookups[lookup_name]

def select_related_descend(field, restricted, requested, load_fields, reverse=False):
"""
Returns True if this field should be used to descend deeper for
select_related() purposes. Used by both the query construction code
(sql.query.fill_related_selections()) and the model instance creation code
(query.get_klass_info()).

Arguments:
* field - the field to be checked
* restricted - a boolean field, indicating if the field list has been
manually restricted using a requested clause)
* requested - The select_related() dictionary.
* load_fields - the set of fields to be loaded on this model
* reverse - boolean, True if we are checking a reverse select related
"""
if not field.remote_field:
return False
if field.remote_field.parent_link and not reverse:
return False
if restricted:
if reverse and field.related_query_name() not in requested:
return False
if not reverse and field.name not in requested:
return False
if not restricted and field.null:
return False
if load_fields:
if field.attname not in load_fields:
if restricted and field.name in requested:
raise InvalidQuery("Field %s.%s cannot be both deferred"
" and traversed using select_related"
" at the same time." %
(field.model._meta.object_name, field.name))
return False
return True

# This function is needed because data descriptors must be defined on a class
# object, not an instance, to have any effect.

def deferred_class_factory(model, attrs):
"""
Returns a class object that is a copy of "model" with the specified "attrs"
being replaced with DeferredAttribute objects. The "pk_value" ties the
deferred attributes to a particular instance of the model.
"""
if not attrs:
return model
opts = model._meta
# Never create deferred models based on deferred model
if model._deferred:
# Deferred models are proxies for the non-deferred model. We never
# create chains of defers => proxy_for_model is the non-deferred
# model.
model = opts.proxy_for_model
# The app registry wants a unique name for each model, otherwise the new
# class won't be created (we get an exception). Therefore, we generate
# the name using the passed in attrs. It's OK to reuse an existing class
# object if the attrs are identical.
name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(attrs)))
name = utils.truncate_name(name, 80, 32)

try:
return opts.apps.get_model(model._meta.app_label, name)

except LookupError:

class Meta:
proxy = True
apps = opts.apps
app_label = opts.app_label

overrides = {attr: DeferredAttribute(attr, model) for attr in attrs}
overrides["Meta"] = Meta
overrides["__module__"] = model.__module__
overrides["_deferred"] = True
return type(str(name), (model,), overrides)

# The above function is also used to unpickle model instances with deferred
# fields.
deferred_class_factory.__safe_for_unpickling__ = True

def refs_aggregate(lookup_parts, aggregates):
"""
A helper method to check if the lookup_parts contains references
to the given aggregates set. Because the LOOKUP_SEP is contained in the
default annotation names we must check each prefix of the lookup_parts
for a match.
"""
for n in range(len(lookup_parts) + 1):
level_n_lookup = LOOKUP_SEP.join(lookup_parts[0:n])
if level_n_lookup in aggregates and aggregates[level_n_lookup].contains_aggregate:
return aggregates[level_n_lookup], lookup_parts[n:]
return False, ()

def refs_expression(lookup_parts, annotations):
"""
A helper method to check if the lookup_parts contains references
to the given annotations set. Because the LOOKUP_SEP is contained in the
default annotation names we must check each prefix of the lookup_parts
for a match.
"""
for n in range(len(lookup_parts) + 1):
level_n_lookup = LOOKUP_SEP.join(lookup_parts[0:n])
if level_n_lookup in annotations and annotations[level_n_lookup]:
return annotations[level_n_lookup], lookup_parts[n:]
return False, ()

def check_rel_lookup_compatibility(model, target_opts, field):
"""
Check that self.model is compatible with target_opts. Compatibility
is OK if:
1) model and opts match (where proxy inheritance is removed)
2) model is parent of opts' model or the other way around
"""
def check(opts):
return (
model._meta.concrete_model == opts.concrete_model or
opts.concrete_model in model._meta.get_parent_list() or
model in opts.get_parent_list()
)
# If the field is a primary key, then doing a query against the field's
# model is ok, too. Consider the case:
# class Restaurant(models.Model):
#     place = OnetoOneField(Place, primary_key=True):
# Restaurant.objects.filter(pk__in=Restaurant.objects.all()).
# If we didn't have the primary key check, then pk__in (== place__in) would
# give Place's opts as the target opts, but Restaurant isn't compatible
# with that. This logic applies only to primary keys, as when doing __in=qs,
# we are going to turn this into __in=qs.values('pk') later on.
return (
check(target_opts) or
(getattr(field, 'primary_key', False) and check(field.model._meta))
)

Source code for django.db.models.expressions

import copy
import datetime

from django.conf import settings
from django.core.exceptions import FieldError
from django.db.backends import utils as backend_utils
from django.db.models import fields
from django.db.models.constants import LOOKUP_SEP
from django.db.models.query_utils import Q, refs_aggregate
from django.utils import six, timezone
from django.utils.functional import cached_property

class Combinable(object):
"""
Provides the ability to combine one or two objects with
some connector. For example F('foo') + F('bar').
"""

# Arithmetic connectors
ADD = '+'
SUB = '-'
MUL = '*'
DIV = '/'
POW = '^'
# The following is a quoted % operator - it is quoted because it can be
# used in strings that also have parameter substitution.
MOD = '%%'

# Bitwise operators - note that these are generated by .bitand()
# and .bitor(), the '&' and '|' are reserved for boolean operator
# usage.
BITAND = '&'
BITOR = '|'

def _combine(self, other, connector, reversed, node=None):
if not hasattr(other, 'resolve_expression'):
# everything must be resolvable to an expression
if isinstance(other, datetime.timedelta):
other = DurationValue(other, output_field=fields.DurationField())
else:
other = Value(other)

if reversed:
return CombinedExpression(other, connector, self)
return CombinedExpression(self, connector, other)

#############
# OPERATORS #
#############

def __add__(self, other):
return self._combine(other, self.ADD, False)

def __sub__(self, other):
return self._combine(other, self.SUB, False)

def __mul__(self, other):
return self._combine(other, self.MUL, False)

def __truediv__(self, other):
return self._combine(other, self.DIV, False)

def __div__(self, other):  # Python 2 compatibility
return type(self).__truediv__(self, other)

def __mod__(self, other):
return self._combine(other, self.MOD, False)

def __pow__(self, other):
return self._combine(other, self.POW, False)

def __and__(self, other):
raise NotImplementedError(
"Use .bitand() and .bitor() for bitwise logical operations."
)

def bitand(self, other):
return self._combine(other, self.BITAND, False)

def __or__(self, other):
raise NotImplementedError(
"Use .bitand() and .bitor() for bitwise logical operations."
)

def bitor(self, other):
return self._combine(other, self.BITOR, False)

def __radd__(self, other):
return self._combine(other, self.ADD, True)

def __rsub__(self, other):
return self._combine(other, self.SUB, True)

def __rmul__(self, other):
return self._combine(other, self.MUL, True)

def __rtruediv__(self, other):
return self._combine(other, self.DIV, True)

def __rdiv__(self, other):  # Python 2 compatibility
return type(self).__rtruediv__(self, other)

def __rmod__(self, other):
return self._combine(other, self.MOD, True)

def __rpow__(self, other):
return self._combine(other, self.POW, True)

def __rand__(self, other):
raise NotImplementedError(
"Use .bitand() and .bitor() for bitwise logical operations."
)

def __ror__(self, other):
raise NotImplementedError(
"Use .bitand() and .bitor() for bitwise logical operations."
)

class BaseExpression(object):
"""
Base class for all query expressions.
"""

# aggregate specific fields
is_summary = False

def __init__(self, output_field=None):
self._output_field = output_field

def get_db_converters(self, connection):
return [self.convert_value] + self.output_field.get_db_converters(connection)

def get_source_expressions(self):
return []

def set_source_expressions(self, exprs):
assert len(exprs) == 0

def _parse_expressions(self, *expressions):
return [
arg if hasattr(arg, 'resolve_expression') else (
F(arg) if isinstance(arg, six.string_types) else Value(arg)
) for arg in expressions
]

def as_sql(self, compiler, connection):
"""
Responsible for returning a (sql, [params]) tuple to be included
in the current query.

Different backends can provide their own implementation, by
providing an `as_{vendor}` method and patching the Expression:

```
def override_as_sql(self, compiler, connection):
# custom logic
return super(Expression, self).as_sql(compiler, connection)
setattr(Expression, 'as_' + connection.vendor, override_as_sql)
```

Arguments:
* compiler: the query compiler responsible for generating the query.
Must have a compile method, returning a (sql, [params]) tuple.
Calling compiler(value) will return a quoted `value`.

* connection: the database connection used for the current query.

Returns: (sql, params)
Where `sql` is a string containing ordered sql parameters to be
replaced with the elements of the list `params`.
"""
raise NotImplementedError("Subclasses must implement as_sql()")

@cached_property
def contains_aggregate(self):
for expr in self.get_source_expressions():
if expr and expr.contains_aggregate:
return True
return False

@cached_property
def contains_column_references(self):
for expr in self.get_source_expressions():
if expr and expr.contains_column_references:
return True
return False

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
"""
Provides the chance to do any preprocessing or validation before being
added to the query.

Arguments:
* query: the backend query implementation
* allow_joins: boolean allowing or denying use of joins
in this query
* reuse: a set of reusable joins for multijoins
* summarize: a terminal aggregate clause
* for_save: whether this expression about to be used in a save or update

Returns: an Expression to be added to the query.
"""
c = self.copy()
c.is_summary = summarize
c.set_source_expressions([
expr.resolve_expression(query, allow_joins, reuse, summarize)
for expr in c.get_source_expressions()
])
return c

def _prepare(self, field):
"""
Hook used by Field.get_prep_lookup() to do custom preparation.
"""
return self

@property
def field(self):
return self.output_field

@cached_property
def output_field(self):
"""
Returns the output type of this expressions.
"""
if self._output_field_or_none is None:
raise FieldError("Cannot resolve expression type, unknown output_field")
return self._output_field_or_none

@cached_property
def _output_field_or_none(self):
"""
Returns the output field of this expression, or None if no output type
can be resolved. Note that the 'output_field' property will raise
FieldError if no type can be resolved, but this attribute allows for
None values.
"""
if self._output_field is None:
self._resolve_output_field()
return self._output_field

def _resolve_output_field(self):
"""
Attempts to infer the output type of the expression. If the output
fields of all source fields match then we can simply infer the same
type here. This isn't always correct, but it makes sense most of the
time.

Consider the difference between `2 + 2` and `2 / 3`. Inferring
the type here is a convenience for the common case. The user should
supply their own output_field with more complex computations.

If a source does not have an `_output_field` then we exclude it from
this check. If all sources are `None`, then an error will be thrown
higher up the stack in the `output_field` property.
"""
if self._output_field is None:
sources = self.get_source_fields()
num_sources = len(sources)
if num_sources == 0:
self._output_field = None
else:
for source in sources:
if self._output_field is None:
self._output_field = source
if source is not None and not isinstance(self._output_field, source.__class__):
raise FieldError(
"Expression contains mixed types. You must set output_field")

def convert_value(self, value, expression, connection, context):
"""
Expressions provide their own converters because users have the option
of manually specifying the output_field which may be a different type
from the one the database returns.
"""
field = self.output_field
internal_type = field.get_internal_type()
if value is None:
return value
elif internal_type == 'FloatField':
return float(value)
elif internal_type.endswith('IntegerField'):
return int(value)
elif internal_type == 'DecimalField':
return backend_utils.typecast_decimal(value)
return value

def get_lookup(self, lookup):
return self.output_field.get_lookup(lookup)

def get_transform(self, name):
return self.output_field.get_transform(name)

def relabeled_clone(self, change_map):
clone = self.copy()
clone.set_source_expressions(
[e.relabeled_clone(change_map) for e in self.get_source_expressions()])
return clone

def copy(self):
c = copy.copy(self)
c.copied = True
return c

def refs_aggregate(self, existing_aggregates):
"""
Does this expression contain a reference to some of the
existing aggregates? If so, returns the aggregate and also
the lookup parts that *weren't* found. So, if
existing_aggregates = {'max_id': Max('id')}
self.name = 'max_id'
queryset.filter(max_id__range=[10,100])
then this method will return Max('id') and those parts of the
name that weren't found. In this case `max_id` is found and the range
portion is returned as ('range',).
"""
for node in self.get_source_expressions():
agg, lookup = node.refs_aggregate(existing_aggregates)
if agg:
return agg, lookup
return False, ()

def get_group_by_cols(self):
if not self.contains_aggregate:
return [self]
cols = []
for source in self.get_source_expressions():
cols.extend(source.get_group_by_cols())
return cols

def get_source_fields(self):
"""
Returns the underlying field types used by this
aggregate.
"""
return [e._output_field_or_none for e in self.get_source_expressions()]

def asc(self):
return OrderBy(self)

def desc(self):
return OrderBy(self, descending=True)

def reverse_ordering(self):
return self

def flatten(self):
"""
Recursively yield this expression and all subexpressions, in
depth-first order.
"""
yield self
for expr in self.get_source_expressions():
if expr:
for inner_expr in expr.flatten():
yield inner_expr

[docs]class Expression(BaseExpression, Combinable):
"""
An expression that can be combined with other expressions.
"""
pass

class CombinedExpression(Expression):

def __init__(self, lhs, connector, rhs, output_field=None):
super(CombinedExpression, self).__init__(output_field=output_field)
self.connector = connector
self.lhs = lhs
self.rhs = rhs

def __repr__(self):
return "<{}: {}>".format(self.__class__.__name__, self)

def __str__(self):
return "{} {} {}".format(self.lhs, self.connector, self.rhs)

def get_source_expressions(self):
return [self.lhs, self.rhs]

def set_source_expressions(self, exprs):
self.lhs, self.rhs = exprs

def as_sql(self, compiler, connection):
try:
lhs_output = self.lhs.output_field
except FieldError:
lhs_output = None
try:
rhs_output = self.rhs.output_field
except FieldError:
rhs_output = None
if (not connection.features.has_native_duration_field and
((lhs_output and lhs_output.get_internal_type() == 'DurationField')
or (rhs_output and rhs_output.get_internal_type() == 'DurationField'))):
return DurationExpression(self.lhs, self.connector, self.rhs).as_sql(compiler, connection)
expressions = []
expression_params = []
sql, params = compiler.compile(self.lhs)
expressions.append(sql)
expression_params.extend(params)
sql, params = compiler.compile(self.rhs)
expressions.append(sql)
expression_params.extend(params)
# order of precedence
expression_wrapper = '(%s)'
sql = connection.ops.combine_expression(self.connector, expressions)
return expression_wrapper % sql, expression_params

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = self.copy()
c.is_summary = summarize
c.lhs = c.lhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)
c.rhs = c.rhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c

class DurationExpression(CombinedExpression):
def compile(self, side, compiler, connection):
if not isinstance(side, DurationValue):
try:
output = side.output_field
except FieldError:
pass
else:
if output.get_internal_type() == 'DurationField':
sql, params = compiler.compile(side)
return connection.ops.format_for_duration_arithmetic(sql), params
return compiler.compile(side)

def as_sql(self, compiler, connection):
connection.ops.check_expression_support(self)
expressions = []
expression_params = []
sql, params = self.compile(self.lhs, compiler, connection)
expressions.append(sql)
expression_params.extend(params)
sql, params = self.compile(self.rhs, compiler, connection)
expressions.append(sql)
expression_params.extend(params)
# order of precedence
expression_wrapper = '(%s)'
sql = connection.ops.combine_duration_expression(self.connector, expressions)
return expression_wrapper % sql, expression_params

[docs]class F(Combinable):
"""
An object capable of resolving references to existing query objects.
"""
def __init__(self, name):
"""
Arguments:
* name: the name of the field this expression references
"""
self.name = name

def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.name)

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
return query.resolve_ref(self.name, allow_joins, reuse, summarize)

def refs_aggregate(self, existing_aggregates):
return refs_aggregate(self.name.split(LOOKUP_SEP), existing_aggregates)

def asc(self):
return OrderBy(self)

def desc(self):
return OrderBy(self, descending=True)

[docs]class Func(Expression):
"""
An SQL function call.
"""
function = None
template = '%(function)s(%(expressions)s)'
arg_joiner = ', '

def __init__(self, *expressions, **extra):
output_field = extra.pop('output_field', None)
super(Func, self).__init__(output_field=output_field)
self.source_expressions = self._parse_expressions(*expressions)
self.extra = extra

def __repr__(self):
args = self.arg_joiner.join(str(arg) for arg in self.source_expressions)
extra = ', '.join(str(key) + '=' + str(val) for key, val in self.extra.items())
if extra:
return "{}({}, {})".format(self.__class__.__name__, args, extra)
return "{}({})".format(self.__class__.__name__, args)

def get_source_expressions(self):
return self.source_expressions

def set_source_expressions(self, exprs):
self.source_expressions = exprs

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = self.copy()
c.is_summary = summarize
for pos, arg in enumerate(c.source_expressions):
c.source_expressions[pos] = arg.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c

def as_sql(self, compiler, connection, function=None, template=None):
connection.ops.check_expression_support(self)
sql_parts = []
params = []
for arg in self.source_expressions:
arg_sql, arg_params = compiler.compile(arg)
sql_parts.append(arg_sql)
params.extend(arg_params)
if function is None:
self.extra['function'] = self.extra.get('function', self.function)
else:
self.extra['function'] = function
self.extra['expressions'] = self.extra['field'] = self.arg_joiner.join(sql_parts)
template = template or self.extra.get('template', self.template)
return template % self.extra, params

def as_sqlite(self, *args, **kwargs):
sql, params = self.as_sql(*args, **kwargs)
try:
if self.output_field.get_internal_type() == 'DecimalField':
sql = 'CAST(%s AS NUMERIC)' % sql
except FieldError:
pass
return sql, params

def copy(self):
copy = super(Func, self).copy()
copy.source_expressions = self.source_expressions[:]
copy.extra = self.extra.copy()
return copy

[docs]class Value(Expression):
"""
Represents a wrapped value as a node within an expression
"""
def __init__(self, value, output_field=None):
"""
Arguments:
* value: the value this expression represents. The value will be
added into the sql parameter list and properly quoted.

* output_field: an instance of the model field type that this
expression will return, such as IntegerField() or CharField().
"""
super(Value, self).__init__(output_field=output_field)
self.value = value

def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.value)

def as_sql(self, compiler, connection):
connection.ops.check_expression_support(self)
val = self.value
# check _output_field to avoid triggering an exception
if self._output_field is not None:
if self.for_save:
val = self.output_field.get_db_prep_save(val, connection=connection)
else:
val = self.output_field.get_db_prep_value(val, connection=connection)
if val is None:
# cx_Oracle does not always convert None to the appropriate
# NULL type (like in case expressions using numbers), so we
# use a literal SQL NULL
return 'NULL', []
return '%s', [val]

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = super(Value, self).resolve_expression(query, allow_joins, reuse, summarize, for_save)
c.for_save = for_save
return c

def get_group_by_cols(self):
return []

class DurationValue(Value):
def as_sql(self, compiler, connection):
connection.ops.check_expression_support(self)
if (connection.features.has_native_duration_field and
connection.features.driver_supports_timedelta_args):
return super(DurationValue, self).as_sql(compiler, connection)
return connection.ops.date_interval_sql(self.value)

[docs]class RawSQL(Expression):
def __init__(self, sql, params, output_field=None):
if output_field is None:
output_field = fields.Field()
self.sql, self.params = sql, params
super(RawSQL, self).__init__(output_field=output_field)

def __repr__(self):
return "{}({}, {})".format(self.__class__.__name__, self.sql, self.params)

def as_sql(self, compiler, connection):
return '(%s)' % self.sql, self.params

def get_group_by_cols(self):
return [self]

class Star(Expression):
def __repr__(self):
return "'*'"

def as_sql(self, compiler, connection):
return '*', []

class Random(Expression):
def __init__(self):
super(Random, self).__init__(output_field=fields.FloatField())

def __repr__(self):
return "Random()"

def as_sql(self, compiler, connection):
return connection.ops.random_function_sql(), []

class Col(Expression):

contains_column_references = True

def __init__(self, alias, target, output_field=None):
if output_field is None:
output_field = target
super(Col, self).__init__(output_field=output_field)
self.alias, self.target = alias, target

def __repr__(self):
return "{}({}, {})".format(
self.__class__.__name__, self.alias, self.target)

def as_sql(self, compiler, connection):
qn = compiler.quote_name_unless_alias
return "%s.%s" % (qn(self.alias), qn(self.target.column)), []

def relabeled_clone(self, relabels):
return self.__class__(relabels.get(self.alias, self.alias), self.target, self.output_field)

def get_group_by_cols(self):
return [self]

def get_db_converters(self, connection):
if self.target == self.output_field:
return self.output_field.get_db_converters(connection)
return (self.output_field.get_db_converters(connection) +
self.target.get_db_converters(connection))

class Ref(Expression):
"""
Reference to column alias of the query. For example, Ref('sum_cost') in
qs.annotate(sum_cost=Sum('cost')) query.
"""
def __init__(self, refs, source):
super(Ref, self).__init__()
self.refs, self.source = refs, source

def __repr__(self):
return "{}({}, {})".format(self.__class__.__name__, self.refs, self.source)

def get_source_expressions(self):
return [self.source]

def set_source_expressions(self, exprs):
self.source, = exprs

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
# The sub-expression `source` has already been resolved, as this is
# just a reference to the name of `source`.
return self

def relabeled_clone(self, relabels):
return self

def as_sql(self, compiler, connection):
return "%s" % connection.ops.quote_name(self.refs), []

def get_group_by_cols(self):
return [self]

[docs]class ExpressionWrapper(Expression):
"""
An expression that can wrap another expression so that it can provide
extra context to the inner expression, such as the output_field.
"""

def __init__(self, expression, output_field):
super(ExpressionWrapper, self).__init__(output_field=output_field)
self.expression = expression

def set_source_expressions(self, exprs):
self.expression = exprs[0]

def get_source_expressions(self):
return [self.expression]

def as_sql(self, compiler, connection):
return self.expression.as_sql(compiler, connection)

def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.expression)

[docs]class When(Expression):
template = 'WHEN %(condition)s THEN %(result)s'

def __init__(self, condition=None, then=None, **lookups):
if lookups and condition is None:
condition, lookups = Q(**lookups), None
if condition is None or not isinstance(condition, Q) or lookups:
raise TypeError("__init__() takes either a Q object or lookups as keyword arguments")
super(When, self).__init__(output_field=None)
self.condition = condition
self.result = self._parse_expressions(then)[0]

def __str__(self):
return "WHEN %r THEN %r" % (self.condition, self.result)

def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self)

def get_source_expressions(self):
return [self.condition, self.result]

def set_source_expressions(self, exprs):
self.condition, self.result = exprs

def get_source_fields(self):
# We're only interested in the fields of the result expressions.
return [self.result._output_field_or_none]

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = self.copy()
c.is_summary = summarize
if hasattr(c.condition, 'resolve_expression'):
c.condition = c.condition.resolve_expression(query, allow_joins, reuse, summarize, False)
c.result = c.result.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c

def as_sql(self, compiler, connection, template=None):
connection.ops.check_expression_support(self)
template_params = {}
sql_params = []
condition_sql, condition_params = compiler.compile(self.condition)
template_params['condition'] = condition_sql
sql_params.extend(condition_params)
result_sql, result_params = compiler.compile(self.result)
template_params['result'] = result_sql
sql_params.extend(result_params)
template = template or self.template
return template % template_params, sql_params

def get_group_by_cols(self):
# This is not a complete expression and cannot be used in GROUP BY.
cols = []
for source in self.get_source_expressions():
cols.extend(source.get_group_by_cols())
return cols

[docs]class Case(Expression):
"""
An SQL searched CASE expression:

CASE
WHEN n > 0
THEN 'positive'
WHEN n < 0
THEN 'negative'
ELSE 'zero'
END
"""
template = 'CASE %(cases)s ELSE %(default)s END'
case_joiner = ' '

def __init__(self, *cases, **extra):
if not all(isinstance(case, When) for case in cases):
raise TypeError("Positional arguments must all be When objects.")
default = extra.pop('default', None)
output_field = extra.pop('output_field', None)
super(Case, self).__init__(output_field)
self.cases = list(cases)
self.default = self._parse_expressions(default)[0]

def __str__(self):
return "CASE %s, ELSE %r" % (', '.join(str(c) for c in self.cases), self.default)

def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self)

def get_source_expressions(self):
return self.cases + [self.default]

def set_source_expressions(self, exprs):
self.cases = exprs[:-1]
self.default = exprs[-1]

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = self.copy()
c.is_summary = summarize
for pos, case in enumerate(c.cases):
c.cases[pos] = case.resolve_expression(query, allow_joins, reuse, summarize, for_save)
c.default = c.default.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c

def copy(self):
c = super(Case, self).copy()
c.cases = c.cases[:]
return c

def as_sql(self, compiler, connection, template=None, extra=None):
connection.ops.check_expression_support(self)
if not self.cases:
return compiler.compile(self.default)
template_params = dict(extra) if extra else {}
case_parts = []
sql_params = []
for case in self.cases:
case_sql, case_params = compiler.compile(case)
case_parts.append(case_sql)
sql_params.extend(case_params)
template_params['cases'] = self.case_joiner.join(case_parts)
default_sql, default_params = compiler.compile(self.default)
template_params['default'] = default_sql
sql_params.extend(default_params)
template = template or self.template
sql = template % template_params
if self._output_field_or_none is not None:
sql = connection.ops.unification_cast_sql(self.output_field) % sql
return sql, sql_params

class Date(Expression):
"""
Add a date selection column.
"""
def __init__(self, lookup, lookup_type):
super(Date, self).__init__(output_field=fields.DateField())
self.lookup = lookup
self.col = None
self.lookup_type = lookup_type

def __repr__(self):
return "{}({}, {})".format(self.__class__.__name__, self.lookup, self.lookup_type)

def get_source_expressions(self):
return [self.col]

def set_source_expressions(self, exprs):
self.col, = exprs

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
copy = self.copy()
copy.col = query.resolve_ref(self.lookup, allow_joins, reuse, summarize)
field = copy.col.output_field
assert isinstance(field, fields.DateField), "%r isn't a DateField." % field.name
if settings.USE_TZ:
assert not isinstance(field, fields.DateTimeField), (
"%r is a DateTimeField, not a DateField." % field.name
)
return copy

def as_sql(self, compiler, connection):
sql, params = self.col.as_sql(compiler, connection)
assert not(params)
return connection.ops.date_trunc_sql(self.lookup_type, sql), []

def copy(self):
copy = super(Date, self).copy()
copy.lookup = self.lookup
copy.lookup_type = self.lookup_type
return copy

def convert_value(self, value, expression, connection, context):
if isinstance(value, datetime.datetime):
value = value.date()
return value

class DateTime(Expression):
"""
Add a datetime selection column.
"""
def __init__(self, lookup, lookup_type, tzinfo):
super(DateTime, self).__init__(output_field=fields.DateTimeField())
self.lookup = lookup
self.col = None
self.lookup_type = lookup_type
if tzinfo is None:
self.tzname = None
else:
self.tzname = timezone._get_timezone_name(tzinfo)
self.tzinfo = tzinfo

def __repr__(self):
return "{}({}, {}, {})".format(
self.__class__.__name__, self.lookup, self.lookup_type, self.tzinfo)

def get_source_expressions(self):
return [self.col]

def set_source_expressions(self, exprs):
self.col, = exprs

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
copy = self.copy()
copy.col = query.resolve_ref(self.lookup, allow_joins, reuse, summarize)
field = copy.col.output_field
assert isinstance(field, fields.DateTimeField), (
"%r isn't a DateTimeField." % field.name
)
return copy

def as_sql(self, compiler, connection):
sql, params = self.col.as_sql(compiler, connection)
assert not(params)
return connection.ops.datetime_trunc_sql(self.lookup_type, sql, self.tzname)

def copy(self):
copy = super(DateTime, self).copy()
copy.lookup = self.lookup
copy.lookup_type = self.lookup_type
copy.tzname = self.tzname
return copy

def convert_value(self, value, expression, connection, context):
if settings.USE_TZ:
if value is None:
raise ValueError(
"Database returned an invalid value in QuerySet.datetimes(). "
"Are time zone definitions for your database and pytz installed?"
)
value = value.replace(tzinfo=None)
value = timezone.make_aware(value, self.tzinfo)
return value

class OrderBy(BaseExpression):
template = '%(expression)s %(ordering)s'

def __init__(self, expression, descending=False):
self.descending = descending
if not hasattr(expression, 'resolve_expression'):
raise ValueError('expression must be an expression type')
self.expression = expression

def __repr__(self):
return "{}({}, descending={})".format(
self.__class__.__name__, self.expression, self.descending)

def set_source_expressions(self, exprs):
self.expression = exprs[0]

def get_source_expressions(self):
return [self.expression]

def as_sql(self, compiler, connection):
connection.ops.check_expression_support(self)
expression_sql, params = compiler.compile(self.expression)
placeholders = {'expression': expression_sql}
placeholders['ordering'] = 'DESC' if self.descending else 'ASC'
return (self.template % placeholders).rstrip(), params

def get_group_by_cols(self):
cols = []
for source in self.get_source_expressions():
cols.extend(source.get_group_by_cols())
return cols

def reverse_ordering(self):
self.descending = not self.descending
return self

def asc(self):
self.descending = False

def desc(self):
self.descending = True

Source code for django.db.models.functions

"""
Classes that represent database functions.
"""
from django.db.models import (
DateTimeField, Func, IntegerField, Transform, Value,
)

[docs]class Coalesce(Func):
"""
Chooses, from left to right, the first non-null expression and returns it.
"""
function = 'COALESCE'

def __init__(self, *expressions, **extra):
if len(expressions) < 2:
raise ValueError('Coalesce must take at least two expressions')
super(Coalesce, self).__init__(*expressions, **extra)

def as_oracle(self, compiler, connection):
# we can't mix TextField (NCLOB) and CharField (NVARCHAR), so convert
# all fields to NCLOB when we expect NCLOB
if self.output_field.get_internal_type() == 'TextField':
class ToNCLOB(Func):
function = 'TO_NCLOB'

expressions = [
ToNCLOB(expression) for expression in self.get_source_expressions()]
self.set_source_expressions(expressions)
return super(Coalesce, self).as_sql(compiler, connection)

class ConcatPair(Func):
"""
A helper class that concatenates two arguments together. This is used
by `Concat` because not all backend databases support more than two
arguments.
"""
function = 'CONCAT'

def __init__(self, left, right, **extra):
super(ConcatPair, self).__init__(left, right, **extra)

def as_sqlite(self, compiler, connection):
coalesced = self.coalesce()
coalesced.arg_joiner = ' || '
coalesced.template = '%(expressions)s'
return super(ConcatPair, coalesced).as_sql(compiler, connection)

def as_mysql(self, compiler, connection):
# Use CONCAT_WS with an empty separator so that NULLs are ignored.
self.function = 'CONCAT_WS'
self.template = "%(function)s('', %(expressions)s)"
return super(ConcatPair, self).as_sql(compiler, connection)

def coalesce(self):
# null on either side results in null for expression, wrap with coalesce
c = self.copy()
expressions = [
Coalesce(expression, Value('')) for expression in c.get_source_expressions()
]
c.set_source_expressions(expressions)
return c

[docs]class Concat(Func):
"""
Concatenates text fields together. Backends that result in an entire
null expression when any arguments are null will wrap each argument in
coalesce functions to ensure we always get a non-null result.
"""
function = None
template = "%(expressions)s"

def __init__(self, *expressions, **extra):
if len(expressions) < 2:
raise ValueError('Concat must take at least two expressions')
paired = self._paired(expressions)
super(Concat, self).__init__(paired, **extra)

def _paired(self, expressions):
# wrap pairs of expressions in successive concat functions
# exp = [a, b, c, d]
# -> ConcatPair(a, ConcatPair(b, ConcatPair(c, d))))
if len(expressions) == 2:
return ConcatPair(*expressions)
return ConcatPair(expressions[0], self._paired(expressions[1:]))

[docs]class Greatest(Func):
"""
Chooses the maximum expression and returns it.

If any expression is null the return value is database-specific:
On Postgres, the maximum not-null expression is returned.
On MySQL, Oracle, and SQLite, if any expression is null, null is returned.
"""
function = 'GREATEST'

def __init__(self, *expressions, **extra):
if len(expressions) < 2:
raise ValueError('Greatest must take at least two expressions')
super(Greatest, self).__init__(*expressions, **extra)

def as_sqlite(self, compiler, connection):
"""Use the MAX function on SQLite."""
return super(Greatest, self).as_sql(compiler, connection, function='MAX')

[docs]class Least(Func):
"""
Chooses the minimum expression and returns it.

If any expression is null the return value is database-specific:
On Postgres, the minimum not-null expression is returned.
On MySQL, Oracle, and SQLite, if any expression is null, null is returned.
"""
function = 'LEAST'

def __init__(self, *expressions, **extra):
if len(expressions) < 2:
raise ValueError('Least must take at least two expressions')
super(Least, self).__init__(*expressions, **extra)

def as_sqlite(self, compiler, connection):
"""Use the MIN function on SQLite."""
return super(Least, self).as_sql(compiler, connection, function='MIN')

[docs]class Length(Transform):
"""Returns the number of characters in the expression"""
function = 'LENGTH'
lookup_name = 'length'

def __init__(self, expression, **extra):
output_field = extra.pop('output_field', IntegerField())
super(Length, self).__init__(expression, output_field=output_field, **extra)

def as_mysql(self, compiler, connection):
self.function = 'CHAR_LENGTH'
return super(Length, self).as_sql(compiler, connection)

[docs]class Lower(Transform):
function = 'LOWER'
lookup_name = 'lower'

def __init__(self, expression, **extra):
super(Lower, self).__init__(expression, **extra)

[docs]class Now(Func):
template = 'CURRENT_TIMESTAMP'

def __init__(self, output_field=None, **extra):
if output_field is None:
output_field = DateTimeField()
super(Now, self).__init__(output_field=output_field, **extra)

def as_postgresql(self, compiler, connection):
# Postgres' CURRENT_TIMESTAMP means "the time at the start of the
# transaction". We use STATEMENT_TIMESTAMP to be cross-compatible with
# other databases.
self.template = 'STATEMENT_TIMESTAMP()'
return self.as_sql(compiler, connection)

[docs]class Substr(Func):
function = 'SUBSTRING'

def __init__(self, expression, pos, length=None, **extra):
"""
expression: the name of a field, or an expression returning a string
pos: an integer > 0, or an expression returning an integer
length: an optional number of characters to return
"""
if not hasattr(pos, 'resolve_expression'):
if pos < 1:
raise ValueError("'pos' must be greater than 0")
pos = Value(pos)
expressions = [expression, pos]
if length is not None:
if not hasattr(length, 'resolve_expression'):
length = Value(length)
expressions.append(length)
super(Substr, self).__init__(*expressions, **extra)

def as_sqlite(self, compiler, connection):
self.function = 'SUBSTR'
return super(Substr, self).as_sql(compiler, connection)

def as_oracle(self, compiler, connection):
self.function = 'SUBSTR'
return super(Substr, self).as_sql(compiler, connection)

[docs]class Upper(Transform):
function = 'UPPER'
lookup_name = 'upper'

def __init__(self, expression, **extra):
super(Upper, self).__init__(expression, **extra)

Source code for django.db.models.manager

import copy
import inspect
from importlib import import_module

from django.db import router
from django.db.models.query import QuerySet
from django.utils import six
from django.utils.encoding import python_2_unicode_compatible

def ensure_default_manager(cls):
"""
Ensures that a Model subclass contains a default manager  and sets the
_default_manager attribute on the class. Also sets up the _base_manager
points to a plain Manager instance (which could be the same as
_default_manager if it's not a subclass of Manager).
"""
if cls._meta.swapped:
setattr(cls, 'objects', SwappedManagerDescriptor(cls))
return
if not getattr(cls, '_default_manager', None):
if any(f.name == 'objects' for f in cls._meta.fields):
raise ValueError(
"Model %s must specify a custom Manager, because it has a "
"field named 'objects'" % cls.__name__
)
# Create the default manager, if needed.
cls.add_to_class('objects', Manager())
cls._base_manager = cls.objects
elif not getattr(cls, '_base_manager', None):
default_mgr = cls._default_manager.__class__
if (default_mgr is Manager or
getattr(default_mgr, "use_for_related_fields", False)):
cls._base_manager = cls._default_manager
else:
# Default manager isn't a plain Manager class, or a suitable
# replacement, so we walk up the base class hierarchy until we hit
# something appropriate.
for base_class in default_mgr.mro()[1:]:
if (base_class is Manager or
getattr(base_class, "use_for_related_fields", False)):
cls.add_to_class('_base_manager', base_class())
return
raise AssertionError(
"Should never get here. Please report a bug, including your "
"model and model manager setup."
)

@python_2_unicode_compatible
class BaseManager(object):
# Tracks each time a Manager instance is created. Used to retain order.
creation_counter = 0

#: If set to True the manager will be serialized into migrations and will
#: thus be available in e.g. RunPython operations
use_in_migrations = False

def __new__(cls, *args, **kwargs):
# We capture the arguments to make returning them trivial
obj = super(BaseManager, cls).__new__(cls)
obj._constructor_args = (args, kwargs)
return obj

def __init__(self):
super(BaseManager, self).__init__()
self._set_creation_counter()
self.model = None
self.name = None
self._inherited = False
self._db = None
self._hints = {}

def __str__(self):
""" Return "app_label.model_label.manager_name". """
return '%s.%s' % (self.model._meta.label, self.name)

def deconstruct(self):
"""
Returns a 5-tuple of the form (as_manager (True), manager_class,
queryset_class, args, kwargs).

Raises a ValueError if the manager is dynamically generated.
"""
qs_class = self._queryset_class
if getattr(self, '_built_with_as_manager', False):
# using MyQuerySet.as_manager()
return (
True,  # as_manager
None,  # manager_class
'%s.%s' % (qs_class.__module__, qs_class.__name__),  # qs_class
None,  # args
None,  # kwargs
)
else:
module_name = self.__module__
name = self.__class__.__name__
# Make sure it's actually there and not an inner class
module = import_module(module_name)
if not hasattr(module, name):
raise ValueError(
"Could not find manager %s in %s.\n"
"Please note that you need to inherit from managers you "
"dynamically generated with 'from_queryset()'."
% (name, module_name)
)
return (
False,  # as_manager
'%s.%s' % (module_name, name),  # manager_class
None,  # qs_class
self._constructor_args[0],  # args
self._constructor_args[1],  # kwargs
)

def check(self, **kwargs):
return []

@classmethod
def _get_queryset_methods(cls, queryset_class):
def create_method(name, method):
def manager_method(self, *args, **kwargs):
return getattr(self.get_queryset(), name)(*args, **kwargs)
manager_method.__name__ = method.__name__
manager_method.__doc__ = method.__doc__
return manager_method

new_methods = {}
# Refs http://bugs.python.org/issue1785.
predicate = inspect.isfunction if six.PY3 else inspect.ismethod
for name, method in inspect.getmembers(queryset_class, predicate=predicate):
# Only copy missing methods.
if hasattr(cls, name):
continue
# Only copy public methods or methods with the attribute `queryset_only=False`.
queryset_only = getattr(method, 'queryset_only', None)
if queryset_only or (queryset_only is None and name.startswith('_')):
continue
# Copy the method onto the manager.
new_methods[name] = create_method(name, method)
return new_methods

@classmethod
def from_queryset(cls, queryset_class, class_name=None):
if class_name is None:
class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
class_dict = {
'_queryset_class': queryset_class,
}
class_dict.update(cls._get_queryset_methods(queryset_class))
return type(class_name, (cls,), class_dict)

def contribute_to_class(self, model, name):
# TODO: Use weakref because of possible memory leak / circular reference.
self.model = model
if not self.name:
self.name = name
# Only contribute the manager if the model is concrete
if model._meta.abstract:
setattr(model, name, AbstractManagerDescriptor(model))
elif model._meta.swapped:
setattr(model, name, SwappedManagerDescriptor(model))
else:
# if not model._meta.abstract and not model._meta.swapped:
setattr(model, name, ManagerDescriptor(self))
if (not getattr(model, '_default_manager', None) or
self.creation_counter < model._default_manager.creation_counter):
model._default_manager = self

abstract = False
if model._meta.abstract or (self._inherited and not self.model._meta.proxy):
abstract = True
model._meta.managers.append((self.creation_counter, self, abstract))

def _set_creation_counter(self):
"""
Sets the creation counter value for this instance and increments the
class-level copy.
"""
self.creation_counter = BaseManager.creation_counter
BaseManager.creation_counter += 1

def _copy_to_model(self, model):
"""
Makes a copy of the manager and assigns it to 'model', which should be
a child of the existing model (used when inheriting a manager from an
abstract base class).
"""
assert issubclass(model, self.model)
mgr = copy.copy(self)
mgr._set_creation_counter()
mgr.model = model
mgr._inherited = True
return mgr

def db_manager(self, using=None, hints=None):
obj = copy.copy(self)
obj._db = using or self._db
obj._hints = hints or self._hints
return obj

@property
def db(self):
return self._db or router.db_for_read(self.model, **self._hints)

#######################
# PROXIES TO QUERYSET #
#######################

def get_queryset(self):
"""
Returns a new QuerySet object.  Subclasses can override this method to
easily customize the behavior of the Manager.
"""
return self._queryset_class(model=self.model, using=self._db, hints=self._hints)

def all(self):
# We can't proxy this method through the `QuerySet` like we do for the
# rest of the `QuerySet` methods. This is because `QuerySet.all()`
# works by creating a "copy" of the current queryset and in making said
# copy, all the cached `prefetch_related` lookups are lost. See the
# implementation of `RelatedManager.get_queryset()` for a better
# understanding of how this comes into play.
return self.get_queryset()

def __eq__(self, other):
return (
isinstance(other, self.__class__) and
self._constructor_args == other._constructor_args
)

def __ne__(self, other):
return not (self == other)

def __hash__(self):
return id(self)

[docs]class Manager(BaseManager.from_queryset(QuerySet)):
pass

class ManagerDescriptor(object):
# This class ensures managers aren't accessible via model instances.
# For example, Poll.objects works, but poll_obj.objects raises AttributeError.
def __init__(self, manager):
self.manager = manager

def __get__(self, instance, type=None):
if instance is not None:
raise AttributeError("Manager isn't accessible via %s instances" % type.__name__)
return self.manager

class AbstractManagerDescriptor(object):
# This class provides a better error message when you try to access a
# manager on an abstract model.
def __init__(self, model):
self.model = model

def __get__(self, instance, type=None):
raise AttributeError("Manager isn't available; %s is abstract" % (
self.model._meta.object_name,
))

class SwappedManagerDescriptor(object):
# This class provides a better error message when you try to access a
# manager on a swapped model.
def __init__(self, model):
self.model = model

def __get__(self, instance, type=None):
raise AttributeError(
"Manager isn't available; '%s.%s' has been swapped for '%s'" % (
self.model._meta.app_label,
self.model._meta.object_name,
self.model._meta.swapped,
)
)

class EmptyManager(Manager):
def __init__(self, model):
super(EmptyManager, self).__init__()
self.model = model

def get_queryset(self):
return super(EmptyManager, self).get_queryset().none()

Source code for django.db.models.query

"""
The main QuerySet implementation. This provides the public API for the ORM.
"""

import copy
import sys
import warnings
from collections import OrderedDict, deque

from django.conf import settings
from django.core import exceptions
from django.db import (
DJANGO_VERSION_PICKLE_KEY, IntegrityError, connections, router,
transaction,
)
from django.db.models import sql
from django.db.models.constants import LOOKUP_SEP
from django.db.models.deletion import Collector
from django.db.models.expressions import Date, DateTime, F
from django.db.models.fields import AutoField
from django.db.models.query_utils import (
InvalidQuery, Q, check_rel_lookup_compatibility, deferred_class_factory,
)
from django.db.models.sql.constants import CURSOR
from django.utils import six, timezone
from django.utils.functional import partition
from django.utils.version import get_version

# The maximum number of items to display in a QuerySet.__repr__
REPR_OUTPUT_SIZE = 20

# Pull into this namespace for backwards compatibility.
EmptyResultSet = sql.EmptyResultSet

class BaseIterable(object):
def __init__(self, queryset):
self.queryset = queryset

class ModelIterable(BaseIterable):
"""
Iterable that yields a model instance for each row.
"""

def __iter__(self):
queryset = self.queryset
db = queryset.db
compiler = queryset.query.get_compiler(using=db)
# Execute the query. This will also fill compiler.select, klass_info,
# and annotations.
results = compiler.execute_sql()
select, klass_info, annotation_col_map = (compiler.select, compiler.klass_info,
compiler.annotation_col_map)
if klass_info is None:
return
model_cls = klass_info['model']
select_fields = klass_info['select_fields']
model_fields_start, model_fields_end = select_fields[0], select_fields[-1] + 1
init_list = [f[0].target.attname
for f in select[model_fields_start:model_fields_end]]
if len(init_list) != len(model_cls._meta.concrete_fields):
init_set = set(init_list)
skip = [f.attname for f in model_cls._meta.concrete_fields
if f.attname not in init_set]
model_cls = deferred_class_factory(model_cls, skip)
related_populators = get_related_populators(klass_info, select, db)
for row in compiler.results_iter(results):
obj = model_cls.from_db(db, init_list, row[model_fields_start:model_fields_end])
if related_populators:
for rel_populator in related_populators:
rel_populator.populate(row, obj)
if annotation_col_map:
for attr_name, col_pos in annotation_col_map.items():
setattr(obj, attr_name, row[col_pos])

# Add the known related objects to the model, if there are any
if queryset._known_related_objects:
for field, rel_objs in queryset._known_related_objects.items():
# Avoid overwriting objects loaded e.g. by select_related
if hasattr(obj, field.get_cache_name()):
continue
pk = getattr(obj, field.get_attname())
try:
rel_obj = rel_objs[pk]
except KeyError:
pass  # may happen in qs1 | qs2 scenarios
else:
setattr(obj, field.name, rel_obj)

yield obj

class ValuesIterable(BaseIterable):
"""
Iterable returned by QuerySet.values() that yields a dict
for each row.
"""

def __iter__(self):
queryset = self.queryset
query = queryset.query
compiler = query.get_compiler(queryset.db)

field_names = list(query.values_select)
extra_names = list(query.extra_select)
annotation_names = list(query.annotation_select)

# extra(select=...) cols are always at the start of the row.
names = extra_names + field_names + annotation_names

for row in compiler.results_iter():
yield dict(zip(names, row))

class ValuesListIterable(BaseIterable):
"""
Iterable returned by QuerySet.values_list(flat=False)
that yields a tuple for each row.
"""

def __iter__(self):
queryset = self.queryset
query = queryset.query
compiler = query.get_compiler(queryset.db)

if not query.extra_select and not query.annotation_select:
for row in compiler.results_iter():
yield tuple(row)
else:
field_names = list(query.values_select)
extra_names = list(query.extra_select)
annotation_names = list(query.annotation_select)

# extra(select=...) cols are always at the start of the row.
names = extra_names + field_names + annotation_names

if queryset._fields:
# Reorder according to fields.
fields = list(queryset._fields) + [f for f in annotation_names if f not in queryset._fields]
else:
fields = names

for row in compiler.results_iter():
data = dict(zip(names, row))
yield tuple(data[f] for f in fields)

class FlatValuesListIterable(BaseIterable):
"""
Iterable returned by QuerySet.values_list(flat=True) that
yields single values.
"""

def __iter__(self):
queryset = self.queryset
compiler = queryset.query.get_compiler(queryset.db)
for row in compiler.results_iter():
yield row[0]

[docs]class QuerySet(object):
"""
Represents a lazy database lookup for a set of objects.
"""

def __init__(self, model=None, query=None, using=None, hints=None):
self.model = model
self._db = using
self._hints = hints or {}
self.query = query or sql.Query(self.model)
self._result_cache = None
self._sticky_filter = False
self._for_write = False
self._prefetch_related_lookups = []
self._prefetch_done = False
self._known_related_objects = {}  # {rel_field, {pk: rel_obj}}
self._iterable_class = ModelIterable
self._fields = None

def as_manager(cls):
# Address the circular dependency between `Queryset` and `Manager`.
from django.db.models.manager import Manager
manager = Manager.from_queryset(cls)()
manager._built_with_as_manager = True
return manager
as_manager.queryset_only = True
as_manager = classmethod(as_manager)

########################
# PYTHON MAGIC METHODS #
########################

def __deepcopy__(self, memo):
"""
Deep copy of a QuerySet doesn't populate the cache
"""
obj = self.__class__()
for k, v in self.__dict__.items():
if k == '_result_cache':
obj.__dict__[k] = None
else:
obj.__dict__[k] = copy.deepcopy(v, memo)
return obj

def __getstate__(self):
"""
Allows the QuerySet to be pickled.
"""
# Force the cache to be fully populated.
self._fetch_all()
obj_dict = self.__dict__.copy()
obj_dict[DJANGO_VERSION_PICKLE_KEY] = get_version()
return obj_dict

def __setstate__(self, state):
msg = None
pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY)
if pickled_version:
current_version = get_version()
if current_version != pickled_version:
msg = ("Pickled queryset instance's Django version %s does"
" not match the current version %s."
% (pickled_version, current_version))
else:
msg = "Pickled queryset instance's Django version is not specified."

if msg:
warnings.warn(msg, RuntimeWarning, stacklevel=2)

self.__dict__.update(state)

def __repr__(self):
data = list(self[:REPR_OUTPUT_SIZE + 1])
if len(data) > REPR_OUTPUT_SIZE:
data[-1] = "...(remaining elements truncated)..."
return repr(data)

def __len__(self):
self._fetch_all()
return len(self._result_cache)

def __iter__(self):
"""
The queryset iterator protocol uses three nested iterators in the
default case:
1. sql.compiler:execute_sql()
- Returns 100 rows at time (constants.GET_ITERATOR_CHUNK_SIZE)
using cursor.fetchmany(). This part is responsible for
doing some column masking, and returning the rows in chunks.
2. sql/compiler.results_iter()
- Returns one row at time. At this point the rows are still just
tuples. In some cases the return values are converted to
Python values at this location.
3. self.iterator()
- Responsible for turning the rows into model objects.
"""
self._fetch_all()
return iter(self._result_cache)

def __bool__(self):
self._fetch_all()
return bool(self._result_cache)

def __nonzero__(self):      # Python 2 compatibility
return type(self).__bool__(self)

def __getitem__(self, k):
"""
Retrieves an item or slice from the set of results.
"""
if not isinstance(k, (slice,) + six.integer_types):
raise TypeError
assert ((not isinstance(k, slice) and (k >= 0)) or
(isinstance(k, slice) and (k.start is None or k.start >= 0) and
(k.stop is None or k.stop >= 0))), \
"Negative indexing is not supported."

if self._result_cache is not None:
return self._result_cache[k]

if isinstance(k, slice):
qs = self._clone()
if k.start is not None:
start = int(k.start)
else:
start = None
if k.stop is not None:
stop = int(k.stop)
else:
stop = None
qs.query.set_limits(start, stop)
return list(qs)[::k.step] if k.step else qs

qs = self._clone()
qs.query.set_limits(k, k + 1)
return list(qs)[0]

def __and__(self, other):
self._merge_sanity_check(other)
if isinstance(other, EmptyQuerySet):
return other
if isinstance(self, EmptyQuerySet):
return self
combined = self._clone()
combined._merge_known_related_objects(other)
combined.query.combine(other.query, sql.AND)
return combined

def __or__(self, other):
self._merge_sanity_check(other)
if isinstance(self, EmptyQuerySet):
return other
if isinstance(other, EmptyQuerySet):
return self
combined = self._clone()
combined._merge_known_related_objects(other)
combined.query.combine(other.query, sql.OR)
return combined

####################################
# METHODS THAT DO DATABASE QUERIES #
####################################

def iterator(self):
"""
An iterator over the results from applying this QuerySet to the
database.
"""
return iter(self._iterable_class(self))

def aggregate(self, *args, **kwargs):
"""
Returns a dictionary containing the calculations (aggregation)
over the current queryset

If args is present the expression is passed as a kwarg using
the Aggregate object's default alias.
"""
if self.query.distinct_fields:
raise NotImplementedError("aggregate() + distinct(fields) not implemented.")
for arg in args:
# The default_alias property may raise a TypeError, so we use
# a try/except construct rather than hasattr in order to remain
# consistent between PY2 and PY3 (hasattr would swallow
# the TypeError on PY2).
try:
arg.default_alias
except (AttributeError, TypeError):
raise TypeError("Complex aggregates require an alias")
kwargs[arg.default_alias] = arg

query = self.query.clone()
for (alias, aggregate_expr) in kwargs.items():
query.add_annotation(aggregate_expr, alias, is_summary=True)
if not query.annotations[alias].contains_aggregate:
raise TypeError("%s is not an aggregate expression" % alias)
return query.get_aggregation(self.db, kwargs.keys())

def count(self):
"""
Performs a SELECT COUNT() and returns the number of records as an
integer.

If the QuerySet is already fully cached this simply returns the length
of the cached results set to avoid multiple SELECT COUNT(*) calls.
"""
if self._result_cache is not None:
return len(self._result_cache)

return self.query.get_count(using=self.db)

def get(self, *args, **kwargs):
"""
Performs the query and returns a single object matching the given
keyword arguments.
"""
clone = self.filter(*args, **kwargs)
if self.query.can_filter() and not self.query.distinct_fields:
clone = clone.order_by()
num = len(clone)
if num == 1:
return clone._result_cache[0]
if not num:
raise self.model.DoesNotExist(
"%s matching query does not exist." %
self.model._meta.object_name
)
raise self.model.MultipleObjectsReturned(
"get() returned more than one %s -- it returned %s!" %
(self.model._meta.object_name, num)
)

def create(self, **kwargs):
"""
Creates a new object with the given kwargs, saving it to the database
and returning the created object.
"""
obj = self.model(**kwargs)
self._for_write = True
obj.save(force_insert=True, using=self.db)
return obj

def _populate_pk_values(self, objs):
for obj in objs:
if obj.pk is None:
obj.pk = obj._meta.pk.get_pk_value_on_save(obj)

def bulk_create(self, objs, batch_size=None):
"""
Inserts each of the instances into the database. This does *not* call
save() on each of the instances, does not send any pre/post save
signals, and does not set the primary key attribute if it is an
autoincrement field. Multi-table models are not supported.
"""
# So this case is fun. When you bulk insert you don't get the primary
# keys back (if it's an autoincrement), so you can't insert into the
# child tables which references this. There are two workarounds, 1)
# this could be implemented if you didn't have an autoincrement pk,
# and 2) you could do it by doing O(n) normal inserts into the parent
# tables to get the primary keys back, and then doing a single bulk
# insert into the childmost table. Some databases might allow doing
# this by using RETURNING clause for the insert query. We're punting
# on these for now because they are relatively rare cases.
assert batch_size is None or batch_size > 0
# Check that the parents share the same concrete model with the our
# model to detect the inheritance pattern ConcreteGrandParent ->
# MultiTableParent -> ProxyChild. Simply checking self.model._meta.proxy
# would not identify that case as involving multiple tables.
for parent in self.model._meta.get_parent_list():
if parent._meta.concrete_model is not self.model._meta.concrete_model:
raise ValueError("Can't bulk create a multi-table inherited model")
if not objs:
return objs
self._for_write = True
connection = connections[self.db]
fields = self.model._meta.concrete_fields
objs = list(objs)
self._populate_pk_values(objs)
with transaction.atomic(using=self.db, savepoint=False):
if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
and self.model._meta.has_auto_field):
self._batched_insert(objs, fields, batch_size)
else:
objs_with_pk, objs_without_pk = partition(lambda o: o.pk is None, objs)
if objs_with_pk:
self._batched_insert(objs_with_pk, fields, batch_size)
if objs_without_pk:
fields = [f for f in fields if not isinstance(f, AutoField)]
self._batched_insert(objs_without_pk, fields, batch_size)

return objs

def get_or_create(self, defaults=None, **kwargs):
"""
Looks up an object with the given kwargs, creating one if necessary.
Returns a tuple of (object, created), where created is a boolean
specifying whether an object was created.
"""
lookup, params = self._extract_model_params(defaults, **kwargs)
# The get() needs to be targeted at the write database in order
# to avoid potential transaction consistency problems.
self._for_write = True
try:
return self.get(**lookup), False
except self.model.DoesNotExist:
return self._create_object_from_params(lookup, params)

def update_or_create(self, defaults=None, **kwargs):
"""
Looks up an object with the given kwargs, updating one with defaults
if it exists, otherwise creates a new one.
Returns a tuple (object, created), where created is a boolean
specifying whether an object was created.
"""
defaults = defaults or {}
lookup, params = self._extract_model_params(defaults, **kwargs)
self._for_write = True
try:
obj = self.get(**lookup)
except self.model.DoesNotExist:
obj, created = self._create_object_from_params(lookup, params)
if created:
return obj, created
for k, v in six.iteritems(defaults):
setattr(obj, k, v)

with transaction.atomic(using=self.db, savepoint=False):
obj.save(using=self.db)
return obj, False

def _create_object_from_params(self, lookup, params):
"""
Tries to create an object using passed params.
Used by get_or_create and update_or_create
"""
try:
with transaction.atomic(using=self.db):
obj = self.create(**params)
return obj, True
except IntegrityError:
exc_info = sys.exc_info()
try:
return self.get(**lookup), False
except self.model.DoesNotExist:
pass
six.reraise(*exc_info)

def _extract_model_params(self, defaults, **kwargs):
"""
Prepares `lookup` (kwargs that are valid model attributes), `params`
(for creating a model instance) based on given kwargs; for use by
get_or_create and update_or_create.
"""
defaults = defaults or {}
lookup = kwargs.copy()
for f in self.model._meta.fields:
if f.attname in lookup:
lookup[f.name] = lookup.pop(f.attname)
params = {k: v for k, v in kwargs.items() if LOOKUP_SEP not in k}
params.update(defaults)
return lookup, params

def _earliest_or_latest(self, field_name=None, direction="-"):
"""
Returns the latest object, according to the model's
'get_latest_by' option or optional given field_name.
"""
order_by = field_name or getattr(self.model._meta, 'get_latest_by')
assert bool(order_by), "earliest() and latest() require either a "\
"field_name parameter or 'get_latest_by' in the model"
assert self.query.can_filter(), \
"Cannot change a query once a slice has been taken."
obj = self._clone()
obj.query.set_limits(high=1)
obj.query.clear_ordering(force_empty=True)
obj.query.add_ordering('%s%s' % (direction, order_by))
return obj.get()

def earliest(self, field_name=None):
return self._earliest_or_latest(field_name=field_name, direction="")

def latest(self, field_name=None):
return self._earliest_or_latest(field_name=field_name, direction="-")

def first(self):
"""
Returns the first object of a query, returns None if no match is found.
"""
objects = list((self if self.ordered else self.order_by('pk'))[:1])
if objects:
return objects[0]
return None

def last(self):
"""
Returns the last object of a query, returns None if no match is found.
"""
objects = list((self.reverse() if self.ordered else self.order_by('-pk'))[:1])
if objects:
return objects[0]
return None

def in_bulk(self, id_list):
"""
Returns a dictionary mapping each of the given IDs to the object with
that ID.
"""
assert self.query.can_filter(), \
"Cannot use 'limit' or 'offset' with in_bulk"
if not id_list:
return {}
qs = self.filter(pk__in=id_list).order_by()
return {obj._get_pk_val(): obj for obj in qs}

def delete(self):
"""
Deletes the records in the current QuerySet.
"""
assert self.query.can_filter(), \
"Cannot use 'limit' or 'offset' with delete."

if self._fields is not None:
raise TypeError("Cannot call delete() after .values() or .values_list()")

del_query = self._clone()

# The delete is actually 2 queries - one to find related objects,
# and one to delete. Make sure that the discovery of related
# objects is performed on the same database as the deletion.
del_query._for_write = True

# Disable non-supported fields.
del_query.query.select_for_update = False
del_query.query.select_related = False
del_query.query.clear_ordering(force_empty=True)

collector = Collector(using=del_query.db)
collector.collect(del_query)
deleted, _rows_count = collector.delete()

# Clear the result cache, in case this QuerySet gets reused.
self._result_cache = None
return deleted, _rows_count

delete.alters_data = True
delete.queryset_only = True

def _raw_delete(self, using):
"""
Deletes objects found from the given queryset in single direct SQL
query. No signals are sent, and there is no protection for cascades.
"""
return sql.DeleteQuery(self.model).delete_qs(self, using)
_raw_delete.alters_data = True

def update(self, **kwargs):
"""
Updates all elements in the current QuerySet, setting all the given
fields to the appropriate values.
"""
assert self.query.can_filter(), \
"Cannot update a query once a slice has been taken."
self._for_write = True
query = self.query.clone(sql.UpdateQuery)
query.add_update_values(kwargs)
with transaction.atomic(using=self.db, savepoint=False):
rows = query.get_compiler(self.db).execute_sql(CURSOR)
self._result_cache = None
return rows
update.alters_data = True

def _update(self, values):
"""
A version of update that accepts field objects instead of field names.
Used primarily for model saving and not intended for use by general
code (it requires too much poking around at model internals to be
useful at that level).
"""
assert self.query.can_filter(), \
"Cannot update a query once a slice has been taken."
query = self.query.clone(sql.UpdateQuery)
query.add_update_fields(values)
self._result_cache = None
return query.get_compiler(self.db).execute_sql(CURSOR)
_update.alters_data = True
_update.queryset_only = False

def exists(self):
if self._result_cache is None:
return self.query.has_results(using=self.db)
return bool(self._result_cache)

def _prefetch_related_objects(self):
# This method can only be called once the result cache has been filled.
prefetch_related_objects(self._result_cache, self._prefetch_related_lookups)
self._prefetch_done = True

##################################################
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
##################################################

def raw(self, raw_query, params=None, translations=None, using=None):
if using is None:
using = self.db
return RawQuerySet(raw_query, model=self.model,
params=params, translations=translations,
using=using)

def _values(self, *fields):
clone = self._clone()
clone._fields = fields

query = clone.query
query.select_related = False
query.clear_deferred_loading()
query.clear_select_fields()

if query.group_by is True:
query.add_fields((f.attname for f in self.model._meta.concrete_fields), False)
query.set_group_by()
query.clear_select_fields()

if fields:
field_names = []
extra_names = []
annotation_names = []
if not query._extra and not query._annotations:
# Shortcut - if there are no extra or annotations, then
# the values() clause must be just field names.
field_names = list(fields)
else:
query.default_cols = False
for f in fields:
if f in query.extra_select:
extra_names.append(f)
elif f in query.annotation_select:
annotation_names.append(f)
else:
field_names.append(f)
query.set_extra_mask(extra_names)
query.set_annotation_mask(annotation_names)
else:
field_names = [f.attname for f in self.model._meta.concrete_fields]

query.values_select = field_names
query.add_fields(field_names, True)

return clone

def values(self, *fields):
clone = self._values(*fields)
clone._iterable_class = ValuesIterable
return clone

def values_list(self, *fields, **kwargs):
flat = kwargs.pop('flat', False)
if kwargs:
raise TypeError('Unexpected keyword arguments to values_list: %s'
% (list(kwargs),))

if flat and len(fields) > 1:
raise TypeError("'flat' is not valid when values_list is called with more than one field.")

clone = self._values(*fields)
clone._iterable_class = FlatValuesListIterable if flat else ValuesListIterable
return clone

def dates(self, field_name, kind, order='ASC'):
"""
Returns a list of date objects representing all available dates for
the given field_name, scoped to 'kind'.
"""
assert kind in ("year", "month", "day"), \
"'kind' must be one of 'year', 'month' or 'day'."
assert order in ('ASC', 'DESC'), \
"'order' must be either 'ASC' or 'DESC'."
return self.annotate(
datefield=Date(field_name, kind),
plain_field=F(field_name)
).values_list(
'datefield', flat=True
).distinct().filter(plain_field__isnull=False).order_by(('-' if order == 'DESC' else '') + 'datefield')

def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
"""
Returns a list of datetime objects representing all available
datetimes for the given field_name, scoped to 'kind'.
"""
assert kind in ("year", "month", "day", "hour", "minute", "second"), \
"'kind' must be one of 'year', 'month', 'day', 'hour', 'minute' or 'second'."
assert order in ('ASC', 'DESC'), \
"'order' must be either 'ASC' or 'DESC'."
if settings.USE_TZ:
if tzinfo is None:
tzinfo = timezone.get_current_timezone()
else:
tzinfo = None
return self.annotate(
datetimefield=DateTime(field_name, kind, tzinfo),
plain_field=F(field_name)
).values_list(
'datetimefield', flat=True
).distinct().filter(plain_field__isnull=False).order_by(('-' if order == 'DESC' else '') + 'datetimefield')

def none(self):
"""
Returns an empty QuerySet.
"""
clone = self._clone()
clone.query.set_empty()
return clone

##################################################################
# PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
##################################################################

def all(self):
"""
Returns a new QuerySet that is a copy of the current one. This allows a
QuerySet to proxy for a model manager in some cases.
"""
return self._clone()

def filter(self, *args, **kwargs):
"""
Returns a new QuerySet instance with the args ANDed to the existing
set.
"""
return self._filter_or_exclude(False, *args, **kwargs)

def exclude(self, *args, **kwargs):
"""
Returns a new QuerySet instance with NOT (args) ANDed to the existing
set.
"""
return self._filter_or_exclude(True, *args, **kwargs)

def _filter_or_exclude(self, negate, *args, **kwargs):
if args or kwargs:
assert self.query.can_filter(), \
"Cannot filter a query once a slice has been taken."

clone = self._clone()
if negate:
clone.query.add_q(~Q(*args, **kwargs))
else:
clone.query.add_q(Q(*args, **kwargs))
return clone

def complex_filter(self, filter_obj):
"""
Returns a new QuerySet instance with filter_obj added to the filters.

filter_obj can be a Q object (or anything with an add_to_query()
method) or a dictionary of keyword lookup arguments.

This exists to support framework features such as 'limit_choices_to',
and usually it will be more natural to use other methods.
"""
if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
clone = self._clone()
clone.query.add_q(filter_obj)
return clone
else:
return self._filter_or_exclude(None, **filter_obj)

def select_for_update(self, nowait=False):
"""
Returns a new QuerySet instance that will select objects with a
FOR UPDATE lock.
"""
obj = self._clone()
obj._for_write = True
obj.query.select_for_update = True
obj.query.select_for_update_nowait = nowait
return obj

def select_related(self, *fields):
"""
Returns a new QuerySet instance that will select related objects.

If fields are specified, they must be ForeignKey fields and only those
related objects are included in the selection.

If select_related(None) is called, the list is cleared.
"""

if self._fields is not None:
raise TypeError("Cannot call select_related() after .values() or .values_list()")

obj = self._clone()
if fields == (None,):
obj.query.select_related = False
elif fields:
obj.query.add_select_related(fields)
else:
obj.query.select_related = True
return obj

def prefetch_related(self, *lookups):
"""
Returns a new QuerySet instance that will prefetch the specified
Many-To-One and Many-To-Many related objects when the QuerySet is
evaluated.

When prefetch_related() is called more than once, the list of lookups to
prefetch is appended to. If prefetch_related(None) is called, the list
is cleared.
"""
clone = self._clone()
if lookups == (None,):
clone._prefetch_related_lookups = []
else:
clone._prefetch_related_lookups.extend(lookups)
return clone

def annotate(self, *args, **kwargs):
"""
Return a query set in which the returned objects have been annotated
with extra data or aggregations.
"""
annotations = OrderedDict()  # To preserve ordering of args
for arg in args:
# The default_alias property may raise a TypeError, so we use
# a try/except construct rather than hasattr in order to remain
# consistent between PY2 and PY3 (hasattr would swallow
# the TypeError on PY2).
try:
if arg.default_alias in kwargs:
raise ValueError("The named annotation '%s' conflicts with the "
"default name for another annotation."
% arg.default_alias)
except (AttributeError, TypeError):
raise TypeError("Complex annotations require an alias")
annotations[arg.default_alias] = arg
annotations.update(kwargs)

clone = self._clone()
names = self._fields
if names is None:
names = {f.name for f in self.model._meta.get_fields()}

for alias, annotation in annotations.items():
if alias in names:
raise ValueError("The annotation '%s' conflicts with a field on "
"the model." % alias)
clone.query.add_annotation(annotation, alias, is_summary=False)

for alias, annotation in clone.query.annotations.items():
if alias in annotations and annotation.contains_aggregate:
if clone._fields is None:
clone.query.group_by = True
else:
clone.query.set_group_by()
break

return clone

def order_by(self, *field_names):
"""
Returns a new QuerySet instance with the ordering changed.
"""
assert self.query.can_filter(), \
"Cannot reorder a query once a slice has been taken."
obj = self._clone()
obj.query.clear_ordering(force_empty=False)
obj.query.add_ordering(*field_names)
return obj

def distinct(self, *field_names):
"""
Returns a new QuerySet instance that will select only distinct results.
"""
assert self.query.can_filter(), \
"Cannot create distinct fields once a slice has been taken."
obj = self._clone()
obj.query.add_distinct_fields(*field_names)
return obj

def extra(self, select=None, where=None, params=None, tables=None,
order_by=None, select_params=None):
"""
Adds extra SQL fragments to the query.
"""
assert self.query.can_filter(), \
"Cannot change a query once a slice has been taken"
clone = self._clone()
clone.query.add_extra(select, select_params, where, params, tables, order_by)
return clone

def reverse(self):
"""
Reverses the ordering of the QuerySet.
"""
clone = self._clone()
clone.query.standard_ordering = not clone.query.standard_ordering
return clone

def defer(self, *fields):
"""
Defers the loading of data for certain fields until they are accessed.
The set of fields to defer is added to any existing set of deferred
fields. The only exception to this is if None is passed in as the only
parameter, in which case all deferrals are removed (None acts as a
reset option).
"""
if self._fields is not None:
raise TypeError("Cannot call defer() after .values() or .values_list()")
clone = self._clone()
if fields == (None,):
clone.query.clear_deferred_loading()
else:
clone.query.add_deferred_loading(fields)
return clone

def only(self, *fields):
"""
Essentially, the opposite of defer. Only the fields passed into this
method and that are not already specified as deferred are loaded
immediately when the queryset is evaluated.
"""
if self._fields is not None:
raise TypeError("Cannot call only() after .values() or .values_list()")
if fields == (None,):
# Can only pass None to defer(), not only(), as the rest option.
# That won't stop people trying to do this, so let's be explicit.
raise TypeError("Cannot pass None as an argument to only().")
clone = self._clone()
clone.query.add_immediate_loading(fields)
return clone

def using(self, alias):
"""
Selects which database this QuerySet should execute its query against.
"""
clone = self._clone()
clone._db = alias
return clone

###################################
# PUBLIC INTROSPECTION ATTRIBUTES #
###################################

def ordered(self):
"""
Returns True if the QuerySet is ordered -- i.e. has an order_by()
clause or a default ordering on the model.
"""
if self.query.extra_order_by or self.query.order_by:
return True
elif self.query.default_ordering and self.query.get_meta().ordering:
return True
else:
return False
ordered = property(ordered)

@property
def db(self):
"Return the database that will be used if this query is executed now"
if self._for_write:
return self._db or router.db_for_write(self.model, **self._hints)
return self._db or router.db_for_read(self.model, **self._hints)

###################
# PRIVATE METHODS #
###################

def _insert(self, objs, fields, return_id=False, raw=False, using=None):
"""
Inserts a new record for the given model. This provides an interface to
the InsertQuery class and is how Model.save() is implemented.
"""
self._for_write = True
if using is None:
using = self.db
query = sql.InsertQuery(self.model)
query.insert_values(fields, objs, raw=raw)
return query.get_compiler(using=using).execute_sql(return_id)
_insert.alters_data = True
_insert.queryset_only = False

def _batched_insert(self, objs, fields, batch_size):
"""
A little helper method for bulk_insert to insert the bulk one batch
at a time. Inserts recursively a batch from the front of the bulk and
then _batched_insert() the remaining objects again.
"""
if not objs:
return
ops = connections[self.db].ops
batch_size = (batch_size or max(ops.bulk_batch_size(fields, objs), 1))
for batch in [objs[i:i + batch_size]
for i in range(0, len(objs), batch_size)]:
self.model._base_manager._insert(batch, fields=fields,
using=self.db)

def _clone(self, **kwargs):
query = self.query.clone()
if self._sticky_filter:
query.filter_is_sticky = True
clone = self.__class__(model=self.model, query=query, using=self._db, hints=self._hints)
clone._for_write = self._for_write
clone._prefetch_related_lookups = self._prefetch_related_lookups[:]
clone._known_related_objects = self._known_related_objects
clone._iterable_class = self._iterable_class
clone._fields = self._fields

clone.__dict__.update(kwargs)
return clone

def _fetch_all(self):
if self._result_cache is None:
self._result_cache = list(self.iterator())
if self._prefetch_related_lookups and not self._prefetch_done:
self._prefetch_related_objects()

def _next_is_sticky(self):
"""
Indicates that the next filter call and the one following that should
be treated as a single filter. This is only important when it comes to
determining when to reuse tables for many-to-many filters. Required so
that we can filter naturally on the results of related managers.

This doesn't return a clone of the current QuerySet (it returns
"self"). The method is only used internally and should be immediately
followed by a filter() that does create a clone.
"""
self._sticky_filter = True
return self

def _merge_sanity_check(self, other):
"""
Checks that we are merging two comparable QuerySet classes.
"""
if self._fields is not None and (
set(self.query.values_select) != set(other.query.values_select) or
set(self.query.extra_select) != set(other.query.extra_select) or
set(self.query.annotation_select) != set(other.query.annotation_select)):
raise TypeError("Merging '%s' classes must involve the same values in each case."
% self.__class__.__name__)

def _merge_known_related_objects(self, other):
"""
Keep track of all known related objects from either QuerySet instance.
"""
for field, objects in other._known_related_objects.items():
self._known_related_objects.setdefault(field, {}).update(objects)

def _prepare(self, field):
if self._fields is not None:
# values() queryset can only be used as nested queries
# if they are set up to select only a single field.
if len(self._fields or self.model._meta.concrete_fields) > 1:
raise TypeError('Cannot use multi-field values as a filter value.')
elif self.model != field.model:
# If the query is used as a subquery for a ForeignKey with non-pk
# target field, make sure to select the target field in the subquery.
foreign_fields = getattr(field, 'foreign_related_fields', ())
if len(foreign_fields) == 1 and not foreign_fields[0].primary_key:
return self.values(foreign_fields[0].name)
return self

def _as_sql(self, connection):
"""
Returns the internal query's SQL and parameters (as a tuple).
"""
if self._fields is not None:
# values() queryset can only be used as nested queries
# if they are set up to select only a single field.
if len(self._fields or self.model._meta.concrete_fields) > 1:
raise TypeError('Cannot use multi-field values as a filter value.')
clone = self._clone()
else:
clone = self.values('pk')

if clone._db is None or connection == connections[clone._db]:
return clone.query.get_compiler(connection=connection).as_nested_sql()
raise ValueError("Can't do subqueries with queries on different DBs.")

# When used as part of a nested query, a queryset will never be an "always
# empty" result.
value_annotation = True

def _add_hints(self, **hints):
"""
Update hinting information for later use by Routers
"""
# If there is any hinting information, add it to what we already know.
# If we have a new hint for an existing key, overwrite with the new value.
self._hints.update(hints)

def _has_filters(self):
"""
Checks if this QuerySet has any filtering going on. Note that this
isn't equivalent for checking if all objects are present in results,
for example qs[1:]._has_filters() -> False.
"""
return self.query.has_filters()

def is_compatible_query_object_type(self, opts, field):
"""
Check that using this queryset as the rhs value for a lookup is
allowed. The opts are the options of the relation's target we are
querying against. For example in .filter(author__in=Author.objects.all())
the opts would be Author's (from the author field) and self.model would
be Author.objects.all() queryset's .model (Author also). The field is
the related field on the lhs side.
"""
# We trust that users of values() know what they are doing.
if self._fields is not None:
return True
return check_rel_lookup_compatibility(self.model, opts, field)
is_compatible_query_object_type.queryset_only = True

class InstanceCheckMeta(type):
def __instancecheck__(self, instance):
return instance.query.is_empty()

class EmptyQuerySet(six.with_metaclass(InstanceCheckMeta)):
"""
Marker class usable for checking if a queryset is empty by .none():
isinstance(qs.none(), EmptyQuerySet) -> True
"""

def __init__(self, *args, **kwargs):
raise TypeError("EmptyQuerySet can't be instantiated")

class RawQuerySet(object):
"""
Provides an iterator which converts the results of raw SQL queries into
annotated model instances.
"""
def __init__(self, raw_query, model=None, query=None, params=None,
translations=None, using=None, hints=None):
self.raw_query = raw_query
self.model = model
self._db = using
self._hints = hints or {}
self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params)
self.params = params or ()
self.translations = translations or {}

def resolve_model_init_order(self):
"""
Resolve the init field names and value positions
"""
model_init_fields = [f for f in self.model._meta.fields if f.column in self.columns]
annotation_fields = [(column, pos) for pos, column in enumerate(self.columns)
if column not in self.model_fields]
model_init_order = [self.columns.index(f.column) for f in model_init_fields]
model_init_names = [f.attname for f in model_init_fields]
return model_init_names, model_init_order, annotation_fields

def __iter__(self):
# Cache some things for performance reasons outside the loop.
db = self.db
compiler = connections[db].ops.compiler('SQLCompiler')(
self.query, connections[db], db
)

query = iter(self.query)

try:
model_init_names, model_init_pos, annotation_fields = self.resolve_model_init_order()

# Find out which model's fields are not present in the query.
skip = set()
for field in self.model._meta.fields:
if field.attname not in model_init_names:
skip.add(field.attname)
if skip:
if self.model._meta.pk.attname in skip:
raise InvalidQuery('Raw query must include the primary key')
model_cls = deferred_class_factory(self.model, skip)
else:
model_cls = self.model
fields = [self.model_fields.get(c) for c in self.columns]
converters = compiler.get_converters([
f.get_col(f.model._meta.db_table) if f else None for f in fields
])
for values in query:
if converters:
values = compiler.apply_converters(values, converters)
# Associate fields to values
model_init_values = [values[pos] for pos in model_init_pos]
instance = model_cls.from_db(db, model_init_names, model_init_values)
if annotation_fields:
for column, pos in annotation_fields:
setattr(instance, column, values[pos])
yield instance
finally:
# Done iterating the Query. If it has its own cursor, close it.
if hasattr(self.query, 'cursor') and self.query.cursor:
self.query.cursor.close()

def __repr__(self):
return "<RawQuerySet: %s>" % self.query

def __getitem__(self, k):
return list(self)[k]

@property
def db(self):
"Return the database that will be used if this query is executed now"
return self._db or router.db_for_read(self.model, **self._hints)

def using(self, alias):
"""
Selects which database this Raw QuerySet should execute its query against.
"""
return RawQuerySet(self.raw_query, model=self.model,
query=self.query.clone(using=alias),
params=self.params, translations=self.translations,
using=alias)

@property
def columns(self):
"""
A list of model field names in the order they'll appear in the
query results.
"""
if not hasattr(self, '_columns'):
self._columns = self.query.get_columns()

# Adjust any column names which don't match field names
for (query_name, model_name) in self.translations.items():
try:
index = self._columns.index(query_name)
self._columns[index] = model_name
except ValueError:
# Ignore translations for non-existent column names
pass

return self._columns

@property
def model_fields(self):
"""
A dict mapping column names to model field names.
"""
if not hasattr(self, '_model_fields'):
converter = connections[self.db].introspection.table_name_converter
self._model_fields = {}
for field in self.model._meta.fields:
name, column = field.get_attname_column()
self._model_fields[converter(column)] = field
return self._model_fields

[docs]class Prefetch(object):
def __init__(self, lookup, queryset=None, to_attr=None):
# `prefetch_through` is the path we traverse to perform the prefetch.
self.prefetch_through = lookup
# `prefetch_to` is the path to the attribute that stores the result.
self.prefetch_to = lookup
if to_attr:
self.prefetch_to = LOOKUP_SEP.join(lookup.split(LOOKUP_SEP)[:-1] + [to_attr])

self.queryset = queryset
self.to_attr = to_attr

def add_prefix(self, prefix):
self.prefetch_through = LOOKUP_SEP.join([prefix, self.prefetch_through])
self.prefetch_to = LOOKUP_SEP.join([prefix, self.prefetch_to])

def get_current_prefetch_through(self, level):
return LOOKUP_SEP.join(self.prefetch_through.split(LOOKUP_SEP)[:level + 1])

def get_current_prefetch_to(self, level):
return LOOKUP_SEP.join(self.prefetch_to.split(LOOKUP_SEP)[:level + 1])

def get_current_to_attr(self, level):
parts = self.prefetch_to.split(LOOKUP_SEP)
to_attr = parts[level]
as_attr = self.to_attr and level == len(parts) - 1
return to_attr, as_attr

def get_current_queryset(self, level):
if self.get_current_prefetch_to(level) == self.prefetch_to:
return self.queryset
return None

def __eq__(self, other):
if isinstance(other, Prefetch):
return self.prefetch_to == other.prefetch_to
return False

def __hash__(self):
return hash(self.__class__) ^ hash(self.prefetch_to)

def normalize_prefetch_lookups(lookups, prefix=None):
"""
Helper function that normalize lookups into Prefetch objects.
"""
ret = []
for lookup in lookups:
if not isinstance(lookup, Prefetch):
lookup = Prefetch(lookup)
if prefix:
lookup.add_prefix(prefix)
ret.append(lookup)
return ret

def prefetch_related_objects(result_cache, related_lookups):
"""
Helper function for prefetch_related functionality

Populates prefetched objects caches for a list of results
from a QuerySet
"""

if len(result_cache) == 0:
return  # nothing to do

related_lookups = normalize_prefetch_lookups(related_lookups)

# We need to be able to dynamically add to the list of prefetch_related
# lookups that we look up (see below).  So we need some book keeping to
# ensure we don't do duplicate work.
done_queries = {}    # dictionary of things like 'foo__bar': [results]

auto_lookups = set()  # we add to this as we go through.
followed_descriptors = set()  # recursion protection

all_lookups = deque(related_lookups)
while all_lookups:
lookup = all_lookups.popleft()
if lookup.prefetch_to in done_queries:
if lookup.queryset:
raise ValueError("'%s' lookup was already seen with a different queryset. "
"You may need to adjust the ordering of your lookups." % lookup.prefetch_to)

continue

# Top level, the list of objects to decorate is the result cache
# from the primary QuerySet. It won't be for deeper levels.
obj_list = result_cache

through_attrs = lookup.prefetch_through.split(LOOKUP_SEP)
for level, through_attr in enumerate(through_attrs):
# Prepare main instances
if len(obj_list) == 0:
break

prefetch_to = lookup.get_current_prefetch_to(level)
if prefetch_to in done_queries:
# Skip any prefetching, and any object preparation
obj_list = done_queries[prefetch_to]
continue

# Prepare objects:
good_objects = True
for obj in obj_list:
# Since prefetching can re-use instances, it is possible to have
# the same instance multiple times in obj_list, so obj might
# already be prepared.
if not hasattr(obj, '_prefetched_objects_cache'):
try:
obj._prefetched_objects_cache = {}
except AttributeError:
# Must be in a QuerySet subclass that is not returning
# Model instances, either in Django or 3rd
# party. prefetch_related() doesn't make sense, so quit
# now.
good_objects = False
break
if not good_objects:
break

# Descend down tree

# We assume that objects retrieved are homogeneous (which is the premise
# of prefetch_related), so what applies to first object applies to all.
first_obj = obj_list[0]
prefetcher, descriptor, attr_found, is_fetched = get_prefetcher(first_obj, through_attr)

if not attr_found:
raise AttributeError("Cannot find '%s' on %s object, '%s' is an invalid "
"parameter to prefetch_related()" %
(through_attr, first_obj.__class__.__name__, lookup.prefetch_through))

if level == len(through_attrs) - 1 and prefetcher is None:
# Last one, this *must* resolve to something that supports
# prefetching, otherwise there is no point adding it and the
# developer asking for it has made a mistake.
raise ValueError("'%s' does not resolve to an item that supports "
"prefetching - this is an invalid parameter to "
"prefetch_related()." % lookup.prefetch_through)

if prefetcher is not None and not is_fetched:
obj_list, additional_lookups = prefetch_one_level(obj_list, prefetcher, lookup, level)
# We need to ensure we don't keep adding lookups from the
# same relationships to stop infinite recursion. So, if we
# are already on an automatically added lookup, don't add
# the new lookups from relationships we've seen already.
if not (lookup in auto_lookups and descriptor in followed_descriptors):
done_queries[prefetch_to] = obj_list
new_lookups = normalize_prefetch_lookups(additional_lookups, prefetch_to)
auto_lookups.update(new_lookups)
all_lookups.extendleft(new_lookups)
followed_descriptors.add(descriptor)
else:
# Either a singly related object that has already been fetched
# (e.g. via select_related), or hopefully some other property
# that doesn't support prefetching but needs to be traversed.

# We replace the current list of parent objects with the list
# of related objects, filtering out empty or missing values so
# that we can continue with nullable or reverse relations.
new_obj_list = []
for obj in obj_list:
try:
new_obj = getattr(obj, through_attr)
except exceptions.ObjectDoesNotExist:
continue
if new_obj is None:
continue
# We special-case `list` rather than something more generic
# like `Iterable` because we don't want to accidentally match
# user models that define __iter__.
if isinstance(new_obj, list):
new_obj_list.extend(new_obj)
else:
new_obj_list.append(new_obj)
obj_list = new_obj_list

def get_prefetcher(instance, attr):
"""
For the attribute 'attr' on the given instance, finds
an object that has a get_prefetch_queryset().
Returns a 4 tuple containing:
(the object with get_prefetch_queryset (or None),
the descriptor object representing this relationship (or None),
a boolean that is False if the attribute was not found at all,
a boolean that is True if the attribute has already been fetched)
"""
prefetcher = None
is_fetched = False

# For singly related objects, we have to avoid getting the attribute
# from the object, as this will trigger the query. So we first try
# on the class, in order to get the descriptor object.
rel_obj_descriptor = getattr(instance.__class__, attr, None)
if rel_obj_descriptor is None:
attr_found = hasattr(instance, attr)
else:
attr_found = True
if rel_obj_descriptor:
# singly related object, descriptor object has the
# get_prefetch_queryset() method.
if hasattr(rel_obj_descriptor, 'get_prefetch_queryset'):
prefetcher = rel_obj_descriptor
if rel_obj_descriptor.is_cached(instance):
is_fetched = True
else:
# descriptor doesn't support prefetching, so we go ahead and get
# the attribute on the instance rather than the class to
# support many related managers
rel_obj = getattr(instance, attr)
if hasattr(rel_obj, 'get_prefetch_queryset'):
prefetcher = rel_obj
return prefetcher, rel_obj_descriptor, attr_found, is_fetched

def prefetch_one_level(instances, prefetcher, lookup, level):
"""
Helper function for prefetch_related_objects

Runs prefetches on all instances using the prefetcher object,
assigning results to relevant caches in instance.

The prefetched objects are returned, along with any additional
prefetches that must be done due to prefetch_related lookups
found from default managers.
"""
# prefetcher must have a method get_prefetch_queryset() which takes a list
# of instances, and returns a tuple:

# (queryset of instances of self.model that are related to passed in instances,
#  callable that gets value to be matched for returned instances,
#  callable that gets value to be matched for passed in instances,
#  boolean that is True for singly related objects,
#  cache name to assign to).

# The 'values to be matched' must be hashable as they will be used
# in a dictionary.

rel_qs, rel_obj_attr, instance_attr, single, cache_name = (
prefetcher.get_prefetch_queryset(instances, lookup.get_current_queryset(level)))
# We have to handle the possibility that the QuerySet we just got back
# contains some prefetch_related lookups. We don't want to trigger the
# prefetch_related functionality by evaluating the query. Rather, we need
# to merge in the prefetch_related lookups.
# Copy the lookups in case it is a Prefetch object which could be reused
# later (happens in nested prefetch_related).
additional_lookups = [
copy.copy(additional_lookup) for additional_lookup
in getattr(rel_qs, '_prefetch_related_lookups', [])
]
if additional_lookups:
# Don't need to clone because the manager should have given us a fresh
# instance, so we access an internal instead of using public interface
# for performance reasons.
rel_qs._prefetch_related_lookups = []

all_related_objects = list(rel_qs)

rel_obj_cache = {}
for rel_obj in all_related_objects:
rel_attr_val = rel_obj_attr(rel_obj)
rel_obj_cache.setdefault(rel_attr_val, []).append(rel_obj)

to_attr, as_attr = lookup.get_current_to_attr(level)
# Make sure `to_attr` does not conflict with a field.
if as_attr and instances:
# We assume that objects retrieved are homogeneous (which is the premise
# of prefetch_related), so what applies to first object applies to all.
model = instances[0].__class__
try:
model._meta.get_field(to_attr)
except exceptions.FieldDoesNotExist:
pass
else:
msg = 'to_attr={} conflicts with a field on the {} model.'
raise ValueError(msg.format(to_attr, model.__name__))

for obj in instances:
instance_attr_val = instance_attr(obj)
vals = rel_obj_cache.get(instance_attr_val, [])

if single:
val = vals[0] if vals else None
to_attr = to_attr if as_attr else cache_name
setattr(obj, to_attr, val)
else:
if as_attr:
setattr(obj, to_attr, vals)
else:
# Cache in the QuerySet.all().
qs = getattr(obj, to_attr).all()
qs._result_cache = vals
# We don't want the individual qs doing prefetch_related now,
# since we have merged this into the current work.
qs._prefetch_done = True
obj._prefetched_objects_cache[cache_name] = qs
return all_related_objects, additional_lookups

class RelatedPopulator(object):
"""
RelatedPopulator is used for select_related() object instantiation.

The idea is that each select_related() model will be populated by a
different RelatedPopulator instance. The RelatedPopulator instances get
klass_info and select (computed in SQLCompiler) plus the used db as
input for initialization. That data is used to compute which columns
to use, how to instantiate the model, and how to populate the links
between the objects.

The actual creation of the objects is done in populate() method. This
method gets row and from_obj as input and populates the select_related()
model instance.
"""
def __init__(self, klass_info, select, db):
self.db = db
# Pre-compute needed attributes. The attributes are:
#  - model_cls: the possibly deferred model class to instantiate
#  - either:
#    - cols_start, cols_end: usually the columns in the row are
#      in the same order model_cls.__init__ expects them, so we
#      can instantiate by model_cls(*row[cols_start:cols_end])
#    - reorder_for_init: When select_related descends to a child
#      class, then we want to reuse the already selected parent
#      data. However, in this case the parent data isn't necessarily
#      in the same order that Model.__init__ expects it to be, so
#      we have to reorder the parent data. The reorder_for_init
#      attribute contains a function used to reorder the field data
#      in the order __init__ expects it.
#  - pk_idx: the index of the primary key field in the reordered
#    model data. Used to check if a related object exists at all.
#  - init_list: the field attnames fetched from the database. For
#    deferred models this isn't the same as all attnames of the
#    model's fields.
#  - related_populators: a list of RelatedPopulator instances if
#    select_related() descends to related models from this model.
#  - cache_name, reverse_cache_name: the names to use for setattr
#    when assigning the fetched object to the from_obj. If the
#    reverse_cache_name is set, then we also set the reverse link.
select_fields = klass_info['select_fields']
from_parent = klass_info['from_parent']
if not from_parent:
self.cols_start = select_fields[0]
self.cols_end = select_fields[-1] + 1
self.init_list = [
f[0].target.attname for f in select[self.cols_start:self.cols_end]
]
self.reorder_for_init = None
else:
model_init_attnames = [
f.attname for f in klass_info['model']._meta.concrete_fields
]
reorder_map = []
for idx in select_fields:
field = select[idx][0].target
init_pos = model_init_attnames.index(field.attname)
reorder_map.append((init_pos, field.attname, idx))
reorder_map.sort()
self.init_list = [v[1] for v in reorder_map]
pos_list = [row_pos for _, _, row_pos in reorder_map]

def reorder_for_init(row):
return [row[row_pos] for row_pos in pos_list]
self.reorder_for_init = reorder_for_init

self.model_cls = self.get_deferred_cls(klass_info, self.init_list)
self.pk_idx = self.init_list.index(self.model_cls._meta.pk.attname)
self.related_populators = get_related_populators(klass_info, select, self.db)
field = klass_info['field']
reverse = klass_info['reverse']
self.reverse_cache_name = None
if reverse:
self.cache_name = field.remote_field.get_cache_name()
self.reverse_cache_name = field.get_cache_name()
else:
self.cache_name = field.get_cache_name()
if field.unique:
self.reverse_cache_name = field.remote_field.get_cache_name()

def get_deferred_cls(self, klass_info, init_list):
model_cls = klass_info['model']
if len(init_list) != len(model_cls._meta.concrete_fields):
init_set = set(init_list)
skip = [
f.attname for f in model_cls._meta.concrete_fields
if f.attname not in init_set
]
model_cls = deferred_class_factory(model_cls, skip)
return model_cls

def populate(self, row, from_obj):
if self.reorder_for_init:
obj_data = self.reorder_for_init(row)
else:
obj_data = row[self.cols_start:self.cols_end]
if obj_data[self.pk_idx] is None:
obj = None
else:
obj = self.model_cls.from_db(self.db, self.init_list, obj_data)
if obj and self.related_populators:
for rel_iter in self.related_populators:
rel_iter.populate(row, obj)
setattr(from_obj, self.cache_name, obj)
if obj and self.reverse_cache_name:
setattr(obj, self.reverse_cache_name, from_obj)

def get_related_populators(klass_info, select, db):
iterators = []
related_klass_infos = klass_info.get('related_klass_infos', [])
for rel_klass_info in related_klass_infos:
rel_cls = RelatedPopulator(rel_klass_info, select, db)
iterators.append(rel_cls)
return iterators

Source code for django.db.models.deletion

from collections import Counter, OrderedDict
from itertools import chain
from operator import attrgetter

from django.db import IntegrityError, connections, transaction
from django.db.models import signals, sql
from django.utils import six

class ProtectedError(IntegrityError):
def __init__(self, msg, protected_objects):
self.protected_objects = protected_objects
super(ProtectedError, self).__init__(msg, protected_objects)

[docs]def CASCADE(collector, field, sub_objs, using):
collector.collect(sub_objs, source=field.remote_field.model,
source_attr=field.name, nullable=field.null)
if field.null and not connections[using].features.can_defer_constraint_checks:
collector.add_field_update(field, None, sub_objs)

[docs]def PROTECT(collector, field, sub_objs, using):
raise ProtectedError("Cannot delete some instances of model '%s' because "
"they are referenced through a protected foreign key: '%s.%s'" % (
field.remote_field.model.__name__, sub_objs[0].__class__.__name__, field.name
),
sub_objs
)

[docs]def SET(value):
if callable(value):
def set_on_delete(collector, field, sub_objs, using):
collector.add_field_update(field, value(), sub_objs)
else:
def set_on_delete(collector, field, sub_objs, using):
collector.add_field_update(field, value, sub_objs)
set_on_delete.deconstruct = lambda: ('django.db.models.SET', (value,), {})
return set_on_delete

[docs]def SET_NULL(collector, field, sub_objs, using):
collector.add_field_update(field, None, sub_objs)

[docs]def SET_DEFAULT(collector, field, sub_objs, using):
collector.add_field_update(field, field.get_default(), sub_objs)

[docs]def DO_NOTHING(collector, field, sub_objs, using):
pass

def get_candidate_relations_to_delete(opts):
# Collect models that contain candidate relations to delete. This may include
# relations coming from proxy models.
candidate_models = {opts}
candidate_models = candidate_models.union(opts.concrete_model._meta.proxied_children)
# For each model, get all candidate fields.
candidate_model_fields = set(chain.from_iterable(
opts.get_fields(include_hidden=True) for opts in candidate_models
))
# The candidate relations are the ones that come from N-1 and 1-1 relations.
# N-N  (i.e., many-to-many) relations aren't candidates for deletion.
return (
f for f in candidate_model_fields
if f.auto_created and not f.concrete and (f.one_to_one or f.one_to_many)
)

class Collector(object):
def __init__(self, using):
self.using = using
# Initially, {model: {instances}}, later values become lists.
self.data = {}
self.field_updates = {}  # {model: {(field, value): {instances}}}
# fast_deletes is a list of queryset-likes that can be deleted without
# fetching the objects into memory.
self.fast_deletes = []

# Tracks deletion-order dependency for databases without transactions
# or ability to defer constraint checks. Only concrete model classes
# should be included, as the dependencies exist only between actual
# database tables; proxy models are represented here by their concrete
# parent.
self.dependencies = {}  # {model: {models}}

def add(self, objs, source=None, nullable=False, reverse_dependency=False):
"""
Adds 'objs' to the collection of objects to be deleted.  If the call is
the result of a cascade, 'source' should be the model that caused it,
and 'nullable' should be set to True if the relation can be null.

Returns a list of all objects that were not already collected.
"""
if not objs:
return []
new_objs = []
model = objs[0].__class__
instances = self.data.setdefault(model, set())
for obj in objs:
if obj not in instances:
new_objs.append(obj)
instances.update(new_objs)
# Nullable relationships can be ignored -- they are nulled out before
# deleting, and therefore do not affect the order in which objects have
# to be deleted.
if source is not None and not nullable:
if reverse_dependency:
source, model = model, source
self.dependencies.setdefault(
source._meta.concrete_model, set()).add(model._meta.concrete_model)
return new_objs

def add_field_update(self, field, value, objs):
"""
Schedules a field update. 'objs' must be a homogeneous iterable
collection of model instances (e.g. a QuerySet).
"""
if not objs:
return
model = objs[0].__class__
self.field_updates.setdefault(
model, {}).setdefault(
(field, value), set()).update(objs)

def can_fast_delete(self, objs, from_field=None):
"""
Determines if the objects in the given queryset-like can be
fast-deleted. This can be done if there are no cascades, no
parents and no signal listeners for the object class.

The 'from_field' tells where we are coming from - we need this to
determine if the objects are in fact to be deleted. Allows also
skipping parent -> child -> parent chain preventing fast delete of
the child.
"""
if from_field and from_field.remote_field.on_delete is not CASCADE:
return False
if not (hasattr(objs, 'model') and hasattr(objs, '_raw_delete')):
return False
model = objs.model
if (signals.pre_delete.has_listeners(model)
or signals.post_delete.has_listeners(model)
or signals.m2m_changed.has_listeners(model)):
return False
# The use of from_field comes from the need to avoid cascade back to
# parent when parent delete is cascading to child.
opts = model._meta
if any(link != from_field for link in opts.concrete_model._meta.parents.values()):
return False
# Foreign keys pointing to this model, both from m2m and other
# models.
for related in get_candidate_relations_to_delete(opts):
if related.field.remote_field.on_delete is not DO_NOTHING:
return False
for field in model._meta.virtual_fields:
if hasattr(field, 'bulk_related_objects'):
# It's something like generic foreign key.
return False
return True

def get_del_batches(self, objs, field):
"""
Returns the objs in suitably sized batches for the used connection.
"""
conn_batch_size = max(
connections[self.using].ops.bulk_batch_size([field.name], objs), 1)
if len(objs) > conn_batch_size:
return [objs[i:i + conn_batch_size]
for i in range(0, len(objs), conn_batch_size)]
else:
return [objs]

def collect(self, objs, source=None, nullable=False, collect_related=True,
source_attr=None, reverse_dependency=False, keep_parents=False):
"""
Adds 'objs' to the collection of objects to be deleted as well as all
parent instances.  'objs' must be a homogeneous iterable collection of
model instances (e.g. a QuerySet).  If 'collect_related' is True,
related objects will be handled by their respective on_delete handler.

If the call is the result of a cascade, 'source' should be the model
that caused it and 'nullable' should be set to True, if the relation
can be null.

If 'reverse_dependency' is True, 'source' will be deleted before the
current model, rather than after. (Needed for cascading to parent
models, the one case in which the cascade follows the forwards
direction of an FK rather than the reverse direction.)

If 'keep_parents' is True, data of parent model's will be not deleted.
"""
if self.can_fast_delete(objs):
self.fast_deletes.append(objs)
return
new_objs = self.add(objs, source, nullable,
reverse_dependency=reverse_dependency)
if not new_objs:
return

model = new_objs[0].__class__

if not keep_parents:
# Recursively collect concrete model's parent models, but not their
# related objects. These will be found by meta.get_fields()
concrete_model = model._meta.concrete_model
for ptr in six.itervalues(concrete_model._meta.parents):
if ptr:
# FIXME: This seems to be buggy and execute a query for each
# parent object fetch. We have the parent data in the obj,
# but we don't have a nice way to turn that data into parent
# object instance.
parent_objs = [getattr(obj, ptr.name) for obj in new_objs]
self.collect(parent_objs, source=model,
source_attr=ptr.remote_field.related_name,
collect_related=False,
reverse_dependency=True)
if collect_related:
for related in get_candidate_relations_to_delete(model._meta):
field = related.field
if field.remote_field.on_delete == DO_NOTHING:
continue
batches = self.get_del_batches(new_objs, field)
for batch in batches:
sub_objs = self.related_objects(related, batch)
if self.can_fast_delete(sub_objs, from_field=field):
self.fast_deletes.append(sub_objs)
elif sub_objs:
field.remote_field.on_delete(self, field, sub_objs, self.using)
for field in model._meta.virtual_fields:
if hasattr(field, 'bulk_related_objects'):
# It's something like generic foreign key.
sub_objs = field.bulk_related_objects(new_objs, self.using)
self.collect(sub_objs, source=model, nullable=True)

def related_objects(self, related, objs):
"""
Gets a QuerySet of objects related to ``objs`` via the relation ``related``.
"""
return related.related_model._base_manager.using(self.using).filter(
**{"%s__in" % related.field.name: objs}
)

def instances_with_model(self):
for model, instances in six.iteritems(self.data):
for obj in instances:
yield model, obj

def sort(self):
sorted_models = []
concrete_models = set()
models = list(self.data)
while len(sorted_models) < len(models):
found = False
for model in models:
if model in sorted_models:
continue
dependencies = self.dependencies.get(model._meta.concrete_model)
if not (dependencies and dependencies.difference(concrete_models)):
sorted_models.append(model)
concrete_models.add(model._meta.concrete_model)
found = True
if not found:
return
self.data = OrderedDict((model, self.data[model])
for model in sorted_models)

def delete(self):
# sort instance collections
for model, instances in self.data.items():
self.data[model] = sorted(instances, key=attrgetter("pk"))

# if possible, bring the models in an order suitable for databases that
# don't support transactions or cannot defer constraint checks until the
# end of a transaction.
self.sort()
# number of objects deleted for each model label
deleted_counter = Counter()

with transaction.atomic(using=self.using, savepoint=False):
# send pre_delete signals
for model, obj in self.instances_with_model():
if not model._meta.auto_created:
signals.pre_delete.send(
sender=model, instance=obj, using=self.using
)

# fast deletes
for qs in self.fast_deletes:
count = qs._raw_delete(using=self.using)
deleted_counter[qs.model._meta.label] += count

# update fields
for model, instances_for_fieldvalues in six.iteritems(self.field_updates):
query = sql.UpdateQuery(model)
for (field, value), instances in six.iteritems(instances_for_fieldvalues):
query.update_batch([obj.pk for obj in instances],
{field.name: value}, self.using)

# reverse instance collections
for instances in six.itervalues(self.data):
instances.reverse()

# delete instances
for model, instances in six.iteritems(self.data):
query = sql.DeleteQuery(model)
pk_list = [obj.pk for obj in instances]
count = query.delete_batch(pk_list, self.using)
deleted_counter[model._meta.label] += count

if not model._meta.auto_created:
for obj in instances:
signals.post_delete.send(
sender=model, instance=obj, using=self.using
)

# update collected instances
for model, instances_for_fieldvalues in six.iteritems(self.field_updates):
for (field, value), instances in six.iteritems(instances_for_fieldvalues):
for obj in instances:
setattr(obj, field.attname, value)
for model, instances in six.iteritems(self.data):
for instance in instances:
setattr(instance, model._meta.pk.attname, None)
return sum(deleted_counter.values()), dict(deleted_counter)

Source code for django.db.models.options

from __future__ import unicode_literals

import warnings
from bisect import bisect
from collections import OrderedDict, defaultdict
from itertools import chain

from django.apps import apps
from django.conf import settings
from django.core.exceptions import FieldDoesNotExist
from django.db import connections
from django.db.models.fields import AutoField
from django.db.models.fields.proxy import OrderWrt
from django.db.models.fields.related import ManyToManyField
from django.utils import six
from django.utils.datastructures import ImmutableList, OrderedSet
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import (
force_text, python_2_unicode_compatible, smart_text,
)
from django.utils.functional import cached_property
from django.utils.lru_cache import lru_cache
from django.utils.text import camel_case_to_spaces
from django.utils.translation import override, string_concat

PROXY_PARENTS = object()

EMPTY_RELATION_TREE = tuple()

IMMUTABLE_WARNING = (
"The return type of '%s' should never be mutated. If you want to manipulate this list "
"for your own use, make a copy first."
)

DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
'unique_together', 'permissions', 'get_latest_by',
'order_with_respect_to', 'app_label', 'db_tablespace',
'abstract', 'managed', 'proxy', 'swappable', 'auto_created',
'index_together', 'apps', 'default_permissions',
'select_on_save', 'default_related_name',
'required_db_features', 'required_db_vendor')

class raise_deprecation(object):
def __init__(self, suggested_alternative):
self.suggested_alternative = suggested_alternative

def __call__(self, fn):
def wrapper(*args, **kwargs):
warnings.warn(
"'%s is an unofficial API that has been deprecated. "
"You may be able to replace it with '%s'" % (
fn.__name__,
self.suggested_alternative,
),
RemovedInDjango110Warning, stacklevel=2
)
return fn(*args, **kwargs)
return wrapper

def normalize_together(option_together):
"""
option_together can be either a tuple of tuples, or a single
tuple of two strings. Normalize it to a tuple of tuples, so that
calling code can uniformly expect that.
"""
try:
if not option_together:
return ()
if not isinstance(option_together, (tuple, list)):
raise TypeError
first_element = next(iter(option_together))
if not isinstance(first_element, (tuple, list)):
option_together = (option_together,)
# Normalize everything to tuples
return tuple(tuple(ot) for ot in option_together)
except TypeError:
# If the value of option_together isn't valid, return it
# verbatim; this will be picked up by the check framework later.
return option_together

def make_immutable_fields_list(name, data):
return ImmutableList(data, warning=IMMUTABLE_WARNING % name)

@python_2_unicode_compatible

[docs]class Options(object):
FORWARD_PROPERTIES = ('fields', 'many_to_many', 'concrete_fields',
'local_concrete_fields', '_forward_fields_map')
REVERSE_PROPERTIES = ('related_objects', 'fields_map', '_relation_tree')

def __init__(self, meta, app_label=None):
self._get_fields_cache = {}
self.proxied_children = []
self.local_fields = []
self.local_many_to_many = []
self.virtual_fields = []
self.model_name = None
self.verbose_name = None
self.verbose_name_plural = None
self.db_table = ''
self.ordering = []
self._ordering_clash = False
self.unique_together = []
self.index_together = []
self.select_on_save = False
self.default_permissions = ('add', 'change', 'delete')
self.permissions = []
self.object_name = None
self.app_label = app_label
self.get_latest_by = None
self.order_with_respect_to = None
self.db_tablespace = settings.DEFAULT_TABLESPACE
self.required_db_features = []
self.required_db_vendor = None
self.meta = meta
self.pk = None
self.has_auto_field = False
self.auto_field = None
self.abstract = False
self.managed = True
self.proxy = False
# For any class that is a proxy (including automatically created
# classes for deferred object loading), proxy_for_model tells us
# which class this model is proxying. Note that proxy_for_model
# can create a chain of proxy models. For non-proxy models, the
# variable is always None.
self.proxy_for_model = None
# For any non-abstract class, the concrete class is the model
# in the end of the proxy_for_model chain. In particular, for
# concrete models, the concrete_model is always the class itself.
self.concrete_model = None
self.swappable = None
self.parents = OrderedDict()
self.auto_created = False

# To handle various inheritance situations, we need to track where
# managers came from (concrete or abstract base classes). `managers`
# keeps a list of 3-tuples of the form:
# (creation_counter, instance, abstract(=True))
self.managers = []

# List of all lookups defined in ForeignKey 'limit_choices_to' options
# from *other* models. Needed for some admin checks. Internal use only.
self.related_fkey_lookups = []

# A custom app registry to use, if you're making a separate model set.
self.apps = apps

self.default_related_name = None

@lru_cache(maxsize=None)
def _map_model(self, link):
# This helper function is used to allow backwards compatibility with
# the previous API. No future methods should use this function.
# It maps a field to (field, model or related_model,) depending on the
# field type.
model = link.model._meta.concrete_model
if model is self.model:
model = None
return link, model

@lru_cache(maxsize=None)
def _map_model_details(self, link):
# This helper function is used to allow backwards compatibility with
# the previous API. No future methods should use this function.
# This function maps a field to a tuple of:
#  (field, model or related_model, direct, is_m2m) depending on the
# field type.
direct = not link.auto_created or link.concrete
model = link.model._meta.concrete_model
if model is self.model:
model = None
m2m = link.is_relation and link.many_to_many
return link, model, direct, m2m

@property
def label(self):
return '%s.%s' % (self.app_label, self.object_name)

@property
def label_lower(self):
return '%s.%s' % (self.app_label, self.model_name)

@property
def app_config(self):
# Don't go through get_app_config to avoid triggering imports.
return self.apps.app_configs.get(self.app_label)

@property
def installed(self):
return self.app_config is not None

@property
def abstract_managers(self):
return [
(counter, instance.name, instance) for counter, instance, abstract
in self.managers if abstract
]

@property
def concrete_managers(self):
return [
(counter, instance.name, instance) for counter, instance, abstract
in self.managers if not abstract
]

def contribute_to_class(self, cls, name):
from django.db import connection
from django.db.backends.utils import truncate_name

cls._meta = self
self.model = cls
# First, construct the default values for these options.
self.object_name = cls.__name__
self.model_name = self.object_name.lower()
self.verbose_name = camel_case_to_spaces(self.object_name)

# Store the original user-defined values for each option,
# for use when serializing the model definition
self.original_attrs = {}

# Next, apply any overridden values from 'class Meta'.
if self.meta:
meta_attrs = self.meta.__dict__.copy()
for name in self.meta.__dict__:
# Ignore any private attributes that Django doesn't care about.
# NOTE: We can't modify a dictionary's contents while looping
# over it, so we loop over the *original* dictionary instead.
if name.startswith('_'):
del meta_attrs[name]
for attr_name in DEFAULT_NAMES:
if attr_name in meta_attrs:
setattr(self, attr_name, meta_attrs.pop(attr_name))
self.original_attrs[attr_name] = getattr(self, attr_name)
elif hasattr(self.meta, attr_name):
setattr(self, attr_name, getattr(self.meta, attr_name))
self.original_attrs[attr_name] = getattr(self, attr_name)

self.unique_together = normalize_together(self.unique_together)
self.index_together = normalize_together(self.index_together)

# verbose_name_plural is a special case because it uses a 's'
# by default.
if self.verbose_name_plural is None:
self.verbose_name_plural = string_concat(self.verbose_name, 's')

# order_with_respect_and ordering are mutually exclusive.
self._ordering_clash = bool(self.ordering and self.order_with_respect_to)

# Any leftover attributes must be invalid.
if meta_attrs != {}:
raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()))
else:
self.verbose_name_plural = string_concat(self.verbose_name, 's')
del self.meta

# If the db_table wasn't provided, use the app_label + model_name.
if not self.db_table:
self.db_table = "%s_%s" % (self.app_label, self.model_name)
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())

def _prepare(self, model):
if self.order_with_respect_to:
# The app registry will not be ready at this point, so we cannot
# use get_field().
query = self.order_with_respect_to
try:
self.order_with_respect_to = next(
f for f in self._get_fields(reverse=False)
if f.name == query or f.attname == query
)
except StopIteration:
raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, query))

self.ordering = ('_order',)
if not any(isinstance(field, OrderWrt) for field in model._meta.local_fields):
model.add_to_class('_order', OrderWrt())
else:
self.order_with_respect_to = None

if self.pk is None:
if self.parents:
# Promote the first parent link in lieu of adding yet another
# field.
field = next(six.itervalues(self.parents))
# Look for a local field with the same name as the
# first parent link. If a local field has already been
# created, use it instead of promoting the parent
already_created = [fld for fld in self.local_fields if fld.name == field.name]
if already_created:
field = already_created[0]
field.primary_key = True
self.setup_pk(field)
else:
auto = AutoField(verbose_name='ID', primary_key=True,
auto_created=True)
model.add_to_class('id', auto)

def add_field(self, field, virtual=False):
# Insert the given field in the order in which it was created, using
# the "creation_counter" attribute of the field.
# Move many-to-many related fields from self.fields into
# self.many_to_many.
if virtual:
self.virtual_fields.append(field)
elif field.is_relation and field.many_to_many:
self.local_many_to_many.insert(bisect(self.local_many_to_many, field), field)
else:
self.local_fields.insert(bisect(self.local_fields, field), field)
self.setup_pk(field)

# If the field being added is a relation to another known field,
# expire the cache on this field and the forward cache on the field
# being referenced, because there will be new relationships in the
# cache. Otherwise, expire the cache of references *to* this field.
# The mechanism for getting at the related model is slightly odd -
# ideally, we'd just ask for field.related_model. However, related_model
# is a cached property, and all the models haven't been loaded yet, so
# we need to make sure we don't cache a string reference.
if field.is_relation and hasattr(field.remote_field, 'model') and field.remote_field.model:
try:
field.remote_field.model._meta._expire_cache(forward=False)
except AttributeError:
pass
self._expire_cache()
else:
self._expire_cache(reverse=False)

def setup_pk(self, field):
if not self.pk and field.primary_key:
self.pk = field
field.serialize = False

def setup_proxy(self, target):
"""
Does the internal setup so that the current model is a proxy for
"target".
"""
self.pk = target._meta.pk
self.proxy_for_model = target
self.db_table = target._meta.db_table

def __repr__(self):
return '<Options for %s>' % self.object_name

def __str__(self):
return "%s.%s" % (smart_text(self.app_label), smart_text(self.model_name))

def can_migrate(self, connection):
"""
Return True if the model can/should be migrated on the `connection`.
`connection` can be either a real connection or a connection alias.
"""
if self.proxy or self.swapped or not self.managed:
return False
if isinstance(connection, six.string_types):
connection = connections[connection]
if self.required_db_vendor:
return self.required_db_vendor == connection.vendor
if self.required_db_features:
return all(getattr(connection.features, feat, False)
for feat in self.required_db_features)
return True

@property
def verbose_name_raw(self):
"""
There are a few places where the untranslated verbose name is needed
(so that we get the same value regardless of currently active
locale).
"""
with override(None):
return force_text(self.verbose_name)

@property
def swapped(self):
"""
Has this model been swapped out for another? If so, return the model
name of the replacement; otherwise, return None.

For historical reasons, model name lookups using get_model() are
case insensitive, so we make sure we are case insensitive here.
"""
if self.swappable:
swapped_for = getattr(settings, self.swappable, None)
if swapped_for:
try:
swapped_label, swapped_object = swapped_for.split('.')
except ValueError:
# setting not in the format app_label.model_name
# raising ImproperlyConfigured here causes problems with
# test cleanup code - instead it is raised in get_user_model
# or as part of validation.
return swapped_for

if '%s.%s' % (swapped_label, swapped_object.lower()) != self.label_lower:
return swapped_for
return None

@cached_property
def fields(self):
"""
Returns a list of all forward fields on the model and its parents,
excluding ManyToManyFields.

Private API intended only to be used by Django itself; get_fields()
combined with filtering of field properties is the public API for
obtaining this field list.
"""
# For legacy reasons, the fields property should only contain forward
# fields that are not virtual or with a m2m cardinality. Therefore we
# pass these three filters as filters to the generator.
# The third lambda is a longwinded way of checking f.related_model - we don't
# use that property directly because related_model is a cached property,
# and all the models may not have been loaded yet; we don't want to cache
# the string reference to the related_model.
is_not_an_m2m_field = lambda f: not (f.is_relation and f.many_to_many)
is_not_a_generic_relation = lambda f: not (f.is_relation and f.one_to_many)
is_not_a_generic_foreign_key = lambda f: not (
f.is_relation and f.many_to_one and not (hasattr(f.remote_field, 'model') and f.remote_field.model)
)
return make_immutable_fields_list(
"fields",
(f for f in self._get_fields(reverse=False) if
is_not_an_m2m_field(f) and is_not_a_generic_relation(f)
and is_not_a_generic_foreign_key(f))
)

@cached_property
def concrete_fields(self):
"""
Returns a list of all concrete fields on the model and its parents.

Private API intended only to be used by Django itself; get_fields()
combined with filtering of field properties is the public API for
obtaining this field list.
"""
return make_immutable_fields_list(
"concrete_fields", (f for f in self.fields if f.concrete)
)

@cached_property
def local_concrete_fields(self):
"""
Returns a list of all concrete fields on the model.

Private API intended only to be used by Django itself; get_fields()
combined with filtering of field properties is the public API for
obtaining this field list.
"""
return make_immutable_fields_list(
"local_concrete_fields", (f for f in self.local_fields if f.concrete)
)

@raise_deprecation(suggested_alternative="get_fields()")
def get_fields_with_model(self):
return [self._map_model(f) for f in self.get_fields()]

@raise_deprecation(suggested_alternative="get_fields()")
def get_concrete_fields_with_model(self):
return [self._map_model(f) for f in self.concrete_fields]

@cached_property
def many_to_many(self):
"""
Returns a list of all many to many fields on the model and its parents.

Private API intended only to be used by Django itself; get_fields()
combined with filtering of field properties is the public API for
obtaining this list.
"""
return make_immutable_fields_list(
"many_to_many",
(f for f in self._get_fields(reverse=False)
if f.is_relation and f.many_to_many)
)

@cached_property
def related_objects(self):
"""
Returns all related objects pointing to the current model. The related
objects can come from a one-to-one, one-to-many, or many-to-many field
relation type.

Private API intended only to be used by Django itself; get_fields()
combined with filtering of field properties is the public API for
obtaining this field list.
"""
all_related_fields = self._get_fields(forward=False, reverse=True, include_hidden=True)
return make_immutable_fields_list(
"related_objects",
(obj for obj in all_related_fields
if not obj.hidden or obj.field.many_to_many)
)

@raise_deprecation(suggested_alternative="get_fields()")
def get_m2m_with_model(self):
return [self._map_model(f) for f in self.many_to_many]

@cached_property
def _forward_fields_map(self):
res = {}
fields = self._get_fields(reverse=False)
for field in fields:
res[field.name] = field
# Due to the way Django's internals work, get_field() should also
# be able to fetch a field by attname. In the case of a concrete
# field with relation, includes the *_id name too
try:
res[field.attname] = field
except AttributeError:
pass
return res

@cached_property
def fields_map(self):
res = {}
fields = self._get_fields(forward=False, include_hidden=True)
for field in fields:
res[field.name] = field
# Due to the way Django's internals work, get_field() should also
# be able to fetch a field by attname. In the case of a concrete
# field with relation, includes the *_id name too
try:
res[field.attname] = field
except AttributeError:
pass
return res

[docs]    def get_field(self, field_name, many_to_many=None):
"""
Returns a field instance given a field name. The field can be either a
forward or reverse field, unless many_to_many is specified; if it is,
only forward fields will be returned.

The many_to_many argument exists for backwards compatibility reasons;
it has been deprecated and will be removed in Django 1.10.
"""
m2m_in_kwargs = many_to_many is not None
if m2m_in_kwargs:
# Always throw a warning if many_to_many is used regardless of
# whether it alters the return type or not.
warnings.warn(
"The 'many_to_many' argument on get_field() is deprecated; "
"use a filter on field.many_to_many instead.",
RemovedInDjango110Warning
)

try:
# In order to avoid premature loading of the relation tree
# (expensive) we prefer checking if the field is a forward field.
field = self._forward_fields_map[field_name]

if many_to_many is False and field.many_to_many:
raise FieldDoesNotExist(
'%s has no field named %r' % (self.object_name, field_name)
)

return field
except KeyError:
# If the app registry is not ready, reverse fields are
# unavailable, therefore we throw a FieldDoesNotExist exception.
if not self.apps.models_ready:
raise FieldDoesNotExist(
"%s has no field named %r. The app cache isn't ready yet, "
"so if this is an auto-created related field, it won't "
"be available yet." % (self.object_name, field_name)
)

try:
if m2m_in_kwargs:
# Previous API does not allow searching reverse fields.
raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, field_name))

# Retrieve field instance by name from cached or just-computed
# field map.
return self.fields_map[field_name]
except KeyError:
raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, field_name))

@raise_deprecation(suggested_alternative="get_field()")
def get_field_by_name(self, name):
return self._map_model_details(self.get_field(name))

@raise_deprecation(suggested_alternative="get_fields()")
def get_all_field_names(self):
names = set()
fields = self.get_fields()
for field in fields:
# For backwards compatibility GenericForeignKey should not be
# included in the results.
if field.is_relation and field.many_to_one and field.related_model is None:
continue
# Relations to child proxy models should not be included.
if (field.model != self.model and
field.model._meta.concrete_model == self.concrete_model):
continue

names.add(field.name)
if hasattr(field, 'attname'):
names.add(field.attname)
return list(names)

@raise_deprecation(suggested_alternative="get_fields()")
def get_all_related_objects(self, local_only=False, include_hidden=False,
include_proxy_eq=False):

include_parents = True if local_only is False else PROXY_PARENTS
fields = self._get_fields(
forward=False, reverse=True,
include_parents=include_parents,
include_hidden=include_hidden,
)
fields = (obj for obj in fields if not isinstance(obj.field, ManyToManyField))
if include_proxy_eq:
children = chain.from_iterable(c._relation_tree
for c in self.concrete_model._meta.proxied_children
if c is not self)
relations = (f.remote_field for f in children
if include_hidden or not f.remote_field.field.remote_field.is_hidden())
fields = chain(fields, relations)
return list(fields)

@raise_deprecation(suggested_alternative="get_fields()")
def get_all_related_objects_with_model(self, local_only=False, include_hidden=False,
include_proxy_eq=False):
return [
self._map_model(f) for f in self.get_all_related_objects(
local_only=local_only,
include_hidden=include_hidden,
include_proxy_eq=include_proxy_eq,
)
]

@raise_deprecation(suggested_alternative="get_fields()")
def get_all_related_many_to_many_objects(self, local_only=False):
include_parents = True if local_only is not True else PROXY_PARENTS
fields = self._get_fields(
forward=False, reverse=True,
include_parents=include_parents, include_hidden=True
)
return [obj for obj in fields if isinstance(obj.field, ManyToManyField)]

@raise_deprecation(suggested_alternative="get_fields()")
def get_all_related_m2m_objects_with_model(self):
fields = self._get_fields(forward=False, reverse=True, include_hidden=True)
return [self._map_model(obj) for obj in fields if isinstance(obj.field, ManyToManyField)]

def get_base_chain(self, model):
"""
Return a list of parent classes leading to `model` (ordered from
closest to most distant ancestor). This has to handle the case where
`model` is a grandparent or even more distant relation.
"""
if not self.parents:
return []
if model in self.parents:
return [model]
for parent in self.parents:
res = parent._meta.get_base_chain(model)
if res:
res.insert(0, parent)
return res
return []

def get_parent_list(self):
"""
Returns all the ancestors of this model as a list ordered by MRO.
Useful for determining if something is an ancestor, regardless of lineage.
"""
result = OrderedSet(self.parents)
for parent in self.parents:
for ancestor in parent._meta.get_parent_list():
result.add(ancestor)
return list(result)

def get_ancestor_link(self, ancestor):
"""
Returns the field on the current model which points to the given
"ancestor". This is possible an indirect link (a pointer to a parent
model, which points, eventually, to the ancestor). Used when
constructing table joins for model inheritance.

Returns None if the model isn't an ancestor of this one.
"""
if ancestor in self.parents:
return self.parents[ancestor]
for parent in self.parents:
# Tries to get a link field from the immediate parent
parent_link = parent._meta.get_ancestor_link(ancestor)
if parent_link:
# In case of a proxied model, the first link
# of the chain to the ancestor is that parent
# links
return self.parents[parent] or parent_link

def _populate_directed_relation_graph(self):
"""
This method is used by each model to find its reverse objects. As this
method is very expensive and is accessed frequently (it looks up every
field in a model, in every app), it is computed on first access and then
is set as a property on every model.
"""
related_objects_graph = defaultdict(list)

all_models = self.apps.get_models(include_auto_created=True)
for model in all_models:
# Abstract model's fields are copied to child models, hence we will
# see the fields from the child models.
if model._meta.abstract:
continue
fields_with_relations = (
f for f in model._meta._get_fields(reverse=False, include_parents=False)
if f.is_relation and f.related_model is not None
)
for f in fields_with_relations:
if not isinstance(f.remote_field.model, six.string_types):
related_objects_graph[f.remote_field.model._meta].append(f)

for model in all_models:
# Set the relation_tree using the internal __dict__. In this way
# we avoid calling the cached property. In attribute lookup,
# __dict__ takes precedence over a data descriptor (such as
# @cached_property). This means that the _meta._relation_tree is
# only called if related_objects is not in __dict__.
related_objects = related_objects_graph[model._meta]
model._meta.__dict__['_relation_tree'] = related_objects
# It seems it is possible that self is not in all_models, so guard
# against that with default for get().
return self.__dict__.get('_relation_tree', EMPTY_RELATION_TREE)

@cached_property
def _relation_tree(self):
return self._populate_directed_relation_graph()

def _expire_cache(self, forward=True, reverse=True):
# This method is usually called by apps.cache_clear(), when the
# registry is finalized, or when a new field is added.
properties_to_expire = []
if forward:
properties_to_expire.extend(self.FORWARD_PROPERTIES)
if reverse and not self.abstract:
properties_to_expire.extend(self.REVERSE_PROPERTIES)

for cache_key in properties_to_expire:
try:
delattr(self, cache_key)
except AttributeError:
pass

self._get_fields_cache = {}

[docs]    def get_fields(self, include_parents=True, include_hidden=False):
"""
Returns a list of fields associated to the model. By default, includes
forward and reverse fields, fields derived from inheritance, but not
hidden fields. The returned fields can be changed using the parameters:

- include_parents: include fields derived from inheritance
- include_hidden:  include fields that have a related_name that
starts with a "+"
"""
if include_parents is False:
include_parents = PROXY_PARENTS
return self._get_fields(include_parents=include_parents, include_hidden=include_hidden)

def _get_fields(self, forward=True, reverse=True, include_parents=True, include_hidden=False,
seen_models=None):
"""
Internal helper function to return fields of the model.
* If forward=True, then fields defined on this model are returned.
* If reverse=True, then relations pointing to this model are returned.
* If include_hidden=True, then fields with is_hidden=True are returned.
* The include_parents argument toggles if fields from parent models
should be included. It has three values: True, False, and
PROXY_PARENTS. When set to PROXY_PARENTS, the call will return all
fields defined for the current model or any of its parents in the
parent chain to the model's concrete model.
"""
if include_parents not in (True, False, PROXY_PARENTS):
raise TypeError("Invalid argument for include_parents: %s" % (include_parents,))
# This helper function is used to allow recursion in ``get_fields()``
# implementation and to provide a fast way for Django's internals to
# access specific subsets of fields.

# We must keep track of which models we have already seen. Otherwise we
# could include the same field multiple times from different models.
topmost_call = False
if seen_models is None:
seen_models = set()
topmost_call = True
seen_models.add(self.model)

# Creates a cache key composed of all arguments
cache_key = (forward, reverse, include_parents, include_hidden, topmost_call)

try:
# In order to avoid list manipulation. Always return a shallow copy
# of the results.
return self._get_fields_cache[cache_key]
except KeyError:
pass

fields = []
# Recursively call _get_fields() on each parent, with the same
# options provided in this call.
if include_parents is not False:
for parent in self.parents:
# In diamond inheritance it is possible that we see the same
# model from two different routes. In that case, avoid adding
# fields from the same parent again.
if parent in seen_models:
continue
if (parent._meta.concrete_model != self.concrete_model and
include_parents == PROXY_PARENTS):
continue
for obj in parent._meta._get_fields(
forward=forward, reverse=reverse, include_parents=include_parents,
include_hidden=include_hidden, seen_models=seen_models):
if hasattr(obj, 'parent_link') and obj.parent_link:
continue
fields.append(obj)
if reverse:
# Tree is computed once and cached until the app cache is expired.
# It is composed of a list of fields pointing to the current model
# from other models.
all_fields = self._relation_tree
for field in all_fields:
# If hidden fields should be included or the relation is not
# intentionally hidden, add to the fields dict.
if include_hidden or not field.remote_field.hidden:
fields.append(field.remote_field)

if forward:
fields.extend(
field for field in chain(self.local_fields, self.local_many_to_many)
)
# Virtual fields are recopied to each child model, and they get a
# different model as field.model in each child. Hence we have to
# add the virtual fields separately from the topmost call. If we
# did this recursively similar to local_fields, we would get field
# instances with field.model != self.model.
if topmost_call:
fields.extend(
f for f in self.virtual_fields
)

# In order to avoid list manipulation. Always
# return a shallow copy of the results
fields = make_immutable_fields_list("get_fields()", fields)

# Store result into cache for later access
self._get_fields_cache[cache_key] = fields
return fields

Source code for django.db.models.fields.related

from __future__ import unicode_literals

import warnings
from functools import partial

from django import forms
from django.apps import apps
from django.core import checks, exceptions
from django.db import connection, router
from django.db.backends import utils
from django.db.models import Q
from django.db.models.deletion import CASCADE, SET_DEFAULT, SET_NULL
from django.db.models.query_utils import PathInfo
from django.db.models.utils import make_model_tuple
from django.utils import six
from django.utils.deprecation import (
RemovedInDjango20Warning, RemovedInDjango110Warning,
)
from django.utils.encoding import force_text, smart_text
from django.utils.functional import cached_property, curry
from django.utils.translation import ugettext_lazy as _
from django.utils.version import get_docs_version

from . import (
AutoField, Field, IntegerField, PositiveIntegerField,
PositiveSmallIntegerField,
)
from .related_descriptors import (
ForwardManyToOneDescriptor, ManyToManyDescriptor,
ReverseManyToOneDescriptor, ReverseOneToOneDescriptor,
)
from .related_lookups import (
RelatedExact, RelatedGreaterThan, RelatedGreaterThanOrEqual, RelatedIn,
RelatedIsNull, RelatedLessThan, RelatedLessThanOrEqual,
)
from .reverse_related import (
ForeignObjectRel, ManyToManyRel, ManyToOneRel, OneToOneRel,
)

RECURSIVE_RELATIONSHIP_CONSTANT = 'self'

def resolve_relation(scope_model, relation):
"""
Transform relation into a model or fully-qualified model string of the form
"app_label.ModelName", relative to scope_model.

The relation argument can be:
* RECURSIVE_RELATIONSHIP_CONSTANT, i.e. the string "self", in which case
the model argument will be returned.
* A bare model name without an app_label, in which case scope_model's
app_label will be prepended.
* An "app_label.ModelName" string.
* A model class, which will be returned unchanged.
"""
# Check for recursive relations
if relation == RECURSIVE_RELATIONSHIP_CONSTANT:
relation = scope_model

# Look for an "app.Model" relation
if isinstance(relation, six.string_types):
if "." not in relation:
relation = "%s.%s" % (scope_model._meta.app_label, relation)

return relation

def lazy_related_operation(function, model, *related_models, **kwargs):
"""
Schedule `function` to be called once `model` and all `related_models`
have been imported and registered with the app registry. `function` will
be called with the newly-loaded model classes as its positional arguments,
plus any optional keyword arguments.

The `model` argument must be a model class. Each subsequent positional
argument is another model, or a reference to another model - see
`resolve_relation()` for the various forms these may take. Any relative
references will be resolved relative to `model`.

This is a convenience wrapper for `Apps.lazy_model_operation` - the app
registry model used is the one found in `model._meta.apps`.
"""
models = [model] + [resolve_relation(model, rel) for rel in related_models]
model_keys = (make_model_tuple(m) for m in models)
apps = model._meta.apps
return apps.lazy_model_operation(partial(function, **kwargs), *model_keys)

def add_lazy_relation(cls, field, relation, operation):
warnings.warn(
"add_lazy_relation() has been superseded by lazy_related_operation() "
"and related methods on the Apps class.",
RemovedInDjango20Warning, stacklevel=2)
# Rearrange args for new Apps.lazy_model_operation
function = lambda local, related, field: operation(field, related, local)
lazy_related_operation(function, cls, relation, field=field)

class RelatedField(Field):
"""
Base class that all relational fields inherit from.
"""

# Field flags
one_to_many = False
one_to_one = False
many_to_many = False
many_to_one = False

@cached_property
def related_model(self):
# Can't cache this property until all the models are loaded.
apps.check_models_ready()
return self.remote_field.model

def check(self, **kwargs):
errors = super(RelatedField, self).check(**kwargs)
errors.extend(self._check_related_name_is_valid())
errors.extend(self._check_relation_model_exists())
errors.extend(self._check_referencing_to_swapped_model())
errors.extend(self._check_clashes())
return errors

def _check_related_name_is_valid(self):
import re
import keyword
related_name = self.remote_field.related_name
if related_name is None:
return []
is_valid_id = True
if keyword.iskeyword(related_name):
is_valid_id = False
if six.PY3:
if not related_name.isidentifier():
is_valid_id = False
else:
if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*\Z', related_name):
is_valid_id = False
if not (is_valid_id or related_name.endswith('+')):
return [
checks.Error(
"The name '%s' is invalid related_name for field %s.%s" %
(self.remote_field.related_name, self.model._meta.object_name,
self.name),
hint="Related name must be a valid Python identifier or end with a '+'",
obj=self,
id='fields.E306',
)
]
return []

def _check_relation_model_exists(self):
rel_is_missing = self.remote_field.model not in self.opts.apps.get_models()
rel_is_string = isinstance(self.remote_field.model, six.string_types)
model_name = self.remote_field.model if rel_is_string else self.remote_field.model._meta.object_name
if rel_is_missing and (rel_is_string or not self.remote_field.model._meta.swapped):
return [
checks.Error(
("Field defines a relation with model '%s', which "
"is either not installed, or is abstract.") % model_name,
hint=None,
obj=self,
id='fields.E300',
)
]
return []

def _check_referencing_to_swapped_model(self):
if (self.remote_field.model not in self.opts.apps.get_models() and
not isinstance(self.remote_field.model, six.string_types) and
self.remote_field.model._meta.swapped):
model = "%s.%s" % (
self.remote_field.model._meta.app_label,
self.remote_field.model._meta.object_name
)
return [
checks.Error(
("Field defines a relation with the model '%s', "
"which has been swapped out.") % model,
hint="Update the relation to point at 'settings.%s'." % self.remote_field.model._meta.swappable,
obj=self,
id='fields.E301',
)
]
return []

def _check_clashes(self):
"""
Check accessor and reverse query name clashes.
"""
from django.db.models.base import ModelBase

errors = []
opts = self.model._meta

# `f.remote_field.model` may be a string instead of a model. Skip if model name is
# not resolved.
if not isinstance(self.remote_field.model, ModelBase):
return []

# Consider that we are checking field `Model.foreign` and the models
# are:
#
#     class Target(models.Model):
#         model = models.IntegerField()
#         model_set = models.IntegerField()
#
#     class Model(models.Model):
#         foreign = models.ForeignKey(Target)
#         m2m = models.ManyToManyField(Target)

# rel_opts.object_name == "Target"
rel_opts = self.remote_field.model._meta
# If the field doesn't install a backward relation on the target model
# (so `is_hidden` returns True), then there are no clashes to check
# and we can skip these fields.
rel_is_hidden = self.remote_field.is_hidden()
rel_name = self.remote_field.get_accessor_name()  # i. e. "model_set"
rel_query_name = self.related_query_name()  # i. e. "model"
field_name = "%s.%s" % (opts.object_name, self.name)  # i. e. "Model.field"

# Check clashes between accessor or reverse query name of `field`
# and any other field name -- i.e. accessor for Model.foreign is
# model_set and it clashes with Target.model_set.
potential_clashes = rel_opts.fields + rel_opts.many_to_many
for clash_field in potential_clashes:
clash_name = "%s.%s" % (rel_opts.object_name,
clash_field.name)  # i. e. "Target.model_set"
if not rel_is_hidden and clash_field.name == rel_name:
errors.append(
checks.Error(
"Reverse accessor for '%s' clashes with field name '%s'." % (field_name, clash_name),
hint=("Rename field '%s', or add/change a related_name "
"argument to the definition for field '%s'.") % (clash_name, field_name),
obj=self,
id='fields.E302',
)
)

if clash_field.name == rel_query_name:
errors.append(
checks.Error(
"Reverse query name for '%s' clashes with field name '%s'." % (field_name, clash_name),
hint=("Rename field '%s', or add/change a related_name "
"argument to the definition for field '%s'.") % (clash_name, field_name),
obj=self,
id='fields.E303',
)
)

# Check clashes between accessors/reverse query names of `field` and
# any other field accessor -- i. e. Model.foreign accessor clashes with
# Model.m2m accessor.
potential_clashes = (r for r in rel_opts.related_objects if r.field is not self)
for clash_field in potential_clashes:
clash_name = "%s.%s" % (  # i. e. "Model.m2m"
clash_field.related_model._meta.object_name,
clash_field.field.name)
if not rel_is_hidden and clash_field.get_accessor_name() == rel_name:
errors.append(
checks.Error(
"Reverse accessor for '%s' clashes with reverse accessor for '%s'." % (field_name, clash_name),
hint=("Add or change a related_name argument "
"to the definition for '%s' or '%s'.") % (field_name, clash_name),
obj=self,
id='fields.E304',
)
)

if clash_field.get_accessor_name() == rel_query_name:
errors.append(
checks.Error(
"Reverse query name for '%s' clashes with reverse query name for '%s'."
% (field_name, clash_name),
hint=("Add or change a related_name argument "
"to the definition for '%s' or '%s'.") % (field_name, clash_name),
obj=self,
id='fields.E305',
)
)

return errors

def db_type(self, connection):
# By default related field will not have a column as it relates to
# columns from another table.
return None

def contribute_to_class(self, cls, name, virtual_only=False):

super(RelatedField, self).contribute_to_class(cls, name, virtual_only=virtual_only)

self.opts = cls._meta

if not cls._meta.abstract:
if self.remote_field.related_name:
related_name = force_text(self.remote_field.related_name) % {
'class': cls.__name__.lower(),
'app_label': cls._meta.app_label.lower()
}
self.remote_field.related_name = related_name

def resolve_related_class(model, related, field):
field.remote_field.model = related
field.do_related_class(related, model)
lazy_related_operation(resolve_related_class, cls, self.remote_field.model, field=self)

def get_forward_related_filter(self, obj):
"""
Return the keyword arguments that when supplied to
self.model.object.filter(), would select all instances related through
this field to the remote obj. This is used to build the querysets
returned by related descriptors. obj is an instance of
self.related_field.model.
"""
return {
'%s__%s' % (self.name, rh_field.name): getattr(obj, rh_field.attname)
for _, rh_field in self.related_fields
}

def get_reverse_related_filter(self, obj):
"""
Complement to get_forward_related_filter(). Return the keyword
arguments that when passed to self.related_field.model.object.filter()
select all instances of self.related_field.model related through
this field to obj. obj is an instance of self.model.
"""
base_filter = {
rh_field.attname: getattr(obj, lh_field.attname)
for lh_field, rh_field in self.related_fields
}
descriptor_filter = self.get_extra_descriptor_filter(obj)
base_q = Q(**base_filter)
if isinstance(descriptor_filter, dict):
return base_q & Q(**descriptor_filter)
elif descriptor_filter:
return base_q & descriptor_filter
return base_q

@property
def swappable_setting(self):
"""
Get the setting that this is powered from for swapping, or None
if it's not swapped in / marked with swappable=False.
"""
if self.swappable:
# Work out string form of "to"
if isinstance(self.remote_field.model, six.string_types):
to_string = self.remote_field.model
else:
to_string = self.remote_field.model._meta.label
return apps.get_swappable_settings_name(to_string)
return None

def set_attributes_from_rel(self):
self.name = (
self.name or
(self.remote_field.model._meta.model_name + '_' + self.remote_field.model._meta.pk.name)
)
if self.verbose_name is None:
self.verbose_name = self.remote_field.model._meta.verbose_name
self.remote_field.set_field_name()

@property
def related(self):
warnings.warn(
"Usage of field.related has been deprecated. Use field.remote_field instead.",
RemovedInDjango110Warning, 2)
return self.remote_field

def do_related_class(self, other, cls):
self.set_attributes_from_rel()
self.contribute_to_related_class(other, self.remote_field)

def get_limit_choices_to(self):
"""
Return ``limit_choices_to`` for this model field.

If it is a callable, it will be invoked and the result will be
returned.
"""
if callable(self.remote_field.limit_choices_to):
return self.remote_field.limit_choices_to()
return self.remote_field.limit_choices_to

def formfield(self, **kwargs):
"""
Pass ``limit_choices_to`` to the field being constructed.

Only passes it if there is a type that supports related fields.
This is a similar strategy used to pass the ``queryset`` to the field
being constructed.
"""
defaults = {}
if hasattr(self.remote_field, 'get_related_field'):
# If this is a callable, do not invoke it here. Just pass
# it in the defaults for when the form class will later be
# instantiated.
limit_choices_to = self.remote_field.limit_choices_to
defaults.update({
'limit_choices_to': limit_choices_to,
})
defaults.update(kwargs)
return super(RelatedField, self).formfield(**defaults)

def related_query_name(self):
"""
Define the name that can be used to identify this related object in a
table-spanning query.
"""
return self.remote_field.related_query_name or self.remote_field.related_name or self.opts.model_name

@property
def target_field(self):
"""
When filtering against this relation, returns the field on the remote
model against which the filtering should happen.
"""
target_fields = self.get_path_info()[-1].target_fields
if len(target_fields) > 1:
raise exceptions.FieldError(
"The relation has multiple target fields, but only single target field was asked for")
return target_fields[0]

class ForeignObject(RelatedField):
"""
Abstraction of the ForeignKey relation, supports multi-column relations.
"""

# Field flags
many_to_many = False
many_to_one = True
one_to_many = False
one_to_one = False

requires_unique_target = True
related_accessor_class = ReverseManyToOneDescriptor
rel_class = ForeignObjectRel

def __init__(self, to, on_delete, from_fields, to_fields, rel=None, related_name=None,
related_query_name=None, limit_choices_to=None, parent_link=False,
swappable=True, **kwargs):

if rel is None:
rel = self.rel_class(
self, to,
related_name=related_name,
related_query_name=related_query_name,
limit_choices_to=limit_choices_to,
parent_link=parent_link,
on_delete=on_delete,
)

super(ForeignObject, self).__init__(rel=rel, **kwargs)

self.from_fields = from_fields
self.to_fields = to_fields
self.swappable = swappable

def check(self, **kwargs):
errors = super(ForeignObject, self).check(**kwargs)
errors.extend(self._check_unique_target())
return errors

def _check_unique_target(self):
rel_is_string = isinstance(self.remote_field.model, six.string_types)
if rel_is_string or not self.requires_unique_target:
return []

try:
self.foreign_related_fields
except exceptions.FieldDoesNotExist:
return []

if not self.foreign_related_fields:
return []

unique_foreign_fields = {
frozenset([f.name])
for f in self.remote_field.model._meta.get_fields()
if getattr(f, 'unique', False)
}
unique_foreign_fields.update({
frozenset(ut)
for ut in self.remote_field.model._meta.unique_together
})
foreign_fields = {f.name for f in self.foreign_related_fields}
has_unique_constraint = any(u <= foreign_fields for u in unique_foreign_fields)

if not has_unique_constraint and len(self.foreign_related_fields) > 1:
field_combination = ', '.join("'%s'" % rel_field.name
for rel_field in self.foreign_related_fields)
model_name = self.remote_field.model.__name__
return [
checks.Error(
"No subset of the fields %s on model '%s' is unique."
% (field_combination, model_name),
hint=(
"Add unique=True on any of those fields or add at "
"least a subset of them to a unique_together constraint."
),
obj=self,
id='fields.E310',
)
]
elif not has_unique_constraint:
field_name = self.foreign_related_fields[0].name
model_name = self.remote_field.model.__name__
return [
checks.Error(
("'%s.%s' must set unique=True "
"because it is referenced by a foreign key.") % (model_name, field_name),
hint=None,
obj=self,
id='fields.E311',
)
]
else:
return []

def deconstruct(self):
name, path, args, kwargs = super(ForeignObject, self).deconstruct()
kwargs['on_delete'] = self.remote_field.on_delete
kwargs['from_fields'] = self.from_fields
kwargs['to_fields'] = self.to_fields

if self.remote_field.related_name is not None:
kwargs['related_name'] = self.remote_field.related_name
if self.remote_field.related_query_name is not None:
kwargs['related_query_name'] = self.remote_field.related_query_name
if self.remote_field.parent_link:
kwargs['parent_link'] = self.remote_field.parent_link
# Work out string form of "to"
if isinstance(self.remote_field.model, six.string_types):
kwargs['to'] = self.remote_field.model
else:
kwargs['to'] = "%s.%s" % (
self.remote_field.model._meta.app_label,
self.remote_field.model._meta.object_name,
)
# If swappable is True, then see if we're actually pointing to the target
# of a swap.
swappable_setting = self.swappable_setting
if swappable_setting is not None:
# If it's already a settings reference, error
if hasattr(kwargs['to'], "setting_name"):
if kwargs['to'].setting_name != swappable_setting:
raise ValueError(
"Cannot deconstruct a ForeignKey pointing to a model "
"that is swapped in place of more than one model (%s and %s)"
% (kwargs['to'].setting_name, swappable_setting)
)
# Set it
from django.db.migrations.writer import SettingsReference
kwargs['to'] = SettingsReference(
kwargs['to'],
swappable_setting,
)
return name, path, args, kwargs

def resolve_related_fields(self):
if len(self.from_fields) < 1 or len(self.from_fields) != len(self.to_fields):
raise ValueError('Foreign Object from and to fields must be the same non-zero length')
if isinstance(self.remote_field.model, six.string_types):
raise ValueError('Related model %r cannot be resolved' % self.remote_field.model)
related_fields = []
for index in range(len(self.from_fields)):
from_field_name = self.from_fields[index]
to_field_name = self.to_fields[index]
from_field = (self if from_field_name == 'self'
else self.opts.get_field(from_field_name))
to_field = (self.remote_field.model._meta.pk if to_field_name is None
else self.remote_field.model._meta.get_field(to_field_name))
related_fields.append((from_field, to_field))
return related_fields

@property
def related_fields(self):
if not hasattr(self, '_related_fields'):
self._related_fields = self.resolve_related_fields()
return self._related_fields

@property
def reverse_related_fields(self):
return [(rhs_field, lhs_field) for lhs_field, rhs_field in self.related_fields]

@property
def local_related_fields(self):
return tuple(lhs_field for lhs_field, rhs_field in self.related_fields)

@property
def foreign_related_fields(self):
return tuple(rhs_field for lhs_field, rhs_field in self.related_fields if rhs_field)

def get_local_related_value(self, instance):
return self.get_instance_value_for_fields(instance, self.local_related_fields)

def get_foreign_related_value(self, instance):
return self.get_instance_value_for_fields(instance, self.foreign_related_fields)

@staticmethod
def get_instance_value_for_fields(instance, fields):
ret = []
opts = instance._meta
for field in fields:
# Gotcha: in some cases (like fixture loading) a model can have
# different values in parent_ptr_id and parent's id. So, use
# instance.pk (that is, parent_ptr_id) when asked for instance.id.
if field.primary_key:
possible_parent_link = opts.get_ancestor_link(field.model)
if (not possible_parent_link or
possible_parent_link.primary_key or
possible_parent_link.model._meta.abstract):
ret.append(instance.pk)
continue
ret.append(getattr(instance, field.attname))
return tuple(ret)

def get_attname_column(self):
attname, column = super(ForeignObject, self).get_attname_column()
return attname, None

def get_joining_columns(self, reverse_join=False):
source = self.reverse_related_fields if reverse_join else self.related_fields
return tuple((lhs_field.column, rhs_field.column) for lhs_field, rhs_field in source)

def get_reverse_joining_columns(self):
return self.get_joining_columns(reverse_join=True)

def get_extra_descriptor_filter(self, instance):
"""
Return an extra filter condition for related object fetching when
user does 'instance.fieldname', that is the extra filter is used in
the descriptor of the field.

The filter should be either a dict usable in .filter(**kwargs) call or
a Q-object. The condition will be ANDed together with the relation's
joining columns.

A parallel method is get_extra_restriction() which is used in
JOIN and subquery conditions.
"""
return {}

def get_extra_restriction(self, where_class, alias, related_alias):
"""
Return a pair condition used for joining and subquery pushdown. The
condition is something that responds to as_sql(compiler, connection)
method.

Note that currently referring both the 'alias' and 'related_alias'
will not work in some conditions, like subquery pushdown.

A parallel method is get_extra_descriptor_filter() which is used in
instance.fieldname related object fetching.
"""
return None

def get_path_info(self):
"""
Get path from this field to the related model.
"""
opts = self.remote_field.model._meta
from_opts = self.model._meta
return [PathInfo(from_opts, opts, self.foreign_related_fields, self, False, True)]

def get_reverse_path_info(self):
"""
Get path from the related model to this field's model.
"""
opts = self.model._meta
from_opts = self.remote_field.model._meta
pathinfos = [PathInfo(from_opts, opts, (opts.pk,), self.remote_field, not self.unique, False)]
return pathinfos

def get_lookup(self, lookup_name):
if lookup_name == 'in':
return RelatedIn
elif lookup_name == 'exact':
return RelatedExact
elif lookup_name == 'gt':
return RelatedGreaterThan
elif lookup_name == 'gte':
return RelatedGreaterThanOrEqual
elif lookup_name == 'lt':
return RelatedLessThan
elif lookup_name == 'lte':
return RelatedLessThanOrEqual
elif lookup_name == 'isnull':
return RelatedIsNull
else:
raise TypeError('Related Field got invalid lookup: %s' % lookup_name)

def get_transform(self, *args, **kwargs):
raise NotImplementedError('Relational fields do not support transforms.')

@property
def attnames(self):
return tuple(field.attname for field in self.local_related_fields)

def get_defaults(self):
return tuple(field.get_default() for field in self.local_related_fields)

def contribute_to_class(self, cls, name, virtual_only=False):
super(ForeignObject, self).contribute_to_class(cls, name, virtual_only=virtual_only)
setattr(cls, self.name, ForwardManyToOneDescriptor(self))

def contribute_to_related_class(self, cls, related):
# Internal FK's - i.e., those with a related name ending with '+' -
# and swapped models don't get a related descriptor.
if not self.remote_field.is_hidden() and not related.related_model._meta.swapped:
setattr(cls, related.get_accessor_name(), self.related_accessor_class(related))
# While 'limit_choices_to' might be a callable, simply pass
# it along for later - this is too early because it's still
# model load time.
if self.remote_field.limit_choices_to:
cls._meta.related_fkey_lookups.append(self.remote_field.limit_choices_to)

[docs]class ForeignKey(ForeignObject):
"""
Provide a many-to-one relation by adding a column to the local model
to hold the remote value.

By default ForeignKey will target the pk of the remote model but this
behavior can be changed by using the ``to_field`` argument.
"""

# Field flags
many_to_many = False
many_to_one = True
one_to_many = False
one_to_one = False

rel_class = ManyToOneRel

empty_strings_allowed = False
default_error_messages = {
'invalid': _('%(model)s instance with %(field)s %(value)r does not exist.')
}
description = _("Foreign Key (type determined by related field)")

def __init__(self, to, on_delete=None, related_name=None, related_query_name=None,
limit_choices_to=None, parent_link=False, to_field=None,
db_constraint=True, **kwargs):
try:
to._meta.model_name
except AttributeError:
assert isinstance(to, six.string_types), (
"%s(%r) is invalid. First parameter to ForeignKey must be "
"either a model, a model name, or the string %r" % (
self.__class__.__name__, to,
RECURSIVE_RELATIONSHIP_CONSTANT,
)
)
else:
# For backwards compatibility purposes, we need to *try* and set
# the to_field during FK construction. It won't be guaranteed to
# be correct until contribute_to_class is called. Refs #12190.
to_field = to_field or (to._meta.pk and to._meta.pk.name)

if on_delete is None:
warnings.warn(
"on_delete will be a required arg for %s in Django 2.0. Set "
"it to models.CASCADE on models and in existing migrations "
"if you want to maintain the current default behavior. "
"See https://docs.djangoproject.com/en/%s/ref/models/fields/"
"#django.db.models.ForeignKey.on_delete" % (
self.__class__.__name__,
get_docs_version(),
),
RemovedInDjango20Warning, 2)
on_delete = CASCADE

elif not callable(on_delete):
warnings.warn(
"The signature for {0} will change in Django 2.0. "
"Pass to_field='{1}' as a kwarg instead of as an arg.".format(
self.__class__.__name__,
on_delete,
),
RemovedInDjango20Warning, 2)
on_delete, to_field = to_field, on_delete

kwargs['rel'] = self.rel_class(
self, to, to_field,
related_name=related_name,
related_query_name=related_query_name,
limit_choices_to=limit_choices_to,
parent_link=parent_link,
on_delete=on_delete,
)

kwargs['db_index'] = kwargs.get('db_index', True)

super(ForeignKey, self).__init__(
to, on_delete, from_fields=['self'], to_fields=[to_field], **kwargs)

self.db_constraint = db_constraint

def check(self, **kwargs):
errors = super(ForeignKey, self).check(**kwargs)
errors.extend(self._check_on_delete())
errors.extend(self._check_unique())
return errors

def _check_on_delete(self):
on_delete = getattr(self.remote_field, 'on_delete', None)
if on_delete == SET_NULL and not self.null:
return [
checks.Error(
'Field specifies on_delete=SET_NULL, but cannot be null.',
hint='Set null=True argument on the field, or change the on_delete rule.',
obj=self,
id='fields.E320',
)
]
elif on_delete == SET_DEFAULT and not self.has_default():
return [
checks.Error(
'Field specifies on_delete=SET_DEFAULT, but has no default value.',
hint='Set a default value, or change the on_delete rule.',
obj=self,
id='fields.E321',
)
]
else:
return []

def _check_unique(self, **kwargs):
return [
checks.Warning(
'Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.',
hint='ForeignKey(unique=True) is usually better served by a OneToOneField.',
obj=self,
id='fields.W342',
)
] if self.unique else []

def deconstruct(self):
name, path, args, kwargs = super(ForeignKey, self).deconstruct()
del kwargs['to_fields']
del kwargs['from_fields']
# Handle the simpler arguments
if self.db_index:
del kwargs['db_index']
else:
kwargs['db_index'] = False
if self.db_constraint is not True:
kwargs['db_constraint'] = self.db_constraint
# Rel needs more work.
to_meta = getattr(self.remote_field.model, "_meta", None)
if self.remote_field.field_name and (
not to_meta or (to_meta.pk and self.remote_field.field_name != to_meta.pk.name)):
kwargs['to_field'] = self.remote_field.field_name
return name, path, args, kwargs

@property
def target_field(self):
return self.foreign_related_fields[0]

def get_reverse_path_info(self):
"""
Get path from the related model to this field's model.
"""
opts = self.model._meta
from_opts = self.remote_field.model._meta
pathinfos = [PathInfo(from_opts, opts, (opts.pk,), self.remote_field, not self.unique, False)]
return pathinfos

def validate(self, value, model_instance):
if self.remote_field.parent_link:
return
super(ForeignKey, self).validate(value, model_instance)
if value is None:
return

using = router.db_for_read(model_instance.__class__, instance=model_instance)
qs = self.remote_field.model._default_manager.using(using).filter(
**{self.remote_field.field_name: value}
)
qs = qs.complex_filter(self.get_limit_choices_to())
if not qs.exists():
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={
'model': self.remote_field.model._meta.verbose_name, 'pk': value,
'field': self.remote_field.field_name, 'value': value,
},  # 'pk' is included for backwards compatibility
)

def get_attname(self):
return '%s_id' % self.name

def get_attname_column(self):
attname = self.get_attname()
column = self.db_column or attname
return attname, column

def get_default(self):
"Here we check if the default value is an object and return the to_field if so."
field_default = super(ForeignKey, self).get_default()
if isinstance(field_default, self.remote_field.model):
return getattr(field_default, self.target_field.attname)
return field_default

def get_db_prep_save(self, value, connection):
if value is None or (value == '' and
(not self.target_field.empty_strings_allowed or
connection.features.interprets_empty_strings_as_nulls)):
return None
else:
return self.target_field.get_db_prep_save(value, connection=connection)

def get_db_prep_value(self, value, connection, prepared=False):
return self.target_field.get_db_prep_value(value, connection, prepared)

def value_to_string(self, obj):
if not obj:
# In required many-to-one fields with only one available choice,
# select that one available choice. Note: For SelectFields
# we have to check that the length of choices is *2*, not 1,
# because SelectFields always have an initial "blank" value.
if not self.blank and self.choices:
choice_list = self.get_choices_default()
if len(choice_list) == 2:
return smart_text(choice_list[1][0])
return super(ForeignKey, self).value_to_string(obj)

def contribute_to_related_class(self, cls, related):
super(ForeignKey, self).contribute_to_related_class(cls, related)
if self.remote_field.field_name is None:
self.remote_field.field_name = cls._meta.pk.name

def formfield(self, **kwargs):
db = kwargs.pop('using', None)
if isinstance(self.remote_field.model, six.string_types):
raise ValueError("Cannot create form field for %r yet, because "
"its related model %r has not been loaded yet" %
(self.name, self.remote_field.model))
defaults = {
'form_class': forms.ModelChoiceField,
'queryset': self.remote_field.model._default_manager.using(db),
'to_field_name': self.remote_field.field_name,
}
defaults.update(kwargs)
return super(ForeignKey, self).formfield(**defaults)

def db_type(self, connection):
# The database column type of a ForeignKey is the column type
# of the field to which it points. An exception is if the ForeignKey
# points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
# in which case the column type is simply that of an IntegerField.
# If the database needs similar types for key fields however, the only
# thing we can do is making AutoField an IntegerField.
rel_field = self.target_field
if (isinstance(rel_field, AutoField) or
(not connection.features.related_fields_match_type and
isinstance(rel_field, (PositiveIntegerField,
PositiveSmallIntegerField)))):
return IntegerField().db_type(connection=connection)
return rel_field.db_type(connection=connection)

def db_parameters(self, connection):
return {"type": self.db_type(connection), "check": []}

def convert_empty_strings(self, value, expression, connection, context):
if (not value) and isinstance(value, six.string_types):
return None
return value

def get_db_converters(self, connection):
converters = super(ForeignKey, self).get_db_converters(connection)
if connection.features.interprets_empty_strings_as_nulls:
converters += [self.convert_empty_strings]
return converters

def get_col(self, alias, output_field=None):
return super(ForeignKey, self).get_col(alias, output_field or self.target_field)

[docs]class OneToOneField(ForeignKey):
"""
A OneToOneField is essentially the same as a ForeignKey, with the exception
that it always carries a "unique" constraint with it and the reverse
relation always returns the object pointed to (since there will only ever
be one), rather than returning a list.
"""

# Field flags
many_to_many = False
many_to_one = False
one_to_many = False
one_to_one = True

related_accessor_class = ReverseOneToOneDescriptor
rel_class = OneToOneRel

description = _("One-to-one relationship")

def __init__(self, to, on_delete=None, to_field=None, **kwargs):
kwargs['unique'] = True

if on_delete is None:
warnings.warn(
"on_delete will be a required arg for %s in Django 2.0. Set "
"it to models.CASCADE on models and in existing migrations "
"if you want to maintain the current default behavior. "
"See https://docs.djangoproject.com/en/%s/ref/models/fields/"
"#django.db.models.ForeignKey.on_delete" % (
self.__class__.__name__,
get_docs_version(),
),
RemovedInDjango20Warning, 2)
on_delete = CASCADE

elif not callable(on_delete):
warnings.warn(
"The signature for {0} will change in Django 2.0. "
"Pass to_field='{1}' as a kwarg instead of as an arg.".format(
self.__class__.__name__,
on_delete,
),
RemovedInDjango20Warning, 2)
to_field = on_delete
on_delete = CASCADE  # Avoid warning in superclass

super(OneToOneField, self).__init__(to, on_delete, to_field=to_field, **kwargs)

def deconstruct(self):
name, path, args, kwargs = super(OneToOneField, self).deconstruct()
if "unique" in kwargs:
del kwargs['unique']
return name, path, args, kwargs

def formfield(self, **kwargs):
if self.remote_field.parent_link:
return None
return super(OneToOneField, self).formfield(**kwargs)

def save_form_data(self, instance, data):
if isinstance(data, self.remote_field.model):
setattr(instance, self.name, data)
else:
setattr(instance, self.attname, data)

def _check_unique(self, **kwargs):
# Override ForeignKey since check isn't applicable here.
return []

def create_many_to_many_intermediary_model(field, klass):
from django.db import models

def set_managed(model, related, through):
through._meta.managed = model._meta.managed or related._meta.managed

to_model = resolve_relation(klass, field.remote_field.model)
name = '%s_%s' % (klass._meta.object_name, field.name)
lazy_related_operation(set_managed, klass, to_model, name)

to = make_model_tuple(to_model)[1]
from_ = klass._meta.model_name
if to == from_:
to = 'to_%s' % to
from_ = 'from_%s' % from_

meta = type(str('Meta'), (object,), {
'db_table': field._get_m2m_db_table(klass._meta),
'auto_created': klass,
'app_label': klass._meta.app_label,
'db_tablespace': klass._meta.db_tablespace,
'unique_together': (from_, to),
'verbose_name': '%(from)s-%(to)s relationship' % {'from': from_, 'to': to},
'verbose_name_plural': '%(from)s-%(to)s relationships' % {'from': from_, 'to': to},
'apps': field.model._meta.apps,
})
# Construct and return the new class.
return type(str(name), (models.Model,), {
'Meta': meta,
'__module__': klass.__module__,
from_: models.ForeignKey(
klass,
related_name='%s+' % name,
db_tablespace=field.db_tablespace,
db_constraint=field.remote_field.db_constraint,
on_delete=CASCADE,
),
to: models.ForeignKey(
to_model,
related_name='%s+' % name,
db_tablespace=field.db_tablespace,
db_constraint=field.remote_field.db_constraint,
on_delete=CASCADE,
)
})

[docs]class ManyToManyField(RelatedField):
"""
Provide a many-to-many relation by using an intermediary model that
holds two ForeignKey fields pointed at the two sides of the relation.

Unless a ``through`` model was provided, ManyToManyField will use the
create_many_to_many_intermediary_model factory to automatically generate
the intermediary model.
"""

# Field flags
many_to_many = True
many_to_one = False
one_to_many = False
one_to_one = False

rel_class = ManyToManyRel

description = _("Many-to-many relationship")

def __init__(self, to, related_name=None, related_query_name=None,
limit_choices_to=None, symmetrical=None, through=None,
through_fields=None, db_constraint=True, db_table=None,
swappable=True, **kwargs):
try:
to._meta
except AttributeError:
assert isinstance(to, six.string_types), (
"%s(%r) is invalid. First parameter to ManyToManyField must be "
"either a model, a model name, or the string %r" %
(self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
)
# Class names must be ASCII in Python 2.x, so we forcibly coerce it
# here to break early if there's a problem.
to = str(to)

if symmetrical is None:
symmetrical = (to == RECURSIVE_RELATIONSHIP_CONSTANT)

if through is not None:
assert db_table is None, (
"Cannot specify a db_table if an intermediary model is used."
)

kwargs['rel'] = self.rel_class(
self, to,
related_name=related_name,
related_query_name=related_query_name,
limit_choices_to=limit_choices_to,
symmetrical=symmetrical,
through=through,
through_fields=through_fields,
db_constraint=db_constraint,
)
self.has_null_arg = 'null' in kwargs

super(ManyToManyField, self).__init__(**kwargs)

self.db_table = db_table
self.swappable = swappable

def check(self, **kwargs):
errors = super(ManyToManyField, self).check(**kwargs)
errors.extend(self._check_unique(**kwargs))
errors.extend(self._check_relationship_model(**kwargs))
errors.extend(self._check_ignored_options(**kwargs))
return errors

def _check_unique(self, **kwargs):
if self.unique:
return [
checks.Error(
'ManyToManyFields cannot be unique.',
hint=None,
obj=self,
id='fields.E330',
)
]
return []

def _check_ignored_options(self, **kwargs):
warnings = []

if self.has_null_arg:
warnings.append(
checks.Warning(
'null has no effect on ManyToManyField.',
hint=None,
obj=self,
id='fields.W340',
)
)

if len(self._validators) > 0:
warnings.append(
checks.Warning(
'ManyToManyField does not support validators.',
hint=None,
obj=self,
id='fields.W341',
)
)

return warnings

def _check_relationship_model(self, from_model=None, **kwargs):
if hasattr(self.remote_field.through, '_meta'):
qualified_model_name = "%s.%s" % (
self.remote_field.through._meta.app_label, self.remote_field.through.__name__)
else:
qualified_model_name = self.remote_field.through

errors = []

if self.remote_field.through not in self.opts.apps.get_models(include_auto_created=True):
# The relationship model is not installed.
errors.append(
checks.Error(
("Field specifies a many-to-many relation through model "
"'%s', which has not been installed.") %
qualified_model_name,
hint=None,
obj=self,
id='fields.E331',
)
)

else:

assert from_model is not None, (
"ManyToManyField with intermediate "
"tables cannot be checked if you don't pass the model "
"where the field is attached to."
)

# Set some useful local variables
to_model = resolve_relation(from_model, self.remote_field.model)
from_model_name = from_model._meta.object_name
if isinstance(to_model, six.string_types):
to_model_name = to_model
else:
to_model_name = to_model._meta.object_name
relationship_model_name = self.remote_field.through._meta.object_name
self_referential = from_model == to_model

# Check symmetrical attribute.
if (self_referential and self.remote_field.symmetrical and
not self.remote_field.through._meta.auto_created):
errors.append(
checks.Error(
'Many-to-many fields with intermediate tables must not be symmetrical.',
hint=None,
obj=self,
id='fields.E332',
)
)

# Count foreign keys in intermediate model
if self_referential:
seen_self = sum(from_model == getattr(field.remote_field, 'model', None)
for field in self.remote_field.through._meta.fields)

if seen_self > 2 and not self.remote_field.through_fields:
errors.append(
checks.Error(
("The model is used as an intermediate model by "
"'%s', but it has more than two foreign keys "
"to '%s', which is ambiguous. You must specify "
"which two foreign keys Django should use via the "
"through_fields keyword argument.") % (self, from_model_name),
hint=("Use through_fields to specify which two "
"foreign keys Django should use."),
obj=self.remote_field.through,
id='fields.E333',
)
)

else:
# Count foreign keys in relationship model
seen_from = sum(from_model == getattr(field.remote_field, 'model', None)
for field in self.remote_field.through._meta.fields)
seen_to = sum(to_model == getattr(field.remote_field, 'model', None)
for field in self.remote_field.through._meta.fields)

if seen_from > 1 and not self.remote_field.through_fields:
errors.append(
checks.Error(
("The model is used as an intermediate model by "
"'%s', but it has more than one foreign key "
"from '%s', which is ambiguous. You must specify "
"which foreign key Django should use via the "
"through_fields keyword argument.") % (self, from_model_name),
hint=('If you want to create a recursive relationship, '
'use ForeignKey("self", symmetrical=False, '
'through="%s").') % relationship_model_name,
obj=self,
id='fields.E334',
)
)

if seen_to > 1 and not self.remote_field.through_fields:
errors.append(
checks.Error(
("The model is used as an intermediate model by "
"'%s', but it has more than one foreign key "
"to '%s', which is ambiguous. You must specify "
"which foreign key Django should use via the "
"through_fields keyword argument.") % (self, to_model_name),
hint=('If you want to create a recursive '
'relationship, use ForeignKey("self", '
'symmetrical=False, through="%s").') % relationship_model_name,
obj=self,
id='fields.E335',
)
)

if seen_from == 0 or seen_to == 0:
errors.append(
checks.Error(
("The model is used as an intermediate model by "
"'%s', but it does not have a foreign key to '%s' or '%s'.") % (
self, from_model_name, to_model_name
),
hint=None,
obj=self.remote_field.through,
id='fields.E336',
)
)

# Validate `through_fields`.
if self.remote_field.through_fields is not None:
# Validate that we're given an iterable of at least two items
# and that none of them is "falsy".
if not (len(self.remote_field.through_fields) >= 2 and
self.remote_field.through_fields[0] and self.remote_field.through_fields[1]):
errors.append(
checks.Error(
("Field specifies 'through_fields' but does not "
"provide the names of the two link fields that should be "
"used for the relation through model "
"'%s'.") % qualified_model_name,
hint=("Make sure you specify 'through_fields' as "
"through_fields=('field1', 'field2')"),
obj=self,
id='fields.E337',
)
)

# Validate the given through fields -- they should be actual
# fields on the through model, and also be foreign keys to the
# expected models.
else:
assert from_model is not None, (
"ManyToManyField with intermediate "
"tables cannot be checked if you don't pass the model "
"where the field is attached to."
)

source, through, target = from_model, self.remote_field.through, self.remote_field.model
source_field_name, target_field_name = self.remote_field.through_fields[:2]

for field_name, related_model in ((source_field_name, source),
(target_field_name, target)):

possible_field_names = []
for f in through._meta.fields:
if hasattr(f, 'remote_field') and getattr(f.remote_field, 'model', None) == related_model:
possible_field_names.append(f.name)
if possible_field_names:
hint = ("Did you mean one of the following foreign "
"keys to '%s': %s?") % (related_model._meta.object_name,
', '.join(possible_field_names))
else:
hint = None

try:
field = through._meta.get_field(field_name)
except exceptions.FieldDoesNotExist:
errors.append(
checks.Error(
("The intermediary model '%s' has no field '%s'.") % (
qualified_model_name, field_name),
hint=hint,
obj=self,
id='fields.E338',
)
)
else:
if not (hasattr(field, 'remote_field') and
getattr(field.remote_field, 'model', None) == related_model):
errors.append(
checks.Error(
"'%s.%s' is not a foreign key to '%s'." % (
through._meta.object_name, field_name,
related_model._meta.object_name),
hint=hint,
obj=self,
id='fields.E339',
)
)

return errors

def deconstruct(self):
name, path, args, kwargs = super(ManyToManyField, self).deconstruct()
# Handle the simpler arguments.
if self.db_table is not None:
kwargs['db_table'] = self.db_table
if self.remote_field.db_constraint is not True:
kwargs['db_constraint'] = self.remote_field.db_constraint
if self.remote_field.related_name is not None:
kwargs['related_name'] = self.remote_field.related_name
if self.remote_field.related_query_name is not None:
kwargs['related_query_name'] = self.remote_field.related_query_name
# Rel needs more work.
if isinstance(self.remote_field.model, six.string_types):
kwargs['to'] = self.remote_field.model
else:
kwargs['to'] = "%s.%s" % (
self.remote_field.model._meta.app_label,
self.remote_field.model._meta.object_name,
)
if getattr(self.remote_field, 'through', None) is not None:
if isinstance(self.remote_field.through, six.string_types):
kwargs['through'] = self.remote_field.through
elif not self.remote_field.through._meta.auto_created:
kwargs['through'] = "%s.%s" % (
self.remote_field.through._meta.app_label,
self.remote_field.through._meta.object_name,
)
# If swappable is True, then see if we're actually pointing to the target
# of a swap.
swappable_setting = self.swappable_setting
if swappable_setting is not None:
# If it's already a settings reference, error.
if hasattr(kwargs['to'], "setting_name"):
if kwargs['to'].setting_name != swappable_setting:
raise ValueError(
"Cannot deconstruct a ManyToManyField pointing to a "
"model that is swapped in place of more than one model "
"(%s and %s)" % (kwargs['to'].setting_name, swappable_setting)
)

from django.db.migrations.writer import SettingsReference
kwargs['to'] = SettingsReference(
kwargs['to'],
swappable_setting,
)
return name, path, args, kwargs

def _get_path_info(self, direct=False):
"""
Called by both direct and indirect m2m traversal.
"""
pathinfos = []
int_model = self.remote_field.through
linkfield1 = int_model._meta.get_field(self.m2m_field_name())
linkfield2 = int_model._meta.get_field(self.m2m_reverse_field_name())
if direct:
join1infos = linkfield1.get_reverse_path_info()
join2infos = linkfield2.get_path_info()
else:
join1infos = linkfield2.get_reverse_path_info()
join2infos = linkfield1.get_path_info()
pathinfos.extend(join1infos)
pathinfos.extend(join2infos)
return pathinfos

def get_path_info(self):
return self._get_path_info(direct=True)

def get_reverse_path_info(self):
return self._get_path_info(direct=False)

def get_choices_default(self):
return Field.get_choices(self, include_blank=False)

def _get_m2m_db_table(self, opts):
"""
Function that can be curried to provide the m2m table name for this
relation.
"""
if self.remote_field.through is not None:
return self.remote_field.through._meta.db_table
elif self.db_table:
return self.db_table
else:
return utils.truncate_name('%s_%s' % (opts.db_table, self.name),
connection.ops.max_name_length())

def _get_m2m_attr(self, related, attr):
"""
Function that can be curried to provide the source accessor or DB
column name for the m2m table.
"""
cache_attr = '_m2m_%s_cache' % attr
if hasattr(self, cache_attr):
return getattr(self, cache_attr)
if self.remote_field.through_fields is not None:
link_field_name = self.remote_field.through_fields[0]
else:
link_field_name = None
for f in self.remote_field.through._meta.fields:
if (f.is_relation and f.remote_field.model == related.related_model and
(link_field_name is None or link_field_name == f.name)):
setattr(self, cache_attr, getattr(f, attr))
return getattr(self, cache_attr)

def _get_m2m_reverse_attr(self, related, attr):
"""
Function that can be curried to provide the related accessor or DB
column name for the m2m table.
"""
cache_attr = '_m2m_reverse_%s_cache' % attr
if hasattr(self, cache_attr):
return getattr(self, cache_attr)
found = False
if self.remote_field.through_fields is not None:
link_field_name = self.remote_field.through_fields[1]
else:
link_field_name = None
for f in self.remote_field.through._meta.fields:
if f.is_relation and f.remote_field.model == related.model:
if link_field_name is None and related.related_model == related.model:
# If this is an m2m-intermediate to self,
# the first foreign key you find will be
# the source column. Keep searching for
# the second foreign key.
if found:
setattr(self, cache_attr, getattr(f, attr))
break
else:
found = True
elif link_field_name is None or link_field_name == f.name:
setattr(self, cache_attr, getattr(f, attr))
break
return getattr(self, cache_attr)

def value_to_string(self, obj):
data = ''
if obj:
qs = getattr(obj, self.name).all()
data = [instance._get_pk_val() for instance in qs]
else:
# In required many-to-many fields with only one available choice,
# select that one available choice.
if not self.blank:
choices_list = self.get_choices_default()
if len(choices_list) == 1:
data = [choices_list[0][0]]
return smart_text(data)

def contribute_to_class(self, cls, name, **kwargs):
# To support multiple relations to self, it's useful to have a non-None
# related name on symmetrical relations for internal reasons. The
# concept doesn't make a lot of sense externally ("you want me to
# specify *what* on my non-reversible relation?!"), so we set it up
# automatically. The funky name reduces the chance of an accidental
# clash.
if self.remote_field.symmetrical and (
self.remote_field.model == "self" or self.remote_field.model == cls._meta.object_name):
self.remote_field.related_name = "%s_rel_+" % name
elif self.remote_field.is_hidden():
# If the backwards relation is disabled, replace the original
# related_name with one generated from the m2m field name. Django
# still uses backwards relations internally and we need to avoid
# clashes between multiple m2m fields with related_name == '+'.
self.remote_field.related_name = "_%s_%s_+" % (cls.__name__.lower(), name)

super(ManyToManyField, self).contribute_to_class(cls, name, **kwargs)

# The intermediate m2m model is not auto created if:
#  1) There is a manually specified intermediate, or
#  2) The class owning the m2m field is abstract.
#  3) The class owning the m2m field has been swapped out.
if not cls._meta.abstract:
if self.remote_field.through:
def resolve_through_model(_, model, field):
field.remote_field.through = model
lazy_related_operation(resolve_through_model, cls, self.remote_field.through, field=self)
elif not cls._meta.swapped:
self.remote_field.through = create_many_to_many_intermediary_model(self, cls)

# Add the descriptor for the m2m relation.
setattr(cls, self.name, ManyToManyDescriptor(self.remote_field, reverse=False))

# Set up the accessor for the m2m table name for the relation.
self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)

def contribute_to_related_class(self, cls, related):
# Internal M2Ms (i.e., those with a related name ending with '+')
# and swapped models don't get a related descriptor.
if not self.remote_field.is_hidden() and not related.related_model._meta.swapped:
setattr(cls, related.get_accessor_name(), ManyToManyDescriptor(self.remote_field, reverse=True))

# Set up the accessors for the column names on the m2m table.
self.m2m_column_name = curry(self._get_m2m_attr, related, 'column')
self.m2m_reverse_name = curry(self._get_m2m_reverse_attr, related, 'column')

self.m2m_field_name = curry(self._get_m2m_attr, related, 'name')
self.m2m_reverse_field_name = curry(self._get_m2m_reverse_attr, related, 'name')

get_m2m_rel = curry(self._get_m2m_attr, related, 'remote_field')
self.m2m_target_field_name = lambda: get_m2m_rel().field_name
get_m2m_reverse_rel = curry(self._get_m2m_reverse_attr, related, 'remote_field')
self.m2m_reverse_target_field_name = lambda: get_m2m_reverse_rel().field_name

def set_attributes_from_rel(self):
pass

def value_from_object(self, obj):
"""
Return the value of this field in the given model instance.
"""
return getattr(obj, self.attname).all()

def save_form_data(self, instance, data):
setattr(instance, self.attname, data)

def formfield(self, **kwargs):
db = kwargs.pop('using', None)
defaults = {
'form_class': forms.ModelMultipleChoiceField,
'queryset': self.remote_field.model._default_manager.using(db),
}
defaults.update(kwargs)
# If initial is passed in, it's a list of related objects, but the
# MultipleChoiceField takes a list of IDs.
if defaults.get('initial') is not None:
initial = defaults['initial']
if callable(initial):
initial = initial()
defaults['initial'] = [i._get_pk_val() for i in initial]
return super(ManyToManyField, self).formfield(**defaults)

def db_type(self, connection):
# A ManyToManyField is not represented by a single column,
# so return None.
return None

def db_parameters(self, connection):
return {"type": None, "check": None}

Source code for django.db.models.fields.files

import datetime
import os
import warnings

from django import forms
from django.core import checks
from django.core.files.base import File
from django.core.files.images import ImageFile
from django.core.files.storage import default_storage
from django.db.models import signals
from django.db.models.fields import Field
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_str, force_text
from django.utils.inspect import func_supports_parameter
from django.utils.translation import ugettext_lazy as _

[docs]class FieldFile(File):
def __init__(self, instance, field, name):
super(FieldFile, self).__init__(None, name)
self.instance = instance
self.field = field
self.storage = field.storage
self._committed = True

def __eq__(self, other):
# Older code may be expecting FileField values to be simple strings.
# By overriding the == operator, it can remain backwards compatibility.
if hasattr(other, 'name'):
return self.name == other.name
return self.name == other

def __ne__(self, other):
return not self.__eq__(other)

def __hash__(self):
return hash(self.name)

# The standard File contains most of the necessary properties, but
# FieldFiles can be instantiated without a name, so that needs to
# be checked for here.

def _require_file(self):
if not self:
raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)

def _get_file(self):
self._require_file()
if not hasattr(self, '_file') or self._file is None:
self._file = self.storage.open(self.name, 'rb')
return self._file

def _set_file(self, file):
self._file = file

def _del_file(self):
del self._file

file = property(_get_file, _set_file, _del_file)

def _get_path(self):
self._require_file()
return self.storage.path(self.name)
path = property(_get_path)

def _get_url(self):
self._require_file()
return self.storage.url(self.name)
url = property(_get_url)

def _get_size(self):
self._require_file()
if not self._committed:
return self.file.size
return self.storage.size(self.name)
size = property(_get_size)

[docs]    def open(self, mode='rb'):
self._require_file()
self.file.open(mode)

# open() doesn't alter the file's contents, but it does reset the pointer
open.alters_data = True

# In addition to the standard File API, FieldFiles have extra methods
# to further manipulate the underlying file, as well as update the
# associated model instance.

[docs]    def save(self, name, content, save=True):
name = self.field.generate_filename(self.instance, name)

if func_supports_parameter(self.storage.save, 'max_length'):
self.name = self.storage.save(name, content, max_length=self.field.max_length)
else:
warnings.warn(
'Backwards compatibility for storage backends without '
'support for the `max_length` argument in '
'Storage.save() will be removed in Django 1.10.',
RemovedInDjango110Warning, stacklevel=2
)
self.name = self.storage.save(name, content)

setattr(self.instance, self.field.name, self.name)

# Update the filesize cache
self._size = content.size
self._committed = True

# Save the object because it has changed, unless save is False
if save:
self.instance.save()

save.alters_data = True

[docs]    def delete(self, save=True):
if not self:
return
# Only close the file if it's already open, which we know by the
# presence of self._file
if hasattr(self, '_file'):
self.close()
del self.file

self.storage.delete(self.name)

self.name = None
setattr(self.instance, self.field.name, self.name)

# Delete the filesize cache
if hasattr(self, '_size'):
del self._size
self._committed = False

if save:
self.instance.save()

delete.alters_data = True

def _get_closed(self):
file = getattr(self, '_file', None)
return file is None or file.closed
closed = property(_get_closed)

[docs]    def close(self):
file = getattr(self, '_file', None)
if file is not None:
file.close()

def __getstate__(self):
# FieldFile needs access to its associated model field and an instance
# it's attached to in order to work properly, but the only necessary
# data to be pickled is the file's name itself. Everything else will
# be restored later, by FileDescriptor below.
return {'name': self.name, 'closed': False, '_committed': True, '_file': None}

class FileDescriptor(object):
"""
The descriptor for the file attribute on the model instance. Returns a
FieldFile when accessed so you can do stuff like::

>>> from myapp.models import MyModel
>>> instance = MyModel.objects.get(pk=1)
>>> instance.file.size

Assigns a file object on assignment so you can do::

>>> with open('/path/to/hello.world', 'r') as f:
...     instance.file = File(f)
"""
def __init__(self, field):
self.field = field

def __get__(self, instance=None, owner=None):
if instance is None:
raise AttributeError(
"The '%s' attribute can only be accessed from %s instances."
% (self.field.name, owner.__name__))

# This is slightly complicated, so worth an explanation.
# instance.file`needs to ultimately return some instance of `File`,
# probably a subclass. Additionally, this returned object needs to have
# the FieldFile API so that users can easily do things like
# instance.file.path and have that delegated to the file storage engine.
# Easy enough if we're strict about assignment in __set__, but if you
# peek below you can see that we're not. So depending on the current
# value of the field we have to dynamically construct some sort of
# "thing" to return.

# The instance dict contains whatever was originally assigned
# in __set__.
file = instance.__dict__[self.field.name]

# If this value is a string (instance.file = "path/to/file") or None
# then we simply wrap it with the appropriate attribute class according
# to the file field. [This is FieldFile for FileFields and
# ImageFieldFile for ImageFields; it's also conceivable that user
# subclasses might also want to subclass the attribute class]. This
# object understands how to convert a path to a file, and also how to
# handle None.
if isinstance(file, six.string_types) or file is None:
attr = self.field.attr_class(instance, self.field, file)
instance.__dict__[self.field.name] = attr

# Other types of files may be assigned as well, but they need to have
# the FieldFile interface added to them. Thus, we wrap any other type of
# File inside a FieldFile (well, the field's attr_class, which is
# usually FieldFile).
elif isinstance(file, File) and not isinstance(file, FieldFile):
file_copy = self.field.attr_class(instance, self.field, file.name)
file_copy.file = file
file_copy._committed = False
instance.__dict__[self.field.name] = file_copy

# Finally, because of the (some would say boneheaded) way pickle works,
# the underlying FieldFile might not actually itself have an associated
# file. So we need to reset the details of the FieldFile in those cases.
elif isinstance(file, FieldFile) and not hasattr(file, 'field'):
file.instance = instance
file.field = self.field
file.storage = self.field.storage

# That was fun, wasn't it?
return instance.__dict__[self.field.name]

def __set__(self, instance, value):
instance.__dict__[self.field.name] = value

[docs]class FileField(Field):

# The class to wrap instance attributes in. Accessing the file object off
# the instance will always return an instance of attr_class.
attr_class = FieldFile

# The descriptor to use for accessing the attribute off of the class.
descriptor_class = FileDescriptor

description = _("File")

def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs):
self._primary_key_set_explicitly = 'primary_key' in kwargs
self._unique_set_explicitly = 'unique' in kwargs

self.storage = storage or default_storage
self.upload_to = upload_to

kwargs['max_length'] = kwargs.get('max_length', 100)
super(FileField, self).__init__(verbose_name, name, **kwargs)

def check(self, **kwargs):
errors = super(FileField, self).check(**kwargs)
errors.extend(self._check_unique())
errors.extend(self._check_primary_key())
return errors

def _check_unique(self):
if self._unique_set_explicitly:
return [
checks.Error(
"'unique' is not a valid argument for a %s." % self.__class__.__name__,
hint=None,
obj=self,
id='fields.E200',
)
]
else:
return []

def _check_primary_key(self):
if self._primary_key_set_explicitly:
return [
checks.Error(
"'primary_key' is not a valid argument for a %s." % self.__class__.__name__,
hint=None,
obj=self,
id='fields.E201',
)
]
else:
return []

def deconstruct(self):
name, path, args, kwargs = super(FileField, self).deconstruct()
if kwargs.get("max_length") == 100:
del kwargs["max_length"]
kwargs['upload_to'] = self.upload_to
if self.storage is not default_storage:
kwargs['storage'] = self.storage
return name, path, args, kwargs

def get_internal_type(self):
return "FileField"

def get_prep_lookup(self, lookup_type, value):
if hasattr(value, 'name'):
value = value.name
return super(FileField, self).get_prep_lookup(lookup_type, value)

def get_prep_value(self, value):
"Returns field's value prepared for saving into a database."
value = super(FileField, self).get_prep_value(value)
# Need to convert File objects provided via a form to unicode for database insertion
if value is None:
return None
return six.text_type(value)

def pre_save(self, model_instance, add):
"Returns field's value just before saving."
file = super(FileField, self).pre_save(model_instance, add)
if file and not file._committed:
# Commit the file to storage prior to saving the model
file.save(file.name, file, save=False)
return file

def contribute_to_class(self, cls, name, **kwargs):
super(FileField, self).contribute_to_class(cls, name, **kwargs)
setattr(cls, self.name, self.descriptor_class(self))

def get_directory_name(self):
return os.path.normpath(force_text(datetime.datetime.now().strftime(force_str(self.upload_to))))

def get_filename(self, filename):
return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename)))

def generate_filename(self, instance, filename):
# If upload_to is a callable, make sure that the path it returns is
# passed through get_valid_name() of the underlying storage.
if callable(self.upload_to):
directory_name, filename = os.path.split(self.upload_to(instance, filename))
filename = self.storage.get_valid_name(filename)
return os.path.normpath(os.path.join(directory_name, filename))

return os.path.join(self.get_directory_name(), self.get_filename(filename))

def save_form_data(self, instance, data):
# Important: None means "no change", other false value means "clear"
# This subtle distinction (rather than a more explicit marker) is
# needed because we need to consume values that are also sane for a
# regular (non Model-) Form to find in its cleaned_data dictionary.
if data is not None:
# This value will be converted to unicode and stored in the
# database, so leaving False as-is is not acceptable.
if not data:
data = ''
setattr(instance, self.name, data)

def formfield(self, **kwargs):
defaults = {'form_class': forms.FileField, 'max_length': self.max_length}
# If a file has been provided previously, then the form doesn't require
# that a new file is provided this time.
# The code to mark the form field as not required is used by
# form_for_instance, but can probably be removed once form_for_instance
# is gone. ModelForm uses a different method to check for an existing file.
if 'initial' in kwargs:
defaults['required'] = False
defaults.update(kwargs)
return super(FileField, self).formfield(**defaults)

class ImageFileDescriptor(FileDescriptor):
"""
Just like the FileDescriptor, but for ImageFields. The only difference is
assigning the width/height to the width_field/height_field, if appropriate.
"""
def __set__(self, instance, value):
previous_file = instance.__dict__.get(self.field.name)
super(ImageFileDescriptor, self).__set__(instance, value)

# To prevent recalculating image dimensions when we are instantiating
# an object from the database (bug #11084), only update dimensions if
# the field had a value before this assignment.  Since the default
# value for FileField subclasses is an instance of field.attr_class,
# previous_file will only be None when we are called from
# Model.__init__().  The ImageField.update_dimension_fields method
# hooked up to the post_init signal handles the Model.__init__() cases.
# Assignment happening outside of Model.__init__() will trigger the
# update right here.
if previous_file is not None:
self.field.update_dimension_fields(instance, force=True)

class ImageFieldFile(ImageFile, FieldFile):
def delete(self, save=True):
# Clear the image dimensions cache
if hasattr(self, '_dimensions_cache'):
del self._dimensions_cache
super(ImageFieldFile, self).delete(save)

[docs]class ImageField(FileField):
attr_class = ImageFieldFile
descriptor_class = ImageFileDescriptor
description = _("Image")

def __init__(self, verbose_name=None, name=None, width_field=None,
height_field=None, **kwargs):
self.width_field, self.height_field = width_field, height_field
super(ImageField, self).__init__(verbose_name, name, **kwargs)

def check(self, **kwargs):
errors = super(ImageField, self).check(**kwargs)
errors.extend(self._check_image_library_installed())
return errors

def _check_image_library_installed(self):
try:
from PIL import Image  # NOQA
except ImportError:
return [
checks.Error(
'Cannot use ImageField because Pillow is not installed.',
hint=('Get Pillow at https://pypi.python.org/pypi/Pillow '
'or run command "pip install Pillow".'),
obj=self,
id='fields.E210',
)
]
else:
return []

def deconstruct(self):
name, path, args, kwargs = super(ImageField, self).deconstruct()
if self.width_field:
kwargs['width_field'] = self.width_field
if self.height_field:
kwargs['height_field'] = self.height_field
return name, path, args, kwargs

def contribute_to_class(self, cls, name, **kwargs):
super(ImageField, self).contribute_to_class(cls, name, **kwargs)
# Attach update_dimension_fields so that dimension fields declared
# after their corresponding image field don't stay cleared by
# Model.__init__, see bug #11196.
# Only run post-initialization dimension update on non-abstract models
if not cls._meta.abstract:
signals.post_init.connect(self.update_dimension_fields, sender=cls)

def update_dimension_fields(self, instance, force=False, *args, **kwargs):
"""
Updates field's width and height fields, if defined.

This method is hooked up to model's post_init signal to update
dimensions after instantiating a model instance.  However, dimensions
won't be updated if the dimensions fields are already populated.  This
avoids unnecessary recalculation when loading an object from the
database.

Dimensions can be forced to update with force=True, which is how
ImageFileDescriptor.__set__ calls this method.
"""
# Nothing to update if the field doesn't have dimension fields.
has_dimension_fields = self.width_field or self.height_field
if not has_dimension_fields:
return

# getattr will call the ImageFileDescriptor's __get__ method, which
# coerces the assigned value into an instance of self.attr_class
# (ImageFieldFile in this case).
file = getattr(instance, self.attname)

# Nothing to update if we have no file and not being forced to update.
if not file and not force:
return

dimension_fields_filled = not(
(self.width_field and not getattr(instance, self.width_field))
or (self.height_field and not getattr(instance, self.height_field))
)
# When both dimension fields have values, we are most likely loading
# data from the database or updating an image field that already had
# an image stored.  In the first case, we don't want to update the
# dimension fields because we are already getting their values from the
# database.  In the second case, we do want to update the dimensions
# fields and will skip this return because force will be True since we
# were called from ImageFileDescriptor.__set__.
if dimension_fields_filled and not force:
return

# file should be an instance of ImageFieldFile or should be None.
if file:
width = file.width
height = file.height
else:
# No file, so clear dimensions fields.
width = None
height = None

# Update the width and height fields.
if self.width_field:
setattr(instance, self.width_field, width)
if self.height_field:
setattr(instance, self.height_field, height)

def formfield(self, **kwargs):
defaults = {'form_class': forms.ImageField}
defaults.update(kwargs)
return super(ImageField, self).formfield(**defaults)

Source code for django.db.backends.base.schema

import hashlib
import logging

from django.db.backends.utils import truncate_name
from django.db.transaction import atomic
from django.utils import six
from django.utils.encoding import force_bytes

logger = logging.getLogger('django.db.backends.schema')

def _related_non_m2m_objects(old_field, new_field):
# Filters out m2m objects from reverse relations.
# Returns (old_relation, new_relation) tuples.
return zip(
(obj for obj in old_field.model._meta.related_objects if not obj.field.many_to_many),
(obj for obj in new_field.model._meta.related_objects if not obj.field.many_to_many)
)

[docs]class BaseDatabaseSchemaEditor(object):
"""
This class (and its subclasses) are responsible for emitting schema-changing
statements to the databases - model creation/removal/alteration, field
renaming, index fiddling, and so on.

It is intended to eventually completely replace DatabaseCreation.

This class should be used by creating an instance for each set of schema
changes (e.g. a migration file), and by first calling start(),
then the relevant actions, and then commit(). This is necessary to allow
things like circular foreign key references - FKs will only be created once
commit() is called.
"""

# Overrideable SQL templates
sql_create_table = "CREATE TABLE %(table)s (%(definition)s)"
sql_rename_table = "ALTER TABLE %(old_table)s RENAME TO %(new_table)s"
sql_retablespace_table = "ALTER TABLE %(table)s SET TABLESPACE %(new_tablespace)s"
sql_delete_table = "DROP TABLE %(table)s CASCADE"

sql_create_column = "ALTER TABLE %(table)s ADD COLUMN %(column)s %(definition)s"
sql_alter_column = "ALTER TABLE %(table)s %(changes)s"
sql_alter_column_type = "ALTER COLUMN %(column)s TYPE %(type)s"
sql_alter_column_null = "ALTER COLUMN %(column)s DROP NOT NULL"
sql_alter_column_not_null = "ALTER COLUMN %(column)s SET NOT NULL"
sql_alter_column_default = "ALTER COLUMN %(column)s SET DEFAULT %(default)s"
sql_alter_column_no_default = "ALTER COLUMN %(column)s DROP DEFAULT"
sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s CASCADE"
sql_rename_column = "ALTER TABLE %(table)s RENAME COLUMN %(old_column)s TO %(new_column)s"
sql_update_with_default = "UPDATE %(table)s SET %(column)s = %(default)s WHERE %(column)s IS NULL"

sql_create_check = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s CHECK (%(check)s)"
sql_delete_check = "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"

sql_create_unique = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s UNIQUE (%(columns)s)"
sql_delete_unique = "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"

sql_create_fk = (
"ALTER TABLE %(table)s ADD CONSTRAINT %(name)s FOREIGN KEY (%(column)s) "
"REFERENCES %(to_table)s (%(to_column)s) DEFERRABLE INITIALLY DEFERRED"
)
sql_create_inline_fk = None
sql_delete_fk = "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"

sql_create_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s)%(extra)s"
sql_delete_index = "DROP INDEX %(name)s"

sql_create_pk = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s PRIMARY KEY (%(columns)s)"
sql_delete_pk = "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s"

def __init__(self, connection, collect_sql=False):
self.connection = connection
self.collect_sql = collect_sql
if self.collect_sql:
self.collected_sql = []

# State-managing methods

def __enter__(self):
self.deferred_sql = []
if self.connection.features.can_rollback_ddl:
self.atomic = atomic(self.connection.alias)
self.atomic.__enter__()
return self

def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
for sql in self.deferred_sql:
self.execute(sql)
if self.connection.features.can_rollback_ddl:
self.atomic.__exit__(exc_type, exc_value, traceback)

# Core utility functions

[docs]    def execute(self, sql, params=[]):
"""
Executes the given SQL statement, with optional parameters.
"""
# Log the command we're running, then run it
logger.debug("%s; (params %r)" % (sql, params))
if self.collect_sql:
ending = "" if sql.endswith(";") else ";"
if params is not None:
self.collected_sql.append((sql % tuple(map(self.quote_value, params))) + ending)
else:
self.collected_sql.append(sql + ending)
else:
with self.connection.cursor() as cursor:
cursor.execute(sql, params)

def quote_name(self, name):
return self.connection.ops.quote_name(name)

@classmethod
def _digest(cls, *args):
"""
Generates a 32-bit digest of a set of arguments that can be used to
shorten identifying names.
"""
h = hashlib.md5()
for arg in args:
h.update(force_bytes(arg))
return h.hexdigest()[:8]

# Field <-> database mapping functions

def column_sql(self, model, field, include_default=False):
"""
Takes a field and returns its column definition.
The field must already have had set_attributes_from_name called.
"""
# Get the column's type and use that as the basis of the SQL
db_params = field.db_parameters(connection=self.connection)
sql = db_params['type']
params = []
# Check for fields that aren't actually columns (e.g. M2M)
if sql is None:
return None, None
# Work out nullability
null = field.null
# If we were told to include a default value, do so
include_default = include_default and not self.skip_default(field)
if include_default:
default_value = self.effective_default(field)
if default_value is not None:
if self.connection.features.requires_literal_defaults:
# Some databases can't take defaults as a parameter (oracle)
# If this is the case, the individual schema backend should
# implement prepare_default
sql += " DEFAULT %s" % self.prepare_default(default_value)
else:
sql += " DEFAULT %s"
params += [default_value]
# Oracle treats the empty string ('') as null, so coerce the null
# option whenever '' is a possible value.
if (field.empty_strings_allowed and not field.primary_key and
self.connection.features.interprets_empty_strings_as_nulls):
null = True
if null and not self.connection.features.implied_column_null:
sql += " NULL"
elif not null:
sql += " NOT NULL"
# Primary key/unique outputs
if field.primary_key:
sql += " PRIMARY KEY"
elif field.unique:
sql += " UNIQUE"
# Optionally add the tablespace if it's an implicitly indexed column
tablespace = field.db_tablespace or model._meta.db_tablespace
if tablespace and self.connection.features.supports_tablespaces and field.unique:
sql += " %s" % self.connection.ops.tablespace_sql(tablespace, inline=True)
# Return the sql
return sql, params

def skip_default(self, field):
"""
Some backends don't accept default values for certain columns types
(i.e. MySQL longtext and longblob).
"""
return False

def prepare_default(self, value):
"""
Only used for backends which have requires_literal_defaults feature
"""
raise NotImplementedError(
'subclasses of BaseDatabaseSchemaEditor for backends which have '
'requires_literal_defaults must provide a prepare_default() method'
)

def effective_default(self, field):
"""
Returns a field's effective database default value
"""
if field.has_default():
default = field.get_default()
elif not field.null and field.blank and field.empty_strings_allowed:
if field.get_internal_type() == "BinaryField":
default = six.binary_type()
else:
default = six.text_type()
else:
default = None
# If it's a callable, call it
if six.callable(default):
default = default()
# Run it through the field's get_db_prep_save method so we can send it
# to the database.
default = field.get_db_prep_save(default, self.connection)
return default

def quote_value(self, value):
"""
Returns a quoted version of the value so it's safe to use in an SQL
string. This is not safe against injection from user code; it is
intended only for use in making SQL scripts or preparing default values
for particularly tricky backends (defaults are not user-defined, though,
so this is safe).
"""
raise NotImplementedError()

# Actions

[docs]    def create_model(self, model):
"""
Takes a model and creates a table for it in the database.
Will also create any accompanying indexes or unique constraints.
"""
# Create column SQL, add FK deferreds if needed
column_sqls = []
params = []
for field in model._meta.local_fields:
# SQL
definition, extra_params = self.column_sql(model, field)
if definition is None:
continue
# Check constraints can go on the column SQL here
db_params = field.db_parameters(connection=self.connection)
if db_params['check']:
definition += " CHECK (%s)" % db_params['check']
# Autoincrement SQL (for backends with inline variant)
col_type_suffix = field.db_type_suffix(connection=self.connection)
if col_type_suffix:
definition += " %s" % col_type_suffix
params.extend(extra_params)
# FK
if field.remote_field and field.db_constraint:
to_table = field.remote_field.model._meta.db_table
to_column = field.remote_field.model._meta.get_field(field.remote_field.field_name).column
if self.connection.features.supports_foreign_keys:
self.deferred_sql.append(self._create_fk_sql(model, field, "_fk_%(to_table)s_%(to_column)s"))
elif self.sql_create_inline_fk:
definition += " " + self.sql_create_inline_fk % {
"to_table": self.quote_name(to_table),
"to_column": self.quote_name(to_column),
}
# Add the SQL to our big list
column_sqls.append("%s %s" % (
self.quote_name(field.column),
definition,
))
# Autoincrement SQL (for backends with post table definition variant)
if field.get_internal_type() == "AutoField":
autoinc_sql = self.connection.ops.autoinc_sql(model._meta.db_table, field.column)
if autoinc_sql:
self.deferred_sql.extend(autoinc_sql)

# Add any unique_togethers (always deferred, as some fields might be
# created afterwards, like geometry fields with some backends)
for fields in model._meta.unique_together:
columns = [model._meta.get_field(field).column for field in fields]
self.deferred_sql.append(self._create_unique_sql(model, columns))
# Make the table
sql = self.sql_create_table % {
"table": self.quote_name(model._meta.db_table),
"definition": ", ".join(column_sqls)
}
if model._meta.db_tablespace:
tablespace_sql = self.connection.ops.tablespace_sql(model._meta.db_tablespace)
if tablespace_sql:
sql += ' ' + tablespace_sql
# Prevent using [] as params, in the case a literal '%' is used in the definition
self.execute(sql, params or None)

# Add any field index and index_together's (deferred as SQLite3 _remake_table needs it)
self.deferred_sql.extend(self._model_indexes_sql(model))

# Make M2M tables
for field in model._meta.local_many_to_many:
if field.remote_field.through._meta.auto_created:
self.create_model(field.remote_field.through)

[docs]    def delete_model(self, model):
"""
Deletes a model from the database.
"""
# Handle auto-created intermediary models
for field in model._meta.local_many_to_many:
if field.remote_field.through._meta.auto_created:
self.delete_model(field.remote_field.through)

# Delete the table
self.execute(self.sql_delete_table % {
"table": self.quote_name(model._meta.db_table),
})

[docs]    def alter_unique_together(self, model, old_unique_together, new_unique_together):
"""
Deals with a model changing its unique_together.
Note: The input unique_togethers must be doubly-nested, not the single-
nested ["foo", "bar"] format.
"""
olds = set(tuple(fields) for fields in old_unique_together)
news = set(tuple(fields) for fields in new_unique_together)
# Deleted uniques
for fields in olds.difference(news):
self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_unique)
# Created uniques
for fields in news.difference(olds):
columns = [model._meta.get_field(field).column for field in fields]
self.execute(self._create_unique_sql(model, columns))

[docs]    def alter_index_together(self, model, old_index_together, new_index_together):
"""
Deals with a model changing its index_together.
Note: The input index_togethers must be doubly-nested, not the single-
nested ["foo", "bar"] format.
"""
olds = set(tuple(fields) for fields in old_index_together)
news = set(tuple(fields) for fields in new_index_together)
# Deleted indexes
for fields in olds.difference(news):
self._delete_composed_index(model, fields, {'index': True}, self.sql_delete_index)
# Created indexes
for field_names in news.difference(olds):
fields = [model._meta.get_field(field) for field in field_names]
self.execute(self._create_index_sql(model, fields, suffix="_idx"))

def _delete_composed_index(self, model, fields, constraint_kwargs, sql):
columns = [model._meta.get_field(field).column for field in fields]
constraint_names = self._constraint_names(model, columns, **constraint_kwargs)
if len(constraint_names) != 1:
raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
len(constraint_names),
model._meta.db_table,
", ".join(columns),
))
self.execute(self._delete_constraint_sql(sql, model, constraint_names[0]))

[docs]    def alter_db_table(self, model, old_db_table, new_db_table):
"""
Renames the table a model points to.
"""
if old_db_table == new_db_table:
return
self.execute(self.sql_rename_table % {
"old_table": self.quote_name(old_db_table),
"new_table": self.quote_name(new_db_table),
})

[docs]    def alter_db_tablespace(self, model, old_db_tablespace, new_db_tablespace):
"""
Moves a model's table between tablespaces
"""
self.execute(self.sql_retablespace_table % {
"table": self.quote_name(model._meta.db_table),
"old_tablespace": self.quote_name(old_db_tablespace),
"new_tablespace": self.quote_name(new_db_tablespace),
})

[docs]    def add_field(self, model, field):
"""
Creates a field on a model.
Usually involves adding a column, but may involve adding a
table instead (for M2M fields)
"""
# Special-case implicit M2M tables
if field.many_to_many and field.remote_field.through._meta.auto_created:
return self.create_model(field.remote_field.through)
# Get the column's definition
definition, params = self.column_sql(model, field, include_default=True)
# It might not actually have a column behind it
if definition is None:
return
# Check constraints can go on the column SQL here
db_params = field.db_parameters(connection=self.connection)
if db_params['check']:
definition += " CHECK (%s)" % db_params['check']
# Build the SQL and run it
sql = self.sql_create_column % {
"table": self.quote_name(model._meta.db_table),
"column": self.quote_name(field.column),
"definition": definition,
}
self.execute(sql, params)
# Drop the default if we need to
# (Django usually does not use in-database defaults)
if not self.skip_default(field) and field.default is not None:
sql = self.sql_alter_column % {
"table": self.quote_name(model._meta.db_table),
"changes": self.sql_alter_column_no_default % {
"column": self.quote_name(field.column),
}
}
self.execute(sql)
# Add an index, if required
if field.db_index and not field.unique:
self.deferred_sql.append(self._create_index_sql(model, [field]))
# Add any FK constraints later
if field.remote_field and self.connection.features.supports_foreign_keys and field.db_constraint:
self.deferred_sql.append(self._create_fk_sql(model, field, "_fk_%(to_table)s_%(to_column)s"))
# Reset connection if required
if self.connection.features.connection_persists_old_columns:
self.connection.close()

[docs]    def remove_field(self, model, field):
"""
Removes a field from a model. Usually involves deleting a column,
but for M2Ms may involve deleting a table.
"""
# Special-case implicit M2M tables
if field.many_to_many and field.remote_field.through._meta.auto_created:
return self.delete_model(field.remote_field.through)
# It might not actually have a column behind it
if field.db_parameters(connection=self.connection)['type'] is None:
return
# Drop any FK constraints, MySQL requires explicit deletion
if field.remote_field:
fk_names = self._constraint_names(model, [field.column], foreign_key=True)
for fk_name in fk_names:
self.execute(self._delete_constraint_sql(self.sql_delete_fk, model, fk_name))
# Delete the column
sql = self.sql_delete_column % {
"table": self.quote_name(model._meta.db_table),
"column": self.quote_name(field.column),
}
self.execute(sql)
# Reset connection if required
if self.connection.features.connection_persists_old_columns:
self.connection.close()

[docs]    def alter_field(self, model, old_field, new_field, strict=False):
"""
Allows a field's type, uniqueness, nullability, default, column,
constraints etc. to be modified.
Requires a copy of the old field as well so we can only perform
changes that are required.
If strict is true, raises errors if the old column does not match old_field precisely.
"""
# Ensure this field is even column-based
old_db_params = old_field.db_parameters(connection=self.connection)
old_type = old_db_params['type']
new_db_params = new_field.db_parameters(connection=self.connection)
new_type = new_db_params['type']
if ((old_type is None and old_field.remote_field is None) or
(new_type is None and new_field.remote_field is None)):
raise ValueError(
"Cannot alter field %s into %s - they do not properly define "
"db_type (are you using a badly-written custom field?)" %
(old_field, new_field),
)
elif old_type is None and new_type is None and (
old_field.remote_field.through and new_field.remote_field.through and
old_field.remote_field.through._meta.auto_created and
new_field.remote_field.through._meta.auto_created):
return self._alter_many_to_many(model, old_field, new_field, strict)
elif old_type is None and new_type is None and (
old_field.remote_field.through and new_field.remote_field.through and
not old_field.remote_field.through._meta.auto_created and
not new_field.remote_field.through._meta.auto_created):
# Both sides have through models; this is a no-op.
return
elif old_type is None or new_type is None:
raise ValueError(
"Cannot alter field %s into %s - they are not compatible types "
"(you cannot alter to or from M2M fields, or add or remove "
"through= on M2M fields)" % (old_field, new_field)
)

self._alter_field(model, old_field, new_field, old_type, new_type,
old_db_params, new_db_params, strict)

def _alter_field(self, model, old_field, new_field, old_type, new_type,
old_db_params, new_db_params, strict=False):
"""Actually perform a "physical" (non-ManyToMany) field update."""

# Drop any FK constraints, we'll remake them later
fks_dropped = set()
if old_field.remote_field and old_field.db_constraint:
fk_names = self._constraint_names(model, [old_field.column], foreign_key=True)
if strict and len(fk_names) != 1:
raise ValueError("Found wrong number (%s) of foreign key constraints for %s.%s" % (
len(fk_names),
model._meta.db_table,
old_field.column,
))
for fk_name in fk_names:
fks_dropped.add((old_field.column,))
self.execute(self._delete_constraint_sql(self.sql_delete_fk, model, fk_name))
# Has unique been removed?
if old_field.unique and (not new_field.unique or (not old_field.primary_key and new_field.primary_key)):
# Find the unique constraint for this field
constraint_names = self._constraint_names(model, [old_field.column], unique=True)
if strict and len(constraint_names) != 1:
raise ValueError("Found wrong number (%s) of unique constraints for %s.%s" % (
len(constraint_names),
model._meta.db_table,
old_field.column,
))
for constraint_name in constraint_names:
self.execute(self._delete_constraint_sql(self.sql_delete_unique, model, constraint_name))
# Drop incoming FK constraints if we're a primary key and things are going
# to change.
if old_field.primary_key and new_field.primary_key and old_type != new_type:
# '_meta.related_field' also contains M2M reverse fields, these
# will be filtered out
for _old_rel, new_rel in _related_non_m2m_objects(old_field, new_field):
rel_fk_names = self._constraint_names(
new_rel.related_model, [new_rel.field.column], foreign_key=True
)
for fk_name in rel_fk_names:
self.execute(self._delete_constraint_sql(self.sql_delete_fk, new_rel.related_model, fk_name))
# Removed an index? (no strict check, as multiple indexes are possible)
if (old_field.db_index and not new_field.db_index and
not old_field.unique and not
(not new_field.unique and old_field.unique)):
# Find the index for this field
index_names = self._constraint_names(model, [old_field.column], index=True)
for index_name in index_names:
self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name))
# Change check constraints?
if old_db_params['check'] != new_db_params['check'] and old_db_params['check']:
constraint_names = self._constraint_names(model, [old_field.column], check=True)
if strict and len(constraint_names) != 1:
raise ValueError("Found wrong number (%s) of check constraints for %s.%s" % (
len(constraint_names),
model._meta.db_table,
old_field.column,
))
for constraint_name in constraint_names:
self.execute(self._delete_constraint_sql(self.sql_delete_check, model, constraint_name))
# Have they renamed the column?
if old_field.column != new_field.column:
self.execute(self._rename_field_sql(model._meta.db_table, old_field, new_field, new_type))
# Next, start accumulating actions to do
actions = []
null_actions = []
post_actions = []
# Type change?
if old_type != new_type:
fragment, other_actions = self._alter_column_type_sql(
model._meta.db_table, old_field, new_field, new_type
)
actions.append(fragment)
post_actions.extend(other_actions)
# When changing a column NULL constraint to NOT NULL with a given
# default value, we need to perform 4 steps:
#  1. Add a default for new incoming writes
#  2. Update existing NULL rows with new default
#  3. Replace NULL constraint with NOT NULL
#  4. Drop the default again.
# Default change?
old_default = self.effective_default(old_field)
new_default = self.effective_default(new_field)
needs_database_default = (
old_default != new_default and
new_default is not None and
not self.skip_default(new_field)
)
if needs_database_default:
if self.connection.features.requires_literal_defaults:
# Some databases can't take defaults as a parameter (oracle)
# If this is the case, the individual schema backend should
# implement prepare_default
actions.append((
self.sql_alter_column_default % {
"column": self.quote_name(new_field.column),
"default": self.prepare_default(new_default),
},
[],
))
else:
actions.append((
self.sql_alter_column_default % {
"column": self.quote_name(new_field.column),
"default": "%s",
},
[new_default],
))
# Nullability change?
if old_field.null != new_field.null:
if (self.connection.features.interprets_empty_strings_as_nulls and
new_field.get_internal_type() in ("CharField", "TextField")):
# The field is nullable in the database anyway, leave it alone
pass
elif new_field.null:
null_actions.append((
self.sql_alter_column_null % {
"column": self.quote_name(new_field.column),
"type": new_type,
},
[],
))
else:
null_actions.append((
self.sql_alter_column_not_null % {
"column": self.quote_name(new_field.column),
"type": new_type,
},
[],
))
# Only if we have a default and there is a change from NULL to NOT NULL
four_way_default_alteration = (
new_field.has_default() and
(old_field.null and not new_field.null)
)
if actions or null_actions:
if not four_way_default_alteration:
# If we don't have to do a 4-way default alteration we can
# directly run a (NOT) NULL alteration
actions = actions + null_actions
# Combine actions together if we can (e.g. postgres)
if self.connection.features.supports_combined_alters and actions:
sql, params = tuple(zip(*actions))
actions = [(", ".join(sql), sum(params, []))]
# Apply those actions
for sql, params in actions:
self.execute(
self.sql_alter_column % {
"table": self.quote_name(model._meta.db_table),
"changes": sql,
},
params,
)
if four_way_default_alteration:
# Update existing rows with default value
self.execute(
self.sql_update_with_default % {
"table": self.quote_name(model._meta.db_table),
"column": self.quote_name(new_field.column),
"default": "%s",
},
[new_default],
)
# Since we didn't run a NOT NULL change before we need to do it
# now
for sql, params in null_actions:
self.execute(
self.sql_alter_column % {
"table": self.quote_name(model._meta.db_table),
"changes": sql,
},
params,
)
if post_actions:
for sql, params in post_actions:
self.execute(sql, params)
# Added a unique?
if (not old_field.unique and new_field.unique) or (
old_field.primary_key and not new_field.primary_key and new_field.unique
):
self.execute(self._create_unique_sql(model, [new_field.column]))
# Added an index?
if (not old_field.db_index and new_field.db_index and
not new_field.unique and not
(not old_field.unique and new_field.unique)):
self.execute(self._create_index_sql(model, [new_field], suffix="_uniq"))
# Type alteration on primary key? Then we need to alter the column
# referring to us.
rels_to_update = []
if old_field.primary_key and new_field.primary_key and old_type != new_type:
rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))
# Changed to become primary key?
# Note that we don't detect unsetting of a PK, as we assume another field
# will always come along and replace it.
if not old_field.primary_key and new_field.primary_key:
# First, drop the old PK
constraint_names = self._constraint_names(model, primary_key=True)
if strict and len(constraint_names) != 1:
raise ValueError("Found wrong number (%s) of PK constraints for %s" % (
len(constraint_names),
model._meta.db_table,
))
for constraint_name in constraint_names:
self.execute(self._delete_constraint_sql(self.sql_delete_pk, model, constraint_name))
# Make the new one
self.execute(
self.sql_create_pk % {
"table": self.quote_name(model._meta.db_table),
"name": self.quote_name(self._create_index_name(model, [new_field.column], suffix="_pk")),
"columns": self.quote_name(new_field.column),
}
)
# Update all referencing columns
rels_to_update.extend(_related_non_m2m_objects(old_field, new_field))
# Handle our type alters on the other end of rels from the PK stuff above
for old_rel, new_rel in rels_to_update:
rel_db_params = new_rel.field.db_parameters(connection=self.connection)
rel_type = rel_db_params['type']
fragment, other_actions = self._alter_column_type_sql(
new_rel.related_model._meta.db_table, old_rel.field, new_rel.field, rel_type
)
self.execute(
self.sql_alter_column % {
"table": self.quote_name(new_rel.related_model._meta.db_table),
"changes": fragment[0],
},
fragment[1],
)
for sql, params in other_actions:
self.execute(sql, params)
# Does it have a foreign key?
if (new_field.remote_field and
(fks_dropped or not old_field.remote_field or not old_field.db_constraint) and
new_field.db_constraint):
self.execute(self._create_fk_sql(model, new_field, "_fk_%(to_table)s_%(to_column)s"))
# Rebuild FKs that pointed to us if we previously had to drop them
if old_field.primary_key and new_field.primary_key and old_type != new_type:
for rel in new_field.model._meta.related_objects:
if not rel.many_to_many:
self.execute(self._create_fk_sql(rel.related_model, rel.field, "_fk"))
# Does it have check constraints we need to add?
if old_db_params['check'] != new_db_params['check'] and new_db_params['check']:
self.execute(
self.sql_create_check % {
"table": self.quote_name(model._meta.db_table),
"name": self.quote_name(self._create_index_name(model, [new_field.column], suffix="_check")),
"column": self.quote_name(new_field.column),
"check": new_db_params['check'],
}
)
# Drop the default if we need to
# (Django usually does not use in-database defaults)
if needs_database_default:
sql = self.sql_alter_column % {
"table": self.quote_name(model._meta.db_table),
"changes": self.sql_alter_column_no_default % {
"column": self.quote_name(new_field.column),
}
}
self.execute(sql)
# Reset connection if required
if self.connection.features.connection_persists_old_columns:
self.connection.close()

def _alter_column_type_sql(self, table, old_field, new_field, new_type):
"""
Hook to specialize column type alteration for different backends,
for cases when a creation type is different to an alteration type
(e.g. SERIAL in PostgreSQL, PostGIS fields).

Should return two things; an SQL fragment of (sql, params) to insert
into an ALTER TABLE statement, and a list of extra (sql, params) tuples
to run once the field is altered.
"""
return (
(
self.sql_alter_column_type % {
"column": self.quote_name(new_field.column),
"type": new_type,
},
[],
),
[],
)

def _alter_many_to_many(self, model, old_field, new_field, strict):
"""
Alters M2Ms to repoint their to= endpoints.
"""
# Rename the through table
if old_field.remote_field.through._meta.db_table != new_field.remote_field.through._meta.db_table:
self.alter_db_table(old_field.remote_field.through, old_field.remote_field.through._meta.db_table,
new_field.remote_field.through._meta.db_table)
# Repoint the FK to the other side
self.alter_field(
new_field.remote_field.through,
# We need the field that points to the target model, so we can tell alter_field to change it -
# this is m2m_reverse_field_name() (as opposed to m2m_field_name, which points to our model)
old_field.remote_field.through._meta.get_field(old_field.m2m_reverse_field_name()),
new_field.remote_field.through._meta.get_field(new_field.m2m_reverse_field_name()),
)
self.alter_field(
new_field.remote_field.through,
# for self-referential models we need to alter field from the other end too
old_field.remote_field.through._meta.get_field(old_field.m2m_field_name()),
new_field.remote_field.through._meta.get_field(new_field.m2m_field_name()),
)

def _create_index_name(self, model, column_names, suffix=""):
"""
Generates a unique name for an index/unique constraint.
"""
# If there is just one column in the index, use a default algorithm from Django
if len(column_names) == 1 and not suffix:
return truncate_name(
'%s_%s' % (model._meta.db_table, self._digest(column_names[0])),
self.connection.ops.max_name_length()
)
# Else generate the name for the index using a different algorithm
table_name = model._meta.db_table.replace('"', '').replace('.', '_')
index_unique_name = '_%s' % self._digest(table_name, *column_names)
max_length = self.connection.ops.max_name_length() or 200
# If the index name is too long, truncate it
index_name = ('%s_%s%s%s' % (
table_name, column_names[0], index_unique_name, suffix,
)).replace('"', '').replace('.', '_')
if len(index_name) > max_length:
part = ('_%s%s%s' % (column_names[0], index_unique_name, suffix))
index_name = '%s%s' % (table_name[:(max_length - len(part))], part)
# It shouldn't start with an underscore (Oracle hates this)
if index_name[0] == "_":
index_name = index_name[1:]
# If it's STILL too long, just hash it down
if len(index_name) > max_length:
index_name = hashlib.md5(force_bytes(index_name)).hexdigest()[:max_length]
# It can't start with a number on Oracle, so prepend D if we need to
if index_name[0].isdigit():
index_name = "D%s" % index_name[:-1]
return index_name

def _create_index_sql(self, model, fields, suffix="", sql=None):
"""
Return the SQL statement to create the index for one or several fields.
`sql` can be specified if the syntax differs from the standard (GIS
indexes, ...).
"""
if len(fields) == 1 and fields[0].db_tablespace:
tablespace_sql = self.connection.ops.tablespace_sql(fields[0].db_tablespace)
elif model._meta.db_tablespace:
tablespace_sql = self.connection.ops.tablespace_sql(model._meta.db_tablespace)
else:
tablespace_sql = ""
if tablespace_sql:
tablespace_sql = " " + tablespace_sql

columns = [field.column for field in fields]
sql_create_index = sql or self.sql_create_index
return sql_create_index % {
"table": self.quote_name(model._meta.db_table),
"name": self.quote_name(self._create_index_name(model, columns, suffix=suffix)),
"columns": ", ".join(self.quote_name(column) for column in columns),
"extra": tablespace_sql,
}

def _model_indexes_sql(self, model):
"""
Return all index SQL statements (field indexes, index_together) for the
specified model, as a list.
"""
if not model._meta.managed or model._meta.proxy or model._meta.swapped:
return []
output = []
for field in model._meta.local_fields:
if field.db_index and not field.unique:
output.append(self._create_index_sql(model, [field], suffix=""))

for field_names in model._meta.index_together:
fields = [model._meta.get_field(field) for field in field_names]
output.append(self._create_index_sql(model, fields, suffix="_idx"))
return output

def _rename_field_sql(self, table, old_field, new_field, new_type):
return self.sql_rename_column % {
"table": self.quote_name(table),
"old_column": self.quote_name(old_field.column),
"new_column": self.quote_name(new_field.column),
"type": new_type,
}

def _create_fk_sql(self, model, field, suffix):
from_table = model._meta.db_table
from_column = field.column
to_table = field.target_field.model._meta.db_table
to_column = field.target_field.column
suffix = suffix % {
"to_table": to_table,
"to_column": to_column,
}

return self.sql_create_fk % {
"table": self.quote_name(from_table),
"name": self.quote_name(self._create_index_name(model, [from_column], suffix=suffix)),
"column": self.quote_name(from_column),
"to_table": self.quote_name(to_table),
"to_column": self.quote_name(to_column),
}

def _create_unique_sql(self, model, columns):
return self.sql_create_unique % {
"table": self.quote_name(model._meta.db_table),
"name": self.quote_name(self._create_index_name(model, columns, suffix="_uniq")),
"columns": ", ".join(self.quote_name(column) for column in columns),
}

def _delete_constraint_sql(self, template, model, name):
return template % {
"table": self.quote_name(model._meta.db_table),
"name": self.quote_name(name),
}

def _constraint_names(self, model, column_names=None, unique=None,
primary_key=None, index=None, foreign_key=None,
check=None):
"""
Returns all constraint names matching the columns and conditions
"""
column_names = list(column_names) if column_names else None
with self.connection.cursor() as cursor:
constraints = self.connection.introspection.get_constraints(cursor, model._meta.db_table)
result = []
for name, infodict in constraints.items():
if column_names is None or column_names == infodict['columns']:
if unique is not None and infodict['unique'] != unique:
continue
if primary_key is not None and infodict['primary_key'] != primary_key:
continue
if index is not None and infodict['index'] != index:
continue
if check is not None and infodict['check'] != check:
continue
if foreign_key is not None and not infodict['foreign_key']:
continue
result.append(name)
return result

Source code for django.db.migrations.operations.fields

from __future__ import unicode_literals

from django.db.models.fields import NOT_PROVIDED
from django.utils import six
from django.utils.functional import cached_property

from .base import Operation

[docs]class AddField(Operation):
"""
Adds a field to a model.
"""

def __init__(self, model_name, name, field, preserve_default=True):
self.model_name = model_name
self.name = name
self.field = field
self.preserve_default = preserve_default

@cached_property
def name_lower(self):
return self.name.lower()

@cached_property
def model_name_lower(self):
return self.model_name.lower()

def deconstruct(self):
kwargs = {
'model_name': self.model_name,
'name': self.name,
'field': self.field,
}
if self.preserve_default is not True:
kwargs['preserve_default'] = self.preserve_default
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
# If preserve default is off, don't use the default for future state
if not self.preserve_default:
field = self.field.clone()
field.default = NOT_PROVIDED
else:
field = self.field
state.models[app_label, self.model_name_lower].fields.append((self.name, field))
state.reload_model(app_label, self.model_name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
to_model = to_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
from_model = from_state.apps.get_model(app_label, self.model_name)
field = to_model._meta.get_field(self.name)
if not self.preserve_default:
field.default = self.field.default
schema_editor.add_field(
from_model,
field,
)
if not self.preserve_default:
field.default = NOT_PROVIDED

def database_backwards(self, app_label, schema_editor, from_state, to_state):
from_model = from_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, from_model):
schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))

def describe(self):
return "Add field %s to %s" % (self.name, self.model_name)

def references_model(self, name, app_label=None):
return name.lower() == self.model_name_lower

def references_field(self, model_name, name, app_label=None):
return self.references_model(model_name) and name.lower() == self.name_lower

[docs]class RemoveField(Operation):
"""
Removes a field from a model.
"""

def __init__(self, model_name, name):
self.model_name = model_name
self.name = name

@cached_property
def name_lower(self):
return self.name.lower()

@cached_property
def model_name_lower(self):
return self.model_name.lower()

def deconstruct(self):
kwargs = {
'model_name': self.model_name,
'name': self.name,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
new_fields = []
for name, instance in state.models[app_label, self.model_name_lower].fields:
if name != self.name:
new_fields.append((name, instance))
state.models[app_label, self.model_name_lower].fields = new_fields
state.reload_model(app_label, self.model_name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
from_model = from_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, from_model):
schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))

def database_backwards(self, app_label, schema_editor, from_state, to_state):
to_model = to_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
from_model = from_state.apps.get_model(app_label, self.model_name)
schema_editor.add_field(from_model, to_model._meta.get_field(self.name))

def describe(self):
return "Remove field %s from %s" % (self.name, self.model_name)

def references_model(self, name, app_label=None):
return name.lower() == self.model_name_lower

def references_field(self, model_name, name, app_label=None):
return self.references_model(model_name) and name.lower() == self.name_lower

[docs]class AlterField(Operation):
"""
Alters a field's database column (e.g. null, max_length) to the provided new field
"""

def __init__(self, model_name, name, field, preserve_default=True):
self.model_name = model_name
self.name = name
self.field = field
self.preserve_default = preserve_default

@cached_property
def name_lower(self):
return self.name.lower()

@cached_property
def model_name_lower(self):
return self.model_name.lower()

def deconstruct(self):
kwargs = {
'model_name': self.model_name,
'name': self.name,
'field': self.field,
}
if self.preserve_default is not True:
kwargs['preserve_default'] = self.preserve_default
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
if not self.preserve_default:
field = self.field.clone()
field.default = NOT_PROVIDED
else:
field = self.field
state.models[app_label, self.model_name_lower].fields = [
(n, field if n == self.name else f)
for n, f in
state.models[app_label, self.model_name_lower].fields
]
state.reload_model(app_label, self.model_name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
to_model = to_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
from_model = from_state.apps.get_model(app_label, self.model_name)
from_field = from_model._meta.get_field(self.name)
to_field = to_model._meta.get_field(self.name)
# If the field is a relatedfield with an unresolved rel.to, just
# set it equal to the other field side. Bandaid fix for AlterField
# migrations that are part of a RenameModel change.
if from_field.remote_field and from_field.remote_field.model:
if isinstance(from_field.remote_field.model, six.string_types):
from_field.remote_field.model = to_field.remote_field.model
elif to_field.remote_field and isinstance(to_field.remote_field.model, six.string_types):
to_field.remote_field.model = from_field.remote_field.model
if not self.preserve_default:
to_field.default = self.field.default
schema_editor.alter_field(from_model, from_field, to_field)
if not self.preserve_default:
to_field.default = NOT_PROVIDED

def database_backwards(self, app_label, schema_editor, from_state, to_state):
self.database_forwards(app_label, schema_editor, from_state, to_state)

def describe(self):
return "Alter field %s on %s" % (self.name, self.model_name)

def references_model(self, name, app_label=None):
return name.lower() == self.model_name_lower

def references_field(self, model_name, name, app_label=None):
return self.references_model(model_name) and name.lower() == self.name_lower

[docs]class RenameField(Operation):
"""
Renames a field on the model. Might affect db_column too.
"""

def __init__(self, model_name, old_name, new_name):
self.model_name = model_name
self.old_name = old_name
self.new_name = new_name

@cached_property
def old_name_lower(self):
return self.old_name.lower()

@cached_property
def new_name_lower(self):
return self.new_name.lower()

@cached_property
def model_name_lower(self):
return self.model_name.lower()

def deconstruct(self):
kwargs = {
'model_name': self.model_name,
'old_name': self.old_name,
'new_name': self.new_name,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
# Rename the field
state.models[app_label, self.model_name_lower].fields = [
(self.new_name if n == self.old_name else n, f)
for n, f in state.models[app_label, self.model_name_lower].fields
]
# Fix index/unique_together to refer to the new field
options = state.models[app_label, self.model_name_lower].options
for option in ('index_together', 'unique_together'):
if option in options:
options[option] = [
[self.new_name if n == self.old_name else n for n in together]
for together in options[option]
]
state.reload_model(app_label, self.model_name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
to_model = to_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
from_model = from_state.apps.get_model(app_label, self.model_name)
schema_editor.alter_field(
from_model,
from_model._meta.get_field(self.old_name),
to_model._meta.get_field(self.new_name),
)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
to_model = to_state.apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
from_model = from_state.apps.get_model(app_label, self.model_name)
schema_editor.alter_field(
from_model,
from_model._meta.get_field(self.new_name),
to_model._meta.get_field(self.old_name),
)

def describe(self):
return "Rename field %s on %s to %s" % (self.old_name, self.model_name, self.new_name)

def references_model(self, name, app_label=None):
return name.lower() == self.model_name_lower

def references_field(self, model_name, name, app_label=None):
return self.references_model(model_name) and (
name.lower() == self.old_name_lower or
name.lower() == self.new_name_lower
)

Source code for django.db.migrations.operations.models

from __future__ import unicode_literals

from django.db import models
from django.db.migrations.operations.base import Operation
from django.db.migrations.state import ModelState
from django.db.models.options import normalize_together
from django.utils import six
from django.utils.functional import cached_property

[docs]class CreateModel(Operation):
"""
Create a model's table.
"""

serialization_expand_args = ['fields', 'options', 'managers']

def __init__(self, name, fields, options=None, bases=None, managers=None):
self.name = name
self.fields = fields
self.options = options or {}
self.bases = bases or (models.Model,)
self.managers = managers or []

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
'fields': self.fields,
}
if self.options:
kwargs['options'] = self.options
if self.bases and self.bases != (models.Model,):
kwargs['bases'] = self.bases
if self.managers and self.managers != [('objects', models.Manager())]:
kwargs['managers'] = self.managers
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
state.add_model(ModelState(
app_label,
self.name,
list(self.fields),
dict(self.options),
tuple(self.bases),
list(self.managers),
))

def database_forwards(self, app_label, schema_editor, from_state, to_state):
model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, model):
schema_editor.create_model(model)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
model = from_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, model):
schema_editor.delete_model(model)

def describe(self):
return "Create %smodel %s" % ("proxy " if self.options.get("proxy", False) else "", self.name)

def references_model(self, name, app_label=None):
strings_to_check = [self.name]
# Check we didn't inherit from the model
for base in self.bases:
if isinstance(base, six.string_types):
strings_to_check.append(base.split(".")[-1])
# Check we have no FKs/M2Ms with it
for fname, field in self.fields:
if field.remote_field:
if isinstance(field.remote_field.model, six.string_types):
strings_to_check.append(field.remote_field.model.split(".")[-1])
# Now go over all the strings and compare them
for string in strings_to_check:
if string.lower() == name.lower():
return True
return False

[docs]class DeleteModel(Operation):
"""
Drops a model's table.
"""

def __init__(self, name):
self.name = name

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
state.remove_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
model = from_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, model):
schema_editor.delete_model(model)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, model):
schema_editor.create_model(model)

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def describe(self):
return "Delete model %s" % (self.name, )

[docs]class RenameModel(Operation):
"""
Renames a model.
"""

def __init__(self, old_name, new_name):
self.old_name = old_name
self.new_name = new_name

@cached_property
def old_name_lower(self):
return self.old_name.lower()

@cached_property
def new_name_lower(self):
return self.new_name.lower()

def deconstruct(self):
kwargs = {
'old_name': self.old_name,
'new_name': self.new_name,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
apps = state.apps
model = apps.get_model(app_label, self.old_name)
model._meta.apps = apps
# Get all of the related objects we need to repoint
all_related_objects = (
f for f in model._meta.get_fields(include_hidden=True)
if f.auto_created and not f.concrete and (not f.hidden or f.many_to_many)
)
# Rename the model
state.models[app_label, self.new_name_lower] = state.models[app_label, self.old_name_lower]
state.models[app_label, self.new_name_lower].name = self.new_name
state.remove_model(app_label, self.old_name_lower)
# Repoint the FKs and M2Ms pointing to us
for related_object in all_related_objects:
if related_object.model is not model:
# The model being renamed does not participate in this relation
# directly. Rather, a superclass does.
continue
# Use the new related key for self referential related objects.
if related_object.related_model == model:
related_key = (app_label, self.new_name_lower)
else:
related_key = (
related_object.related_model._meta.app_label,
related_object.related_model._meta.model_name,
)
new_fields = []
for name, field in state.models[related_key].fields:
if name == related_object.field.name:
field = field.clone()
field.remote_field.model = "%s.%s" % (app_label, self.new_name)
new_fields.append((name, field))
state.models[related_key].fields = new_fields
state.reload_model(*related_key)
state.reload_model(app_label, self.new_name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
new_model = to_state.apps.get_model(app_label, self.new_name)
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
old_model = from_state.apps.get_model(app_label, self.old_name)
# Move the main table
schema_editor.alter_db_table(
new_model,
old_model._meta.db_table,
new_model._meta.db_table,
)
# Alter the fields pointing to us
for related_object in old_model._meta.related_objects:
if related_object.related_model == old_model:
model = new_model
related_key = (app_label, self.new_name_lower)
else:
model = related_object.related_model
related_key = (
related_object.related_model._meta.app_label,
related_object.related_model._meta.model_name,
)
to_field = to_state.apps.get_model(
*related_key
)._meta.get_field(related_object.field.name)
schema_editor.alter_field(
model,
related_object.field,
to_field,
)
# Rename M2M fields whose name is based on this model's name.
fields = zip(old_model._meta.local_many_to_many, new_model._meta.local_many_to_many)
for (old_field, new_field) in fields:
# Skip self-referential fields as these are renamed above.
if new_field.model == new_field.related_model or not new_field.remote_field.through._meta.auto_created:
continue
# Rename the M2M table that's based on this model's name.
old_m2m_model = old_field.remote_field.through
new_m2m_model = new_field.remote_field.through
schema_editor.alter_db_table(
new_m2m_model,
old_m2m_model._meta.db_table,
new_m2m_model._meta.db_table,
)
# Rename the column in the M2M table that's based on this
# model's name.
schema_editor.alter_field(
new_m2m_model,
old_m2m_model._meta.get_field(old_model._meta.model_name),
new_m2m_model._meta.get_field(new_model._meta.model_name),
)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
self.new_name_lower, self.old_name_lower = self.old_name_lower, self.new_name_lower
self.new_name, self.old_name = self.old_name, self.new_name

self.database_forwards(app_label, schema_editor, from_state, to_state)

self.new_name_lower, self.old_name_lower = self.old_name_lower, self.new_name_lower
self.new_name, self.old_name = self.old_name, self.new_name

def references_model(self, name, app_label=None):
return (
name.lower() == self.old_name_lower or
name.lower() == self.new_name_lower
)

def describe(self):
return "Rename model %s to %s" % (self.old_name, self.new_name)

[docs]class AlterModelTable(Operation):
"""
Renames a model's table
"""

def __init__(self, name, table):
self.name = name
self.table = table

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
'table': self.table,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
state.models[app_label, self.name_lower].options["db_table"] = self.table
state.reload_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
new_model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
old_model = from_state.apps.get_model(app_label, self.name)
schema_editor.alter_db_table(
new_model,
old_model._meta.db_table,
new_model._meta.db_table,
)
# Rename M2M fields whose name is based on this model's db_table
for (old_field, new_field) in zip(old_model._meta.local_many_to_many, new_model._meta.local_many_to_many):
if new_field.remote_field.through._meta.auto_created:
schema_editor.alter_db_table(
new_field.remote_field.through,
old_field.remote_field.through._meta.db_table,
new_field.remote_field.through._meta.db_table,
)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
return self.database_forwards(app_label, schema_editor, from_state, to_state)

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def describe(self):
return "Rename table for %s to %s" % (self.name, self.table)

[docs]class AlterUniqueTogether(Operation):
"""
Changes the value of unique_together to the target one.
Input value of unique_together must be a set of tuples.
"""
option_name = "unique_together"

def __init__(self, name, unique_together):
self.name = name
unique_together = normalize_together(unique_together)
self.unique_together = set(tuple(cons) for cons in unique_together)

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
'unique_together': self.unique_together,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
model_state = state.models[app_label, self.name_lower]
model_state.options[self.option_name] = self.unique_together
state.reload_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
new_model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
old_model = from_state.apps.get_model(app_label, self.name)
schema_editor.alter_unique_together(
new_model,
getattr(old_model._meta, self.option_name, set()),
getattr(new_model._meta, self.option_name, set()),
)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
return self.database_forwards(app_label, schema_editor, from_state, to_state)

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def references_field(self, model_name, name, app_label=None):
return (
self.references_model(model_name, app_label) and
(
not self.unique_together or
any((name in together) for together in self.unique_together)
)
)

def describe(self):
return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.unique_together or ''))

[docs]class AlterIndexTogether(Operation):
"""
Changes the value of index_together to the target one.
Input value of index_together must be a set of tuples.
"""
option_name = "index_together"

def __init__(self, name, index_together):
self.name = name
index_together = normalize_together(index_together)
self.index_together = set(tuple(cons) for cons in index_together)

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
'index_together': self.index_together,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
model_state = state.models[app_label, self.name_lower]
model_state.options[self.option_name] = self.index_together
state.reload_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
new_model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, new_model):
old_model = from_state.apps.get_model(app_label, self.name)
schema_editor.alter_index_together(
new_model,
getattr(old_model._meta, self.option_name, set()),
getattr(new_model._meta, self.option_name, set()),
)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
return self.database_forwards(app_label, schema_editor, from_state, to_state)

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def references_field(self, model_name, name, app_label=None):
return (
self.references_model(model_name, app_label) and
(
not self.index_together or
any((name in together) for together in self.index_together)
)
)

def describe(self):
return "Alter %s for %s (%s constraint(s))" % (self.option_name, self.name, len(self.index_together or ''))

[docs]class AlterOrderWithRespectTo(Operation):
"""
Represents a change with the order_with_respect_to option.
"""

def __init__(self, name, order_with_respect_to):
self.name = name
self.order_with_respect_to = order_with_respect_to

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
'order_with_respect_to': self.order_with_respect_to,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
model_state = state.models[app_label, self.name_lower]
model_state.options['order_with_respect_to'] = self.order_with_respect_to
state.reload_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
to_model = to_state.apps.get_model(app_label, self.name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
from_model = from_state.apps.get_model(app_label, self.name)
# Remove a field if we need to
if from_model._meta.order_with_respect_to and not to_model._meta.order_with_respect_to:
schema_editor.remove_field(from_model, from_model._meta.get_field("_order"))
# Add a field if we need to (altering the column is untouched as
# it's likely a rename)
elif to_model._meta.order_with_respect_to and not from_model._meta.order_with_respect_to:
field = to_model._meta.get_field("_order")
if not field.has_default():
field.default = 0
schema_editor.add_field(
from_model,
field,
)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
self.database_forwards(app_label, schema_editor, from_state, to_state)

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def references_field(self, model_name, name, app_label=None):
return (
self.references_model(model_name, app_label) and
(
self.order_with_respect_to is None or
name == self.order_with_respect_to
)
)

def describe(self):
return "Set order_with_respect_to on %s to %s" % (self.name, self.order_with_respect_to)

[docs]class AlterModelOptions(Operation):
"""
Sets new model options that don't directly affect the database schema
(like verbose_name, permissions, ordering). Python code in migrations
may still need them.
"""

# Model options we want to compare and preserve in an AlterModelOptions op
ALTER_OPTION_KEYS = [
"get_latest_by",
"managed",
"ordering",
"permissions",
"default_permissions",
"select_on_save",
"verbose_name",
"verbose_name_plural",
]

def __init__(self, name, options):
self.name = name
self.options = options

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
kwargs = {
'name': self.name,
'options': self.options,
}
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
model_state = state.models[app_label, self.name_lower]
model_state.options = dict(model_state.options)
model_state.options.update(self.options)
for key in self.ALTER_OPTION_KEYS:
if key not in self.options and key in model_state.options:
del model_state.options[key]
state.reload_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
pass

def database_backwards(self, app_label, schema_editor, from_state, to_state):
pass

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def describe(self):
return "Change Meta options on %s" % (self.name, )

[docs]class AlterModelManagers(Operation):
"""
Alters the model's managers
"""

serialization_expand_args = ['managers']

def __init__(self, name, managers):
self.name = name
self.managers = managers

@cached_property
def name_lower(self):
return self.name.lower()

def deconstruct(self):
return (
self.__class__.__name__,
[self.name, self.managers],
{}
)

def state_forwards(self, app_label, state):
model_state = state.models[app_label, self.name_lower]
model_state.managers = list(self.managers)
state.reload_model(app_label, self.name_lower)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
pass

def database_backwards(self, app_label, schema_editor, from_state, to_state):
pass

def references_model(self, name, app_label=None):
return name.lower() == self.name_lower

def describe(self):
return "Change managers on %s" % (self.name, )

Source code for django.db.migrations.operations.special

from __future__ import unicode_literals

from django.db import router

from .base import Operation

[docs]class SeparateDatabaseAndState(Operation):
"""
Takes two lists of operations - ones that will be used for the database,
and ones that will be used for the state change. This allows operations
that don't support state change to have it applied, or have operations
that affect the state or not the database, or so on.
"""

serialization_expand_args = ['database_operations', 'state_operations']

def __init__(self, database_operations=None, state_operations=None):
self.database_operations = database_operations or []
self.state_operations = state_operations or []

def deconstruct(self):
kwargs = {}
if self.database_operations:
kwargs['database_operations'] = self.database_operations
if self.state_operations:
kwargs['state_operations'] = self.state_operations
return (
self.__class__.__name__,
[],
kwargs
)

def state_forwards(self, app_label, state):
for state_operation in self.state_operations:
state_operation.state_forwards(app_label, state)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
# We calculate state separately in here since our state functions aren't useful
for database_operation in self.database_operations:
to_state = from_state.clone()
database_operation.state_forwards(app_label, to_state)
database_operation.database_forwards(app_label, schema_editor, from_state, to_state)
from_state = to_state

def database_backwards(self, app_label, schema_editor, from_state, to_state):
# We calculate state separately in here since our state functions aren't useful
base_state = to_state
for pos, database_operation in enumerate(reversed(self.database_operations)):
to_state = base_state.clone()
for dbop in self.database_operations[:-(pos + 1)]:
dbop.state_forwards(app_label, to_state)
from_state = to_state.clone()
database_operation.state_forwards(app_label, from_state)
database_operation.database_backwards(app_label, schema_editor, from_state, to_state)

def describe(self):
return "Custom state/database change combination"

[docs]class RunSQL(Operation):
"""
Runs some raw SQL. A reverse SQL statement may be provided.

Also accepts a list of operations that represent the state change effected
by this SQL change, in case it's custom column/table creation/deletion.
"""
noop = ''

def __init__(self, sql, reverse_sql=None, state_operations=None, hints=None):
self.sql = sql
self.reverse_sql = reverse_sql
self.state_operations = state_operations or []
self.hints = hints or {}

def deconstruct(self):
kwargs = {
'sql': self.sql,
}
if self.reverse_sql is not None:
kwargs['reverse_sql'] = self.reverse_sql
if self.state_operations:
kwargs['state_operations'] = self.state_operations
if self.hints:
kwargs['hints'] = self.hints
return (
self.__class__.__name__,
[],
kwargs
)

@property
def reversible(self):
return self.reverse_sql is not None

def state_forwards(self, app_label, state):
for state_operation in self.state_operations:
state_operation.state_forwards(app_label, state)

def database_forwards(self, app_label, schema_editor, from_state, to_state):
if router.allow_migrate(schema_editor.connection.alias, app_label, **self.hints):
self._run_sql(schema_editor, self.sql)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
if self.reverse_sql is None:
raise NotImplementedError("You cannot reverse this operation")
if router.allow_migrate(schema_editor.connection.alias, app_label, **self.hints):
self._run_sql(schema_editor, self.reverse_sql)

def describe(self):
return "Raw SQL operation"

def _run_sql(self, schema_editor, sqls):
if isinstance(sqls, (list, tuple)):
for sql in sqls:
params = None
if isinstance(sql, (list, tuple)):
elements = len(sql)
if elements == 2:
sql, params = sql
else:
raise ValueError("Expected a 2-tuple but got %d" % elements)
schema_editor.execute(sql, params=params)
elif sqls != RunSQL.noop:
statements = schema_editor.connection.ops.prepare_sql_script(sqls)
for statement in statements:
schema_editor.execute(statement, params=None)

[docs]class RunPython(Operation):
"""
Runs Python code in a context suitable for doing versioned ORM operations.
"""

reduces_to_sql = False

def __init__(self, code, reverse_code=None, atomic=True, hints=None):
self.atomic = atomic
# Forwards code
if not callable(code):
raise ValueError("RunPython must be supplied with a callable")
self.code = code
# Reverse code
if reverse_code is None:
self.reverse_code = None
else:
if not callable(reverse_code):
raise ValueError("RunPython must be supplied with callable arguments")
self.reverse_code = reverse_code
self.hints = hints or {}

def deconstruct(self):
kwargs = {
'code': self.code,
}
if self.reverse_code is not None:
kwargs['reverse_code'] = self.reverse_code
if self.atomic is not True:
kwargs['atomic'] = self.atomic
if self.hints:
kwargs['hints'] = self.hints
return (
self.__class__.__name__,
[],
kwargs
)

@property
def reversible(self):
return self.reverse_code is not None

def state_forwards(self, app_label, state):
# RunPython objects have no state effect. To add some, combine this
# with SeparateDatabaseAndState.
pass

def database_forwards(self, app_label, schema_editor, from_state, to_state):
if router.allow_migrate(schema_editor.connection.alias, app_label, **self.hints):
# We now execute the Python code in a context that contains a 'models'
# object, representing the versioned models as an app registry.
# We could try to override the global cache, but then people will still
# use direct imports, so we go with a documentation approach instead.
self.code(from_state.apps, schema_editor)

def database_backwards(self, app_label, schema_editor, from_state, to_state):
if self.reverse_code is None:
raise NotImplementedError("You cannot reverse this operation")
if router.allow_migrate(schema_editor.connection.alias, app_label, **self.hints):
self.reverse_code(from_state.apps, schema_editor)

def describe(self):
return "Raw Python operation"

@staticmethod

[docs]    def noop(apps, schema_editor):
return None

Source code for django.template.engine

import warnings

from django.core.exceptions import ImproperlyConfigured
from django.utils import lru_cache, six
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.functional import cached_property
from django.utils.module_loading import import_string

from .base import Context, Template
from .context import _builtin_context_processors
from .exceptions import TemplateDoesNotExist
from .library import import_library

_context_instance_undefined = object()
_dictionary_undefined = object()
_dirs_undefined = object()

[docs]class Engine(object):
default_builtins = [
'django.template.defaulttags',
'django.template.defaultfilters',
'django.template.loader_tags',
]

def __init__(self, dirs=None, app_dirs=False,
allowed_include_roots=None, context_processors=None,
debug=False, loaders=None, string_if_invalid='',
file_charset='utf-8', libraries=None, builtins=None):
if dirs is None:
dirs = []
if allowed_include_roots is None:
allowed_include_roots = []
if context_processors is None:
context_processors = []
if loaders is None:
loaders = ['django.template.loaders.filesystem.Loader']
if app_dirs:
loaders += ['django.template.loaders.app_directories.Loader']
else:
if app_dirs:
raise ImproperlyConfigured(
"app_dirs must not be set when loaders is defined.")
if libraries is None:
libraries = {}
if builtins is None:
builtins = []

if isinstance(allowed_include_roots, six.string_types):
raise ImproperlyConfigured(
"allowed_include_roots must be a tuple, not a string.")

self.dirs = dirs
self.app_dirs = app_dirs
self.allowed_include_roots = allowed_include_roots
self.context_processors = context_processors
self.debug = debug
self.loaders = loaders
self.string_if_invalid = string_if_invalid
self.file_charset = file_charset
self.libraries = libraries
self.template_libraries = self.get_template_libraries(libraries)
self.builtins = self.default_builtins + builtins
self.template_builtins = self.get_template_builtins(self.builtins)

@staticmethod
@lru_cache.lru_cache()

[docs]    def get_default():
"""
When only one DjangoTemplates backend is configured, returns it.

Raises ImproperlyConfigured otherwise.

This is required for preserving historical APIs that rely on a
globally available, implicitly configured engine such as:

>>> from django.template import Context, Template
>>> template = Template("Hello {{ name }}!")
>>> context = Context({'name': "world"})
>>> template.render(context)
'Hello world!'
"""
# Since Engine is imported in django.template and since
# DjangoTemplates is a wrapper around this Engine class,
# local imports are required to avoid import loops.
from django.template import engines
from django.template.backends.django import DjangoTemplates
django_engines = [engine for engine in engines.all()
if isinstance(engine, DjangoTemplates)]
if len(django_engines) == 1:
# Unwrap the Engine instance inside DjangoTemplates
return django_engines[0].engine
elif len(django_engines) == 0:
raise ImproperlyConfigured(
"No DjangoTemplates backend is configured.")
else:
raise ImproperlyConfigured(
"Several DjangoTemplates backends are configured. "
"You must select one explicitly.")

@cached_property
def template_context_processors(self):
context_processors = _builtin_context_processors
context_processors += tuple(self.context_processors)
return tuple(import_string(path) for path in context_processors)

def get_template_builtins(self, builtins):
return [import_library(x) for x in builtins]

def get_template_libraries(self, libraries):
loaded = {}
for name, path in libraries.items():
loaded[name] = import_library(path)
return loaded

@cached_property
def template_loaders(self):
return self.get_template_loaders(self.loaders)

def get_template_loaders(self, template_loaders):
loaders = []
for template_loader in template_loaders:
loader = self.find_template_loader(template_loader)
if loader is not None:
loaders.append(loader)
return loaders

def find_template_loader(self, loader):
if isinstance(loader, (tuple, list)):
args = list(loader[1:])
loader = loader[0]
else:
args = []

if isinstance(loader, six.string_types):
loader_class = import_string(loader)

if getattr(loader_class, '_accepts_engine_in_init', False):
args.insert(0, self)
else:
warnings.warn(
"%s inherits from django.template.loader.BaseLoader "
"instead of django.template.loaders.base.Loader. " %
loader, RemovedInDjango110Warning, stacklevel=2)

return loader_class(*args)
else:
raise ImproperlyConfigured(
"Invalid value in template loaders configuration: %r" % loader)

def find_template(self, name, dirs=None, skip=None):
tried = []
for loader in self.template_loaders:
if loader.supports_recursion:
try:
template = loader.get_template(
name, template_dirs=dirs, skip=skip,
)
return template, template.origin
except TemplateDoesNotExist as e:
tried.extend(e.tried)
else:
# RemovedInDjango20Warning: Use old api for non-recursive
# loaders.
try:
return loader(name, dirs)
except TemplateDoesNotExist:
pass
raise TemplateDoesNotExist(name, tried=tried)

[docs]    def from_string(self, template_code):
"""
Returns a compiled Template object for the given template code,
handling template inheritance recursively.
"""
return Template(template_code, engine=self)

[docs]    def get_template(self, template_name, dirs=_dirs_undefined):
"""
Returns a compiled Template object for the given template name,
handling template inheritance recursively.
"""
if dirs is _dirs_undefined:
dirs = None
else:
warnings.warn(
"The dirs argument of get_template is deprecated.",
RemovedInDjango110Warning, stacklevel=2)

template, origin = self.find_template(template_name, dirs)
if not hasattr(template, 'render'):
# template needs to be compiled
template = Template(template, origin, template_name, engine=self)
return template

# This method was originally a function defined in django.template.loader.
# It was moved here in Django 1.8 when encapsulating the Django template
# engine in this Engine class. It's still called by deprecated code but it
# will be removed in Django 1.10. It's superseded by a new render_to_string
# function in django.template.loader.

def render_to_string(self, template_name, context=None,
context_instance=_context_instance_undefined,
dirs=_dirs_undefined,
dictionary=_dictionary_undefined):
if context_instance is _context_instance_undefined:
context_instance = None
else:
warnings.warn(
"The context_instance argument of render_to_string is "
"deprecated.", RemovedInDjango110Warning, stacklevel=3)
if dirs is _dirs_undefined:
# Do not set dirs to None here to avoid triggering the deprecation
# warning in select_template or get_template.
pass
else:
warnings.warn(
"The dirs argument of render_to_string is deprecated.",
RemovedInDjango110Warning, stacklevel=3)
if dictionary is _dictionary_undefined:
dictionary = None
else:
warnings.warn(
"The dictionary argument of render_to_string was renamed to "
"context.", RemovedInDjango110Warning, stacklevel=3)
context = dictionary

if isinstance(template_name, (list, tuple)):
t = self.select_template(template_name, dirs)
else:
t = self.get_template(template_name, dirs)
if not context_instance:
# Django < 1.8 accepted a Context in `context` even though that's
# unintended. Preserve this ability but don't rewrap `context`.
if isinstance(context, Context):
return t.render(context)
else:
return t.render(Context(context))
if not context:
return t.render(context_instance)
# Add the context to the context stack, ensuring it gets removed again
# to keep the context_instance in the same state it started in.
with context_instance.push(context):
return t.render(context_instance)

[docs]    def select_template(self, template_name_list, dirs=_dirs_undefined):
"""
Given a list of template names, returns the first that can be loaded.
"""
if dirs is _dirs_undefined:
# Do not set dirs to None here to avoid triggering the deprecation
# warning in get_template.
pass
else:
warnings.warn(
"The dirs argument of select_template is deprecated.",
RemovedInDjango110Warning, stacklevel=3)

if not template_name_list:
raise TemplateDoesNotExist("No template names provided")
not_found = []
for template_name in template_name_list:
try:
return self.get_template(template_name, dirs)
except TemplateDoesNotExist as exc:
if exc.args[0] not in not_found:
not_found.append(exc.args[0])
continue
# If we get here, none of the templates could be loaded
raise TemplateDoesNotExist(', '.join(not_found))

Source code for django.template.utils

import os
import warnings
from collections import Counter, OrderedDict

from django.apps import apps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import lru_cache
from django.utils._os import upath
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.functional import cached_property
from django.utils.module_loading import import_string

class InvalidTemplateEngineError(ImproperlyConfigured):
pass

class EngineHandler(object):
def __init__(self, templates=None):
"""
templates is an optional list of template engine definitions
(structured like settings.TEMPLATES).
"""
self._templates = templates
self._engines = {}

@cached_property
def templates(self):
if self._templates is None:
self._templates = settings.TEMPLATES

if not self._templates:
warnings.warn(
"You haven't defined a TEMPLATES setting. You must do so "
"before upgrading to Django 1.10. Otherwise Django will be "
"unable to load templates.", RemovedInDjango110Warning)
self._templates = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': settings.TEMPLATE_DIRS,
'OPTIONS': {
'allowed_include_roots': settings.ALLOWED_INCLUDE_ROOTS,
'context_processors': settings.TEMPLATE_CONTEXT_PROCESSORS,
'debug': settings.TEMPLATE_DEBUG,
'loaders': settings.TEMPLATE_LOADERS,
'string_if_invalid': settings.TEMPLATE_STRING_IF_INVALID,
},
},
]

templates = OrderedDict()
backend_names = []
for tpl in self._templates:
tpl = tpl.copy()
try:
# This will raise an exception if 'BACKEND' doesn't exist or
# isn't a string containing at least one dot.
default_name = tpl['BACKEND'].rsplit('.', 2)[-2]
except Exception:
invalid_backend = tpl.get('BACKEND', '<not defined>')
raise ImproperlyConfigured(
"Invalid BACKEND for a template engine: {}. Check "
"your TEMPLATES setting.".format(invalid_backend))

tpl.setdefault('NAME', default_name)
tpl.setdefault('DIRS', [])
tpl.setdefault('APP_DIRS', False)
tpl.setdefault('OPTIONS', {})

templates[tpl['NAME']] = tpl
backend_names.append(tpl['NAME'])

counts = Counter(backend_names)
duplicates = [alias for alias, count in counts.most_common() if count > 1]
if duplicates:
raise ImproperlyConfigured(
"Template engine aliases aren't unique, duplicates: {}. "
"Set a unique NAME for each engine in settings.TEMPLATES."
.format(", ".join(duplicates)))

return templates

def __getitem__(self, alias):
try:
return self._engines[alias]
except KeyError:
try:
params = self.templates[alias]
except KeyError:
raise InvalidTemplateEngineError(
"Could not find config for '{}' "
"in settings.TEMPLATES".format(alias))

# If importing or initializing the backend raises an exception,
# self._engines[alias] isn't set and this code may get executed
# again, so we must preserve the original params. See #24265.
params = params.copy()
backend = params.pop('BACKEND')
engine_cls = import_string(backend)
engine = engine_cls(params)

self._engines[alias] = engine
return engine

def __iter__(self):
return iter(self.templates)

def all(self):
return [self[alias] for alias in self]

@lru_cache.lru_cache()
def get_app_template_dirs(dirname):
"""
Return an iterable of paths of directories to load app templates from.

dirname is the name of the subdirectory containing templates inside
installed applications.
"""
template_dirs = []
for app_config in apps.get_app_configs():
if not app_config.path:
continue
template_dir = os.path.join(app_config.path, dirname)
if os.path.isdir(template_dir):
template_dirs.append(upath(template_dir))
# Immutable return value because it will be cached and shared by callers.
return tuple(template_dirs)

Source code for django.template.base

"""
This is the Django template system.

How it works:

The Lexer.tokenize() function converts a template string (i.e., a string containing
markup with custom template tags) to tokens, which can be either plain text
(TOKEN_TEXT), variables (TOKEN_VAR) or block statements (TOKEN_BLOCK).

The Parser() class takes a list of tokens in its constructor, and its parse()
method returns a compiled template -- which is, under the hood, a list of
Node objects.

Each Node is responsible for creating some sort of output -- e.g. simple text
(TextNode), variable values in a given context (VariableNode), results of basic
logic (IfNode), results of looping (ForNode), or anything else. The core Node
types are TextNode, VariableNode, IfNode and ForNode, but plugin modules can
define their own custom node types.

Each Node has a render() method, which takes a Context and returns a string of
the rendered node. For example, the render() method of a Variable Node returns
the variable's value as a string. The render() method of a ForNode returns the
rendered output of whatever was inside the loop, recursively.

The Template class is a convenient wrapper that takes care of template
compilation and rendering.

Usage:

The only thing you should ever use directly in this file is the Template class.
Create a compiled template object with a template_string, then call render()
with a context. In the compilation stage, the TemplateSyntaxError exception
will be raised if the template doesn't have proper syntax.

Sample code:

>>> from django import template
>>> s = '<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>'
>>> t = template.Template(s)

(t is now a compiled template, and its render() method can be called multiple
times with multiple contexts)

>>> c = template.Context({'test':True, 'varvalue': 'Hello'})
>>> t.render(c)
'<html><h1>Hello</h1></html>'
>>> c = template.Context({'test':False, 'varvalue': 'Hello'})
>>> t.render(c)
'<html></html>'
"""

from __future__ import unicode_literals

import inspect
import logging
import re
import warnings

from django.template.context import (  # NOQA: imported for backwards compatibility
BaseContext, Context, ContextPopException, RequestContext,
)
from django.utils import six
from django.utils.deprecation import (
DeprecationInstanceCheck, RemovedInDjango20Warning,
RemovedInDjango110Warning,
)
from django.utils.encoding import (
force_str, force_text, python_2_unicode_compatible,
)
from django.utils.formats import localize
from django.utils.html import conditional_escape, escape
from django.utils.inspect import getargspec
from django.utils.safestring import (
EscapeData, SafeData, mark_for_escaping, mark_safe,
)
from django.utils.text import (
get_text_list, smart_split, unescape_string_literal,
)
from django.utils.timezone import template_localtime
from django.utils.translation import pgettext_lazy, ugettext_lazy

from .exceptions import TemplateSyntaxError

TOKEN_TEXT = 0
TOKEN_VAR = 1
TOKEN_BLOCK = 2
TOKEN_COMMENT = 3
TOKEN_MAPPING = {
TOKEN_TEXT: 'Text',
TOKEN_VAR: 'Var',
TOKEN_BLOCK: 'Block',
TOKEN_COMMENT: 'Comment',
}

# template syntax constants
FILTER_SEPARATOR = '|'
FILTER_ARGUMENT_SEPARATOR = ':'
VARIABLE_ATTRIBUTE_SEPARATOR = '.'
BLOCK_TAG_START = '{%'
BLOCK_TAG_END = '%}'
VARIABLE_TAG_START = '{{'
VARIABLE_TAG_END = '}}'
COMMENT_TAG_START = '{#'
COMMENT_TAG_END = '#}'
TRANSLATOR_COMMENT_MARK = 'Translators'
SINGLE_BRACE_START = '{'
SINGLE_BRACE_END = '}'

# what to report as the origin for templates that come from non-loader sources
# (e.g. strings)
UNKNOWN_SOURCE = '<unknown source>'

# match a variable or block tag and capture the entire tag, including start/end
# delimiters
tag_re = (re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' %
(re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))))

logger = logging.getLogger('django.template')

class TemplateEncodingError(Exception):
pass

@python_2_unicode_compatible
class VariableDoesNotExist(Exception):

def __init__(self, msg, params=()):
self.msg = msg
self.params = params

def __str__(self):
return self.msg % tuple(force_text(p, errors='replace') for p in self.params)

[docs]class Origin(object):
def __init__(self, name, template_name=None, loader=None):
self.name = name
self.template_name = template_name
self.loader = loader

def __str__(self):
return self.name

def __eq__(self, other):
if not isinstance(other, Origin):
return False

return (
self.name == other.name and
self.loader == other.loader
)

@property
def loader_name(self):
if self.loader:
return '%s.%s' % (
self.loader.__module__, self.loader.__class__.__name__,
)

class StringOrigin(six.with_metaclass(DeprecationInstanceCheck, Origin)):
alternative = 'django.template.Origin'
deprecation_warning = RemovedInDjango20Warning

[docs]class Template(object):
def __init__(self, template_string, origin=None, name=None, engine=None):
try:
template_string = force_text(template_string)
except UnicodeDecodeError:
raise TemplateEncodingError("Templates can only be constructed "
"from unicode or UTF-8 strings.")
# If Template is instantiated directly rather than from an Engine and
# exactly one Django template engine is configured, use that engine.
# This is required to preserve backwards-compatibility for direct use
# e.g. Template('...').render(Context({...}))
if engine is None:
from .engine import Engine
engine = Engine.get_default()
if origin is None:
origin = Origin(UNKNOWN_SOURCE)
self.name = name
self.origin = origin
self.engine = engine
self.source = template_string
self.nodelist = self.compile_nodelist()

def __iter__(self):
for node in self.nodelist:
for subnode in node:
yield subnode

def _render(self, context):
return self.nodelist.render(context)

[docs]    def render(self, context):
"Display stage -- can be called many times"
context.render_context.push()
try:
if context.template is None:
with context.bind_template(self):
context.template_name = self.name
return self._render(context)
else:
return self._render(context)
finally:
context.render_context.pop()

def compile_nodelist(self):
"""
Parse and compile the template source into a nodelist. If debug
is True and an exception occurs during parsing, the exception is
is annotated with contextual line information where it occurred in the
template source.
"""
if self.engine.debug:
lexer = DebugLexer(self.source)
else:
lexer = Lexer(self.source)

tokens = lexer.tokenize()
parser = Parser(
tokens, self.engine.template_libraries, self.engine.template_builtins,
self.origin,
)

try:
return parser.parse()
except Exception as e:
if self.engine.debug:
e.template_debug = self.get_exception_info(e, e.token)
raise

def get_exception_info(self, exception, token):
"""
Return a dictionary containing contextual line information of where
the exception occurred in the template. The following information is
provided:

message
The message of the exception raised.

source_lines
The lines before, after, and including the line the exception
occurred on.

line
The line number the exception occurred on.

before, during, after
The line the exception occurred on split into three parts:
1. The content before the token that raised the error.
2. The token that raised the error.
3. The content after the token that raised the error.

total
The number of lines in source_lines.

top
The line number where source_lines starts.

bottom
The line number where source_lines ends.

start
The start position of the token in the template source.

end
The end position of the token in the template source.
"""
start, end = token.position
context_lines = 10
line = 0
upto = 0
source_lines = []
before = during = after = ""
for num, next in enumerate(linebreak_iter(self.source)):
if start >= upto and end <= next:
line = num
before = escape(self.source[upto:start])
during = escape(self.source[start:end])
after = escape(self.source[end:next])
source_lines.append((num, escape(self.source[upto:next])))
upto = next
total = len(source_lines)

top = max(1, line - context_lines)
bottom = min(total, line + 1 + context_lines)

# In some rare cases exc_value.args can be empty or an invalid
# unicode string.
try:
message = force_text(exception.args[0])
except (IndexError, UnicodeDecodeError):
message = '(Could not get exception message)'

return {
'message': message,
'source_lines': source_lines[top:bottom],
'before': before,
'during': during,
'after': after,
'top': top,
'bottom': bottom,
'total': total,
'line': line,
'name': self.origin.name,
'start': start,
'end': end,
}

def linebreak_iter(template_source):
yield 0
p = template_source.find('\n')
while p >= 0:
yield p + 1
p = template_source.find('\n', p + 1)
yield len(template_source) + 1

class Token(object):
def __init__(self, token_type, contents, position=None, lineno=None):
"""
A token representing a string from the template.

token_type
One of TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK, or TOKEN_COMMENT.

contents
The token source string.

position
An optional tuple containing the start and end index of the token
in the template source. This is used for traceback information
when debug is on.

lineno
The line number the token appears on in the template source.
This is used for traceback information and gettext files.
"""
self.token_type, self.contents = token_type, contents
self.lineno = lineno
self.position = position

def __str__(self):
token_name = TOKEN_MAPPING[self.token_type]
return ('<%s token: "%s...">' %
(token_name, self.contents[:20].replace('\n', '')))

def split_contents(self):
split = []
bits = iter(smart_split(self.contents))
for bit in bits:
# Handle translation-marked template pieces
if bit.startswith(('_("', "_('")):
sentinel = bit[2] + ')'
trans_bit = [bit]
while not bit.endswith(sentinel):
bit = next(bits)
trans_bit.append(bit)
bit = ' '.join(trans_bit)
split.append(bit)
return split

class Lexer(object):
def __init__(self, template_string):
self.template_string = template_string
self.verbatim = False

def tokenize(self):
"""
Return a list of tokens from a given template_string.
"""
in_tag = False
lineno = 1
result = []
for bit in tag_re.split(self.template_string):
if bit:
result.append(self.create_token(bit, None, lineno, in_tag))
in_tag = not in_tag
lineno += bit.count('\n')
return result

def create_token(self, token_string, position, lineno, in_tag):
"""
Convert the given token string into a new Token object and return it.
If in_tag is True, we are processing something that matched a tag,
otherwise it should be treated as a literal string.
"""
if in_tag and token_string.startswith(BLOCK_TAG_START):
# The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.
# We could do len(BLOCK_TAG_START) to be more "correct", but we've
# hard-coded the 2s here for performance. And it's not like
# the TAG_START values are going to change anytime, anyway.
block_content = token_string[2:-2].strip()
if self.verbatim and block_content == self.verbatim:
self.verbatim = False
if in_tag and not self.verbatim:
if token_string.startswith(VARIABLE_TAG_START):
token = Token(TOKEN_VAR, token_string[2:-2].strip(), position, lineno)
elif token_string.startswith(BLOCK_TAG_START):
if block_content[:9] in ('verbatim', 'verbatim '):
self.verbatim = 'end%s' % block_content
token = Token(TOKEN_BLOCK, block_content, position, lineno)
elif token_string.startswith(COMMENT_TAG_START):
content = ''
if token_string.find(TRANSLATOR_COMMENT_MARK):
content = token_string[2:-2].strip()
token = Token(TOKEN_COMMENT, content, position, lineno)
else:
token = Token(TOKEN_TEXT, token_string, position, lineno)
return token

class DebugLexer(Lexer):
def tokenize(self):
"""
Split a template string into tokens and annotates each token with its
start and end position in the source. This is slower than the default
lexer so we only use it when debug is True.
"""
lineno = 1
result = []
upto = 0
for match in tag_re.finditer(self.template_string):
start, end = match.span()
if start > upto:
token_string = self.template_string[upto:start]
result.append(self.create_token(token_string, (upto, start), lineno, in_tag=False))
lineno += token_string.count('\n')
upto = start
token_string = self.template_string[start:end]
result.append(self.create_token(token_string, (start, end), lineno, in_tag=True))
lineno += token_string.count('\n')
upto = end
last_bit = self.template_string[upto:]
if last_bit:
result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), lineno, in_tag=False))
return result

class Parser(object):
def __init__(self, tokens, libraries=None, builtins=None, origin=None):
self.tokens = tokens
self.tags = {}
self.filters = {}
self.command_stack = []

if libraries is None:
libraries = {}
if builtins is None:
builtins = []

self.libraries = libraries
for builtin in builtins:
self.add_library(builtin)
self.origin = origin

def parse(self, parse_until=None):
"""
Iterate through the parser tokens and compiles each one into a node.

If parse_until is provided, parsing will stop once one of the
specified tokens has been reached. This is formatted as a list of
tokens, e.g. ['elif', 'else', 'endif']. If no matching token is
reached, raise an exception with the unclosed block tag details.
"""
if parse_until is None:
parse_until = []
nodelist = NodeList()
while self.tokens:
token = self.next_token()
# Use the raw values here for TOKEN_* for a tiny performance boost.
if token.token_type == 0:  # TOKEN_TEXT
self.extend_nodelist(nodelist, TextNode(token.contents), token)
elif token.token_type == 1:  # TOKEN_VAR
if not token.contents:
raise self.error(token, 'Empty variable tag on line %d' % token.lineno)
try:
filter_expression = self.compile_filter(token.contents)
except TemplateSyntaxError as e:
raise self.error(token, e)
var_node = VariableNode(filter_expression)
self.extend_nodelist(nodelist, var_node, token)
elif token.token_type == 2:  # TOKEN_BLOCK
try:
command = token.contents.split()[0]
except IndexError:
raise self.error(token, 'Empty block tag on line %d' % token.lineno)
if command in parse_until:
# A matching token has been reached. Return control to
# the caller. Put the token back on the token list so the
# caller knows where it terminated.
self.prepend_token(token)
return nodelist
# Add the token to the command stack. This is used for error
# messages if further parsing fails due to an unclosed block
# tag.
self.command_stack.append((command, token))
# Get the tag callback function from the ones registered with
# the parser.
try:
compile_func = self.tags[command]
except KeyError:
self.invalid_block_tag(token, command, parse_until)
# Compile the callback into a node object and add it to
# the node list.
try:
compiled_result = compile_func(self, token)
except Exception as e:
raise self.error(token, e)
self.extend_nodelist(nodelist, compiled_result, token)
# Compile success. Remove the token from the command stack.
self.command_stack.pop()
if parse_until:
self.unclosed_block_tag(parse_until)
return nodelist

def skip_past(self, endtag):
while self.tokens:
token = self.next_token()
if token.token_type == TOKEN_BLOCK and token.contents == endtag:
return
self.unclosed_block_tag([endtag])

def extend_nodelist(self, nodelist, node, token):
# Check that non-text nodes don't appear before an extends tag.
if node.must_be_first and nodelist.contains_nontext:
raise self.error(
token, '%r must be the first tag in the template.' % node,
)
if isinstance(nodelist, NodeList) and not isinstance(node, TextNode):
nodelist.contains_nontext = True
# Set origin and token here since we can't modify the node __init__()
# method.
node.token = token
node.origin = self.origin
nodelist.append(node)

def error(self, token, e):
"""
Return an exception annotated with the originating token. Since the
parser can be called recursively, check if a token is already set. This
ensures the innermost token is highlighted if an exception occurs,
e.g. a compile error within the body of an if statement.
"""
if not isinstance(e, Exception):
e = TemplateSyntaxError(e)
if not hasattr(e, 'token'):
e.token = token
return e

def invalid_block_tag(self, token, command, parse_until=None):
if parse_until:
raise self.error(
token,
"Invalid block tag on line %d: '%s', expected %s. Did you "
"forget to register or load this tag?" % (
token.lineno,
command,
get_text_list(["'%s'" % p for p in parse_until]),
),
)
raise self.error(
token,
"Invalid block tag on line %d: '%s'. Did you forget to register "
"or load this tag?" % (token.lineno, command)
)

def unclosed_block_tag(self, parse_until):
command, token = self.command_stack.pop()
msg = "Unclosed tag on line %d: '%s'. Looking for one of: %s." % (
token.lineno,
command,
', '.join(parse_until),
)
raise self.error(token, msg)

def next_token(self):
return self.tokens.pop(0)

def prepend_token(self, token):
self.tokens.insert(0, token)

def delete_first_token(self):
del self.tokens[0]

def add_library(self, lib):
self.tags.update(lib.tags)
self.filters.update(lib.filters)

def compile_filter(self, token):
"""
Convenient wrapper for FilterExpression
"""
return FilterExpression(token, self)

def find_filter(self, filter_name):
if filter_name in self.filters:
return self.filters[filter_name]
else:
raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)

# This only matches constant *strings* (things in quotes or marked for
# translation). Numbers are treated as variables for implementation reasons
# (so that they retain their type when passed to filters).
constant_string = r"""
(?:%(i18n_open)s%(strdq)s%(i18n_close)s|
%(i18n_open)s%(strsq)s%(i18n_close)s|
%(strdq)s|
%(strsq)s)
""" % {
'strdq': r'"[^"\\]*(?:\\.[^"\\]*)*"',  # double-quoted string
'strsq': r"'[^'\\]*(?:\\.[^'\\]*)*'",  # single-quoted string
'i18n_open': re.escape("_("),
'i18n_close': re.escape(")"),
}
constant_string = constant_string.replace("\n", "")

filter_raw_string = r"""
^(?P<constant>%(constant)s)|
^(?P<var>[%(var_chars)s]+|%(num)s)|
(?:\s*%(filter_sep)s\s*
(?P<filter_name>\w+)
(?:%(arg_sep)s
(?:
(?P<constant_arg>%(constant)s)|
(?P<var_arg>[%(var_chars)s]+|%(num)s)
)
)?
)""" % {
'constant': constant_string,
'num': r'[-+\.]?\d[\d\.e]*',
'var_chars': "\w\.",
'filter_sep': re.escape(FILTER_SEPARATOR),
'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR),
}

filter_re = re.compile(filter_raw_string, re.UNICODE | re.VERBOSE)

class FilterExpression(object):
"""
Parses a variable token and its optional filters (all as a single string),
and return a list of tuples of the filter name and arguments.
Sample::

>>> token = 'variable|default:"Default value"|date:"Y-m-d"'
>>> p = Parser('')
>>> fe = FilterExpression(token, p)
>>> len(fe.filters)
2
>>> fe.var
<Variable: 'variable'>
"""
def __init__(self, token, parser):
self.token = token
matches = filter_re.finditer(token)
var_obj = None
filters = []
upto = 0
for match in matches:
start = match.start()
if upto != start:
raise TemplateSyntaxError("Could not parse some characters: "
"%s|%s|%s" %
(token[:upto], token[upto:start],
token[start:]))
if var_obj is None:
var, constant = match.group("var", "constant")
if constant:
try:
var_obj = Variable(constant).resolve({})
except VariableDoesNotExist:
var_obj = None
elif var is None:
raise TemplateSyntaxError("Could not find variable at "
"start of %s." % token)
else:
var_obj = Variable(var)
else:
filter_name = match.group("filter_name")
args = []
constant_arg, var_arg = match.group("constant_arg", "var_arg")
if constant_arg:
args.append((False, Variable(constant_arg).resolve({})))
elif var_arg:
args.append((True, Variable(var_arg)))
filter_func = parser.find_filter(filter_name)
self.args_check(filter_name, filter_func, args)
filters.append((filter_func, args))
upto = match.end()
if upto != len(token):
raise TemplateSyntaxError("Could not parse the remainder: '%s' "
"from '%s'" % (token[upto:], token))

self.filters = filters
self.var = var_obj

def resolve(self, context, ignore_failures=False):
if isinstance(self.var, Variable):
try:
obj = self.var.resolve(context)
except VariableDoesNotExist:
if ignore_failures:
obj = None
else:
string_if_invalid = context.template.engine.string_if_invalid
if string_if_invalid:
if '%s' in string_if_invalid:
return string_if_invalid % self.var
else:
return string_if_invalid
else:
obj = string_if_invalid
else:
obj = self.var
for func, args in self.filters:
arg_vals = []
for lookup, arg in args:
if not lookup:
arg_vals.append(mark_safe(arg))
else:
arg_vals.append(arg.resolve(context))
if getattr(func, 'expects_localtime', False):
obj = template_localtime(obj, context.use_tz)
if getattr(func, 'needs_autoescape', False):
new_obj = func(obj, autoescape=context.autoescape, *arg_vals)
else:
new_obj = func(obj, *arg_vals)
if getattr(func, 'is_safe', False) and isinstance(obj, SafeData):
obj = mark_safe(new_obj)
elif isinstance(obj, EscapeData):
obj = mark_for_escaping(new_obj)
else:
obj = new_obj
return obj

def args_check(name, func, provided):
provided = list(provided)
# First argument, filter input, is implied.
plen = len(provided) + 1
# Check to see if a decorator is providing the real function.
func = getattr(func, '_decorated_function', func)

args, _, _, defaults = getargspec(func)
alen = len(args)
dlen = len(defaults or [])
# Not enough OR Too many
if plen < (alen - dlen) or plen > alen:
raise TemplateSyntaxError("%s requires %d arguments, %d provided" %
(name, alen - dlen, plen))

return True
args_check = staticmethod(args_check)

def __str__(self):
return self.token

def resolve_variable(path, context):
"""
Returns the resolved variable, which may contain attribute syntax, within
the given context.

Deprecated; use the Variable class instead.
"""
warnings.warn("resolve_variable() is deprecated. Use django.template."
"Variable(path).resolve(context) instead",
RemovedInDjango110Warning, stacklevel=2)
return Variable(path).resolve(context)

class Variable(object):
"""
A template variable, resolvable against a given context. The variable may
be a hard-coded string (if it begins and ends with single or double quote
marks)::

>>> c = {'article': {'section':'News'}}
>>> Variable('article.section').resolve(c)
'News'
>>> Variable('article').resolve(c)
{'section': 'News'}
>>> class AClass: pass
>>> c = AClass()
>>> c.article = AClass()
>>> c.article.section = 'News'

(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
"""

def __init__(self, var):
self.var = var
self.literal = None
self.lookups = None
self.translate = False
self.message_context = None

if not isinstance(var, six.string_types):
raise TypeError(
"Variable must be a string or number, got %s" % type(var))
try:
# First try to treat this variable as a number.
#
# Note that this could cause an OverflowError here that we're not
# catching. Since this should only happen at compile time, that's
# probably OK.
self.literal = float(var)

# So it's a float... is it an int? If the original value contained a
# dot or an "e" then it was a float, not an int.
if '.' not in var and 'e' not in var.lower():
self.literal = int(self.literal)

# "2." is invalid
if var.endswith('.'):
raise ValueError

except ValueError:
# A ValueError means that the variable isn't a number.
if var.startswith('_(') and var.endswith(')'):
# The result of the lookup should be translated at rendering
# time.
self.translate = True
var = var[2:-1]
# If it's wrapped with quotes (single or double), then
# we're also dealing with a literal.
try:
self.literal = mark_safe(unescape_string_literal(var))
except ValueError:
# Otherwise we'll set self.lookups so that resolve() knows we're
# dealing with a bonafide variable
if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_':
raise TemplateSyntaxError("Variables and attributes may "
"not begin with underscores: '%s'" %
var)
self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))

def resolve(self, context):
"""Resolve this variable against a given context."""
if self.lookups is not None:
# We're dealing with a variable that needs to be resolved
value = self._resolve_lookup(context)
else:
# We're dealing with a literal, so it's already been "resolved"
value = self.literal
if self.translate:
is_safe = isinstance(value, SafeData)
msgid = value.replace('%', '%%')
msgid = mark_safe(msgid) if is_safe else msgid
if self.message_context:
return pgettext_lazy(self.message_context, msgid)
else:
return ugettext_lazy(msgid)
return value

def __repr__(self):
return "<%s: %r>" % (self.__class__.__name__, self.var)

def __str__(self):
return self.var

def _resolve_lookup(self, context):
"""
Performs resolution of a real variable (i.e. not a literal) against the
given context.

As indicated by the method's name, this method is an implementation
detail and shouldn't be called by external code. Use Variable.resolve()
instead.
"""
current = context
try:  # catch-all for silent variable failures
for bit in self.lookups:
try:  # dictionary lookup
current = current[bit]
# ValueError/IndexError are for numpy.array lookup on
# numpy < 1.9 and 1.9+ respectively
except (TypeError, AttributeError, KeyError, ValueError, IndexError):
try:  # attribute lookup
# Don't return class attributes if the class is the context:
if isinstance(current, BaseContext) and getattr(type(current), bit):
raise AttributeError
current = getattr(current, bit)
except (TypeError, AttributeError) as e:
# Reraise an AttributeError raised by a @property
if (isinstance(e, AttributeError) and
not isinstance(current, BaseContext) and bit in dir(current)):
raise
try:  # list-index lookup
current = current[int(bit)]
except (IndexError,  # list index out of range
ValueError,  # invalid literal for int()
KeyError,    # current is a dict without `int(bit)` key
TypeError):  # unsubscriptable object
raise VariableDoesNotExist("Failed lookup for key "
"[%s] in %r",
(bit, current))  # missing attribute
if callable(current):
if getattr(current, 'do_not_call_in_templates', False):
pass
elif getattr(current, 'alters_data', False):
current = context.template.engine.string_if_invalid
else:
try:  # method call (assuming no args required)
current = current()
except TypeError:
try:
inspect.getcallargs(current)
except TypeError:  # arguments *were* required
current = context.template.engine.string_if_invalid  # invalid method call
else:
raise
except Exception as e:
template_name = getattr(context, 'template_name', None) or 'unknown'
logger.debug(
"Exception while resolving variable '%s' in template '%s'.",
bit,
template_name,
exc_info=True,
)

if getattr(e, 'silent_variable_failure', False):
current = context.template.engine.string_if_invalid
else:
raise

return current

class Node(object):
# Set this to True for nodes that must be first in the template (although
# they can be preceded by text nodes.
must_be_first = False
child_nodelists = ('nodelist',)
token = None

def render(self, context):
"""
Return the node rendered as a string.
"""
pass

def render_annotated(self, context):
"""
Render the node. If debug is True and an exception occurs during
rendering, the exception is annotated with contextual line information
where it occurred in the template. For internal usage this method is
preferred over using the render method directly.
"""
try:
return self.render(context)
except Exception as e:
if context.template.engine.debug and not hasattr(e, 'template_debug'):
e.template_debug = context.template.get_exception_info(e, self.token)
raise

def __iter__(self):
yield self

def get_nodes_by_type(self, nodetype):
"""
Return a list of all nodes (within this node and its nodelist)
of the given type
"""
nodes = []
if isinstance(self, nodetype):
nodes.append(self)
for attr in self.child_nodelists:
nodelist = getattr(self, attr, None)
if nodelist:
nodes.extend(nodelist.get_nodes_by_type(nodetype))
return nodes

class NodeList(list):
# Set to True the first time a non-TextNode is inserted by
# extend_nodelist().
contains_nontext = False

def render(self, context):
bits = []
for node in self:
if isinstance(node, Node):
bit = node.render_annotated(context)
else:
bit = node
bits.append(force_text(bit))
return mark_safe(''.join(bits))

def get_nodes_by_type(self, nodetype):
"Return a list of all nodes of the given type"
nodes = []
for node in self:
nodes.extend(node.get_nodes_by_type(nodetype))
return nodes

class TextNode(Node):
def __init__(self, s):
self.s = s

def __repr__(self):
rep = "<%s: %r>" % (self.__class__.__name__, self.s[:25])
return force_str(rep, 'ascii', errors='replace')

def render(self, context):
return self.s

def render_value_in_context(value, context):
"""
Converts any value to a string to become part of a rendered template. This
means escaping, if required, and conversion to a unicode object. If value
is a string, it is expected to have already been translated.
"""
value = template_localtime(value, use_tz=context.use_tz)
value = localize(value, use_l10n=context.use_l10n)
value = force_text(value)
if ((context.autoescape and not isinstance(value, SafeData)) or
isinstance(value, EscapeData)):
return conditional_escape(value)
else:
return value

class VariableNode(Node):
def __init__(self, filter_expression):
self.filter_expression = filter_expression

def __repr__(self):
return "<Variable Node: %s>" % self.filter_expression

def render(self, context):
try:
output = self.filter_expression.resolve(context)
except UnicodeDecodeError:
# Unicode conversion can fail sometimes for reasons out of our
# control (e.g. exception rendering). In that case, we fail
# quietly.
return ''
return render_value_in_context(output, context)

# Regex for token keyword arguments
kwarg_re = re.compile(r"(?:(\w+)=)?(.+)")

def token_kwargs(bits, parser, support_legacy=False):
"""
A utility method for parsing token keyword arguments.

:param bits: A list containing remainder of the token (split by spaces)
that is to be checked for arguments. Valid arguments will be removed
from this list.

:param support_legacy: If set to true ``True``, the legacy format
``1 as foo`` will be accepted. Otherwise, only the standard ``foo=1``
format is allowed.

:returns: A dictionary of the arguments retrieved from the ``bits`` token
list.

There is no requirement for all remaining token ``bits`` to be keyword
arguments, so the dictionary will be returned as soon as an invalid
argument format is reached.
"""
if not bits:
return {}
match = kwarg_re.match(bits[0])
kwarg_format = match and match.group(1)
if not kwarg_format:
if not support_legacy:
return {}
if len(bits) < 3 or bits[1] != 'as':
return {}

kwargs = {}
while bits:
if kwarg_format:
match = kwarg_re.match(bits[0])
if not match or not match.group(1):
return kwargs
key, value = match.groups()
del bits[:1]
else:
if len(bits) < 3 or bits[1] != 'as':
return kwargs
key, value = bits[2], bits[0]
del bits[:3]
kwargs[key] = parser.compile_filter(value)
if bits and not kwarg_format:
if bits[0] != 'and':
return kwargs
del bits[:1]
return kwargs

Source code for django.template.context_processors

"""
A set of request processors that return dictionaries to be merged into a
template context. Each function takes the request object as its only parameter
and returns a dictionary to add to the context.

These are referenced from the 'context_processors' option of the configuration
of a DjangoTemplates backend and used by RequestContext.
"""

from __future__ import unicode_literals

from django.conf import settings
from django.middleware.csrf import get_token
from django.utils.encoding import smart_text
from django.utils.functional import SimpleLazyObject, lazy

def csrf(request):
"""
Context processor that provides a CSRF token, or the string 'NOTPROVIDED' if
it has not been provided by either a view decorator or the middleware
"""
def _get_val():
token = get_token(request)
if token is None:
# In order to be able to provide debugging info in the
# case of misconfiguration, we use a sentinel value
# instead of returning an empty dict.
return 'NOTPROVIDED'
else:
return smart_text(token)

return {'csrf_token': SimpleLazyObject(_get_val)}

[docs]def debug(request):
"""
Returns context variables helpful for debugging.
"""
context_extras = {}
if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
context_extras['debug'] = True
from django.db import connection
# Return a lazy reference that computes connection.queries on access,
# to ensure it contains queries triggered after this function runs.
context_extras['sql_queries'] = lazy(lambda: connection.queries, list)
return context_extras

def i18n(request):
from django.utils import translation

context_extras = {}
context_extras['LANGUAGES'] = settings.LANGUAGES
context_extras['LANGUAGE_CODE'] = translation.get_language()
context_extras['LANGUAGE_BIDI'] = translation.get_language_bidi()

return context_extras

[docs]def tz(request):
from django.utils import timezone

return {'TIME_ZONE': timezone.get_current_timezone_name()}

[docs]def static(request):
"""
Adds static-related context variables to the context.
"""
return {'STATIC_URL': settings.STATIC_URL}

def media(request):
"""
Adds media-related context variables to the context.
"""
return {'MEDIA_URL': settings.MEDIA_URL}

def request(request):
return {'request': request}

Source code for django.template.context

import warnings
from contextlib import contextmanager
from copy import copy

from django.utils.deprecation import RemovedInDjango110Warning

# Hard-coded processor for easier use of CSRF protection.
_builtin_context_processors = ('django.template.context_processors.csrf',)

_current_app_undefined = object()

[docs]class ContextPopException(Exception):
"pop() has been called more times than push()"
pass

class ContextDict(dict):
def __init__(self, context, *args, **kwargs):
super(ContextDict, self).__init__(*args, **kwargs)

context.dicts.append(self)
self.context = context

def __enter__(self):
return self

def __exit__(self, *args, **kwargs):
self.context.pop()

class BaseContext(object):
def __init__(self, dict_=None):
self._reset_dicts(dict_)

def _reset_dicts(self, value=None):
builtins = {'True': True, 'False': False, 'None': None}
self.dicts = [builtins]
if value is not None:
self.dicts.append(value)

def __copy__(self):
duplicate = copy(super(BaseContext, self))
duplicate.dicts = self.dicts[:]
return duplicate

def __repr__(self):
return repr(self.dicts)

def __iter__(self):
for d in reversed(self.dicts):
yield d

def push(self, *args, **kwargs):
dicts = []
for d in args:
if isinstance(d, BaseContext):
dicts += d.dicts[1:]
else:
dicts.append(d)
return ContextDict(self, *dicts, **kwargs)

def pop(self):
if len(self.dicts) == 1:
raise ContextPopException
return self.dicts.pop()

def __setitem__(self, key, value):
"Set a variable in the current context"
self.dicts[-1][key] = value

def __getitem__(self, key):
"Get a variable's value, starting at the current context and going upward"
for d in reversed(self.dicts):
if key in d:
return d[key]
raise KeyError(key)

def __delitem__(self, key):
"Delete a variable from the current context"
del self.dicts[-1][key]

def has_key(self, key):
for d in self.dicts:
if key in d:
return True
return False

def __contains__(self, key):
return self.has_key(key)

def get(self, key, otherwise=None):
for d in reversed(self.dicts):
if key in d:
return d[key]
return otherwise

def setdefault(self, key, default=None):
try:
return self[key]
except KeyError:
self[key] = default
return default

def new(self, values=None):
"""
Returns a new context with the same properties, but with only the
values given in 'values' stored.
"""
new_context = copy(self)
new_context._reset_dicts(values)
return new_context

def flatten(self):
"""
Returns self.dicts as one dictionary
"""
flat = {}
for d in self.dicts:
flat.update(d)
return flat

def __eq__(self, other):
"""
Compares two contexts by comparing theirs 'dicts' attributes.
"""
if isinstance(other, BaseContext):
# because dictionaries can be put in different order
# we have to flatten them like in templates
return self.flatten() == other.flatten()

# if it's not comparable return false
return False

[docs]class Context(BaseContext):
"A stack container for variable context"
def __init__(self, dict_=None, autoescape=True,
current_app=_current_app_undefined,
use_l10n=None, use_tz=None):
if current_app is not _current_app_undefined:
warnings.warn(
"The current_app argument of Context is deprecated. Use "
"RequestContext and set the current_app attribute of its "
"request instead.", RemovedInDjango110Warning, stacklevel=2)
self.autoescape = autoescape
self._current_app = current_app
self.use_l10n = use_l10n
self.use_tz = use_tz
self.template_name = "unknown"
self.render_context = RenderContext()
# Set to the original template -- as opposed to extended or included
# templates -- during rendering, see bind_template.
self.template = None
super(Context, self).__init__(dict_)

@property
def current_app(self):
return None if self._current_app is _current_app_undefined else self._current_app

@property
def is_current_app_set(self):
return self._current_app is not _current_app_undefined

@contextmanager
def bind_template(self, template):
if self.template is not None:
raise RuntimeError("Context is already bound to a template")
self.template = template
try:
yield
finally:
self.template = None

def __copy__(self):
duplicate = super(Context, self).__copy__()
duplicate.render_context = copy(self.render_context)
return duplicate

[docs]    def update(self, other_dict):
"Pushes other_dict to the stack of dictionaries in the Context"
if not hasattr(other_dict, '__getitem__'):
raise TypeError('other_dict must be a mapping (dictionary-like) object.')
if isinstance(other_dict, BaseContext):
other_dict = other_dict.dicts[1:].pop()
return ContextDict(self, other_dict)

class RenderContext(BaseContext):
"""
A stack container for storing Template state.

RenderContext simplifies the implementation of template Nodes by providing a
safe place to store state between invocations of a node's `render` method.

The RenderContext also provides scoping rules that are more sensible for
'template local' variables. The render context stack is pushed before each
template is rendered, creating a fresh scope with nothing in it. Name
resolution fails if a variable is not found at the top of the RequestContext
stack. Thus, variables are local to a specific template and don't affect the
rendering of other templates as they would if they were stored in the normal
template context.
"""
def __iter__(self):
for d in self.dicts[-1]:
yield d

def has_key(self, key):
return key in self.dicts[-1]

def get(self, key, otherwise=None):
return self.dicts[-1].get(key, otherwise)

def __getitem__(self, key):
return self.dicts[-1][key]

[docs]class RequestContext(Context):
"""
This subclass of template.Context automatically populates itself using
the processors defined in the engine's configuration.
Additional processors can be specified as a list of callables
using the "processors" keyword argument.
"""
def __init__(self, request, dict_=None, processors=None,
current_app=_current_app_undefined,
use_l10n=None, use_tz=None):
# current_app isn't passed here to avoid triggering the deprecation
# warning in Context.__init__.
super(RequestContext, self).__init__(
dict_, use_l10n=use_l10n, use_tz=use_tz)
if current_app is not _current_app_undefined:
warnings.warn(
"The current_app argument of RequestContext is deprecated. "
"Set the current_app attribute of its request instead.",
RemovedInDjango110Warning, stacklevel=2)
self._current_app = current_app
self.request = request
self._processors = () if processors is None else tuple(processors)
self._processors_index = len(self.dicts)

# placeholder for context processors output
self.update({})

# empty dict for any new modifications
# (so that context processors don't overwrite them)
self.update({})

@contextmanager
def bind_template(self, template):
if self.template is not None:
raise RuntimeError("Context is already bound to a template")

self.template = template
# Set context processors according to the template engine's settings.
processors = (template.engine.template_context_processors +
self._processors)
updates = {}
for processor in processors:
updates.update(processor(self.request))
self.dicts[self._processors_index] = updates

try:
yield
finally:
self.template = None
# Unset context processors.
self.dicts[self._processors_index] = {}

def new(self, values=None):
new_context = super(RequestContext, self).new(values)
# This is for backwards-compatibility: RequestContexts created via
# Context.new don't include values from context processors.
if hasattr(new_context, '_processors_index'):
del new_context._processors_index
return new_context

def make_context(context, request=None):
"""
Create a suitable Context from a plain dict and optionally an HttpRequest.
"""
if request is None:
context = Context(context)
else:
# The following pattern is required to ensure values from
# context override those from template context processors.
original_context = context
context = RequestContext(request)
if original_context:
context.push(original_context)
return context

Source code for django.template.response

import warnings

from django.http import HttpResponse
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning

from .backends.django import DjangoTemplates, Template as BackendTemplate
from .base import Template
from .context import Context, RequestContext, _current_app_undefined
from .loader import get_template, select_template

class ContentNotRenderedError(Exception):
pass

[docs]class SimpleTemplateResponse(HttpResponse):
rendering_attrs = ['template_name', 'context_data', '_post_render_callbacks']

[docs]    def __init__(self, template, context=None, content_type=None, status=None,
charset=None, using=None):
if isinstance(template, Template):
warnings.warn(
"{}'s template argument cannot be a django.template.Template "
"anymore. It may be a backend-specific template like those "
"created by get_template().".format(self.__class__.__name__),
RemovedInDjango110Warning, stacklevel=2)
template = BackendTemplate(template, DjangoTemplates)

# It would seem obvious to call these next two members 'template' and
# 'context', but those names are reserved as part of the test Client
# API. To avoid the name collision, we use different names.
self.template_name = template
self.context_data = context

self.using = using

self._post_render_callbacks = []

# _request stores the current request object in subclasses that know
# about requests, like TemplateResponse. It's defined in the base class
# to minimize code duplication.
# It's called self._request because self.request gets overwritten by
# django.test.client.Client. Unlike template_name and context_data,
# _request should not be considered part of the public API.
self._request = None

# content argument doesn't make sense here because it will be replaced
# with rendered template so we always pass empty string in order to
# prevent errors and provide shorter signature.
super(SimpleTemplateResponse, self).__init__('', content_type, status, charset)

# _is_rendered tracks whether the template and context has been baked
# into a final response.
# Super __init__ doesn't know any better than to set self.content to
# the empty string we just gave it, which wrongly sets _is_rendered
# True, so we initialize it to False after the call to super __init__.
self._is_rendered = False

def __getstate__(self):
"""Pickling support function.

Ensures that the object can't be pickled before it has been
rendered, and that the pickled state only includes rendered
data, not the data used to construct the response.
"""
obj_dict = self.__dict__.copy()
if not self._is_rendered:
raise ContentNotRenderedError('The response content must be '
'rendered before it can be pickled.')
for attr in self.rendering_attrs:
if attr in obj_dict:
del obj_dict[attr]

return obj_dict

[docs]    def resolve_template(self, template):
"Accepts a template object, path-to-template or list of paths"
if isinstance(template, (list, tuple)):
return select_template(template, using=self.using)
elif isinstance(template, six.string_types):
return get_template(template, using=self.using)
else:
return template

def _resolve_template(self, template):
# This wrapper deprecates returning a django.template.Template in
# subclasses that override resolve_template. It can be removed in
# Django 1.10.
new_template = self.resolve_template(template)
if isinstance(new_template, Template):
warnings.warn(
"{}.resolve_template() must return a backend-specific "
"template like those created by get_template(), not a "
"{}.".format(
self.__class__.__name__, new_template.__class__.__name__),
RemovedInDjango110Warning, stacklevel=2)
new_template = BackendTemplate(new_template, DjangoTemplates)
return new_template

[docs]    def resolve_context(self, context):
return context

def _resolve_context(self, context):
# This wrapper deprecates returning a Context or a RequestContext in
# subclasses that override resolve_context. It can be removed in
# Django 1.10. If returning a Context or a RequestContext works by
# accident, it won't be an issue per se, but it won't be officially
# supported either.
new_context = self.resolve_context(context)
if isinstance(new_context, RequestContext) and self._request is None:
self._request = new_context.request
if isinstance(new_context, Context):
warnings.warn(
"{}.resolve_context() must return a dict, not a {}.".format(
self.__class__.__name__, new_context.__class__.__name__),
RemovedInDjango110Warning, stacklevel=2)
# It would be tempting to do new_context = new_context.flatten()
# here but that would cause template context processors to run for
# TemplateResponse(request, template, Context({})), which would be
# backwards-incompatible. As a consequence another deprecation
# warning will be raised when rendering the template. There isn't
# much we can do about that.
return new_context

@property
def rendered_content(self):
"""Returns the freshly rendered content for the template and context
described by the TemplateResponse.

This *does not* set the final content of the response. To set the
response content, you must either call render(), or set the
content explicitly using the value of this property.
"""
template = self._resolve_template(self.template_name)
context = self._resolve_context(self.context_data)
content = template.render(context, self._request)
return content

[docs]    def add_post_render_callback(self, callback):
"""Adds a new post-rendering callback.

If the response has already been rendered,
invoke the callback immediately.
"""
if self._is_rendered:
callback(self)
else:
self._post_render_callbacks.append(callback)

[docs]    def render(self):
"""Renders (thereby finalizing) the content of the response.

If the content has already been rendered, this is a no-op.

Returns the baked response instance.
"""
retval = self
if not self._is_rendered:
self.content = self.rendered_content
for post_callback in self._post_render_callbacks:
newretval = post_callback(retval)
if newretval is not None:
retval = newretval
return retval

@property
def is_rendered(self):
return self._is_rendered

def __iter__(self):
if not self._is_rendered:
raise ContentNotRenderedError('The response content must be '
'rendered before it can be iterated over.')
return super(SimpleTemplateResponse, self).__iter__()

@property
def content(self):
if not self._is_rendered:
raise ContentNotRenderedError('The response content must be '
'rendered before it can be accessed.')
return super(SimpleTemplateResponse, self).content

@content.setter
def content(self, value):
"""Sets the content for the response
"""
HttpResponse.content.fset(self, value)
self._is_rendered = True

[docs]class TemplateResponse(SimpleTemplateResponse):
rendering_attrs = SimpleTemplateResponse.rendering_attrs + ['_request', '_current_app']

[docs]    def __init__(self, request, template, context=None, content_type=None,
status=None, current_app=_current_app_undefined, charset=None,
using=None):
# As a convenience we'll allow callers to provide current_app without
# having to avoid needing to create the RequestContext directly
if current_app is not _current_app_undefined:
warnings.warn(
"The current_app argument of TemplateResponse is deprecated. "
"Set the current_app attribute of its request instead.",
RemovedInDjango110Warning, stacklevel=2)
request.current_app = current_app
super(TemplateResponse, self).__init__(
template, context, content_type, status, charset, using)
self._request = request

Source code for django.template.loader

import warnings

from django.utils import six
from django.utils.deprecation import (
DeprecationInstanceCheck, RemovedInDjango20Warning,
RemovedInDjango110Warning,
)

from . import engines
from .backends.django import DjangoTemplates
from .base import Origin
from .engine import (
_context_instance_undefined, _dictionary_undefined, _dirs_undefined,
)
from .exceptions import TemplateDoesNotExist
from .loaders import base

[docs]def get_template(template_name, dirs=_dirs_undefined, using=None):
"""
Loads and returns a template for the given name.

Raises TemplateDoesNotExist if no such template exists.
"""
chain = []
engines = _engine_list(using)
for engine in engines:
try:
# This is required for deprecating the dirs argument. Simply
# return engine.get_template(template_name) in Django 1.10.
if isinstance(engine, DjangoTemplates):
return engine.get_template(template_name, dirs)
elif dirs is not _dirs_undefined:
warnings.warn(
"Skipping template backend %s because its get_template "
"method doesn't support the dirs argument." % engine.name,
stacklevel=2)
else:
return engine.get_template(template_name)
except TemplateDoesNotExist as e:
chain.append(e)

raise TemplateDoesNotExist(template_name, chain=chain)

[docs]def select_template(template_name_list, dirs=_dirs_undefined, using=None):
"""
Loads and returns a template for one of the given names.

Tries names in order and returns the first template found.

Raises TemplateDoesNotExist if no such template exists.
"""
chain = []
engines = _engine_list(using)
for template_name in template_name_list:
for engine in engines:
try:
# This is required for deprecating the dirs argument. Simply
# use engine.get_template(template_name) in Django 1.10.
if isinstance(engine, DjangoTemplates):
return engine.get_template(template_name, dirs)
elif dirs is not _dirs_undefined:
warnings.warn(
"Skipping template backend %s because its get_template "
"method doesn't support the dirs argument." % engine.name,
stacklevel=2)
else:
return engine.get_template(template_name)
except TemplateDoesNotExist as e:
chain.append(e)

if template_name_list:
raise TemplateDoesNotExist(', '.join(template_name_list), chain=chain)
else:
raise TemplateDoesNotExist("No template names provided")

[docs]def render_to_string(template_name, context=None,
context_instance=_context_instance_undefined,
dirs=_dirs_undefined,
dictionary=_dictionary_undefined,
request=None, using=None):
"""
Loads a template and renders it with a context. Returns a string.

template_name may be a string or a list of strings.
"""
if (context_instance is _context_instance_undefined
and dirs is _dirs_undefined
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
if isinstance(template_name, (list, tuple)):
template = select_template(template_name, using=using)
else:
template = get_template(template_name, using=using)
return template.render(context, request)

else:
chain = []
# Some deprecated arguments were passed - use the legacy code path
for engine in _engine_list(using):
try:
# This is required for deprecating properly arguments specific
# to Django templates. Remove Engine.render_to_string() at the
# same time as this code path in Django 1.10.
if isinstance(engine, DjangoTemplates):
if request is not None:
raise ValueError(
"render_to_string doesn't support the request argument "
"when some deprecated arguments are passed.")
# Hack -- use the internal Engine instance of DjangoTemplates.
return engine.engine.render_to_string(
template_name, context, context_instance, dirs, dictionary)
elif context_instance is not _context_instance_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the context_instance argument." %
engine.name, stacklevel=2)
elif dirs is not _dirs_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the dirs argument." % engine.name,
stacklevel=2)
elif dictionary is not _dictionary_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the dictionary argument." %
engine.name, stacklevel=2)
except TemplateDoesNotExist as e:
chain.append(e)
continue

if template_name:
if isinstance(template_name, (list, tuple)):
template_name = ', '.join(template_name)
raise TemplateDoesNotExist(template_name, chain=chain)
else:
raise TemplateDoesNotExist("No template names provided")

def _engine_list(using=None):
return engines.all() if using is None else [engines[using]]

class BaseLoader(base.Loader):
_accepts_engine_in_init = False

def __init__(self, *args, **kwargs):
warnings.warn(
"django.template.loader.BaseLoader was superseded by "
"django.template.loaders.base.Loader.",
RemovedInDjango110Warning, stacklevel=2)
super(BaseLoader, self).__init__(*args, **kwargs)

class LoaderOrigin(six.with_metaclass(DeprecationInstanceCheck, Origin)):
alternative = 'django.template.Origin'
deprecation_warning = RemovedInDjango20Warning

Source code for django.template.exceptions

"""
This module contains generic exceptions used by template backends. Although,
due to historical reasons, the Django template language also internally uses
these exceptions, other exceptions specific to the DTL should not be added
here.
"""

[docs]class TemplateDoesNotExist(Exception):
"""
The exception used when a template does not exist. Accepts the following
optional arguments:

backend
The template backend class used when raising this exception.

tried
A list of sources that were tried when finding the template. This
is formatted as a list of tuples containing (origin, status), where
origin is an Origin object or duck type and status is a string with the
reason the template wasn't found.

chain
A list of intermediate TemplateDoesNotExist exceptions. This is used to
encapsulate multiple exceptions when loading templates from multiple
engines.
"""
def __init__(self, msg, tried=None, backend=None, chain=None):
self.backend = backend
if tried is None:
tried = []
self.tried = tried
if chain is None:
chain = []
self.chain = chain
super(TemplateDoesNotExist, self).__init__(msg)

[docs]class TemplateSyntaxError(Exception):
"""
The exception used for syntax errors during parsing or rendering.
"""
pass

Source code for django.template.loaders.base

import warnings

from django.template import Origin, Template, TemplateDoesNotExist
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.inspect import func_supports_parameter

[docs]class Loader(object):
# Only used to raise a deprecation warning. Remove in Django 1.10.
_accepts_engine_in_init = True

def __init__(self, engine):
self.engine = engine

def __call__(self, template_name, template_dirs=None):
# RemovedInDjango20Warning: Allow loaders to be called like functions.
return self.load_template(template_name, template_dirs)

[docs]    def get_template(self, template_name, template_dirs=None, skip=None):
"""
Calls self.get_template_sources() and returns a Template object for
the first template matching template_name. If skip is provided,
template origins in skip are ignored. This is used to avoid recursion
during template extending.
"""
tried = []

args = [template_name]
# RemovedInDjango20Warning: Add template_dirs for compatibility with
# old loaders
if func_supports_parameter(self.get_template_sources, 'template_dirs'):
args.append(template_dirs)

for origin in self.get_template_sources(*args):
if skip is not None and origin in skip:
tried.append((origin, 'Skipped'))
continue

try:
contents = self.get_contents(origin)
except TemplateDoesNotExist:
tried.append((origin, 'Source does not exist'))
continue
else:
return Template(
contents, origin, origin.template_name, self.engine,
)

raise TemplateDoesNotExist(template_name, tried=tried)

[docs]    def load_template(self, template_name, template_dirs=None):
warnings.warn(
'The load_template() method is deprecated. Use get_template() '
'instead.', RemovedInDjango20Warning,
)
source, display_name = self.load_template_source(
template_name, template_dirs,
)
origin = Origin(
name=display_name,
template_name=template_name,
loader=self,
)
try:
template = Template(source, origin, template_name, self.engine)
except TemplateDoesNotExist:
# If compiling the template we found raises TemplateDoesNotExist,
# back off to returning the source and display name for the
# template we were asked to load. This allows for correct
# identification of the actual template that does not exist.
return source, display_name
else:
return template, None

[docs]    def get_template_sources(self, template_name):
"""
An iterator that yields possible matching template paths for a
template name.
"""
raise NotImplementedError(
'subclasses of Loader must provide a get_template_sources() method'
)

[docs]    def load_template_source(self, template_name, template_dirs=None):
"""
RemovedInDjango20Warning: Returns a tuple containing the source and
origin for the given template name.
"""
raise NotImplementedError(
'subclasses of Loader must provide a load_template_source() method'
)

def reset(self):
"""
Resets any state maintained by the loader instance (e.g. cached
templates or cached loader modules).
"""
pass

@property
def supports_recursion(self):
"""
RemovedInDjango20Warning: This is an internal property used by the
ExtendsNode during the deprecation of non-recursive loaders.
"""
return hasattr(self, 'get_contents')

Source code for django.template.backends.jinja2

# Since this package contains a "django" module, this is required on Python 2.
from __future__ import absolute_import

import sys

import jinja2

from django.conf import settings
from django.template import TemplateDoesNotExist, TemplateSyntaxError
from django.utils import six
from django.utils.module_loading import import_string

from .base import BaseEngine
from .utils import csrf_input_lazy, csrf_token_lazy

[docs]class Jinja2(BaseEngine):

app_dirname = 'jinja2'

def __init__(self, params):
params = params.copy()
options = params.pop('OPTIONS').copy()
super(Jinja2, self).__init__(params)

environment = options.pop('environment', 'jinja2.Environment')
environment_cls = import_string(environment)

options.setdefault('autoescape', True)
options.setdefault('loader', jinja2.FileSystemLoader(self.template_dirs))
options.setdefault('auto_reload', settings.DEBUG)
options.setdefault('undefined',
jinja2.DebugUndefined if settings.DEBUG else jinja2.Undefined)

self.env = environment_cls(**options)

def from_string(self, template_code):
return Template(self.env.from_string(template_code))

def get_template(self, template_name):
try:
return Template(self.env.get_template(template_name))
except jinja2.TemplateNotFound as exc:
six.reraise(
TemplateDoesNotExist,
TemplateDoesNotExist(exc.name, backend=self),
sys.exc_info()[2],
)
except jinja2.TemplateSyntaxError as exc:
new = TemplateSyntaxError(exc.args)
new.template_debug = get_exception_info(exc)
six.reraise(TemplateSyntaxError, new, sys.exc_info()[2])

class Template(object):

def __init__(self, template):
self.template = template
self.origin = Origin(
name=template.filename, template_name=template.name,
)

def render(self, context=None, request=None):
if context is None:
context = {}
if request is not None:
context['request'] = request
context['csrf_input'] = csrf_input_lazy(request)
context['csrf_token'] = csrf_token_lazy(request)
return self.template.render(context)

class Origin(object):
"""
A container to hold debug information as described in the template API
documentation.
"""
def __init__(self, name, template_name):
self.name = name
self.template_name = template_name

def get_exception_info(exception):
"""
Formats exception information for display on the debug page using the
structure described in the template API documentation.
"""
context_lines = 10
lineno = exception.lineno
lines = list(enumerate(exception.source.strip().split("\n"), start=1))
during = lines[lineno - 1][1]
total = len(lines)
top = max(0, lineno - context_lines - 1)
bottom = min(total, lineno + context_lines)

return {
'name': exception.filename,
'message': exception.message,
'source_lines': lines[top:bottom],
'line': lineno,
'before': '',
'during': during,
'after': '',
'total': total,
'top': top,
'bottom': bottom,
}

Source code for django.template.backends.django

# Since this package contains a "django" module, this is required on Python 2.
from __future__ import absolute_import

import sys
import warnings
from importlib import import_module
from pkgutil import walk_packages

from django.apps import apps
from django.conf import settings
from django.template import TemplateDoesNotExist
from django.template.context import Context, RequestContext, make_context
from django.template.engine import Engine, _dirs_undefined
from django.template.library import InvalidTemplateLibrary
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning

from .base import BaseEngine

[docs]class DjangoTemplates(BaseEngine):

app_dirname = 'templates'

def __init__(self, params):
params = params.copy()
options = params.pop('OPTIONS').copy()
options.setdefault('debug', settings.DEBUG)
options.setdefault('file_charset', settings.FILE_CHARSET)
libraries = options.get('libraries', {})
options['libraries'] = self.get_templatetag_libraries(libraries)
super(DjangoTemplates, self).__init__(params)
self.engine = Engine(self.dirs, self.app_dirs, **options)

def from_string(self, template_code):
return Template(self.engine.from_string(template_code), self)

def get_template(self, template_name, dirs=_dirs_undefined):
try:
return Template(self.engine.get_template(template_name, dirs), self)
except TemplateDoesNotExist as exc:
reraise(exc, self)

def get_templatetag_libraries(self, custom_libraries):
"""
Return a collation of template tag libraries from installed
applications and the supplied custom_libraries argument.
"""
libraries = get_installed_libraries()
libraries.update(custom_libraries)
return libraries

class Template(object):

def __init__(self, template, backend):
self.template = template
self.backend = backend

@property
def origin(self):
return self.template.origin

def render(self, context=None, request=None):
# A deprecation path is required here to cover the following usage:
# >>> from django.template import Context
# >>> from django.template.loader import get_template
# >>> template = get_template('hello.html')
# >>> template.render(Context({'name': 'world'}))
# In Django 1.7 get_template() returned a django.template.Template.
# In Django 1.8 it returns a django.template.backends.django.Template.
# In Django 1.10 the isinstance checks should be removed. If passing a
# Context or a RequestContext works by accident, it won't be an issue
# per se, but it won't be officially supported either.
if isinstance(context, RequestContext):
if request is not None and request is not context.request:
raise ValueError(
"render() was called with a RequestContext and a request "
"argument which refer to different requests. Make sure "
"that the context argument is a dict or at least that "
"the two arguments refer to the same request.")
warnings.warn(
"render() must be called with a dict, not a RequestContext.",
RemovedInDjango110Warning, stacklevel=2)

elif isinstance(context, Context):
warnings.warn(
"render() must be called with a dict, not a Context.",
RemovedInDjango110Warning, stacklevel=2)

else:
context = make_context(context, request)

try:
return self.template.render(context)
except TemplateDoesNotExist as exc:
reraise(exc, self.backend)

def copy_exception(exc, backend=None):
"""
Create a new TemplateDoesNotExist. Preserve its declared attributes and
template debug data but discard __traceback__, __context__, and __cause__
to make this object suitable for keeping around (in a cache, for example).
"""
backend = backend or exc.backend
new = exc.__class__(*exc.args, tried=exc.tried, backend=backend, chain=exc.chain)
if hasattr(exc, 'template_debug'):
new.template_debug = exc.template_debug
return new

def reraise(exc, backend):
"""
Reraise TemplateDoesNotExist while maintaining template debug information.
"""
new = copy_exception(exc, backend)
six.reraise(exc.__class__, new, sys.exc_info()[2])

def get_installed_libraries():
"""
Return the built-in template tag libraries and those from installed
applications. Libraries are stored in a dictionary where keys are the
individual module names, not the full module paths. Example:
django.templatetags.i18n is stored as i18n.
"""
libraries = {}
candidates = ['django.templatetags']
candidates.extend(
'%s.templatetags' % app_config.name
for app_config in apps.get_app_configs())

for candidate in candidates:
try:
pkg = import_module(candidate)
except ImportError:
# No templatetags package defined. This is safe to ignore.
continue

if hasattr(pkg, '__path__'):
for name in get_package_libraries(pkg):
libraries[name[len(candidate) + 1:]] = name

return libraries

def get_package_libraries(pkg):
"""
Recursively yield template tag libraries defined in submodules of a
package.
"""
for entry in walk_packages(pkg.__path__, pkg.__name__ + '.'):
try:
module = import_module(entry[1])
except ImportError as e:
raise InvalidTemplateLibrary(
"Invalid template library specified. ImportError raised when "
"trying to load '%s': %s" % (entry[1], e)
)

if hasattr(module, 'register'):
yield entry[1]

Source code for django.conf.urls

import warnings
from importlib import import_module

from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import (
LocaleRegexURLResolver, RegexURLPattern, RegexURLResolver,
)
from django.utils import six
from django.utils.deprecation import (
RemovedInDjango20Warning, RemovedInDjango110Warning,
)

__all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']

handler400 = 'django.views.defaults.bad_request'
handler403 = 'django.views.defaults.permission_denied'
handler404 = 'django.views.defaults.page_not_found'
handler500 = 'django.views.defaults.server_error'

[docs]def include(arg, namespace=None, app_name=None):
if app_name and not namespace:
raise ValueError('Must specify a namespace if specifying app_name.')
if app_name:
warnings.warn(
'The app_name argument to django.conf.urls.include() is deprecated. '
'Set the app_name in the included URLconf instead.',
RemovedInDjango20Warning, stacklevel=2
)

if isinstance(arg, tuple):
# callable returning a namespace hint
try:
urlconf_module, app_name = arg
except ValueError:
if namespace:
raise ImproperlyConfigured(
'Cannot override the namespace for a dynamic module that provides a namespace'
)
warnings.warn(
'Passing a 3-tuple to django.conf.urls.include() is deprecated. '
'Pass a 2-tuple containing the list of patterns and app_name, '
'and provide the namespace argument to include() instead.',
RemovedInDjango20Warning, stacklevel=2
)
urlconf_module, app_name, namespace = arg
else:
# No namespace hint - use manually provided namespace
urlconf_module = arg

if isinstance(urlconf_module, six.string_types):
urlconf_module = import_module(urlconf_module)
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
app_name = getattr(urlconf_module, 'app_name', app_name)
if namespace and not app_name:
warnings.warn(
'Specifying a namespace in django.conf.urls.include() without '
'providing an app_name is deprecated. Set the app_name attribute '
'in the included module, or pass a 2-tuple containing the list of '
'patterns and app_name instead.',
RemovedInDjango20Warning, stacklevel=2
)

namespace = namespace or app_name

# Make sure we can iterate through the patterns (without this, some
# testcases will break).
if isinstance(patterns, (list, tuple)):
for url_pattern in patterns:
# Test if the LocaleRegexURLResolver is used within the include;
# this should throw an error since this is not allowed!
if isinstance(url_pattern, LocaleRegexURLResolver):
raise ImproperlyConfigured(
'Using i18n_patterns in an included URLconf is not allowed.')

return (urlconf_module, app_name, namespace)

[docs]def patterns(prefix, *args):
warnings.warn(
'django.conf.urls.patterns() is deprecated and will be removed in '
'Django 1.10. Update your urlpatterns to be a list of '
'django.conf.urls.url() instances instead.',
RemovedInDjango110Warning, stacklevel=2
)
pattern_list = []
for t in args:
if isinstance(t, (list, tuple)):
t = url(prefix=prefix, *t)
elif isinstance(t, RegexURLPattern):
t.add_prefix(prefix)
pattern_list.append(t)
return pattern_list

[docs]def url(regex, view, kwargs=None, name=None, prefix=''):
if isinstance(view, (list, tuple)):
# For include(...) processing.
urlconf_module, app_name, namespace = view
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
else:
if isinstance(view, six.string_types):
warnings.warn(
'Support for string view arguments to url() is deprecated and '
'will be removed in Django 1.10 (got %s). Pass the callable '
'instead.' % view,
RemovedInDjango110Warning, stacklevel=2
)
if not view:
raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
if prefix:
view = prefix + '.' + view
return RegexURLPattern(regex, view, kwargs, name)

Source code for django.conf.urls.i18n

import warnings

from django.conf import settings
from django.conf.urls import patterns, url
from django.core.urlresolvers import LocaleRegexURLResolver
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning
from django.views.i18n import set_language

[docs]def i18n_patterns(prefix, *args):
"""
Adds the language code prefix to every URL pattern within this
function. This may only be used in the root URLconf, not in an included
URLconf.
"""
if isinstance(prefix, six.string_types):
warnings.warn(
"Calling i18n_patterns() with the `prefix` argument and with tuples "
"instead of django.conf.urls.url() instances is deprecated and "
"will no longer work in Django 1.10. Use a list of "
"django.conf.urls.url() instances instead.",
RemovedInDjango110Warning, stacklevel=2
)
pattern_list = patterns(prefix, *args)
else:
pattern_list = [prefix] + list(args)
if not settings.USE_I18N:
return pattern_list
return [LocaleRegexURLResolver(pattern_list)]

urlpatterns = [
url(r'^setlang/$', set_language, name='set_language'),
]

Source code for django.apps.config

import os
from importlib import import_module

from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
from django.utils._os import upath
from django.utils.module_loading import module_has_submodule

MODELS_MODULE_NAME = 'models'

[docs]class AppConfig(object):
"""
Class representing a Django application and its configuration.
"""

def __init__(self, app_name, app_module):
# Full Python path to the application eg. 'django.contrib.admin'.
self.name = app_name

# Root module for the application eg. <module 'django.contrib.admin'
# from 'django/contrib/admin/__init__.pyc'>.
self.module = app_module

# The following attributes could be defined at the class level in a
# subclass, hence the test-and-set pattern.

# Last component of the Python path to the application eg. 'admin'.
# This value must be unique across a Django project.
if not hasattr(self, 'label'):
self.label = app_name.rpartition(".")[2]

# Human-readable name for the application eg. "Admin".
if not hasattr(self, 'verbose_name'):
self.verbose_name = self.label.title()

# Filesystem path to the application directory eg.
# u'/usr/lib/python2.7/dist-packages/django/contrib/admin'. Unicode on
# Python 2 and a str on Python 3.
if not hasattr(self, 'path'):
self.path = self._path_from_module(app_module)

# Module containing models eg. <module 'django.contrib.admin.models'
# from 'django/contrib/admin/models.pyc'>. Set by import_models().
# None if the application doesn't have a models module.
self.models_module = None

# Mapping of lower case model names to model classes. Initially set to
# None to prevent accidental access before import_models() runs.
self.models = None

def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.label)

def _path_from_module(self, module):
"""Attempt to determine app's filesystem path from its module."""
# See #21874 for extended discussion of the behavior of this method in
# various cases.
# Convert paths to list because Python 3's _NamespacePath does not
# support indexing.
paths = list(getattr(module, '__path__', []))
if len(paths) != 1:
filename = getattr(module, '__file__', None)
if filename is not None:
paths = [os.path.dirname(filename)]
else:
# For unknown reasons, sometimes the list returned by __path__
# contains duplicates that must be removed (#25246).
paths = list(set(paths))
if len(paths) > 1:
raise ImproperlyConfigured(
"The app module %r has multiple filesystem locations (%r); "
"you must configure this app with an AppConfig subclass "
"with a 'path' class attribute." % (module, paths))
elif not paths:
raise ImproperlyConfigured(
"The app module %r has no filesystem location, "
"you must configure this app with an AppConfig subclass "
"with a 'path' class attribute." % (module,))
return upath(paths[0])

@classmethod
def create(cls, entry):
"""
Factory that creates an app config from an entry in INSTALLED_APPS.
"""
try:
# If import_module succeeds, entry is a path to an app module,
# which may specify an app config class with default_app_config.
# Otherwise, entry is a path to an app config class or an error.
module = import_module(entry)

except ImportError:
# Track that importing as an app module failed. If importing as an
# app config class fails too, we'll trigger the ImportError again.
module = None

mod_path, _, cls_name = entry.rpartition('.')

# Raise the original exception when entry cannot be a path to an
# app config class.
if not mod_path:
raise

else:
try:
# If this works, the app module specifies an app config class.
entry = module.default_app_config
except AttributeError:
# Otherwise, it simply uses the default app config class.
return cls(entry, module)
else:
mod_path, _, cls_name = entry.rpartition('.')

# If we're reaching this point, we must attempt to load the app config
# class located at <mod_path>.<cls_name>
mod = import_module(mod_path)
try:
cls = getattr(mod, cls_name)
except AttributeError:
if module is None:
# If importing as an app module failed, that error probably
# contains the most informative traceback. Trigger it again.
import_module(entry)
else:
raise

# Check for obvious errors. (This check prevents duck typing, but
# it could be removed if it became a problem in practice.)
if not issubclass(cls, AppConfig):
raise ImproperlyConfigured(
"'%s' isn't a subclass of AppConfig." % entry)

# Obtain app name here rather than in AppClass.__init__ to keep
# all error checking for entries in INSTALLED_APPS in one place.
try:
app_name = cls.name
except AttributeError:
raise ImproperlyConfigured(
"'%s' must supply a name attribute." % entry)

# Ensure app_name points to a valid module.
app_module = import_module(app_name)

# Entry is a path to an app config class.
return cls(app_name, app_module)

def check_models_ready(self):
"""
Raises an exception if models haven't been imported yet.
"""
if self.models is None:
raise AppRegistryNotReady(
"Models for app '%s' haven't been imported yet." % self.label)

[docs]    def get_model(self, model_name):
"""
Returns the model with the given case-insensitive model_name.

Raises LookupError if no model exists with this name.
"""
self.check_models_ready()
try:
return self.models[model_name.lower()]
except KeyError:
raise LookupError(
"App '%s' doesn't have a '%s' model." % (self.label, model_name))

[docs]    def get_models(self, include_auto_created=False,
include_deferred=False, include_swapped=False):
"""
Returns an iterable of models.

By default, the following models aren't included:

- auto-created models for many-to-many relations without
an explicit intermediate table,
- models created to satisfy deferred attribute queries,
- models that have been swapped out.

Set the corresponding keyword argument to True to include such models.
Keyword arguments aren't documented; they're a private API.
"""
self.check_models_ready()
for model in self.models.values():
if model._deferred and not include_deferred:
continue
if model._meta.auto_created and not include_auto_created:
continue
if model._meta.swapped and not include_swapped:
continue
yield model

def import_models(self, all_models):
# Dictionary of models for this app, primarily maintained in the
# 'all_models' attribute of the Apps this AppConfig is attached to.
# Injected as a parameter because it gets populated when models are
# imported, which might happen before populate() imports models.
self.models = all_models

if module_has_submodule(self.module, MODELS_MODULE_NAME):
models_module_name = '%s.%s' % (self.name, MODELS_MODULE_NAME)
self.models_module = import_module(models_module_name)

[docs]    def ready(self):
"""
Override this method in subclasses to run code when Django starts.
"""

Source code for django.apps.registry

import sys
import threading
import warnings
from collections import Counter, OrderedDict, defaultdict
from functools import partial

from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
from django.utils import lru_cache

from .config import AppConfig

class Apps(object):
"""
A registry that stores the configuration of installed applications.

It also keeps track of models eg. to provide reverse-relations.
"""

def __init__(self, installed_apps=()):
# installed_apps is set to None when creating the master registry
# because it cannot be populated at that point. Other registries must
# provide a list of installed apps and are populated immediately.
if installed_apps is None and hasattr(sys.modules[__name__], 'apps'):
raise RuntimeError("You must supply an installed_apps argument.")

# Mapping of app labels => model names => model classes. Every time a
# model is imported, ModelBase.__new__ calls apps.register_model which
# creates an entry in all_models. All imported models are registered,
# regardless of whether they're defined in an installed application
# and whether the registry has been populated. Since it isn't possible
# to reimport a module safely (it could reexecute initialization code)
# all_models is never overridden or reset.
self.all_models = defaultdict(OrderedDict)

# Mapping of labels to AppConfig instances for installed apps.
self.app_configs = OrderedDict()

# Stack of app_configs. Used to store the current state in
# set_available_apps and set_installed_apps.
self.stored_app_configs = []

# Whether the registry is populated.
self.apps_ready = self.models_ready = self.ready = False

# Lock for thread-safe population.
self._lock = threading.Lock()

# Maps ("app_label", "modelname") tuples to lists of functions to be
# called when the corresponding model is ready. Used by this class's
# `lazy_model_operation()` and `do_pending_operations()` methods.
self._pending_operations = defaultdict(list)

# Populate apps and models, unless it's the master registry.
if installed_apps is not None:
self.populate(installed_apps)

def populate(self, installed_apps=None):
"""
Loads application configurations and models.

This method imports each application module and then each model module.

It is thread safe and idempotent, but not reentrant.
"""
if self.ready:
return

# populate() might be called by two threads in parallel on servers
# that create threads before initializing the WSGI callable.
with self._lock:
if self.ready:
return

# app_config should be pristine, otherwise the code below won't
# guarantee that the order matches the order in INSTALLED_APPS.
if self.app_configs:
raise RuntimeError("populate() isn't reentrant")

# Load app configs and app modules.
for entry in installed_apps:
if isinstance(entry, AppConfig):
app_config = entry
else:
app_config = AppConfig.create(entry)
if app_config.label in self.app_configs:
raise ImproperlyConfigured(
"Application labels aren't unique, "
"duplicates: %s" % app_config.label)

self.app_configs[app_config.label] = app_config

# Check for duplicate app names.
counts = Counter(
app_config.name for app_config in self.app_configs.values())
duplicates = [
name for name, count in counts.most_common() if count > 1]
if duplicates:
raise ImproperlyConfigured(
"Application names aren't unique, "
"duplicates: %s" % ", ".join(duplicates))

self.apps_ready = True

# Load models.
for app_config in self.app_configs.values():
all_models = self.all_models[app_config.label]
app_config.import_models(all_models)

self.clear_cache()

self.models_ready = True

for app_config in self.get_app_configs():
app_config.ready()

self.ready = True

def check_apps_ready(self):
"""
Raises an exception if all apps haven't been imported yet.
"""
if not self.apps_ready:
raise AppRegistryNotReady("Apps aren't loaded yet.")

def check_models_ready(self):
"""
Raises an exception if all models haven't been imported yet.
"""
if not self.models_ready:
raise AppRegistryNotReady("Models aren't loaded yet.")

def get_app_configs(self):
"""
Imports applications and returns an iterable of app configs.
"""
self.check_apps_ready()
return self.app_configs.values()

def get_app_config(self, app_label):
"""
Imports applications and returns an app config for the given label.

Raises LookupError if no application exists with this label.
"""
self.check_apps_ready()
try:
return self.app_configs[app_label]
except KeyError:
message = "No installed app with label '%s'." % app_label
for app_config in self.get_app_configs():
if app_config.name == app_label:
message += " Did you mean '%s'?" % app_config.label
break
raise LookupError(message)

# This method is performance-critical at least for Django's test suite.
@lru_cache.lru_cache(maxsize=None)
def get_models(self, include_auto_created=False,
include_deferred=False, include_swapped=False):
"""
Returns a list of all installed models.

By default, the following models aren't included:

- auto-created models for many-to-many relations without
an explicit intermediate table,
- models created to satisfy deferred attribute queries,
- models that have been swapped out.

Set the corresponding keyword argument to True to include such models.
"""
self.check_models_ready()

result = []
for app_config in self.app_configs.values():
result.extend(list(app_config.get_models(
include_auto_created, include_deferred, include_swapped)))
return result

def get_model(self, app_label, model_name=None):
"""
Returns the model matching the given app_label and model_name.

As a shortcut, this function also accepts a single argument in the
form <app_label>.<model_name>.

model_name is case-insensitive.

Raises LookupError if no application exists with this label, or no
model exists with this name in the application. Raises ValueError if
called with a single argument that doesn't contain exactly one dot.
"""
self.check_models_ready()
if model_name is None:
app_label, model_name = app_label.split('.')
return self.get_app_config(app_label).get_model(model_name.lower())

def register_model(self, app_label, model):
# Since this method is called when models are imported, it cannot
# perform imports because of the risk of import loops. It mustn't
# call get_app_config().
model_name = model._meta.model_name
app_models = self.all_models[app_label]
if model_name in app_models:
if (model.__name__ == app_models[model_name].__name__ and
model.__module__ == app_models[model_name].__module__):
warnings.warn(
"Model '%s.%s' was already registered. "
"Reloading models is not advised as it can lead to inconsistencies, "
"most notably with related models." % (app_label, model_name),
RuntimeWarning, stacklevel=2)
else:
raise RuntimeError(
"Conflicting '%s' models in application '%s': %s and %s." %
(model_name, app_label, app_models[model_name], model))
app_models[model_name] = model
self.do_pending_operations(model)
self.clear_cache()

def is_installed(self, app_name):
"""
Checks whether an application with this name exists in the registry.

app_name is the full name of the app eg. 'django.contrib.admin'.
"""
self.check_apps_ready()
return any(ac.name == app_name for ac in self.app_configs.values())

def get_containing_app_config(self, object_name):
"""
Look for an app config containing a given object.

object_name is the dotted Python path to the object.

Returns the app config for the inner application in case of nesting.
Returns None if the object isn't in any registered app config.
"""
self.check_apps_ready()
candidates = []
for app_config in self.app_configs.values():
if object_name.startswith(app_config.name):
subpath = object_name[len(app_config.name):]
if subpath == '' or subpath[0] == '.':
candidates.append(app_config)
if candidates:
return sorted(candidates, key=lambda ac: -len(ac.name))[0]

def get_registered_model(self, app_label, model_name):
"""
Similar to get_model(), but doesn't require that an app exists with
the given app_label.

It's safe to call this method at import time, even while the registry
is being populated.
"""
model = self.all_models[app_label].get(model_name.lower())
if model is None:
raise LookupError(
"Model '%s.%s' not registered." % (app_label, model_name))
return model

@lru_cache.lru_cache(maxsize=None)
def get_swappable_settings_name(self, to_string):
"""
For a given model string (e.g. "auth.User"), return the name of the
corresponding settings name if it refers to a swappable model. If the
referred model is not swappable, return None.

This method is decorated with lru_cache because it's performance
critical when it comes to migrations. Since the swappable settings don't
change after Django has loaded the settings, there is no reason to get
the respective settings attribute over and over again.
"""
for model in self.get_models(include_swapped=True):
swapped = model._meta.swapped
# Is this model swapped out for the model given by to_string?
if swapped and swapped == to_string:
return model._meta.swappable
# Is this model swappable and the one given by to_string?
if model._meta.swappable and model._meta.label == to_string:
return model._meta.swappable
return None

def set_available_apps(self, available):
"""
Restricts the set of installed apps used by get_app_config[s].

available must be an iterable of application names.

set_available_apps() must be balanced with unset_available_apps().

Primarily used for performance optimization in TransactionTestCase.

This method is safe is the sense that it doesn't trigger any imports.
"""
available = set(available)
installed = set(app_config.name for app_config in self.get_app_configs())
if not available.issubset(installed):
raise ValueError("Available apps isn't a subset of installed "
"apps, extra apps: %s" % ", ".join(available - installed))

self.stored_app_configs.append(self.app_configs)
self.app_configs = OrderedDict(
(label, app_config)
for label, app_config in self.app_configs.items()
if app_config.name in available)
self.clear_cache()

def unset_available_apps(self):
"""
Cancels a previous call to set_available_apps().
"""
self.app_configs = self.stored_app_configs.pop()
self.clear_cache()

def set_installed_apps(self, installed):
"""
Enables a different set of installed apps for get_app_config[s].

installed must be an iterable in the same format as INSTALLED_APPS.

set_installed_apps() must be balanced with unset_installed_apps(),
even if it exits with an exception.

Primarily used as a receiver of the setting_changed signal in tests.

This method may trigger new imports, which may add new models to the
registry of all imported models. They will stay in the registry even
after unset_installed_apps(). Since it isn't possible to replay
imports safely (eg. that could lead to registering listeners twice),
models are registered when they're imported and never removed.
"""
if not self.ready:
raise AppRegistryNotReady("App registry isn't ready yet.")
self.stored_app_configs.append(self.app_configs)
self.app_configs = OrderedDict()
self.apps_ready = self.models_ready = self.ready = False
self.clear_cache()
self.populate(installed)

def unset_installed_apps(self):
"""
Cancels a previous call to set_installed_apps().
"""
self.app_configs = self.stored_app_configs.pop()
self.apps_ready = self.models_ready = self.ready = True
self.clear_cache()

def clear_cache(self):
"""
Clears all internal caches, for methods that alter the app registry.

This is mostly used in tests.
"""
# Call expire cache on each model. This will purge
# the relation tree and the fields cache.
self.get_models.cache_clear()
if self.ready:
# Circumvent self.get_models() to prevent that the cache is refilled.
# This particularly prevents that an empty value is cached while cloning.
for app_config in self.app_configs.values():
for model in app_config.get_models(include_auto_created=True):
model._meta._expire_cache()

def lazy_model_operation(self, function, *model_keys):
"""
Take a function and a number of ("app_label", "modelname") tuples, and
when all the corresponding models have been imported and registered,
call the function with the model classes as its arguments.

The function passed to this method must accept exactly n models as
arguments, where n=len(model_keys).
"""
# If this function depends on more than one model, we recursively turn
# it into a chain of functions that accept a single model argument and
# pass each in turn to lazy_model_operation.
model_key, more_models = model_keys[0], model_keys[1:]
if more_models:
supplied_fn = function

def function(model):
next_function = partial(supplied_fn, model)
# Annotate the function with its field for retrieval in
# migrations.state.StateApps.
if getattr(supplied_fn, 'keywords', None):
next_function.field = supplied_fn.keywords.get('field')
self.lazy_model_operation(next_function, *more_models)

# If the model is already loaded, pass it to the function immediately.
# Otherwise, delay execution until the class is prepared.
try:
model_class = self.get_registered_model(*model_key)
except LookupError:
self._pending_operations[model_key].append(function)
else:
function(model_class)

def do_pending_operations(self, model):
"""
Take a newly-prepared model and pass it to each function waiting for
it. This is called at the very end of `Apps.register_model()`.
"""
key = model._meta.app_label, model._meta.model_name
for function in self._pending_operations.pop(key, []):
function(model)

apps = Apps(installed_apps=None)

Source code for unittest.runner

"""Running tests"""

import sys
import time

from . import result
from .signals import registerResult

__unittest = True

class _WritelnDecorator(object):
"""Used to decorate file-like objects with a handy 'writeln' method"""
def __init__(self,stream):
self.stream = stream

def __getattr__(self, attr):
if attr in ('stream', '__getstate__'):
raise AttributeError(attr)
return getattr(self.stream,attr)

def writeln(self, arg=None):
if arg:
self.write(arg)
self.write('\n') # text-mode streams translate to \r\n if needed

class TextTestResult(result.TestResult):
"""A test result class that can print formatted text results to a stream.

Used by TextTestRunner.
"""
separator1 = '=' * 70
separator2 = '-' * 70

def __init__(self, stream, descriptions, verbosity):
super(TextTestResult, self).__init__(stream, descriptions, verbosity)
self.stream = stream
self.showAll = verbosity > 1
self.dots = verbosity == 1
self.descriptions = descriptions

def getDescription(self, test):
doc_first_line = test.shortDescription()
if self.descriptions and doc_first_line:
return '\n'.join((str(test), doc_first_line))
else:
return str(test)

def startTest(self, test):
super(TextTestResult, self).startTest(test)
if self.showAll:
self.stream.write(self.getDescription(test))
self.stream.write(" ... ")
self.stream.flush()

def addSuccess(self, test):
super(TextTestResult, self).addSuccess(test)
if self.showAll:
self.stream.writeln("ok")
elif self.dots:
self.stream.write('.')
self.stream.flush()

def addError(self, test, err):
super(TextTestResult, self).addError(test, err)
if self.showAll:
self.stream.writeln("ERROR")
elif self.dots:
self.stream.write('E')
self.stream.flush()

def addFailure(self, test, err):
super(TextTestResult, self).addFailure(test, err)
if self.showAll:
self.stream.writeln("FAIL")
elif self.dots:
self.stream.write('F')
self.stream.flush()

def addSkip(self, test, reason):
super(TextTestResult, self).addSkip(test, reason)
if self.showAll:
self.stream.writeln("skipped {0!r}".format(reason))
elif self.dots:
self.stream.write("s")
self.stream.flush()

def addExpectedFailure(self, test, err):
super(TextTestResult, self).addExpectedFailure(test, err)
if self.showAll:
self.stream.writeln("expected failure")
elif self.dots:
self.stream.write("x")
self.stream.flush()

def addUnexpectedSuccess(self, test):
super(TextTestResult, self).addUnexpectedSuccess(test)
if self.showAll:
self.stream.writeln("unexpected success")
elif self.dots:
self.stream.write("u")
self.stream.flush()

def printErrors(self):
if self.dots or self.showAll:
self.stream.writeln()
self.printErrorList('ERROR', self.errors)
self.printErrorList('FAIL', self.failures)

def printErrorList(self, flavour, errors):
for test, err in errors:
self.stream.writeln(self.separator1)
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
self.stream.writeln(self.separator2)
self.stream.writeln("%s" % err)

class TextTestRunner(object):
"""A test runner class that displays results in textual form.

It prints out the names of tests as they are run, errors as they
occur, and a summary of the results at the end of the test run.
"""
resultclass = TextTestResult

def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
failfast=False, buffer=False, resultclass=None):
self.stream = _WritelnDecorator(stream)
self.descriptions = descriptions
self.verbosity = verbosity
self.failfast = failfast
self.buffer = buffer
if resultclass is not None:
self.resultclass = resultclass

def _makeResult(self):
return self.resultclass(self.stream, self.descriptions, self.verbosity)

def run(self, test):
"Run the given test case or test suite."
result = self._makeResult()
registerResult(result)
result.failfast = self.failfast
result.buffer = self.buffer
startTime = time.time()
startTestRun = getattr(result, 'startTestRun', None)
if startTestRun is not None:
startTestRun()
try:
test(result)
finally:
stopTestRun = getattr(result, 'stopTestRun', None)
if stopTestRun is not None:
stopTestRun()
stopTime = time.time()
timeTaken = stopTime - startTime
result.printErrors()
if hasattr(result, 'separator2'):
self.stream.writeln(result.separator2)
run = result.testsRun
self.stream.writeln("Ran %d test%s in %.3fs" %
(run, run != 1 and "s" or "", timeTaken))
self.stream.writeln()

expectedFails = unexpectedSuccesses = skipped = 0
try:
results = map(len, (result.expectedFailures,
result.unexpectedSuccesses,
result.skipped))
except AttributeError:
pass
else:
expectedFails, unexpectedSuccesses, skipped = results

infos = []
if not result.wasSuccessful():
self.stream.write("FAILED")
failed, errored = map(len, (result.failures, result.errors))
if failed:
infos.append("failures=%d" % failed)
if errored:
infos.append("errors=%d" % errored)
else:
self.stream.write("OK")
if skipped:
infos.append("skipped=%d" % skipped)
if expectedFails:
infos.append("expected failures=%d" % expectedFails)
if unexpectedSuccesses:
infos.append("unexpected successes=%d" % unexpectedSuccesses)
if infos:
self.stream.writeln(" (%s)" % (", ".join(infos),))
else:
self.stream.write("\n")
return result

Source code for unittest.loader

"""Loading unittests."""

import os
import re
import sys
import traceback
import types

from functools import cmp_to_key as _CmpToKey
from fnmatch import fnmatch

from . import case, suite

__unittest = True

# what about .pyc or .pyo (etc)
# we would need to avoid loading the same tests multiple times
# from '.py', '.pyc' *and* '.pyo'
VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)

def _make_failed_import_test(name, suiteClass):
message = 'Failed to import test module: %s\n%s' % (name, traceback.format_exc())
return _make_failed_test('ModuleImportFailure', name, ImportError(message),
suiteClass)

def _make_failed_load_tests(name, exception, suiteClass):
return _make_failed_test('LoadTestsFailure', name, exception, suiteClass)

def _make_failed_test(classname, methodname, exception, suiteClass):
def testFailure(self):
raise exception
attrs = {methodname: testFailure}
TestClass = type(classname, (case.TestCase,), attrs)
return suiteClass((TestClass(methodname),))

class TestLoader(object):
"""
This class is responsible for loading tests according to various criteria
and returning them wrapped in a TestSuite
"""
testMethodPrefix = 'test'
sortTestMethodsUsing = cmp
suiteClass = suite.TestSuite
_top_level_dir = None

def loadTestsFromTestCase(self, testCaseClass):
"""Return a suite of all tests cases contained in testCaseClass"""
if issubclass(testCaseClass, suite.TestSuite):
raise TypeError("Test cases should not be derived from TestSuite." \
" Maybe you meant to derive from TestCase?")
testCaseNames = self.getTestCaseNames(testCaseClass)
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
testCaseNames = ['runTest']
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
return loaded_suite

def loadTestsFromModule(self, module, use_load_tests=True):
"""Return a suite of all tests cases contained in the given module"""
tests = []
for name in dir(module):
obj = getattr(module, name)
if isinstance(obj, type) and issubclass(obj, case.TestCase):
tests.append(self.loadTestsFromTestCase(obj))

load_tests = getattr(module, 'load_tests', None)
tests = self.suiteClass(tests)
if use_load_tests and load_tests is not None:
try:
return load_tests(self, tests, None)
except Exception, e:
return _make_failed_load_tests(module.__name__, e,
self.suiteClass)
return tests

def loadTestsFromName(self, name, module=None):
"""Return a suite of all tests cases given a string specifier.

The name may resolve either to a module, a test case class, a
test method within a test case class, or a callable object which
returns a TestCase or TestSuite instance.

The method optionally resolves the names relative to a given module.
"""
parts = name.split('.')
if module is None:
parts_copy = parts[:]
while parts_copy:
try:
module = __import__('.'.join(parts_copy))
break
except ImportError:
del parts_copy[-1]
if not parts_copy:
raise
parts = parts[1:]
obj = module
for part in parts:
parent, obj = obj, getattr(obj, part)

if isinstance(obj, types.ModuleType):
return self.loadTestsFromModule(obj)
elif isinstance(obj, type) and issubclass(obj, case.TestCase):
return self.loadTestsFromTestCase(obj)
elif (isinstance(obj, types.UnboundMethodType) and
isinstance(parent, type) and
issubclass(parent, case.TestCase)):
name = parts[-1]
inst = parent(name)
return self.suiteClass([inst])
elif isinstance(obj, suite.TestSuite):
return obj
elif hasattr(obj, '__call__'):
test = obj()
if isinstance(test, suite.TestSuite):
return test
elif isinstance(test, case.TestCase):
return self.suiteClass([test])
else:
raise TypeError("calling %s returned %s, not a test" %
(obj, test))
else:
raise TypeError("don't know how to make test from: %s" % obj)

def loadTestsFromNames(self, names, module=None):
"""Return a suite of all tests cases found using the given sequence
of string specifiers. See 'loadTestsFromName()'.
"""
suites = [self.loadTestsFromName(name, module) for name in names]
return self.suiteClass(suites)

def getTestCaseNames(self, testCaseClass):
"""Return a sorted sequence of method names found within testCaseClass
"""
def isTestMethod(attrname, testCaseClass=testCaseClass,
prefix=self.testMethodPrefix):
return attrname.startswith(prefix) and \
hasattr(getattr(testCaseClass, attrname), '__call__')
testFnNames = filter(isTestMethod, dir(testCaseClass))
if self.sortTestMethodsUsing:
testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
return testFnNames

def discover(self, start_dir, pattern='test*.py', top_level_dir=None):
"""Find and return all test modules from the specified start
directory, recursing into subdirectories to find them. Only test files
that match the pattern will be loaded. (Using shell style pattern
matching.)

All test modules must be importable from the top level of the project.
If the start directory is not the top level directory then the top
level directory must be specified separately.

If a test package name (directory with '__init__.py') matches the
pattern then the package will be checked for a 'load_tests' function. If
this exists then it will be called with loader, tests, pattern.

If load_tests exists then discovery does  *not* recurse into the package,
load_tests is responsible for loading all tests in the package.

The pattern is deliberately not stored as a loader attribute so that
packages can continue discovery themselves. top_level_dir is stored so
load_tests does not need to pass this argument in to loader.discover().
"""
set_implicit_top = False
if top_level_dir is None and self._top_level_dir is not None:
# make top_level_dir optional if called from load_tests in a package
top_level_dir = self._top_level_dir
elif top_level_dir is None:
set_implicit_top = True
top_level_dir = start_dir

top_level_dir = os.path.abspath(top_level_dir)

if not top_level_dir in sys.path:
# all test modules must be importable from the top level directory
# should we *unconditionally* put the start directory in first
# in sys.path to minimise likelihood of conflicts between installed
# modules and development versions?
sys.path.insert(0, top_level_dir)
self._top_level_dir = top_level_dir

is_not_importable = False
if os.path.isdir(os.path.abspath(start_dir)):
start_dir = os.path.abspath(start_dir)
if start_dir != top_level_dir:
is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
else:
# support for discovery from dotted module names
try:
__import__(start_dir)
except ImportError:
is_not_importable = True
else:
the_module = sys.modules[start_dir]
top_part = start_dir.split('.')[0]
start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
if set_implicit_top:
self._top_level_dir = self._get_directory_containing_module(top_part)
sys.path.remove(top_level_dir)

if is_not_importable:
raise ImportError('Start directory is not importable: %r' % start_dir)

tests = list(self._find_tests(start_dir, pattern))
return self.suiteClass(tests)

def _get_directory_containing_module(self, module_name):
module = sys.modules[module_name]
full_path = os.path.abspath(module.__file__)

if os.path.basename(full_path).lower().startswith('__init__.py'):
return os.path.dirname(os.path.dirname(full_path))
else:
# here we have been given a module rather than a package - so
# all we can do is search the *same* directory the module is in
# should an exception be raised instead
return os.path.dirname(full_path)

def _get_name_from_path(self, path):
path = os.path.splitext(os.path.normpath(path))[0]

_relpath = os.path.relpath(path, self._top_level_dir)
assert not os.path.isabs(_relpath), "Path must be within the project"
assert not _relpath.startswith('..'), "Path must be within the project"

name = _relpath.replace(os.path.sep, '.')
return name

def _get_module_from_name(self, name):
__import__(name)
return sys.modules[name]

def _match_path(self, path, full_path, pattern):
# override this method to use alternative matching strategy
return fnmatch(path, pattern)

def _find_tests(self, start_dir, pattern):
"""Used by discovery. Yields test suites it loads."""
paths = os.listdir(start_dir)

for path in paths:
full_path = os.path.join(start_dir, path)
if os.path.isfile(full_path):
if not VALID_MODULE_NAME.match(path):
# valid Python identifiers only
continue
if not self._match_path(path, full_path, pattern):
continue
# if the test file matches, load it
name = self._get_name_from_path(full_path)
try:
module = self._get_module_from_name(name)
except:
yield _make_failed_import_test(name, self.suiteClass)
else:
mod_file = os.path.abspath(getattr(module, '__file__', full_path))
realpath = os.path.splitext(mod_file)[0]
fullpath_noext = os.path.splitext(full_path)[0]
if realpath.lower() != fullpath_noext.lower():
module_dir = os.path.dirname(realpath)
mod_name = os.path.splitext(os.path.basename(full_path))[0]
expected_dir = os.path.dirname(full_path)
msg = ("%r module incorrectly imported from %r. Expected %r. "
"Is this module globally installed?")
raise ImportError(msg % (mod_name, module_dir, expected_dir))
yield self.loadTestsFromModule(module)
elif os.path.isdir(full_path):
if not os.path.isfile(os.path.join(full_path, '__init__.py')):
continue

load_tests = None
tests = None
if fnmatch(path, pattern):
# only check load_tests if the package directory itself matches the filter
name = self._get_name_from_path(full_path)
package = self._get_module_from_name(name)
load_tests = getattr(package, 'load_tests', None)
tests = self.loadTestsFromModule(package, use_load_tests=False)

if load_tests is None:
if tests is not None:
# tests loaded from package file
yield tests
# recurse into the package
for test in self._find_tests(full_path, pattern):
yield test
else:
try:
yield load_tests(self, tests, pattern)
except Exception, e:
yield _make_failed_load_tests(package.__name__, e,
self.suiteClass)

defaultTestLoader = TestLoader()

def _makeLoader(prefix, sortUsing, suiteClass=None):
loader = TestLoader()
loader.sortTestMethodsUsing = sortUsing
loader.testMethodPrefix = prefix
if suiteClass:
loader.suiteClass = suiteClass
return loader

def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)

def makeSuite(testCaseClass, prefix='test', sortUsing=cmp,
suiteClass=suite.TestSuite):
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)

def findTestCases(module, prefix='test', sortUsing=cmp,
suiteClass=suite.TestSuite):
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)

Source code for unittest.suite

"""TestSuite"""

import sys

from . import case
from . import util

__unittest = True

def _call_if_exists(parent, attr):
func = getattr(parent, attr, lambda: None)
func()

class BaseTestSuite(object):
"""A simple test suite that doesn't provide class or module shared fixtures.
"""
def __init__(self, tests=()):
self._tests = []
self.addTests(tests)

def __repr__(self):
return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))

def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return list(self) == list(other)

def __ne__(self, other):
return not self == other

# Can't guarantee hash invariant, so flag as unhashable
__hash__ = None

def __iter__(self):
return iter(self._tests)

def countTestCases(self):
cases = 0
for test in self:
cases += test.countTestCases()
return cases

def addTest(self, test):
# sanity checks
if not hasattr(test, '__call__'):
raise TypeError("{} is not callable".format(repr(test)))
if isinstance(test, type) and issubclass(test,
(case.TestCase, TestSuite)):
raise TypeError("TestCases and TestSuites must be instantiated "
"before passing them to addTest()")
self._tests.append(test)

def addTests(self, tests):
if isinstance(tests, basestring):
raise TypeError("tests must be an iterable of tests, not a string")
for test in tests:
self.addTest(test)

def run(self, result):
for test in self:
if result.shouldStop:
break
test(result)
return result

def __call__(self, *args, **kwds):
return self.run(*args, **kwds)

def debug(self):
"""Run the tests without collecting errors in a TestResult"""
for test in self:
test.debug()

class TestSuite(BaseTestSuite):
"""A test suite is a composite test consisting of a number of TestCases.

For use, create an instance of TestSuite, then add test case instances.
When all tests have been added, the suite can be passed to a test
runner, such as TextTestRunner. It will run the individual test cases
in the order in which they were added, aggregating the results. When
subclassing, do not forget to call the base class constructor.
"""

def run(self, result, debug=False):
topLevel = False
if getattr(result, '_testRunEntered', False) is False:
result._testRunEntered = topLevel = True

for test in self:
if result.shouldStop:
break

if _isnotsuite(test):
self._tearDownPreviousClass(test, result)
self._handleModuleFixture(test, result)
self._handleClassSetUp(test, result)
result._previousTestClass = test.__class__

if (getattr(test.__class__, '_classSetupFailed', False) or
getattr(result, '_moduleSetUpFailed', False)):
continue

if not debug:
test(result)
else:
test.debug()

if topLevel:
self._tearDownPreviousClass(None, result)
self._handleModuleTearDown(result)
result._testRunEntered = False
return result

def debug(self):
"""Run the tests without collecting errors in a TestResult"""
debug = _DebugResult()
self.run(debug, True)

################################

def _handleClassSetUp(self, test, result):
previousClass = getattr(result, '_previousTestClass', None)
currentClass = test.__class__
if currentClass == previousClass:
return
if result._moduleSetUpFailed:
return
if getattr(currentClass, "__unittest_skip__", False):
return

try:
currentClass._classSetupFailed = False
except TypeError:
# test may actually be a function
# so its class will be a builtin-type
pass

setUpClass = getattr(currentClass, 'setUpClass', None)
if setUpClass is not None:
_call_if_exists(result, '_setupStdout')
try:
setUpClass()
except Exception as e:
if isinstance(result, _DebugResult):
raise
currentClass._classSetupFailed = True
className = util.strclass(currentClass)
errorName = 'setUpClass (%s)' % className
self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')

def _get_previous_module(self, result):
previousModule = None
previousClass = getattr(result, '_previousTestClass', None)
if previousClass is not None:
previousModule = previousClass.__module__
return previousModule

def _handleModuleFixture(self, test, result):
previousModule = self._get_previous_module(result)
currentModule = test.__class__.__module__
if currentModule == previousModule:
return

self._handleModuleTearDown(result)

result._moduleSetUpFailed = False
try:
module = sys.modules[currentModule]
except KeyError:
return
setUpModule = getattr(module, 'setUpModule', None)
if setUpModule is not None:
_call_if_exists(result, '_setupStdout')
try:
setUpModule()
except Exception, e:
if isinstance(result, _DebugResult):
raise
result._moduleSetUpFailed = True
errorName = 'setUpModule (%s)' % currentModule
self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')

def _addClassOrModuleLevelException(self, result, exception, errorName):
error = _ErrorHolder(errorName)
addSkip = getattr(result, 'addSkip', None)
if addSkip is not None and isinstance(exception, case.SkipTest):
addSkip(error, str(exception))
else:
result.addError(error, sys.exc_info())

def _handleModuleTearDown(self, result):
previousModule = self._get_previous_module(result)
if previousModule is None:
return
if result._moduleSetUpFailed:
return

try:
module = sys.modules[previousModule]
except KeyError:
return

tearDownModule = getattr(module, 'tearDownModule', None)
if tearDownModule is not None:
_call_if_exists(result, '_setupStdout')
try:
tearDownModule()
except Exception as e:
if isinstance(result, _DebugResult):
raise
errorName = 'tearDownModule (%s)' % previousModule
self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')

def _tearDownPreviousClass(self, test, result):
previousClass = getattr(result, '_previousTestClass', None)
currentClass = test.__class__
if currentClass == previousClass:
return
if getattr(previousClass, '_classSetupFailed', False):
return
if getattr(result, '_moduleSetUpFailed', False):
return
if getattr(previousClass, "__unittest_skip__", False):
return

tearDownClass = getattr(previousClass, 'tearDownClass', None)
if tearDownClass is not None:
_call_if_exists(result, '_setupStdout')
try:
tearDownClass()
except Exception, e:
if isinstance(result, _DebugResult):
raise
className = util.strclass(previousClass)
errorName = 'tearDownClass (%s)' % className
self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')

class _ErrorHolder(object):
"""
Placeholder for a TestCase inside a result. As far as a TestResult
is concerned, this looks exactly like a unit test. Used to insert
arbitrary errors into a test suite run.
"""
# Inspired by the ErrorHolder from Twisted:
# http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py

# attribute used by TestResult._exc_info_to_string
failureException = None

def __init__(self, description):
self.description = description

def id(self):
return self.description

def shortDescription(self):
return None

def __repr__(self):
return "<ErrorHolder description=%r>" % (self.description,)

def __str__(self):
return self.id()

def run(self, result):
# could call result.addError(...) - but this test-like object
# shouldn't be run anyway
pass

def __call__(self, result):
return self.run(result)

def countTestCases(self):
return 0

def _isnotsuite(test):
"A crude way to tell apart testcases and suites with duck-typing"
try:
iter(test)
except TypeError:
return True
return False

class _DebugResult(object):
"Used by the TestSuite to hold previous class when running in debug."
_previousTestClass = None
_moduleSetUpFailed = False
shouldStop = False