Take Notes from the Definitive Guide to Django

Take Notes from the Definitive Guide to Django

Installing Django: python setup.py install

Add django-admin.py to your environment path.

django-admin.py startproject mysite

It creates the following files:

__init__.py: A file required for Python; treat the directory as a package

manage.py: A command-line utility that lets you interact with this Django project

settings.py: Settings/configuration for this Django project

urls.py: a “table of contents” of the URL declarations for this Django project;

The Development Server

python manage.py runserver

The development server automatically detects changes to your Python code and reloads as necessary, so you don’t have to restart the server between changes.

CHANGING THE HOST OR THE PORT

By default, the development server runs on port 8000, listening only for local connections. You can change the server’s port:

python manage.py runserver 8080

python manage.py runserver 0.0.0.0:8080 make Django listens on any network inter-face, thus allow others to connect to the development server:

Mapping URLs to Views

A view function is simply a Python function that takes aWeb request and returns aWeb response.

URLconf is a mapping between URL patterns and the view functions that should be called for those URL patterns.

Django expects to find urlpatterns in your ROOT_URLCONF module. It defines the mapping between URLs and the code that handles those URLs.

(r'^time/$', current_datetime).

How Django Processes a Request

The command python manage.py runserver imports a file called settings.py from the same directory. This file contains setting--ROOT_URLCONF which tells Django which Python module should be used as the URLconf for this Web site.

When a request comes in, Django loads the URLconf pointed to by the ROOT_URLCONF setting. Then it checks each of the URLpatterns in that URLconf in order, comparing the requested URL with the patterns one at a time, until it finds one that matches. When it finds one that matches, it calls the view function associated with that pattern, passing an HttpRequest object as the first parameter to the function.

The view function is responsible for returning an HttpResponse object.

Dynamic URLs

/time/plus/3/ is better than /time/plus?hours=3.

Django’s URLconf system encourages pretty URLs by making it easier to use pretty URLs than not to.

Wildcard URLpatterns

(r'^time/plus/\d+/$', hours_ahead),

We pass data to view function by placing parentheses around the data in the URLpattern that we want to save.

(r'^time/plus/(\d{1,2})/$', hours_ahead),

def hours_ahead(request, offset):

Django’s Pretty Error Pages

At any point in your view, temporarily insert an assert False to trigger the error page. Then, you can view the local variables and state of the program.

The Django Template System

Any text surrounded by a pair of braces ({{ person_name }}) is a variable.

Any text that’s surrounded by curly braces and percent signs (e.g., {% if ordered_warranty %}) is a template tag.

With a filter, you can alter the display of a variable. {{ ship_date|date:"F j, Y" }}

Filters are attached using a pipe character (|), as a reference to Unix pipes.

Context Variable Lookup

You can call methods in Django templates.

t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')

t.render(Context({'var': 'hello'}))

You don’t include parentheses in the method calls, and it’s not possible to pass arguments to the methods; you can only call methods that have no required arguments.

Dots are also used to access list indices.

t = Template('Item 2 is {{ items.2 }}.')

c = Context({'items': ['apples', 'bananas', 'carrots']})

Negative list indices are not allowed. {{ items.-1 }}would cause a TemplateSyntaxError.

Summary about dot lookups

When the template system encounters a dot in a variable name, it tries the following lookups, in this order:

Dictionary lookup (e.g., foo["bar"])

Attribute lookup (e.g., foo.bar)

Method call (e.g., foo.bar())

List-index lookup (e.g., foo[bar])

The system uses the first lookup type that works. It’s short-circuiting logic.

Dot lookups can be nested multiple levels deep. {{ person.name.upper }}

Method Call Behavior

If, during the method lookup, a method raises an exception, the exception will be propagated, unless the exception has a silent_variable_failure attribute whose value is True. If the exception does have a silent_variable_failure attribute, the variable will render as an empty string,

A method call will work only if the method has no required arguments. Otherwise, the system will move to the next lookup type (list-index lookup).

Obviously, some methods have side effects, and it would be foolish at best, and possibly even a security hole, to allow the template system to access them.

To prevent methods from running, set the function attribute alters_data on the method:

def delete(self):

delete.alters_data = True

The template system won’t execute any method marked in this way.

How Invalid Variables Are Handled

By default, if a variable doesn’t exist, the template system renders it as an empty string, failing silently, rather than raising an exception.

Playing with Context Objects

You can add and delete items from a Context object using standard Python dictionary syntax:

Basic Template Tags and Filters

Comments {# This is a comment #}

A comment cannot span multiple lines. This limitation improves template parsing performance.

Filters

Template filters are simple ways of altering the value of variables before they’re displayed. {{ name|lower }}

Use a pipe (|) to apply a filter, Filters can be chained.

{{ my_text|escape|linebreaks }}

Some filters take arguments.

{{ bio|truncatewords:"30" }}

Filter arguments are always in double quotes.

addslashes: Adds a backslash before any backslash, single quote, or double quote. This is useful if the produced text is included in a JavaScript string.

date: Formats a date or datetime object according to a format string given in the parameter.

escape: Escapes ampersands, quotes, and angle brackets in the given string. This is useful for sanitizing user-submitted data and for ensuring data is valid XML or XHTML. Specifically, escapemakes these conversions:

Converts & to & etc.

length

Django doesn’t require that you use its template language.

A template cannot set a variable or change the value of a variable.

A template cannot call raw Python code.

Using Templates in Views

Template Loading

In order to use this template-loading API, first you’ll need to tell the framework where you store your templates. The place to do this is in your settings file.

A Django settings file is the place to put configuration for your Django instance, settings.py

DEBUG = True

ROOT_URLCONF = 'mysite.urls'

TEMPLATE_DIRS setting tells Django’s template-loading mechanism where to look for templates. By default, it’s an empty tuple.

TEMPLATE_DIRS = (

'/home/django/mysite/templates',

os.path.join(os.path.dirname(__file__), 'templates').replace('\\', '/'),(better way))

The “magic” Python variable __file__ is automatically set to the file name of the Python module in which the code lives.

from django.template.loader import get_template

t = get_template('current_datetime.html')

html = t.render(Context({'current_date': now}))

If get_template() cannot find the template with the given name, it raises a TemplateDoesNotExist exception.

render_to_response() return render_to_response('current_datetime.html', {'current_date': now})

The locals() Trick

It’s slightly redundant to give names for temporary variables and give names for the template variables. A built-in Python function called locals() returns a dictionary mapping all local variable names to their values. It includes all variables defined at that point in the function’s execution.

current_date = datetime.datetime.now()

return render_to_response('current_datetime.html', locals())

One thing to watch out for when using locals() is that it includes every local variable, which may comprise more variables than you actually want your template to have access to.

Subdirectories in get_template() t = get_template('dateapp/current_datetime.html')

The include Template Tag

{% include %} allows you to include the contents of another template. {% include 'nav.html' %}

If a template with the given name isn’t found,

If DEBUG is set to True, you’ll see the TemplateDoesNotExist exception on a Django error page.

If DEBUG is set to False, the tag will fail silently, displaying nothing in the place of the tag.

Template Inheritance

Template inheritance lets you build a base “skeleton” template that contains all the common parts of your site and defines “blocks” that child templates can override.

base.html defines a simple HTML skeleton document that we’ll use for all the pages on the site. Child templates can override, or add to, or leave alone the contents of the blocks.

All the {% block %} tags do is tell the template engine that a child template may override those portions of the template.

current_datetime.html:

{% extends "base.html" %}

{% block title %}The current time{% endblock %}

If you use {% extends %} in a template, it must be the first template tag in that template. Otherwise, template inheritance won’t work.

Generally, the more {% block %} tags in your base templates, the better. It’s better to have more hooks than fewer hooks.

If you find duplicating code in a number of templates, it probably means you should move that code 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.

The template name you pass to {% extends %} is loaded using the same method that get_template() uses. That is, the template name is appended to your TEMPLATE_DIRS setting.

In most cases, the argument to {% extends %} will be a string, but it can also be a variable.

Interacting with a Database: Models

Configuring the Database

Database configuration lives in the Django settings file, called settings.py by default.

Run command “python manage.py shell”

Use python manage.py shell whenever you need to drop into the Python interpreter to do Django-specific tinkering.Once you’ve entered the shell, type these commands to test your database configuration:

from django.db import connection

cursor = connection.cursor()

If nothing happens, then your database is configured properly. Otherwise, check the error message for clues about what’s wrong.

Create new app

python manage.py startapp books

Your First Model

from django.db import models

class Author(models.Model):

salutation = models.CharField(max_length=10)

Attention: maxlength was changed to max_length in Django-final-1.0.

Each model is represented by a Python class that is a subclass of django.db.models.Model.

Django can generate that CREATE TABLE statement automatically.

If you don’t define a primary key in model, Django would automatically gives every model an integer primary key field called id. Each Django model is required to have a single-column primary key.

Installing the Model

The first step is to activate these models in our Django project. We do that by adding the books app to the list of installed apps in the settings file.

INSTALLED_APPS = ('mysite.books',)

Validate the models:

python manage.py validate

Anytime you think you have problems with models, run it to check whether your models’ syntax and logic are correct.

python manage.py sqlall books generate CREATE TABLE statements for models in app.

Table names are automatically generated by combining the name of the app (books) and the lowercased name of the model (publisher, book, and author). You can override this behavior.

Django adds a primary key for each table automatically—theid fields.

Django appends "_id" to the foreign key field name.

The foreign key relationship is made explicit by a REFERENCES statement.

These CREATE TABLE statements are tailored to the database you’re using,

The sqlall command just prints output to the screen.

Django provides an easier way of committing the SQL to the database by the syncdb command.

python manage.py syncdb commit the SQL to the database by the syncdb command.

python manage.py dbshell figures out which command-line client to run, depending on DATABASE_SERVER setting.

Basic Data Access

To create an object, just import the appropriate model class and instantiate it by passing in values for each field.

To save the object to the database, call the save()method on the object. Behind the scenes, Django executes an SQL INSERT statement here.

To retrieve objects from the database, use the attribute Publisher.objects. Fetch a list of all Publisher objects in the database with the statement Publisher.objects.all().

Behind the scenes, Django executes an SQL SELECT statement here.

Adding Model String Representations

Add a method called __str__(), it tells Python how to display the “string” representation of an object.

Inserting and Updating Data

publisher_list = Publisher.objects.all();p.save()

Selecting Objects

Publisher.objects.all()

For more on the Zen of Python, try typing “import this” at a Python prompt.

objects is a manager, it takes care of all “table-level” operations on data including, most important, data lookup. All objects automatically get an objects manager; you’ll use it any time you want to look up model instances. all() is a method on the objects manager that returns all the rows in the database. Though this object looks like a list, it’s actually a QuerySet—an object that represents some set of rows from the database.

Any database lookup is going to follow this general pattern—we’ll call methods on the manager attached to the model we want to query against.

Filtering Data

Publisher.objects.filter(name="Apress Publishing")

Publisher.objects.filter(country="U.S.A.", state_province="CA")

filter() takes keyword arguments that get translated into the appropriate SQL WHERE clauses.

By default the lookups use the SQL = operator to do exact match lookups.

Other lookup types are available:

Publisher.objects.filter(name__contains="press")

Many other types of lookups are available, including icontains (case-insensitive LIKE), startswith and endswith, and range (SQL BETWEEN queries).

Retrieving Single Objects

Publisher.objects.get(name="Apress Publishing")

A query resulting in multiple objects or no object will cause an exception:

Ordering Data

Publisher.objects.order_by("name")

Publisher.objects.order_by("country", "address")

Publisher.objects.order_by("-name")

While this flexibility is useful, using order_by() all the time can be quite repetitive. Most of the time you’ll have a particular field you usually want to order by. In these cases, Django lets you attach a default ordering to the model:

class Meta:

ordering = ["name"]

This ordering = ["name"] bit tells Django that unless an ordering is given explicitly with order_by(), all publishers should be ordered by name.

Django uses the internal class Meta as a place to specify additional metadata about a model.

Chaining Lookups

Publisher.objects.filter(country="U.S.A.").order_by("-name")

Slicing Data

Publisher.objects.all()[0] (MyModel.objects.all()[:5])

This translates roughly to the following:

SELECT id, name, address, city, state_province, country, website FROM book_publisher ORDER BY name LIMIT 1;

Deleting Objects

apress.delete()

delete objects in bulk by calling delete() on the result of some lookup:

publishers = Publisher.objects.all()

publishers.delete()

The Django Administration Site

1. Activating the Admin Interface

Create a admin.py file under app dir,

from django.contrib import admin

admin.site.register(Publisher)

2. Install the admin application.

Do this by adding django.contrib.admin to your INSTALLED_APPS setting and running python manage.py syncdb. This second step will install the extra database tables the admin interface uses.

When you first ran syncdb, you were probably asked about creating a superuser. If you didn’t do so at that time, you’ll need to run django/contrib/auth/bin/create_superuser.py to create an admin user. Otherwise, you won’t be able to log in to the admin interface.

3. Add the URL pattern to your urls.py.

urlpatterns = patterns('', (r'^admin/doc/', include('django.contrib.admindocs.urls')),

(r'^admin/(.*)', admin.site.root),)

Users,Groups, and Permissions

Normal” admin users—that is, active, nonsuperuser staff members—are granted access that depends on a set of assigned permissions. Each object editable through the admin interface has three permissions: a create permission, an edit permission, and a delete permission.

Customizing the Admin Interface

class BookAdmin(admin.ModelAdmin):

admin.site.register(Book,BookAdmin)

This is same as admin.site.register(Book), show all fields.

class BookAdmin(admin.ModelAdmin):

list_display = ('title', 'publisher', 'publication_date')

list_filter = ('publisher', 'publication_date')

ordering = ('-publication_date',)

search_fields = ('title',)

The list_display option controls which columns appear in the change list table. By default, the change list displays only a single column that contains the object’s string representation.

The list_filter option creates the filtering bar on the right side of the list.

The filters show up as long as there are at least two values to choose from.

The ordering option controls the order in which the objects are presented in the admin

interface. It’s simply a list of fields by which to order the results; prefixing a field with

a minus sign reverses the given order.

Finally, the search_fields option creates a field that allows text searches.

Customizing the Admin Interface’s Look and Feel

The Django admin site is powered by Django itself, and its interfaces use Django’s own template system. admin/base_site.html lives in the Django admin template directory - django/contrib/admin/templates,

To customize this base_site.html template, copy that template into an admin subdirectory of whichever directory you’re using in TEMPLATE_DIRS.

For example, if your TEMPLATE_DIRS includes "/home/mytemplates", then copy django/contrib/admin/templates/admin/base_site.html to /home/mytemplates/admin/base_site.html. Don’t forget that admin subdirectory.Then, just edit the new admin/base_site.html file to replace the generic Django text with your own site’s name as you see fit.

You might wonder how, if TEMPLATE_DIRS was empty by default, Django found the default admin templates. The answer is that, by default, Django automatically looks for templates within a templates/ subdirectory in each application package as a fallback.

Customizing the Admin Index Page

By default, it displays all available applications, according to your INSTALLED_APPS setting, sorted by the name of the application.

The template to customize is admin/index.html.

Edit the file, and you’ll see it uses a template tag called {% get_admin_app_list as app_list %}. This tag retrieves every installed Django application. Instead of using the tag, you can hard-code links to object-specific admin pages in whatever way you think is best.

python manage.py help

Form Processing

from django.db.models import Q

def search(request):

query = request.GET.get('q', '')

if query:

qset = (

Q(title__icontains=query) |

Q(authors__first_name__icontains=query) |

Q(authors__last_name__icontains=query)

)

results = Book.objects.filter(qset).distinct()

else:

results = []

return render_to_response("books/search.html", {

"results": results,

"query": query

})

request.GET and request.POST object.

Q objects are used to build up complex queries.Technically, these Q objects comprise a QuerySet.

icontains is a case-insensitive search that uses the SQL LIKE operator in the underlying database.

Adding .distinct() to the filter lookup eliminates any duplicate results.

search.html:

<form action="." method="GET">

<label for="q">Search: </label>

<input type="text" name="q" value="{{ query|escape }}">

<input type="submit" value="Search">

</form>

{% if query %}

<h2>Results for "{{ query|escape }}":</h2>

{% if results %}

<ul>

{% for book in results %}

<li>{{ book|escape }}</l1>

{% endfor %}

</ul>

{% else %}

<p>No books found</p>

{% endif %}

{% endif %}

The form’s action is ., which means “the current URL.” This is a standard best practice: don’t use separate views for the form page and the results page—use a single one that serves the form and search results.

Everywhere query is used, we pass it through the escape filter to make sure that any potentially malicious search text is filtered out before being inserted into the page.

It’s vital that you do this with any user-submitted content! Otherwise you open your site up to cross-site scripting (XSS) attacks.

Creating a Feedback Form

forms.py

from django import forms

TOPIC_CHOICES = (

('general', 'General enquiry'),

('bug', 'Bug report'),

('suggestion', 'Suggestion'),

)

class ContactForm(forms.Form):

topic = forms.ChoiceField(choices=TOPIC_CHOICES)

message = forms.CharField()

sender = forms.EmailField(required=False)

The django.newforms module also contains a number of Field classes.

The form object itself knows how to do a number of useful things. It can validate a collection of data, it can generate its own HTML “widgets,” it can construct a set of useful error messages and, if we’re feeling lazy, it can even draw the entire form for us.

def contact(request):

form = ContactForm()

return render_to_response('contact.html', {'form': form})

Section of contact.html:

<form action="." method="POST">

<table>

{{ form.as_table }}

</table>

<p><input type="submit" value="Submit"></p>

</form>

{{ form.as_table }}. form is our ContactForm instance, as passed to render_to_response. as_table is amethod on that object that renders the form as a sequence of table rows (as_ul and as_p can also be used).

message = forms.CharField(widget=forms.Textarea())

The forms framework separates out the presentation logic for each field into a set of widgets. Each field type has a default widget, but you can easily override the default, or provide a custom widget of your own.

def contact(request):

if request.method == 'POST':

form = ContactForm(request.POST)

else:

form = ContactForm()

return render_to_response('contact.html', {'form': form})

A form instance can be in one of two states: bound or unbound. A bound instance is attached to a dictionary (or dictionary-like object) and knows how to validate and redisplay the data from it. An unbound form has no data associated with it and simply knows how to display itself.

Setting initial data

Passing data directly to the form constructor binds that data and indicates that validation should be performed. Often, though, we need to display an initial form with some of the fields prefilled, We can do this with the initial keyword argument:

form = CommentForm(initial={'sender': 'user@example.com'})

If our form will always use the same default values, we can configure them in the form definition itself:

message = forms.CharField(initial="Replace with your feedback"

Processing the Submission

The forms framework does more than just validate the data; it also converts it into Python types.

We use form.cleaned_data:

Django’s EmailMessage class, which provides advanced features such as attachments, multipart emails, and full control over email headers.

from django.core.mail import send_mail

def contact(request):

if request.method == 'POST':

form = ContactForm(request.POST)

if form.is_valid():

topic = form.cleaned_data['topic']

message = form.cleaned_data['message']

sender = form.cleaned_data.get('sender', 'noreply@example.com')

send_mail(

'Feedback from your site, topic: %s' % topic,

message, sender,

['administrator@example.com']

)

return HttpResponseRedirect('/contact/thanks/')

else:

form = ContactForm()

return render_to_response('contact.html', {'form': form})

If a user selects Refresh on a page that was displayed by a POST request, that request will be epeated. Redirect after POST is a useful pattern that can help avoid this scenario: after a successful POST has been processed, redirect the user to another page rather than returning HTML directly.

Custom Validation Rules

If our rule is something we will reuse again and again, we can create a custom field type. Most custom validations are one-off affairs, though, and can be tied directly to the form class.

def clean_message(self):

message = self.cleaned_data.get('message', '')

num_words = len(message.split())

if num_words < 4:

raise forms.ValidationError("Not enough words!")

return message

This new method will be called after the default field validator, It is important that we explicitly return the value for the field at the end of the method. This allows us to modify the value (or convert it to a different Python type) within our custom validation method. If we forget, the return statement and then None will be returned, and the original value will be lost.

A Custom Look and Feel

The quickest way to customize the form’s presentation is with CSS.

Each field widget (<input type="text">, <select>, <textarea>, or similar) can be rendered individually by accessing {{ form.fieldname }}. Any errors associated with a field are available as {{ form.fieldname.errors }}. We can use these form variables to construct a custom template for our contact form:

<form action="." method="POST">

<div class="fieldWrapper">{{ form.topic.errors }} <label for="id_topic">Feedback:</label> {{ form.topic }} </div>

</form>

{{ form.message.errors }} will display as a <ul class="errorlist"> if errors are present and a blank string if the field is valid (or the form is unbound). We can also treat form.message.errors as a Boolean or even iterate over it as a list <div class="fieldWrapper{% if form.message.errors %} errors{% endif %}">

{% if form.message.errors %}

<ol>{% for error in form.message.errors %}<li><strong>{{ error|escape }}</strong></li>{% endfor %} </ol>

{% endif %}

Creating Forms from Models

----------Changed-------

from django.forms import form_for_model

PublisherForm = form_for_model(Publisher)

---------------------------------------

ModelForm

If you’re building a database-driven app, chances are you’ll have forms that map closely to Django models. For this reason, Django provides a helper class that let you create a Form class from a Django model.

from django.forms import ModelForm

class PublisherForm(ModelForm):

class Meta:

model = Publisher

PublisherForm is a Form subclass, just like the ContactForm class we created manually earlier on. We can use it in much the same way:

Since forms derived from models are often used to save new instances of the model to the database, the form class created by form_for_model includes a convenient save() method. This deals with the common case; You’re welcome to ignore it if you want to do something a bit more involved with the submitted data.

form_for_instance() is a related method that can create a preinitialized form from an instance of amodel class. This is useful for creating “edit” forms.

Advanced Views and URLconfs

URLconf Tricks

Streamlining Function Imports

Django offers another way of specifying the view function for a particular pattern in the URLconf: you can pass a string containing the module name and function name rather than the function object itself.

(r'^now/$', 'mysite.views.current_datetime'),

(r'^now/in_london/$', 'mysite.views.now_in_london'),

Using this technique, it’s no longer necessary to import the view functions. Django automatically imports the appropriate view function the first time it’s needed, according to the string describing the name and path of the view function.

A further shortcut you can take when using the string technique is to factor out a common “view prefix.” In our URLconf example, each of the view strings starts with 'mysite.views', which is redundant to type. We can factor out that common prefix and pass it as the first argument to patterns().

urlpatterns = patterns('mysite.views',(r'^now/$', 'current_datetime'),

(r'^now/in_london/$', 'now_in_london'),)

You don’t put a trailing dot (".") in the prefix, nor do you put a leading dot in the view strings. Django puts those in automatically.

Using Multiple View Prefixes

urlpatterns = patterns('mysite.views', (r'^/?$', 'archive_index'),

(r'^(\d{4})/([a-z]{3})/$', 'archive_month'),)

urlpatterns += patterns('weblog.views', (r'^tag/(\w+)/$', 'tag'),)

urlpatterns variable can be constructed dynamically.

Special-Casing URLs in Debug Mode

Speaking of constructing urlpatterns dynamically, you might want to take advantage of this technique to alter your URLconf’s behavior while in Django’s debug mode. To do this, just check the value of the DEBUG setting at runtime.

from django.conf import settings

if settings.DEBUG:

urlpatterns += patterns('',(r'^debuginfo$', 'mysite.views.debug'),)

Using Named Groups

In all of our URLconf examples so far, we’ve used simple, non-named regular expression groups—that is, we put parentheses around parts of the URL we wanted to capture, and Django passes that captured text to the view function as a positional argument. 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.

urlpatterns = patterns('', (r'^articles/(?P<year>\d{4})/$', views.year_archive),

(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),)

The captured values are passed to view functions as keyword arguments rather than positional arguments.

With named groups, though, /articles/2006/03/ request would result in this function call: month_archive(request, year='2006', month='03')

In practice, using named groups makes your URLconfs slightly more explicit and less prone to argument-order bugs—and you can reorder the arguments in your views’ function definitions.

Understanding the Matching/Grouping Algorithm

A caveat with using named groups in a URLconf is that a single URLconf pattern cannot contain both named and non-named groups. If you do this, Django won’t throw any errors, but you’ll probably find that your URLs aren’t matching as you expect. Specifically, here’s the algorithm the URLconf parser follows with respect to named groups vs. non-named groups in a regular expression:

If there are any named arguments, it will use those, ignoring non-named arguments.

Otherwise, it will pass all non-named arguments as positional arguments.

In both cases, it will pass any extra options as keyword arguments.

Passing Extra Options to View Functions

Each pattern in a URLconf may include a third item: a dictionary of keyword arguments to pass to the view function.

urlpatterns = patterns('', (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),

(r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),)

# views.py

def foobar_view(request, template_name):

m_list = MyModel.objects.filter(is_new=True)

return render_to_response(template_name, {'m_list': m_list})

Faking Captured URLconf Values

urlpatterns = patterns('', (r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}),

(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),)

The cool thing here is that you don’t have to change your view function at all. The view function only cares that it gets month and day parameters—it doesn’t matter whether they come from the URL capturing itself or extra parameters.

Making a View Generic

urlpatterns = patterns('',(r'^events/$', views.object_list, {'model': models.Event}),

(r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),)

def object_list(request, model):

obj_list = model.objects.all()

template_name = 'mysite/%s_list.html' % model.__name__.lower()

return render_to_response(template_name, {'object_list': obj_list})

Giving a View Configuration Options

A common bit of an application to make configurable is the template name:def my_view(request, template_name):

var = do_something()

return render_to_response(template_name, {'var': var})

Understanding Precedence of Captured Values vs. Extra Options

When there’s a conflict, extra URLconf parameters get precedence over captured parameters.

urlpatterns = patterns('',(r'^mydata/(?P<id>\d+)/$', views.my_view, {'id': 3}),)

That means any request (e.g., /mydata/2/ or /mydata/432432/) will be treated as if id is set to 3, regardless of the value captured in the URL.

Using Default View Arguments

Another convenient trick is to specify default parameters for a view’s arguments. This tells the view which value to use for a parameter by default if none is specified.

urlpatterns = patterns('', (r'^blog/$', views.page), (r'^blog/page(?P<num>\d+)/$', views.page),)

def page(request, num="1"):

Special-Casing Views

Take advantage of the linear way a URLconf is processed and put the special case first.

Capturing Text in URLs

Each captured argument is sent to the view as a plain Python string, regardless of what sort of match the regular expression makes.

def day_archive(request, year, month, day)

date = datetime.date(int(year), int(month), int(day))

Including Other URLconfs

(r'^weblog/', include('mysite.blog.urls')),

(r'^photos/', include('mysite.photos.urls')),

(r'^about/$', 'mysite.views.about')

There’s an important gotcha here: the regular expressions in this example that point to an include() do not have a $ (end-of-string match character) but do include 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.

Here’s the URLconf mysite.blog.urls:

urlpatterns = patterns('', (r'^(\d\d\d\d)/$', 'mysite.blog.views.year_detail'),

(r'^(\d\d\d\d)/(\d\d)/$', 'mysite.blog.views.month_detail'),)

How Captured Parameters Work with include()

An included URLconf receives any captured parameters from parent URLconfs:

# root urls.py

urlpatterns = patterns('', (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),)

# foo/urls/blog.py

urlpatterns = patterns('',(r'^$', 'foo.views.blog_index'), (r'^archive/$', 'foo.views.blog_archive'),)

In this example, the captured username variable is passed to the included URLconf and hence, to every view function within that URLconf.

The captured parameters will always be passed to every line in the included URLconf, regardless of whether the line’s view actually accepts those parameters as valid. For this reason, this technique is useful only if you’re certain that every view in the included URLconf accepts the parameters you’re passing.

How Extra URLconf Options Work with include()

Similarly, you can pass extra URLconf options to include(), just as you can pass extra URLconf options to a normal view—as a dictionary. When you do this, each line in the included

URLconf will be passed the extra options.

Generic Views

Django ships with generic views to do the following:

Perform common “simple” tasks: redirect to a different page and render a given template.

Display list and detail pages for a single object.

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.

Using Generic Views

All of these views are used by creating configuration dictionaries in your URLconf files and passing those dictionaries as the third member of the URLconf tuple for a given pattern.

urls.py: ('^about/$', direct_to_template, {'template': 'about.html'})

Because this generic view—and all the others—is a regular view function like any other, we can reuse it inside our own views.

('^about/(w+)/$', about_pages),

def about_pages(request, page):

try:

return direct_to_template(request, template="about/%s.html" % page)

except TemplateDoesNotExist:

raise Http404()

Generic Views of Objects

To build a list page of all books, we’d use a URLconf along these lines:

from django.views.generic import list_detail

publisher_info = {"queryset" : Publisher.objects.all()}

urlpatterns = patterns('',(r'^publishers/$', list_detail.object_list, publisher_info))

We still need to write a template, however. We could explicitly tell the object_list view which template to use by including a template_name key in the extra arguments dictionary, 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". This template will be rendered against a context containing a variable called object_list that contains all the book objects.

Extending Generic Views

Making “Friendly” Template Contexts

publisher_info = {"queryset" : Publisher.objects.all(),"template_object_name" : "publisher"}

urlpatterns = patterns('', (r'^publishers/$', list_detail.object_list, publisher_info))

Providing a useful template_object_name is always a good idea.

Adding Extra Context

all generic views take an extra optional parameter, extra_context. This is a dictionary of extra objects that will be added to the template’s context.

publisher_info = {"queryset" : Publisher.objects.all(),

"extra_context" : {"publisher_list" : Publisher.objects.all()}}

This would populate a {{ publisher_list }} variable in the template context. This pattern can be used to pass any information down into the template for the generic view. It’s very handy.

The problem has to do with when the queries in extra_context are evaluated. Because this example puts Publisher.objects.all() in the URLconf, it will be evaluated only once (when the URLconf is first loaded). Once you add or remove publishers, you’ll notice that the generic view doesn’t reflect those changes until you reload the Web server.


This problem doesn’t apply to the queryset generic view argument. Since Django knows that particular QuerySet should never be cached, the generic view takes care of clearing the cache when each view is rendered.


The solution is to use a callback in extra_context instead of a value. Any callable (i.e., a function) that’s passed to extra_context will be evaluated when the view is rendered (instead of only once). You could do this with an explicitly defined function:

def get_publishers():

return Publisher.objects.all()

book_info = {"queryset" : Publisher.objects.all(),"extra_context" : {"publisher_list" : get_publishers}}

Or you could use a less obvious but shorter version that relies on the fact that Publisher.

objects.all is itself a callable:

book_info = {"queryset" : Book.objects.all(),"extra_context" : {"publisher_list" : Publisher.objects.all}}

The lack of parentheses after Publisher.objects.all; this references the function without actually calling it.

Viewing Subsets of Objects

apress_books = {"queryset": Book.objects.filter(publisher__name="Apress Publishing"),

"template_name" : "books/apress_list.html"}

(r'^publishers/$', list_detail.object_list, publisher_info),

(r'^books/apress/$', list_detail.object_list, apress_books),

Complex Filtering with Wrapper Functions

What if we wanted to write a view that displayed all the books by some arbitrary publisher? We can “wrap” the object_list generic view to avoid writing a lot of code by hand.

urlpatterns = patterns('',(r'^publishers/$', list_detail.object_list, publisher_info),

(r'^books/(\w+)/$', books_by_publisher),)

from django.http import Http404

from django.views.generic import list_detail

def books_by_publisher(request, name):

try:

publisher = Publisher.objects.get(name__iexact=name)

except Publisher.DoesNotExist:

raise Http404

return list_detail.object_list(

request,

queryset = Book.objects.filter(publisher=publisher),

template_name = "books/books_by_publisher.html",

template_object_name = "books",

extra_context = {"publisher" : publisher}

)

Performing Extra Work

def author_list_plaintext(request):

response = list_detail.object_list(

request,

queryset = Author.objects.all(),

mimetype = "text/plain",

template_name = "books/author_list.txt"

)

response["Content-Disposition"] = "attachment; filename=authors.txt"

return response

This works because the generic views return simple HttpResponse objects that can be treated like dictionaries to set HTTP headers. This Content-Disposition business, by the way, instructs the browser to download and save the page instead of displaying it in the browser.

Extending the Template Engine

Template Language Review

A template is a text document, or a normal Python string, that is marked up using the Django template language. A template can contain block tags and variables.

A block tag Block tags are surrounded by {% and %}:{% if is_logged_in %}{% else %}{% endif %}

A variable is a symbol within a template that outputs a value. Variable tags are surrounded by {{ and }}:

A context is a name-value mapping (similar to a Python dictionary) that is passed to a template.

A template renders a context by replacing the variable “holes” with values from the context and executing all block tags.

RequestContext and Context Processors

When rendering a template, you need a context. Usually this is an instance of django.template. Context, but Django also comes with a special subclass, django.template.RequestContext, that acts slightly differently. RequestContext adds a bunch of variables to your template context by default—things like the HttpRequest object or information about the currently logged-in user. Use RequestContext when you don’t want to have to specify the same set of variables in a series of templates.

RequestContext and context processors were created to solve this problem. Context processors let you specify a number of variables that get set in each context automatically—without you having to specify the variables in each render_to_response() call. The catch is that you have to use RequestContext instead of Context when you render a template.

The most low-level way of using context processors is to create some processors and pass them to RequestContext.

from django.template import loader, RequestContext

def custom_proc(request):

"A context processor that provides 'app', 'user' and 'ip_address'."

return {

'app': 'My app',

'user': request.user,

'ip_address': request.META['REMOTE_ADDR']

}

c = RequestContext(request, {'message': 'I am the fourth view.'},

processors=[custom_proc])

custom_proc is a context processor—it takes an HttpRequest object and returns a dictionary of variables to use in the template context.

RequestContext requires the First argument to be an HttpRequest object—the one that was passed into the view function in the first place (request). Second, RequestContext takes an optional processors argument, which is a list or tuple of context processor functions to use.


Each view still has the flexibility to introduce any custom template variables it might need.

To use context processors with render_to_response(). Do this with the context_instance argument.

return render_to_response('template1.html', {'message': 'I am view 1.'},

context_instance=RequestContext(request, processors=[custom_proc]))


Django provides support for global context processors.

The TEMPLATE_CONTEXT_PROCESSORS setting designates which context processors should always be applied to RequestContext. This removes the need to specify processors each time you use RequestContext.

By default, TEMPLATE_CONTEXT_PROCESSORS is set to the following:

TEMPLATE_CONTEXT_PROCESSORS = (

'django.core.context_processors.auth',

'django.core.context_processors.debug',

'django.core.context_processors.i18n',

'django.core.context_processors.media',

)

Each processor is applied in order. That is, 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.

django.core.context_processors.auth

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these variables:

user: A django.contrib.auth.models.User instance representing the currently logged-in user (or an AnonymousUser instance, if the client isn’t logged in).

messages: A list of messages (as strings) for the currently logged-in user. Behind the scenes, this variable calls request.user.get_and_delete_messages() for every request. That method collects the user’s messages and deletes them from the database.

perms: An instance of django.core.context_processors.PermWrapper, which represents the permissions the currently logged-in user has.

django.core.context_processors.debug

This processor pushes debugging information down to the template layer.

If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every RequestContext will contain these variables:

debug: The value of your DEBUG setting (either True or False). You can use this variable 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 the order in which the queries were issued.

Because debugging information is sensitive, this context processor will add variables to the context only if both of the following conditions are true:

The DEBUG setting is True.

The request came from an IP address in the INTERNAL_IPS setting.

django.core.context_processors.i18n

If this processor is enabled, every RequestContext will contain these variables:

LANGUAGES: The value of the LANGUAGES setting

LANGUAGE_CODE: request.LANGUAGE_CODE if it exists; otherwise, the value of the LANGUAGE_CODE setting

django.core.context_processors.request

If this processor is enabled, every RequestContext will contain a variable request, which is the current HttpRequest object. This processor is not enabled by default; you have to activate it.

Inside Template Loading

Generally, you’ll store templates in files on your filesystem, but you can use custom template loaders to load templates from other sources.

Django has two ways to load templates:

django.template.loader.get_template(template_name): get_template returns the compiled template (a Template object) for the template with the given name. If the template doesn’t exist, a TemplateDoesNotExist exception will be raised.

django.template.loader.select_template(template_name_list): select_template is just like get_template, except it takes a list of template names. Of the list, it returns the first template that exists. If none of the templates exist, a TemplateDoesNotExist exception will be raised.


Some of loaders are disabled by default, but you can activate them by editing the TEMPLATE_LOADERS setting. TEMPLATE_LOADERS should be a tuple of strings, where each string represents a template loader. These template loaders ship with Django:

django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.

django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.

Note that the loader performs an optimization when it is first imported: it caches a list of the INSTALLED_APPS packages that have a templates subdirectory. This loader is enabled by default.

django.template.loaders.eggs.load_template_source: This loader is just like app_directories, except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; you’ll need to enable it if you’re using eggs to distribute your application.

Extending the Template System

Creating a Template Library

Creating a template library is a two-step process:

1. Decide which Django application should house the template library. If you’ve created an application via manage.py startapp, you can put it in there, or you can create another application solely for the template library.

2. Create a templatetags directory in the appropriate Django application’s package. It should be on the same level as models.py, views.py, and so forth.

Create two empty files in the templatetags directory: an __init__.py file (to indicate to Python that this is a package containing Python code) and a file that will contain your custom tag/filter definitions. The name of the latter file is what you’ll use to load the tags later. For example, if your custom tags/filters are in a file called poll_extras.py, you’d write the following in a template:

{% load poll_extras %}

The {% load %} tag looks at your INSTALLED_APPS setting and only allows the loading of template libraries within installed Django applications. This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every Django installation.


If you write a template library that isn’t tied to any particular models/views, it’s valid and quite normal to have a Django application package that contains only a templatetags package. 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 application.


To be a valid tag library, the module must contain amodule-level variable named register that is a template.Library instance. This template.Library instance is the data structure in which all the tags and filters are registered. So, near the top of your module, insert the following:

from django import template

register = template.Library()

Writing Custom Template Filters

Custom filters are just Python functions that take one or two arguments:

The value of the variable (input)

The value of the argument, which 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 contents of the variable var and the argument "bar".

Filter functions should always return something. They shouldn’t raise exceptions, and they should fail silently. If there’s an error, they should return either the original input or an empty string, whichever makes more sense.

def cut(value, arg):

return value.replace(arg, “”)

{{ somevariable|cut:"0" }}

When 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)

The Library.filter()method takes two arguments:• The name of the filter (a string)

The filter function itself

If you’re using Python 2.4 or above, you can use register.filter() as a decorator instead:

@register.filter(name='cut')

def cut(value, arg):

If you leave off the name argument, Django will use the function’s name as the filter name.

Writing Custom Template Tags

Tags are more complex than filters, because tags can do nearly anything.

Template system works in a two-step process: compiling and rendering. To define a custom template tag, you need to tell Django how to manage both steps when it gets to your tag.

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. Thus, a compiled template is simply a list of Node objects.

When you call render() on a compiled template, the template calls render() on each Node in its node list, with the given context. The results are all concatenated 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 it encounters, the template parser 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.

Write a template tag sample, {% current_time %}, to display the current date/time, formatted according to a parameter given in the tag.

<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:

msg = '%r tag requires a single argument' % token.contents[0]

raise template.TemplateSyntaxError(msg)

return CurrentTimeNode(format_string[1:-1])

parser is the template parser object.

token.contents is a string of the raw contents of the tag.

The token.split_contents()method separates the arguments on spaces while keeping quoted strings together. Avoid using token.contents.split() (which just uses Python’s standard string-splitting semantics). It’s not as robust, as it naively splits on all spaces, including those within quoted strings.

This function is responsible for raising django.template.TemplateSyntaxError, with helpful messages, for any syntax error.

Don’t hard-code the tag’s name in your error messages, because that couples the tag’s name to your function. token.split_contents()[0] will always be the name of your tag—even when the tag has no arguments.

The function returns a CurrentTimeNode (which we’ll create shortly) containing 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 with format_string[1:-1].

Template tag compilation functions must return a Node subclass; Any other return value is an error.

Writing the Template Node

The second step in writing custom tags is to define a Node subclass that has a render() method.

import datetime

class CurrentTimeNode(template.Node):

def __init__(self, format_string):

self.format_string = format_string

def render(self, context):

now = datetime.datetime.now()

return now.strftime(self.format_string)

Like template filters, these rendering functions should fail silently instead of raising errors. The only time that template tags are allowed to raise errors is at compilation time.

Registering the Tag

Finally, you need to register the tag with your module’s Library instance. Just instantiate a template.Library instance and call its tag()method.

register.tag('current_time', do_current_time)

The tag() method takes two arguments:

The name of the template tag (string). Function will be used.

The compilation function.

It is also possible to use register.tag as a decorator in Python 2.4 and above:

@register.tag(name="current_time")

def do_current_time(parser, token):

@register.tag

def shout(parser, token):

Setting a Variable in the Context

To set a variable in the context, use dictionary assignment on the context object in the render() method.

class CurrentTimeNode2(template.Node):

def __init__(self, format_string):

self.format_string = format_string

def render(self, context):

now = datetime.datetime.now()

context['current_time'] = now.strftime(self.format_string)

return ''

Note that render() returns an empty string. render() should always return a string, so if all the template tag does is set a variable, render() should return an empty string.

{% current_time2 "%Y-%M-%d %I:%M %p" %}

<p>The time is {{ current_time }}.</p>

A cleaner solution is to make the template tag specify the name of the variable to be set, like so:

{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}

<p>The current time is {{ my_current_time }}.</p>

To do so, you’ll need to refactor both the compilation function and the Node class, as follows:

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):

now = datetime.datetime.now()

context[self.var_name] = 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:

msg = '%r tag requires arguments' % token.contents[0]

raise template.TemplateSyntaxError(msg)

m = re.search(r'(.*?) as (\w+)', arg)

if m:

fmt, var_name = m.groups()

else:

msg = '%r tag had invalid arguments' % tag_name

raise template.TemplateSyntaxError(msg)

if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")):

msg = "%r tag's argument should be in quotes" % tag_name

raise template.TemplateSyntaxError(msg)

return CurrentTimeNode3(fmt[1:-1], var_name)

Parsing Until Another Block Tag

Template tags can work as blocks containing other tags (think {% if %}, {% for %}, etc.). To create a template tag like this, use parser.parse() in your compilation function.

Here’s how the standard {% comment %} tag is 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 ''

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. So in the preceding example, nodelist is a list of all nodes between {% 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() to prevent that tag from being processed twice. Then CommentNode.render() simply returns an empty string. Anything between {% comment %} and {% endcomment %} is ignored.

Parsing Until Another Block Tag and Saving Contents

Here’s a custom template tag, {% upper %}, that capitalizes everything between itself and {% endupper %}:

This time, we pass the resulting nodelist to Node:

@register.tag

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 self.nodelist.render(context) in UpperNode.render(). This simply calls render() on each Node in the node list.

See more examples in django/template/defaulttags.py.

Shortcut for Simple Tags

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 one argument, wraps it in a render function and the other necessary bits mentioned previously, and registers it with the template system.

def current_time(format_string):

return datetime.datetime.now().strftime(format_string)

register.simple_tag(current_time)

In Python 2.4, the decorator syntax also works:

@register.simple_tag

def current_time(token):

A couple of things to notice about the simple_tag helper function are as follows:

Only the (single) argument is passed into our function.

Checking for the required number of arguments 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 receive a plain string.

Inclusion Tags

Another common template tag is the type that displays some data by rendering another template.

Let’s write a tag that produces a list of choices for a simple multiple-choice Poll object. We’ll use the tag like this:

{% show_results poll %}

def show_books_for_author(author):

books = author.book_set.all()

return {'books': books}

Next, we create the template used to render the tag’s output.

<ul>

{% for book in books %}

<li> {{ book }} </li>

{% endfor %}

</ul>

Finally, we create and register the inclusion tag by calling the inclusion_tag()method on a Library object.

Following our example, if the preceding template is in a file called polls/result_snippet.html, we register the tag like this:

register.inclusion_tag('polls/result_snippet.html')(show_results)

As always, Python 2.4 decorator syntax works as well.

@register.inclusion_tag('results.html')

def show_results(poll):

Sometimes, your inclusion tags need access to values from the parent template’s context. 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.

@register.inclusion_tag('link.html', takes_context=True)

def jump_link(context):

return {

'link': context['home_link'],

'title': context['home_title'],

}

The template link.htmlmight contain the following:

Jump directly to <a href="{{ link }}">{{ title }}</a>.

Then, anytime you want to use that custom tag, load its library and call it without any arguments, like so:

{% jump_link %}

Writing Custom Template Loaders

A template loader—that is, each entry in the TEMPLATE_LOADERS setting—is expected to be a callable with this interface:

load_template_source(template_name, template_dirs=None)

If you're using Django's render_to_response() shortcut to populate a template with the contents of a dictionary, your template will be passed a Context instance by default (not a RequestContext). To use a RequestContext in your template rendering, pass an optional third argument to render_to_response(): a RequestContext instance. Your code might look like this:

def some_view(request):

return render_to_response('my_template.html',

my_data_dictionary,

context_instance=RequestContext(request))

Sessions, Users, and Registration

Cookies

A cookie is a small piece of information that browsers store on behalf of Web servers. Every time a browser requests a page from a certain server, it gives back the cookie that it initially received.

Getting and Setting Cookies

Every request object has a COOKIES object that acts like a dictionary; you can use it to read any cookies that the browser has sent to the view.

if "favorite_color" in request.COOKIES:

request.COOKIES["favorite_color"])

Use the set_cookie()method on an HttpResponse object.

if "favorite_color" in request.GET:

response.set_cookie("favorite_color", request.GET["favorite_color"])

You can also pass a number of optional arguments to response.set_cookie() that control aspects of the cookie.

Cookie Options

Parameter Default Description

max_age None

expires None

path "/" domain None The domain that this cookie is valid for. You can use this parameter to set a cross-domain cookie. For example, domain=".example.com" will set a cookie that is readable by the domains www.example.com, www2.example.com, and an.other.sub.domain.example.com. If this parameter is set to None, a cookie will only be readable by the domain that set it.

secure False If set to True, this parameter instructs the browser to return this

cookie only to pages accessed over HTTPS.

The Mixed Blessing of Cookies

Resourceful users can always use tools like mechanize (http://wwwsearch.sourceforge.net/mechanize/) to construct HTTP requests by hand.

Django’s Session Framework

This 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 use only a hashed session ID—not the data itself—thus protecting you from most of the common cookie problems.

Enabling Sessions

1. Edit your MIDDLEWARE_CLASSES setting and make sure MIDDLEWARE_CLASSES contains 'django.contrib.sessions.middleware.SessionMiddleware'.

2. Make sure 'django.contrib.sessions' is in your INSTALLED_APPS setting (and run manage.py syncdb if you have to add it).

Using Sessions in Views

When SessionMiddleware is activated, each HttpRequest object will have a session attribute, which is a dictionary-like object.

request.session["fav_color"] = "blue"

# Get a session value -- this could be called in a different view, or many requests later (or both):

fav_color = request.session["fav_color"]

del request.session["fav_color"]

if "fav_color" in request.session:

def login(request):

try:

m = Member.objects.get(username__exact=request.POST['username'])

if m.password == request.POST['password']:

request.session['member_id'] = m.id

except Member.DoesNotExist:

return HttpResponse("Your username and password didn't match.")

def logout(request):

del request.session['member_id']

Setting Test Cookies

Django provides an easy way to test whether a user’s browser accepts cookies. You just need to call request.session.set_test_cookie() in a view and check request.session.test_cookie_worked() in a subsequent view—not in the same view call.

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.

Using Sessions Outside of Views

Internally, each session is just a normal Django model defined in django.contrib.sessions.models. Each session is identified by amore-or-less random 32-character hash stored in a cookie. 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

You’ll need to call get_decoded() to get the actual session data. This is necessary because the dictionary is stored in an encoded format:

s.session_data

s.get_decoded()

When Sessions Are Saved

By default, Django only saves to the database if the session has been modified To change this default behavior, set SESSION_SAVE_EVERY_REQUEST to True. If SESSION_SAVE_EVERY_REQUEST is True, Django will save the session to the database on every single request, even if it wasn’t changed.

Note that the session cookie is sent only 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.

Other Session Settings

Settings That Influence Cookie Behavior

Setting Default

SESSION_COOKIE_DOMAIN None

SESSION_COOKIE_NAME "sessionid"

SESSION_COOKIE_SECURE False

TECHNICAL DETAILS

Session data is stored in a database table named django_session.

Users and Authentication

Django’s auth/auth system consists of a number of parts:

Users, Permissions, Groups

Messages: A simple way to queue and display system messages to users

Profiles: Amechanism to extend the user object with custom fields

Enabling Authentication Support

  1. Make sure the session framework is installed. Keeping track of users obviously requires cookies, and thus builds on the session framework.

2. Put 'django.contrib.auth' in your INSTALLED_APPS setting and run manage.py syncdb.

3. Make sure that 'django.contrib.auth.middleware.AuthenticationMiddleware' is in your MIDDLEWARE_CLASSES setting—after SessionMiddleware.

With that installation out of the way, we’re ready to deal with users in view functions. The main interface you’ll use to access users within a view is request.user; this is an object that represents the currently logged-in user. If the user isn’t logged in, this will instead be an AnonymousUser object.

if request.user.is_authenticated():

Using Users

Fields on User Objects

date_joined A datetime designating when the account was created. This is set to the current date/time by default when the account is created.

has_perm(perm) Returns True if the user has the specified permission, where perm is in the format "package.codename".

has_perms(perm_list) Returns True if the user has all of the specified permissions.

has_module_perms(app_label) Returns True if the user has any permissions in the given appname.

get_and_delete_messages() Returns a list of Message objects in the user’s queue and deletes the messages from the queue.

get_profile()

Logging In and Out

Use methods in django.contrib.auth: authenticate() and login().

from django.contrib import auth

user = auth.authenticate(username='john', password='secret')

if user is not None:

def login(request):

username = request.POST['username']

user = auth.authenticate(username=username, password=password)

if user is not None and user.is_active:

auth.login(request, user)

# Redirect to a success page.

return HttpResponseRedirect("/account/loggedin/")

else:

return HttpResponseRedirect("/account/invalid/")

def logout(request):

auth.logout(request)

return HttpResponseRedirect("/account/loggedout/")

In practice, you usually will not need to write your own login/logout functions; the authentication system comes with a set of views for generically handling logging in and out.

The first step in using the authentication views is to wire them up in your URLconf. You’ll need to add this snippet:

from django.contrib.auth.views import login, logout

(r'^accounts/login/$', login),

(r'^accounts/logout/$', logout),

By default, the login view renders a template at registration/login.html.

If the user successfully logs in, he or she will be redirected to /accounts/profile/ by default. You can override this by providing a hidden field called next with the URL to redirect to after logging in. You can also pass this value as a GET parameter to the login view and it will be automatically added to the context as a variable called next that you can insert into that hidden field.

By default, The logout view renders a template at registration/logged_out.html (which usually contains a “You’ve successfully logged out” message). However,you can call the view with an extra argument, next_page, which will instruct the view to redirect after a logout.

Limiting Access to Logged-in Users

The simple, raw way to limit access to pages is to check request.user.is_authenticated() and redirect to a login page:

def my_view(request):

if not request.user.is_authenticated():

return HttpResponseRedirect('/login/?next=%s' % request.path)

esle

return render_to_response('myapp/login_error.html')

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 /accounts/login/, passing the current absolute URL in the query string as next, for example: /accounts/login/?next=/polls/3/.

If the user is logged in, execute the view normally. The view code can then assume that the user is logged in.

Limiting Access to Users Who Pass a Test

The raw way:

def vote(request):

if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):

Again, Django provides a shortcut called user_passes_test. It takes arguments and generates a specialized decorator for your particular situation:

def user_can_vote(user):

return user.is_authenticated() and user.has_perm("polls.can_vote")

@user_passes_text(user_can_vote, login_url="/login/")

def vote(request):

user_passes_test takes one required argument: a callable that takes a User object and returns True if the user is allowed to view the page. user_passes_test does not automatically check that the User is authenticated; you should do that yourself.

Django provides a shortcut for that case: the permission_required() decorator.

@permission_required('polls.can_vote', login_url="/login/")

def vote(request):

LIMITING ACCESS TO GENERIC VIEWS

You’ll need to write a thin wrapper around the view and point your URLconf to your wrapper instead of the generic view itself.

from django.views.generic.date_based import object_detail

@login_required

def limited_object_detail(*args, **kwargs):

return object_detail(*args, **kwargs)

Managing Users, Permissions, and Groups

Creating Users

from django.contrib.auth.models import User

user=User.objects.create_user(username='john',email='jlennon@beatles.com',password='xxx')

user.is_staff = True

user.save()

Changing Passwords

>>> user = User.objects.get(username='john')

>>> user.set_password('goo goo goo joob')

>>> user.save()

Don’t set the password attribute directly unless you know what you’re doing. The password is actually stored as a salted hash and thus can’t be edited directly.

The User.set_password() and User.check_password() functions handle the setting and checking of these values behind the scenes.

Handling Registration

from django.contrib.auth.forms import UserCreationForm

def register(request):

form = UserCreationForm()

if request.method == 'POST':

data = request.POST.copy()

errors = form.get_validation_errors(data)

if not errors:

new_user = form.save(data)

return HttpResponseRedirect("/books/")

else:

data, errors = {}, {}

return render_to_response("registration/register.html", {'form' : forms.FormWrapper(form, data, errors) })

Using Authentication Data in Templates

The currently logged-in user and permissions are made available in the template context when you use RequestContext.

Technically, these variables are only made available in the template context if you use RequestContext and your TEMPLATE_CONTEXT_PROCESSORS setting contains "django.core.context_processors.auth", which is the default.

When using RequestContext, the current user (either a User instance or an AnonymousUser instance) is stored in the template variable {{ user }}:

{% if user.is_authenticated %}{{ user.username }}.

{% else %} <p>Welcome, new user. Please log in.</p>

{% endif %}

This user’s permissions are stored in the template variable {{ perms }}. There are two ways you can use this perms object. You can use something like {{ perms.polls }} to check if the user has any permissions for some given application, or you can use something like {{ perms.polls.can_vote }} to check if the user has a specific permission.

{% if perms.polls %}

{% if perms.polls.can_vote %}

{% endif %}

{% else %}

{% endif %}

The Other Bits: Permissions, Groups, Messages, and Profiles

Permissions

Permissions are set globally per type of object, not per specific object instance. These three basic permissions—add, change, and delete—are automatically created for each Django model that has a class Admin. Behind the scenes, these permissions are added to the auth_permission database table when you run manage.py syncdb.

These permissions will be of the form "<app>.<action>_<object_name>". That is, if you have a polls application with a Choicemodel, you’ll get permissions named "polls.add_choice", "polls.change_choice", and "polls.delete_choice".

If you initialize your database and add class Admin to models after the fact, you’ll need to run syncdb again to create any missing permissions for your installed applications.

You can also create custom permissions for a given model object using the permissions attribute on Meta.

class USCitizen(models.Model):

class Meta:

permissions = (

# Permission identifier human-readable permission name

("can_drive", "Can drive"),

("can_vote", "Can vote in elections"),

("can_drink", "Can drink alcohol"), )

This only creates those extra permissions when you run syncdb; it’s up to you to check for these permissions in your views. Just like users, permissions are implemented in a Django model that lives in django. contrib.auth.models.

Groups

groups are also just Django models that live in django.contrib.auth.models.

Messages

The message system is a lightweight way to queue messages for given users. Amessage is associated with a User. There’s no concept of expiration or timestamps.

To queue and display messages:

To create a new message, use user.message_set.create(message='message_text').

To retrieve/delete messages, use user.get_and_delete_messages(), which returns a list of Message objects in the user’s queue (if any) and deletes the messages from the queue.

def create_playlist(request, songs):

request.user.message_set.create( message="Your playlist was added successfully." )

return render_to_response("playlists/create.html", context_instance=RequestContext(request))

When you use RequestContext, the currently logged-in user and his or her messages are made available in the template context as the template variable {{ messages }}.

{% if messages %}<ul> {% for message in messages %} <li>{{ message }}</li> {% endfor %}</ul>{% endif %}

Note that RequestContext calls get_and_delete_messages behind the scenes, so any messages will be deleted even if you don’t display them.

Profiles

Many sites need to store more user information than is available on the standard User object.Thus, Django provides a lightweight way of defining a “profile” object that’s linked to a given user.

The first step in creating a profile is to define amodel that holds the profile information. The only requirement Django places on this model is that it have a unique ForeignKey to the Usermodel; this field must be named user.

from django.contrib.auth.models import User

class MySiteProfile(models.Model):

# This is the only required field

user = models.ForeignKey(User, unique=True)

# The rest is completely up to you...

favorite_band = models.CharField(maxlength=100, blank=True)

Set the AUTH_PROFILE_MODULE to be the identifier for your model to tell Django where to look for this profile object.

AUTH_PROFILE_MODULE = "myapp.mysiteprofile"

Once that’s done, you can access a user’s profile by calling user.get_profile(). This function could raise a SiteProfileNotAvailable exception if AUTH_PROFILE_MODULE isn’t defined, or it could raise a DoesNotExist exception if the user doesn’t have a profile already (you’ll usually catch that exception and create a new profile at that time).

Caching

Django also works well with “upstream” caches, such as Squid (http://www.squid-cache.org/) 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.

Other Contributed Subframeworks

Django aims to follow this philosophy, and it includes its own standard library of add-ons useful for common Web development tasks.

The Django Standard Library

Django’s standard library lives in the package django.contrib. Within each subpackage is a separate piece of add-on functionality.

django.contrib consists of these packages:

admin: The automatic admin site.

auth: Django’s authentication framework.

comments: A comments application.

contenttypes: A framework for hooking into “types” of content, where each installed

Django model is a separate content type. This framework is used internally by other “contrib” applications and is mostly intended for very advanced Django developers. Those developers should find out more about this application by reading the source code in django/contrib/contenttypes/.

csrf: Protection against cross-site request forgery (CSRF). See the later section titled “CSRF Protection.”

databrowse: An application for browsing your data. Databrowse was released too recently to be covered in this book, but you can read the latest documentation online at http://www.djangoproject.com/documentation/databrowse/.

flatpages: A framework for managing simple “flat” HTML content in a database.

formtools: A set of high-level abstractions for Django forms.

humanize: A set of Django template filters useful for adding a “human touch” to data.

markup: A set of Django template filters that implement a number of common markup

languages.

redirects: A framework for managing redirects.

sessions: Django’s session framework.

sitemaps: A framework for generating sitemap XML files. This feature is not covered in this

book, but you can read the latest documentation online at http://www.djangoproject.com/

documentation/sitemaps/.

sites: A framework that lets you operate multiple Web sites from the same database

and Django installation. See the next section, “Sites.”

syndication: A framework for generating syndication feeds in RSS and Atom. See

Flatpages

Django’s flatpages application, which lives in the package django.contrib.flatpages. This application lets you manage such one-off pages via Django’s admin site, and it lets you specify templates for them using Django’s template system. It uses Django models behind the scenes, which means it stores the pages in a database, just like the rest of your data, and you can access flatpages with the standard Django database API.

Flatpages are keyed by their URL and site. When you create a flatpage, you specify which URL it’s associated with, along with which site(s) it’s on.

Using Flatpages

To install the flatpages application, follow these steps:

1. Add 'django.contrib.flatpages' to your INSTALLED_APPS. django.contrib.flatpages

depends on django.contrib.sites, so make sure both packages are in INSTALLED_APPS.

2. Add 'django.contrib.flatpages.middleware.FlatpageFallbackMiddlewareyou’re your MIDDLEWARE_CLASSES setting.

3. Run the command manage.py syncdb to install the two required tables into your database.

Using the Redirects Framework

To install the redirects application, follow these steps:

1. Add 'django.contrib.redirects' to your INSTALLED_APPS.

2. Add 'django.contrib.redirects.middleware.RedirectFallbackMiddleware to MIDDLEWARE_CLASSES setting.

3. Run the command manage.py syncdb to install the single required table into your database.

manage.py syncdb creates a django_redirect table in your database. This is a simple lookup table with site_id, old_path, and new_path fields.

Once you’ve created redirects, the RedirectFallbackMiddleware class 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.

Then it follows these steps:

If it finds amatch, and new_path is not empty, it redirects to new_path.

If it finds amatch, and new_path is empty, it sends a 410 (“Gone”) HTTP header and an empty (contentless) response.

If it doesn’t find amatch, the request continues to be processed as usual.

The middleware only gets activated for 404 errors—not for 500 errors or responses of any other status code.

The order of MIDDLEWARE_CLASSES matters. Generally, you can put RedirectFallbackMiddleware toward the end of the list, because it’s a last resort.

Adding, Changing, and Deleting Redirects

You can add, change, and delete redirects in two ways: via the admin interface and via the Python API.

Via the Python API

Redirects are represented by a standard Django model that lives in django/contrib/redirects/models.py. Hence, you can access redirect objects via the Django database API, for example:

>>> from django.contrib.redirects.models import Redirect

>>> from django.contrib.sites.models import Site

red = Redirect(site=Site.objects.get(id=1), old_path='/music/',new_path='/sections/arts/music/')

>>> red.save()

>>> Redirect.objects.get(old_path='/music/')

Form Tools

django.contrib.formtools.preview

This is an abstraction of a common workflow: display an HTML form, force a preview (of some object created by the form), and then do something with the submission.

It takes care of the following:

Displays the form as HTML on aWeb page

Validates the form data once it’s submitted via POST:

If it’s valid, displays a preview page

If it’s not valid, redisplays the form with error messages

At the preview page, if the preview confirmation button is clicked, calls a hook that you define (a done()method)

Markup Filters

The following collection of template filters implements common markup languages:

textile: Implements Textile (http://en.wikipedia.org/wiki/Textile_%28markup_language%29)

markdown: Implements Markdown (http://en.wikipedia.org/wiki/Markdown)

restructuredtext: Implements ReStructured Text (http://en.wikipedia.org/wiki/ReStructuredText)

In each case, the filter expects formatted markup as a string and returns a string representing the marked-up text. For example, the textile filter converts text that is marked up in Textile format to HTML:

{% load markup %}

{{ object.content|textile }}

To activate these filters, add 'django.contrib.markup' to your INSTALLED_APPS setting. Once you’ve done that, use {% load markup %} in a template, and you’ll have access to these filters.

Deploying Django

Using Django with Apache and mod_python

mod_python (http://www.djangoproject.com/r/mod_python/) is an Apache plug-in that 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.

Django requires Apache 2.x and mod_python 3.x.

Basic Configuration

First have Apache installed with the mod_python module activated.

LoadModule python_module /usr/lib/apache2/modules/mod_python.so

<Location "/">

SetHandler python-program

PythonHandler django.core.handlers.modpython

SetEnv DJANGO_SETTINGS_MODULE mysite.settings

PythonDebug On

</Location>

Make sure to replace mysite.settings with the appropriate DJANGO_SETTINGS_MODULE for your site. This tells Apache, “Use mod_python for any URL at or under ‘/’, using the Django mod_python handler.” It passes the value of DJANGO_SETTINGS_MODULE so mod_python knows which settings to use.

we’re using the <Location> directive, not the <Directory> directive. The latter is used for pointing at places on your filesystem, whereas <Location> points at places in the URL structure of aWeb site. <Directory> would be meaningless here.

Apache likely runs as a different user than your normal login and may have a different path and PYTHONPATH. You may need to tell mod_python how to find your project and Django itself: PythonPath "['/path/to/project', '/path/to/django'] + sys.path", you can also add directives such as PythonAutoReload Off for performance. You should set PythonDebug Off on a production server.

Running Multiple Django Installations on the Same Apache Instance

To accomplish this, just use VirtualHost like so:

NameVirtualHost *

<VirtualHost *>

ServerName www.example.com

# ...

SetEnv DJANGO_SETTINGS_MODULE mysite.settings

</VirtualHost>

<VirtualHost *>

ServerName www2.example.com

# ...

SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings

</VirtualHost>

If you need to put two Django installations within the same VirtualHost, you’ll need to take a special precaution to ensure mod_python’s code cache doesn’t mess things up. Use the PythonInterpreter directive to give different <Location> directives separate interpreters:

<VirtualHost *>

ServerName www.example.com

# ...

<Location "/something">

SetEnv DJANGO_SETTINGS_MODULE mysite.settings

PythonInterpreter mysite

</Location>

<Location "/otherthing">

SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings

PythonInterpreter mysite_other

</Location>

</VirtualHost>

The values of PythonInterpreter don’t really matter, as long as they’re different between the two Location blocks.

Running a Development Server with mod_python

Because mod_python caches loaded Python code, when deploying Django sites on mod_python you’ll need to restart Apache each time you make changes to your code, here’s a quick trick to avoid it: just add MaxRequestsPerChild 1 to your config file to force Apach to reload everything for each request. But don’t do that on a production server,

If you have the need to print debugging information in a mod_python setup, you’ll probably want to use Python’s standard logging package. More information is available at http://docs.python.org/lib/module-logging.html. Alternatively, you can add the debugging information to the template of your page.

Serving Django and Media Files from the Same Apache Instance

Django should not be used to serve media files itself; leave 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. For more information, see the “Scaling” section.

If, however, you have no option but to serve media files on the same Apache VirtualHost as Django, here’s how you can turn off mod_python for a particular part of the site:

<Location "/media/">

SetHandler None

</Location>

Change Location to the root URL of your media files.

You can also use <LocationMatch> to match a regular expression.

<Location "/">

SetHandler python-program

PythonHandler django.core.handlers.modpython

SetEnv DJANGO_SETTINGS_MODULE mysite.settings

</Location>

<Location "/media/">SetHandler None</Location>

<LocationMatch "\.(jpg|gif|png)$">SetHandler None</LocationMatch>

Error Handling

When you use Apache/mod_python, errors will be caught by Django—in other words, they won’t propagate to the Apache level and won’t appear in the Apache error_log.

The article “Getting mod_python Working” details this procedure: http://www.djangoproject.com/r/articles/getting-modpython-working/.

Using Django with FastCGI

Although Django under Apache and mod_python is the most robust deployment setup, many people use shared hosting, on which FastCGI is the only available deployment option. Additionally, in some situations, FastCGI allows better security and possibly better performance than mod_python. For small sites, FastCGI can also be more lightweight than Apache.

FastCGI Overview

FastCGI is an efficient way of letting an external application serve pages to aWeb server. The Web server delegates the incoming Web requests (via a socket) to FastCGI, which executes the code and passes the response back to the Web server, which, in turn, passes it back to the client’s Web browser.

Like mod_python, FastCGI allows code to stay in memory, allowing requests to be served with no startup time. Unlike mod_python, a FastCGI process doesn’t run inside the Web server process, but in a separate, persistent process.


Each Apache process gets a copy of the Apache engine, complete with all the features of Apache that Django simply doesn’t take advantage of. FastCGI processes, on the other hand, only have the memory overhead of Python and Django.

Due to the nature of FastCGI, it’s also possible to have processes that run under a different user account than the Web server process. That’s a nice security benefit on shared systems, because it means you can secure your code from other users.

Before you can start using FastCGI with Django, you’ll need to install flup, a Python library for dealing with FastCGI.

Middleware

Middleware Installation

To activate a middleware component, add it to the MIDDLEWARE_CLASSES tuple in your settings module. In MIDDLEWARE_CLASSES, each middleware component is represented by a string: the full Python path to the middleware’s class name.

Here’s the default MIDDLEWARE_CLASSES created by django-admin.py startproject:

'django.middleware.common.CommonMiddleware',

'django.contrib.sessions.middleware.SessionMiddleware',

'django.contrib.auth.middleware.AuthenticationMiddleware',

'django.middleware.doc.XViewMiddleware'

The order is significant. On the request and view phases, Django applies middleware in the order given in MIDDLEWARE_CLASSES, and on the response and exception phases, Django applies middleware in reverse order.

Middleware Methods

Initializer: __init__(self)

Use __init__() to perform systemwide setup for a given middleware class. For performance reasons, each activated middleware class is instantiated only once per server process. This means that __init__() is called only once—at server startup—not for individual requests.

Request Preprocessor: process_request(self, request)

This method gets called as soon as the request has been received—before Django has parsed the URL to determine which view to run. It gets passed the HttpRequest object, which you may modify at will.

process_request() should return either None or an HttpResponse object.

If it returns None, Django will continue processing this request, executing any other middleware and then the appropriate view.

If it returns an HttpResponse object, Django won’t bother calling any other middleware (of any type) or the appropriate view. Django will immediately return that HttpResponse.

View Preprocessor: process_view(self, request, view, args, kwargs)

This method gets called after the request preprocessor is called and Django has determined which view to execute, but before that view has actually been executed.

Response Postprocessor: process_response(self, request, response)

This method gets called after the view function is called and the response is generated. Here, the processor can modify the content of a response; one obvious use case is content compression, such as gzipping of the request’s HTML.

Exception Postprocessor: process_exception(self, request,exception)

This method gets called only if something goes wrong and a view raises an uncaught exception. You can use this hook to send error notifications, dump postmortem information to a log, or even try to recover from the error automatically.

Built-in Middleware

Authentication Support Middleware

Middleware class: django.contrib.auth.middleware.AuthenticationMiddleware

This middleware enables authentication support. It adds the request.user attribute, representing the currently logged-in user, to every incoming HttpRequest object.

Common”Middleware

Middleware class: django.middleware.common.CommonMiddleware

This middleware adds a few conveniences for perfectionists:

Forbids access to user agents in the DISALLOWED_USER_AGENTS setting: If provided, this setting should be a list of compiled regular expression objects that are matched against the user-agent header for each incoming request.

import re

DISALLOWED_USER_AGENTS = (

re.compile(r'^OmniExplorer_Bot'),

re.compile(r'^Googlebot')

)

Note the import re, because DISALLOWED_USER_AGENTS requires its values to be compiled regexes

Performs URL rewriting based on the APPEND_SLASH and PREPEND_WWW settings: If APPEND_SLASH is True, URLs that lack a trailing slash will be redirected to the same URL with a trailing slash, unless the last component in the path contains a period.

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.

Handles ETags based on the USE_ETAGS setting: ETags are an HTTP-level optimization for caching pages conditionally. If USE_ETAGS is set to True, Django will calculate an ETag for each request by MD5-hashing the page content, and it will take care of sending Not Modified responses, if appropriate.

Compression Middleware

Middleware class: django.middleware.gzip.GZipMiddleware

This middleware automatically compresses content for browsers that understand gzip compression (all modern browsers). This can greatly reduce the amount of bandwidth aWeb server consumes. The tradeoff is that it takes a bit of processing time to compress pages.

Conditional GET Middleware

Middleware class: django.middleware.http.ConditionalGetMiddleware

This middleware provides support for 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 304 (“Not modified”) response.

Reverse Proxy Support (X-Forwarded-For Middleware)

Middleware class: django.middleware.http.SetRemoteAddrFromForwardedFor

This is useful if you’re sitting behind a reverse proxy that causes each request’s REMOTE_ADDR to be set to 127.0.0.1.

Session Support Middleware

Middleware class: django.contrib.sessions.middleware.SessionMiddleware

Sitewide Cache Middleware

Middleware class: django.middleware.cache.CacheMiddleware

This middleware caches each Django-powered page.

Transaction Middleware

Middleware class: django.middleware.transaction.TransactionMiddleware

This middleware binds a database COMMIT or ROLLBACK to the request/response phase. If a view function runs successfully, a COMMIT is issued. If the view raises an exception, a ROLLBACK is issued.

The order of this middleware in the stack is important. Middleware modules running outside of it run with commit-on-save—the default Django behavior. Middleware modules running inside it (coming later in the stack) will be under the same transaction control as the view functions.

X-View”Middleware

Middleware class: django.middleware.doc.XViewMiddleware

This middleware sends custom X-View HTTP headers to HEAD requests that come from IP addresses defined in the INTERNAL_IPS setting. This is used by Django’s automatic documentation system.

Internationalization

IF YOU DON’T NEED INTERNATIONALIZATION

Django’s internationalization hooks are enabled by default, which incurs a small bit of overhead. If you don’t use internationalization, you should set USE_I18N = False in your settings file. If USE_I18N is set to False, then Django will make some optimizations so as not to load the internationalization machinery. You’ll probably also want to remove 'django.core.context_processors.i18n' from your TEMPLATE_CONTEXT_PROCESSORS setting.

Specifying Translation Strings in Python Code

Standard Translation Functions

Specify a translation string by using the function _().

In this example, the text "Welcome to my site." is marked as a translation string:

def my_view(request):

output = _("Welcome to my site.")

return HttpResponse(output)

The function django.utils.translation.gettext() is identical to _().

from django.utils.translation import gettext

output = gettext("Welcome to my site.")

The strings you pass to _() or gettext() can take placeholders, specified with Python’s standard named-string interpolation syntax,

output = _('%(name)s is my name.') % {'name': n}

Marking Strings As No-op

Use the function django.utils.translation.gettext_noop() to mark a string as a translation string without actually translating it at that moment. Strings thus marked aren’t translated until the last possible moment.

Use this approach if you have constant strings that should be stored in the original language—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.

Lazy Translation

Use the function django.utils.translation.gettext_lazy() to translate strings lazily—when the value is accessed rather than when the gettext_lazy() function is called.

For example, to mark a field’s help_text attribute as translatable, do the following:

from django.utils.translation import gettext_lazy

class MyThing(models.Model):

name = models.CharField(help_text=gettext_lazy('This is the help text'))

In this example, gettext_lazy() stores 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 template rendering on the Django admin site.

If you don’t like the verbose name gettext_lazy, you can just alias it as _ (underscore).

from django.utils.translation import gettext_lazy as _

class MyThing(models.Model):

name = models.CharField(help_text=_('This is the help text'))

Pluralization

Use the function django.utils.translation.ngettext() to specify messages that have different singular and plural forms, for example:

from django.utils.translation import ngettext

def hello_world(request, count):

page = ngettext(

'there is %(count)d object',

'there are %(count)d objects', count

) % {'count': count}

return HttpResponse(page)

ngettext takes three arguments: the singular translation string, the plural translation string, and the number of objects .

Specifying Translation Strings in Template Code

To give your template access to these tags, put {% load i18n %} toward the top of your template.

The {% trans %} template tag marks a string for translations:

<title>{% trans "This is the title." %}</title>

If you only want to mark a value for translation, but translate it later, use the noop option: <title>{% trans "value" noop %}</title>

If your translations require variables (placeholders), use {% blocktrans %}, for example:

{% blocktrans %}This will have {{ value }} inside.{% endblocktrans %}

If you need to bind more than one expression inside a blocktrans tag, separate the pieces with and:

{% blocktrans with book|title as book_t and author|title as author_t %}

This is {{ book_t }} by {{ author_t }}

{% endblocktrans %}

To pluralize, specify both the singular and plural forms with the {% plural %} tag, which appears within {% blocktrans %} and {% endblocktrans %}:

{% blocktrans count list|length as counter %}

There is only one {{ name }} object.

{% plural %}

There are {{ counter }} {{ name }} objects.

{% endblocktrans %}

When you use RequestContext, your templates have access to three translation-specific variables:

{{ LANGUAGES }} is a list of tuples in which the first element is the language code and the second is the language name (in that language).

{{ LANGUAGE_CODE }} is the current user’s preferred language, as a string (e.g., en-us).

{{ LANGUAGE_BIDI }} is the current language’s writing system. 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).

You can also load these values using template tags:

{% load i18n %}

{% get_current_language as LANGUAGE_CODE %}

{% get_available_languages as LANGUAGES %}

{% get_current_language_bidi as LANGUAGE_BIDI %}

Creating Language Files

Message files have a .po file extension.

Django comes with a tool, bin/make-messages.py, that automates the creation and maintenance of these files. To create or update amessage file, run this command:

python django-admin.py makemessages -l de

python make-messages.py -l de

Where de is the language code for the message file you want to create.

The script runs over the entire tree it is run on and pulls out all strings marked for translation. It creates (or updates) amessage file in the directory conf/locale. In the de example, the file will be conf/locale/de/LC_MESSAGES/django.po.

If the script is run over your project source tree or your application source tree, it will do the same, but the location of the locale directory is locale/LANG/LC_MESSAGES. The first time you run it on your tree you’ll need to create the locale directory.


Post a Comment

Labels

Java (159) Lucene-Solr (110) All (60) Interview (59) J2SE (53) Algorithm (37) Eclipse (35) Soft Skills (35) Code Example (31) Linux (26) JavaScript (23) Spring (22) Windows (22) Web Development (20) Tools (19) Nutch2 (18) Bugs (17) Debug (15) Defects (14) Text Mining (14) J2EE (13) Network (13) PowerShell (11) Chrome (9) Continuous Integration (9) How to (9) Learning code (9) Performance (9) UIMA (9) html (9) Design (8) Dynamic Languages (8) Http Client (8) Maven (8) Security (8) Trouble Shooting (8) bat (8) blogger (8) Big Data (7) Google (7) Guava (7) JSON (7) Problem Solving (7) ANT (6) Coding Skills (6) Database (6) Scala (6) Shell (6) css (6) Algorithm Series (5) Cache (5) IDE (5) Lesson Learned (5) Miscs (5) Programmer Skills (5) System Design (5) Tips (5) adsense (5) xml (5) AIX (4) Code Quality (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) OpenNLP (4) Project Managment (4) Python (4) Spark (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Become a Better You (3) Concurrency (3) Eclipse RCP (3) English (3) Firefox (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Distributed (2) Fiddler (2) Google Drive (2) Gson (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Life (2) Logging (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Bit Operation (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Mac (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) Review (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Troubleshooting (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts