Removed use of non-standard indentation rules in docs, and the custom transform that supported them.

Doc writers should be aware that we are now back to normal ReST rules
regarding blockquotes.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16955 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2011-10-10 17:32:33 +00:00
parent af244e47cc
commit c61987d75a
8 changed files with 777 additions and 797 deletions

View File

@ -62,7 +62,6 @@ def setup(app):
app.add_config_value('django_next_version', '0.0', True)
app.add_directive('versionadded', VersionDirective)
app.add_directive('versionchanged', VersionDirective)
app.add_transform(SuppressBlockquotes)
app.add_builder(DjangoStandaloneHTMLBuilder)
@ -99,27 +98,6 @@ class VersionDirective(Directive):
return ret
class SuppressBlockquotes(transforms.Transform):
"""
Remove the default blockquotes that encase indented list, tables, etc.
"""
default_priority = 300
suppress_blockquote_child_nodes = (
nodes.bullet_list,
nodes.enumerated_list,
nodes.definition_list,
nodes.literal_block,
nodes.doctest_block,
nodes.line_block,
nodes.table
)
def apply(self):
for node in self.document.traverse(nodes.block_quote):
if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes):
node.replace_self(node.children[0])
class DjangoHTMLTranslator(SmartyPantsHTMLTranslator):
"""
Django-specific reST to HTML tweaks.

View File

@ -16,31 +16,31 @@ Overview
There are seven steps in activating the Django admin site:
1. Add ``'django.contrib.admin'`` to your :setting:`INSTALLED_APPS`
setting.
1. Add ``'django.contrib.admin'`` to your :setting:`INSTALLED_APPS`
setting.
2. The admin has four dependencies - :mod:`django.contrib.auth`,
:mod:`django.contrib.contenttypes`,
:mod:`django.contrib.messages` and
:mod:`django.contrib.sessions`. If these applications are not
in your :setting:`INSTALLED_APPS` list, add them.
2. The admin has four dependencies - :mod:`django.contrib.auth`,
:mod:`django.contrib.contenttypes`,
:mod:`django.contrib.messages` and
:mod:`django.contrib.sessions`. If these applications are not
in your :setting:`INSTALLED_APPS` list, add them.
3. Add ``django.contrib.messages.context_processors.messages`` to
:setting:`TEMPLATE_CONTEXT_PROCESSORS` and
:class:`~django.contrib.messages.middleware.MessageMiddleware` to
:setting:`MIDDLEWARE_CLASSES`.
3. Add ``django.contrib.messages.context_processors.messages`` to
:setting:`TEMPLATE_CONTEXT_PROCESSORS` and
:class:`~django.contrib.messages.middleware.MessageMiddleware` to
:setting:`MIDDLEWARE_CLASSES`.
4. Determine which of your application's models should be editable in the
admin interface.
4. Determine which of your application's models should be editable in the
admin interface.
5. For each of those models, optionally create a ``ModelAdmin`` class that
encapsulates the customized admin functionality and options for that
particular model.
5. For each of those models, optionally create a ``ModelAdmin`` class that
encapsulates the customized admin functionality and options for that
particular model.
6. Instantiate an ``AdminSite`` and tell it about each of your models and
``ModelAdmin`` classes.
6. Instantiate an ``AdminSite`` and tell it about each of your models and
``ModelAdmin`` classes.
7. Hook the ``AdminSite`` instance into your URLconf.
7. Hook the ``AdminSite`` instance into your URLconf.
Other topics
------------
@ -239,54 +239,54 @@ subclass::
The ``field_options`` dictionary can have the following keys:
* ``fields``
A tuple of field names to display in this fieldset. This key is
required.
* ``fields``
A tuple of field names to display in this fieldset. This key is
required.
Example::
Example::
{
'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
}
{
'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
}
Just like with the :attr:`~ModelAdmin.fields` option, to display
multiple fields on the same line, wrap those fields in their own
tuple. In this example, the ``first_name`` and ``last_name`` fields
will display on the same line::
Just like with the :attr:`~ModelAdmin.fields` option, to display
multiple fields on the same line, wrap those fields in their own
tuple. In this example, the ``first_name`` and ``last_name`` fields
will display on the same line::
{
'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
}
{
'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
}
.. versionadded:: 1.2
.. versionadded:: 1.2
``fields`` can contain values defined in
:attr:`~ModelAdmin.readonly_fields` to be displayed as read-only.
``fields`` can contain values defined in
:attr:`~ModelAdmin.readonly_fields` to be displayed as read-only.
* ``classes``
A list containing extra CSS classes to apply to the fieldset.
* ``classes``
A list containing extra CSS classes to apply to the fieldset.
Example::
Example::
{
'classes': ['wide', 'extrapretty'],
}
{
'classes': ['wide', 'extrapretty'],
}
Two useful classes defined by the default admin site stylesheet are
``collapse`` and ``wide``. Fieldsets with the ``collapse`` style
will be initially collapsed in the admin and replaced with a small
"click to expand" link. Fieldsets with the ``wide`` style will be
given extra horizontal space.
Two useful classes defined by the default admin site stylesheet are
``collapse`` and ``wide``. Fieldsets with the ``collapse`` style
will be initially collapsed in the admin and replaced with a small
"click to expand" link. Fieldsets with the ``wide`` style will be
given extra horizontal space.
* ``description``
A string of optional extra text to be displayed at the top of each
fieldset, under the heading of the fieldset.
* ``description``
A string of optional extra text to be displayed at the top of each
fieldset, under the heading of the fieldset.
Note that this value is *not* HTML-escaped when it's displayed in
the admin interface. This lets you include HTML if you so desire.
Alternatively you can use plain text and
``django.utils.html.escape()`` to escape any HTML special
characters.
Note that this value is *not* HTML-escaped when it's displayed in
the admin interface. This lets you include HTML if you so desire.
Alternatively you can use plain text and
``django.utils.html.escape()`` to escape any HTML special
characters.
.. attribute:: ModelAdmin.filter_horizontal
@ -400,129 +400,129 @@ subclass::
You have four possible values that can be used in ``list_display``:
* A field of the model. For example::
* A field of the model. For example::
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
* A callable that accepts one parameter for the model instance. For
example::
* A callable that accepts one parameter for the model instance. For
example::
def upper_case_name(obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
def upper_case_name(obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
class PersonAdmin(admin.ModelAdmin):
list_display = (upper_case_name,)
* A string representing an attribute on the ``ModelAdmin``. This
behaves same as the callable. For example::
class PersonAdmin(admin.ModelAdmin):
list_display = ('upper_case_name',)
def upper_case_name(self, obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
class PersonAdmin(admin.ModelAdmin):
list_display = (upper_case_name,)
* A string representing an attribute on the model. This behaves almost
the same as the callable, but ``self`` in this context is the model
instance. Here's a full model example::
* A string representing an attribute on the ``ModelAdmin``. This
behaves same as the callable. For example::
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
class PersonAdmin(admin.ModelAdmin):
list_display = ('upper_case_name',)
def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
def upper_case_name(self, obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
* A string representing an attribute on the model. This behaves almost
the same as the callable, but ``self`` in this context is the model
instance. Here's a full model example::
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')
A few special cases to note about ``list_display``:
* If the field is a ``ForeignKey``, Django will display the
``__unicode__()`` of the related object.
* If the field is a ``ForeignKey``, Django will display the
``__unicode__()`` of the related object.
* ``ManyToManyField`` fields aren't supported, because that would
entail executing a separate SQL statement for each row in the table.
If you want to do this nonetheless, give your model a custom method,
and add that method's name to ``list_display``. (See below for more
on custom methods in ``list_display``.)
* ``ManyToManyField`` fields aren't supported, because that would
entail executing a separate SQL statement for each row in the table.
If you want to do this nonetheless, give your model a custom method,
and add that method's name to ``list_display``. (See below for more
on custom methods in ``list_display``.)
* If the field is a ``BooleanField`` or ``NullBooleanField``, Django
will display a pretty "on" or "off" icon instead of ``True`` or
``False``.
* If the field is a ``BooleanField`` or ``NullBooleanField``, Django
will display a pretty "on" or "off" icon instead of ``True`` or
``False``.
* If the string given is a method of the model, ``ModelAdmin`` or a
callable, Django will HTML-escape the output by default. If you'd
rather not escape the output of the method, give the method an
``allow_tags`` attribute whose value is ``True``.
* If the string given is a method of the model, ``ModelAdmin`` or a
callable, Django will HTML-escape the output by default. If you'd
rather not escape the output of the method, give the method an
``allow_tags`` attribute whose value is ``True``.
Here's a full example model::
Here's a full example model::
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_name(self):
return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
colored_name.allow_tags = True
def colored_name(self):
return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
colored_name.allow_tags = True
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'colored_name')
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'colored_name')
* If the string given is a method of the model, ``ModelAdmin`` or a
callable that returns True or False Django will display a pretty
"on" or "off" icon if you give the method a ``boolean`` attribute
whose value is ``True``.
* If the string given is a method of the model, ``ModelAdmin`` or a
callable that returns True or False Django will display a pretty
"on" or "off" icon if you give the method a ``boolean`` attribute
whose value is ``True``.
Here's a full example model::
Here's a full example model::
class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField()
class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField()
def born_in_fifties(self):
return self.birthday.strftime('%Y')[:3] == '195'
born_in_fifties.boolean = True
def born_in_fifties(self):
return self.birthday.strftime('%Y')[:3] == '195'
born_in_fifties.boolean = True
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'born_in_fifties')
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'born_in_fifties')
* The ``__str__()`` and ``__unicode__()`` methods are just as valid in
``list_display`` as any other model method, so it's perfectly OK to
do this::
* The ``__str__()`` and ``__unicode__()`` methods are just as valid in
``list_display`` as any other model method, so it's perfectly OK to
do this::
list_display = ('__unicode__', 'some_other_field')
list_display = ('__unicode__', 'some_other_field')
* Usually, elements of ``list_display`` that aren't actual database
fields can't be used in sorting (because Django does all the sorting
at the database level).
* Usually, elements of ``list_display`` that aren't actual database
fields can't be used in sorting (because Django does all the sorting
at the database level).
However, if an element of ``list_display`` represents a certain
database field, you can indicate this fact by setting the
``admin_order_field`` attribute of the item.
However, if an element of ``list_display`` represents a certain
database field, you can indicate this fact by setting the
``admin_order_field`` attribute of the item.
For example::
For example::
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_first_name(self):
return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
colored_first_name.allow_tags = True
colored_first_name.admin_order_field = 'first_name'
def colored_first_name(self):
return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
colored_first_name.allow_tags = True
colored_first_name.admin_order_field = 'first_name'
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')
The above will tell Django to order by the ``first_name`` field when
trying to sort by ``colored_first_name`` in the admin.
The above will tell Django to order by the ``first_name`` field when
trying to sort by ``colored_first_name`` in the admin.
.. attribute:: ModelAdmin.list_display_links
@ -561,12 +561,12 @@ subclass::
``list_editable`` interacts with a couple of other options in
particular ways; you should note the following rules:
* Any field in ``list_editable`` must also be in ``list_display``.
You can't edit a field that's not displayed!
* Any field in ``list_editable`` must also be in ``list_display``.
You can't edit a field that's not displayed!
* The same field can't be listed in both ``list_editable`` and
``list_display_links`` -- a field can't be both a form and
a link.
* The same field can't be listed in both ``list_editable`` and
``list_display_links`` -- a field can't be both a form and
a link.
You'll get a validation error if either of these rules are broken.
@ -582,119 +582,119 @@ subclass::
``list_filter`` should be a list of elements, where each element should be
of one of the following types:
* a field name, where the specified field should be either a
``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``,
``IntegerField``, ``ForeignKey`` or ``ManyToManyField``, for example::
* a field name, where the specified field should be either a
``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``,
``IntegerField``, ``ForeignKey`` or ``ManyToManyField``, for example::
class PersonAdmin(ModelAdmin):
list_filter = ('is_staff', 'company')
class PersonAdmin(ModelAdmin):
list_filter = ('is_staff', 'company')
.. versionadded:: 1.3
.. versionadded:: 1.3
Field names in ``list_filter`` can also span relations
using the ``__`` lookup, for example::
Field names in ``list_filter`` can also span relations
using the ``__`` lookup, for example::
class PersonAdmin(UserAdmin):
list_filter = ('company__name',)
class PersonAdmin(UserAdmin):
list_filter = ('company__name',)
* a class inheriting from :mod:`django.contrib.admin.SimpleListFilter`,
which you need to provide the ``title`` and ``parameter_name``
attributes to and override the ``lookups`` and ``queryset`` methods,
e.g.::
* a class inheriting from :mod:`django.contrib.admin.SimpleListFilter`,
which you need to provide the ``title`` and ``parameter_name``
attributes to and override the ``lookups`` and ``queryset`` methods,
e.g.::
from django.utils.translation import ugettext_lazy as _
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _
from django.contrib.admin import SimpleListFilter
class DecadeBornListFilter(SimpleListFilter):
# Human-readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _('decade born')
class DecadeBornListFilter(SimpleListFilter):
# Human-readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _('decade born')
# Parameter for the filter that will be used in the URL query.
parameter_name = 'decade'
# Parameter for the filter that will be used in the URL query.
parameter_name = 'decade'
def lookups(self, request, model_admin):
"""
Returns a list of tuples. The first element in each
tuple is the coded value for the option that will
appear in the URL query. The second element is the
human-readable name for the option that will appear
in the right sidebar.
"""
return (
('80s', _('in the eighties')),
('90s', _('in the nineties')),
)
def lookups(self, request, model_admin):
"""
Returns a list of tuples. The first element in each
tuple is the coded value for the option that will
appear in the URL query. The second element is the
human-readable name for the option that will appear
in the right sidebar.
"""
return (
('80s', _('in the eighties')),
('90s', _('in the nineties')),
)
def queryset(self, request, queryset):
"""
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
"""
# Compare the requested value (either '80s' or 'other')
# to decide how to filter the queryset.
if self.value() == '80s':
return queryset.filter(birthday__year__gte=1980,
birthday__year__lte=1989)
if self.value() == '90s':
return queryset.filter(birthday__year__gte=1990,
birthday__year__lte=1999)
def queryset(self, request, queryset):
"""
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
"""
# Compare the requested value (either '80s' or 'other')
# to decide how to filter the queryset.
if self.value() == '80s':
return queryset.filter(birthday__year__gte=1980,
birthday__year__lte=1989)
if self.value() == '90s':
return queryset.filter(birthday__year__gte=1990,
birthday__year__lte=1999)
class PersonAdmin(ModelAdmin):
list_filter = (DecadeBornListFilter,)
class PersonAdmin(ModelAdmin):
list_filter = (DecadeBornListFilter,)
.. note::
.. note::
As a convenience, the ``HttpRequest`` object is passed to the
``lookups`` and ``queryset`` methods, for example::
As a convenience, the ``HttpRequest`` object is passed to the
``lookups`` and ``queryset`` methods, for example::
class AuthDecadeBornListFilter(DecadeBornListFilter):
class AuthDecadeBornListFilter(DecadeBornListFilter):
def lookups(self, request, model_admin):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter,
self).lookups(request, model_admin)
def lookups(self, request, model_admin):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter,
self).lookups(request, model_admin)
def queryset(self, request, queryset):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter,
self).queryset(request, queryset)
def queryset(self, request, queryset):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter,
self).queryset(request, queryset)
Also as a convenience, the ``ModelAdmin`` object is passed to
the ``lookups`` method, for example if you want to base the
lookups on the available data::
Also as a convenience, the ``ModelAdmin`` object is passed to
the ``lookups`` method, for example if you want to base the
lookups on the available data::
class AdvancedDecadeBornListFilter(DecadeBornListFilter):
class AdvancedDecadeBornListFilter(DecadeBornListFilter):
def lookups(self, request, model_admin):
"""
Only show the lookups if there actually is
anyone born in the corresponding decades.
"""
qs = model_admin.queryset(request)
if qs.filter(birthday__year__gte=1980,
birthday__year__lte=1989).exists():
yield ('80s', _('in the eighties'))
if qs.filter(birthday__year__gte=1990,
birthday__year__lte=1999).exists():
yield ('90s', _('in the nineties'))
def lookups(self, request, model_admin):
"""
Only show the lookups if there actually is
anyone born in the corresponding decades.
"""
qs = model_admin.queryset(request)
if qs.filter(birthday__year__gte=1980,
birthday__year__lte=1989).exists():
yield ('80s', _('in the eighties'))
if qs.filter(birthday__year__gte=1990,
birthday__year__lte=1999).exists():
yield ('90s', _('in the nineties'))
* a tuple, where the first element is a field name and the second
element is a class inheriting from
:mod:`django.contrib.admin.FieldListFilter`, for example::
* a tuple, where the first element is a field name and the second
element is a class inheriting from
:mod:`django.contrib.admin.FieldListFilter`, for example::
from django.contrib.admin import BooleanFieldListFilter
from django.contrib.admin import BooleanFieldListFilter
class PersonAdmin(ModelAdmin):
list_filter = (
('is_staff', BooleanFieldListFilter),
)
class PersonAdmin(ModelAdmin):
list_filter = (
('is_staff', BooleanFieldListFilter),
)
.. note::
.. note::
The ``FieldListFilter`` API is currently considered internal
and prone to refactoring.
The ``FieldListFilter`` API is currently considered internal
and prone to refactoring.
.. attribute:: ModelAdmin.list_max_show_all
@ -1076,11 +1076,11 @@ templates used by the :class:`ModelAdmin` views:
However, the ``self.my_view`` function registered above suffers from two
problems:
* It will *not* perform any permission checks, so it will be accessible
to the general public.
* It will *not* provide any header details to prevent caching. This means
if the page retrieves data from the database, and caching middleware is
active, the page could show outdated information.
* It will *not* perform any permission checks, so it will be accessible
to the general public.
* It will *not* provide any header details to prevent caching. This means
if the page retrieves data from the database, and caching middleware is
active, the page could show outdated information.
Since this is usually not what you want, Django provides a convenience
wrapper to check permissions and mark the view as non-cacheable. This
@ -1356,8 +1356,8 @@ information.
Django provides two subclasses of ``InlineModelAdmin`` and they are:
* :class:`~django.contrib.admin.TabularInline`
* :class:`~django.contrib.admin.StackedInline`
* :class:`~django.contrib.admin.TabularInline`
* :class:`~django.contrib.admin.StackedInline`
The difference between these two is merely the template used to render
them.
@ -1735,11 +1735,11 @@ Templates which may be overridden per app or model
Not every template in ``contrib/admin/templates/admin`` may be overridden per
app or per model. The following can:
* ``app_index.html``
* ``change_form.html``
* ``change_list.html``
* ``delete_confirmation.html``
* ``object_history.html``
* ``app_index.html``
* ``change_form.html``
* ``change_list.html``
* ``delete_confirmation.html``
* ``object_history.html``
For those templates that cannot be overridden in this way, you may still
override them for your entire project. Just place the new version in your
@ -1920,28 +1920,28 @@ accessible using Django's :ref:`URL reversing system <naming-url-patterns>`.
The :class:`AdminSite` provides the following named URL patterns:
====================== ======================== =============
Page URL name Parameters
====================== ======================== =============
Index ``index``
Logout ``logout``
Password change ``password_change``
Password change done ``password_change_done``
i18n javascript ``jsi18n``
Application index page ``app_list`` ``app_label``
====================== ======================== =============
====================== ======================== =============
Page URL name Parameters
====================== ======================== =============
Index ``index``
Logout ``logout``
Password change ``password_change``
Password change done ``password_change_done``
i18n javascript ``jsi18n``
Application index page ``app_list`` ``app_label``
====================== ======================== =============
Each :class:`ModelAdmin` instance provides an additional set of named URLs:
====================== =============================================== =============
Page URL name Parameters
====================== =============================================== =============
Changelist ``{{ app_label }}_{{ model_name }}_changelist``
Add ``{{ app_label }}_{{ model_name }}_add``
History ``{{ app_label }}_{{ model_name }}_history`` ``object_id``
Delete ``{{ app_label }}_{{ model_name }}_delete`` ``object_id``
Change ``{{ app_label }}_{{ model_name }}_change`` ``object_id``
====================== =============================================== =============
====================== =============================================== =============
Page URL name Parameters
====================== =============================================== =============
Changelist ``{{ app_label }}_{{ model_name }}_changelist``
Add ``{{ app_label }}_{{ model_name }}_add``
History ``{{ app_label }}_{{ model_name }}_history`` ``object_id``
Delete ``{{ app_label }}_{{ model_name }}_delete`` ``object_id``
Change ``{{ app_label }}_{{ model_name }}_change`` ``object_id``
====================== =============================================== =============
These named URLs are registered with the application namespace ``admin``, and
with an instance namespace corresponding to the name of the Site instance.

View File

@ -125,12 +125,12 @@ moderate comments"``) can approve and delete comments. This can also be
done through the ``admin`` as you'll see later. You might also want to
customize the following templates:
* ``flag.html``
* ``flagged.html``
* ``approve.html``
* ``approved.html``
* ``delete.html``
* ``deleted.html``
* ``flag.html``
* ``flagged.html``
* ``approve.html``
* ``approved.html``
* ``delete.html``
* ``deleted.html``
found under the directory structure we saw for ``form.html``.
@ -185,9 +185,9 @@ in-built with :doc:`generic comment moderation
</ref/contrib/comments/moderation>`. The comment moderation has the following
features (all of which or only certain can be enabled):
* Enable comments for a particular model instance.
* Close comments after a particular (user-defined) number of days.
* Email new comments to the site-staff.
* Enable comments for a particular model instance.
* Close comments after a particular (user-defined) number of days.
* Email new comments to the site-staff.
To enable comment moderation, we subclass the :class:`CommentModerator` and
register it with the moderation features we want. Let us suppose we want to

View File

@ -36,49 +36,49 @@ Supported countries
Countries currently supported by :mod:`~django.contrib.localflavor` are:
* Argentina_
* Australia_
* Austria_
* Belgium_
* Brazil_
* Canada_
* Chile_
* China_
* Colombia_
* Croatia_
* Czech_
* Ecuador_
* Finland_
* France_
* Germany_
* Iceland_
* India_
* Indonesia_
* Ireland_
* Israel_
* Italy_
* Japan_
* Kuwait_
* Macedonia_
* Mexico_
* `The Netherlands`_
* Norway_
* Peru_
* Poland_
* Portugal_
* Paraguay_
* Romania_
* Russia_
* Slovakia_
* Slovenia_
* `South Africa`_
* Spain_
* Sweden_
* Switzerland_
* Turkey_
* `United Kingdom`_
* `United States of America`_
* Uruguay_
* Argentina_
* Australia_
* Austria_
* Belgium_
* Brazil_
* Canada_
* Chile_
* China_
* Colombia_
* Croatia_
* Czech_
* Ecuador_
* Finland_
* France_
* Germany_
* Iceland_
* India_
* Indonesia_
* Ireland_
* Israel_
* Italy_
* Japan_
* Kuwait_
* Macedonia_
* Mexico_
* `The Netherlands`_
* Norway_
* Peru_
* Poland_
* Portugal_
* Paraguay_
* Romania_
* Russia_
* Slovakia_
* Slovenia_
* `South Africa`_
* Spain_
* Sweden_
* Switzerland_
* Turkey_
* `United Kingdom`_
* `United States of America`_
* Uruguay_
The ``django.contrib.localflavor`` package also includes a ``generic`` subpackage,
containing useful code that is not specific to one particular country or culture.
@ -1286,13 +1286,13 @@ United States of America (``us``)
A form field that validates input as a U.S. Social Security Number (SSN).
A valid SSN must obey the following rules:
* Format of XXX-XX-XXXX
* No group of digits consisting entirely of zeroes
* Leading group of digits cannot be 666
* Number not in promotional block 987-65-4320 through 987-65-4329
* Number not one known to be invalid due to widespread promotional
use or distribution (e.g., the Woolworth's number or the 1962
promotional number)
* Format of XXX-XX-XXXX
* No group of digits consisting entirely of zeroes
* Leading group of digits cannot be 666
* Number not in promotional block 987-65-4320 through 987-65-4329
* Number not one known to be invalid due to widespread promotional
use or distribution (e.g., the Woolworth's number or the 1962
promotional number)
.. class:: us.forms.USStateField

View File

@ -24,57 +24,57 @@ actually occurs until you do something to evaluate the queryset.
You can evaluate a ``QuerySet`` in the following ways:
* **Iteration.** A ``QuerySet`` is iterable, and it executes its database
query the first time you iterate over it. For example, this will print
the headline of all entries in the database::
* **Iteration.** A ``QuerySet`` is iterable, and it executes its database
query the first time you iterate over it. For example, this will print
the headline of all entries in the database::
for e in Entry.objects.all():
print e.headline
for e in Entry.objects.all():
print e.headline
* **Slicing.** As explained in :ref:`limiting-querysets`, a ``QuerySet`` can
be sliced, using Python's array-slicing syntax. Usually slicing a
``QuerySet`` returns another (unevaluated) ``QuerySet``, but Django will
execute the database query if you use the "step" parameter of slice
syntax.
* **Slicing.** As explained in :ref:`limiting-querysets`, a ``QuerySet`` can
be sliced, using Python's array-slicing syntax. Usually slicing a
``QuerySet`` returns another (unevaluated) ``QuerySet``, but Django will
execute the database query if you use the "step" parameter of slice
syntax.
* **Pickling/Caching.** See the following section for details of what
is involved when `pickling QuerySets`_. The important thing for the
purposes of this section is that the results are read from the database.
* **Pickling/Caching.** See the following section for details of what
is involved when `pickling QuerySets`_. The important thing for the
purposes of this section is that the results are read from the database.
* **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it.
This is for convenience in the Python interactive interpreter, so you can
immediately see your results when using the API interactively.
* **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it.
This is for convenience in the Python interactive interpreter, so you can
immediately see your results when using the API interactively.
* **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it.
This, as you might expect, returns the length of the result list.
* **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it.
This, as you might expect, returns the length of the result list.
Note: *Don't* use ``len()`` on ``QuerySet``\s if all you want to do is
determine the number of records in the set. It's much more efficient to
handle a count at the database level, using SQL's ``SELECT COUNT(*)``,
and Django provides a ``count()`` method for precisely this reason. See
``count()`` below.
Note: *Don't* use ``len()`` on ``QuerySet``\s if all you want to do is
determine the number of records in the set. It's much more efficient to
handle a count at the database level, using SQL's ``SELECT COUNT(*)``,
and Django provides a ``count()`` method for precisely this reason. See
``count()`` below.
* **list().** Force evaluation of a ``QuerySet`` by calling ``list()`` on
it. For example::
* **list().** Force evaluation of a ``QuerySet`` by calling ``list()`` on
it. For example::
entry_list = list(Entry.objects.all())
entry_list = list(Entry.objects.all())
Be warned, though, that this could have a large memory overhead, because
Django will load each element of the list into memory. In contrast,
iterating over a ``QuerySet`` will take advantage of your database to
load data and instantiate objects only as you need them.
Be warned, though, that this could have a large memory overhead, because
Django will load each element of the list into memory. In contrast,
iterating over a ``QuerySet`` will take advantage of your database to
load data and instantiate objects only as you need them.
* **bool().** Testing a ``QuerySet`` in a boolean context, such as using
``bool()``, ``or``, ``and`` or an ``if`` statement, will cause the query
to be executed. If there is at least one result, the ``QuerySet`` is
``True``, otherwise ``False``. For example::
* **bool().** Testing a ``QuerySet`` in a boolean context, such as using
``bool()``, ``or``, ``and`` or an ``if`` statement, will cause the query
to be executed. If there is at least one result, the ``QuerySet`` is
``True``, otherwise ``False``. For example::
if Entry.objects.filter(headline="Test"):
print "There is at least one Entry with the headline Test"
if Entry.objects.filter(headline="Test"):
print "There is at least one Entry with the headline Test"
Note: *Don't* use this if all you want to do is determine if at least one
result exists, and don't need the actual objects. It's more efficient to
use :meth:`exists() <QuerySet.exists>` (see below).
Note: *Don't* use this if all you want to do is determine if at least one
result exists, and don't need the actual objects. It's more efficient to
use :meth:`exists() <QuerySet.exists>` (see below).
.. _pickling QuerySets:
@ -411,35 +411,35 @@ Example::
A few subtleties that are worth mentioning:
* If you have a field called ``foo`` that is a
:class:`~django.db.models.ForeignKey`, the default ``values()`` call
will return a dictionary key called ``foo_id``, since this is the name
of the hidden model attribute that stores the actual value (the ``foo``
attribute refers to the related model). When you are calling
``values()`` and passing in field names, you can pass in either ``foo``
or ``foo_id`` and you will get back the same thing (the dictionary key
will match the field name you passed in).
* If you have a field called ``foo`` that is a
:class:`~django.db.models.ForeignKey`, the default ``values()`` call
will return a dictionary key called ``foo_id``, since this is the name
of the hidden model attribute that stores the actual value (the ``foo``
attribute refers to the related model). When you are calling
``values()`` and passing in field names, you can pass in either ``foo``
or ``foo_id`` and you will get back the same thing (the dictionary key
will match the field name you passed in).
For example::
For example::
>>> Entry.objects.values()
[{'blog_id': 1, 'headline': u'First Entry', ...}, ...]
>>> Entry.objects.values()
[{'blog_id': 1, 'headline': u'First Entry', ...}, ...]
>>> Entry.objects.values('blog')
[{'blog': 1}, ...]
>>> Entry.objects.values('blog')
[{'blog': 1}, ...]
>>> Entry.objects.values('blog_id')
[{'blog_id': 1}, ...]
>>> Entry.objects.values('blog_id')
[{'blog_id': 1}, ...]
* When using ``values()`` together with :meth:`distinct()`, be aware that
ordering can affect the results. See the note in :meth:`distinct` for
details.
* When using ``values()`` together with :meth:`distinct()`, be aware that
ordering can affect the results. See the note in :meth:`distinct` for
details.
* If you use a ``values()`` clause after an :meth:`extra()` call,
any fields defined by a ``select`` argument in the :meth:`extra()` must
be explicitly included in the ``values()`` call. Any :meth:`extra()` call
made after a ``values()`` call will have its extra selected fields
ignored.
* If you use a ``values()`` clause after an :meth:`extra()` call,
any fields defined by a ``select`` argument in the :meth:`extra()` must
be explicitly included in the ``values()`` call. Any :meth:`extra()` call
made after a ``values()`` call will have its extra selected fields
ignored.
A ``ValuesQuerySet`` is useful when you know you're only going to need values
from a small number of the available fields and you won't need the
@ -524,11 +524,11 @@ model.
``datetime.datetime`` object in the result list is "truncated" to the given
``type``.
* ``"year"`` returns a list of all distinct year values for the field.
* ``"month"`` returns a list of all distinct year/month values for the
field.
* ``"day"`` returns a list of all distinct year/month/day values for the
field.
* ``"year"`` returns a list of all distinct year values for the field.
* ``"month"`` returns a list of all distinct year/month values for the
field.
* ``"day"`` returns a list of all distinct year/month/day values for the
field.
``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or
``'DESC'``. This specifies how to order the results.
@ -832,153 +832,155 @@ principle, so you should avoid them if possible.
Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None
of the arguments is required, but you should use at least one of them.
* ``select``
The ``select`` argument lets you put extra fields in the ``SELECT``
clause. It should be a dictionary mapping attribute names to SQL
clauses to use to calculate that attribute.
* ``select``
Example::
The ``select`` argument lets you put extra fields in the ``SELECT``
clause. It should be a dictionary mapping attribute names to SQL
clauses to use to calculate that attribute.
Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
Example::
As a result, each ``Entry`` object will have an extra attribute,
``is_recent``, a boolean representing whether the entry's ``pub_date``
is greater than Jan. 1, 2006.
Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
Django inserts the given SQL snippet directly into the ``SELECT``
statement, so the resulting SQL of the above example would be something
like::
As a result, each ``Entry`` object will have an extra attribute,
``is_recent``, a boolean representing whether the entry's ``pub_date``
is greater than Jan. 1, 2006.
SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
FROM blog_entry;
Django inserts the given SQL snippet directly into the ``SELECT``
statement, so the resulting SQL of the above example would be something
like::
SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
FROM blog_entry;
The next example is more advanced; it does a subquery to give each
resulting ``Blog`` object an ``entry_count`` attribute, an integer count
of associated ``Entry`` objects::
The next example is more advanced; it does a subquery to give each
resulting ``Blog`` object an ``entry_count`` attribute, an integer count
of associated ``Entry`` objects::
Blog.objects.extra(
select={
'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
},
)
Blog.objects.extra(
select={
'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
},
)
In this particular case, we're exploiting the fact that the query will
already contain the ``blog_blog`` table in its ``FROM`` clause.
In this particular case, we're exploiting the fact that the query will
already contain the ``blog_blog`` table in its ``FROM`` clause.
The resulting SQL of the above example would be::
The resulting SQL of the above example would be::
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;
Note that the parentheses required by most database engines around
subqueries are not required in Django's ``select`` clauses. Also note
that some database backends, such as some MySQL versions, don't support
subqueries.
Note that the parentheses required by most database engines around
subqueries are not required in Django's ``select`` clauses. Also note
that some database backends, such as some MySQL versions, don't support
subqueries.
In some rare cases, you might wish to pass parameters to the SQL
fragments in ``extra(select=...)``. For this purpose, use the
``select_params`` parameter. Since ``select_params`` is a sequence and
the ``select`` attribute is a dictionary, some care is required so that
the parameters are matched up correctly with the extra select pieces.
In this situation, you should use a
:class:`django.utils.datastructures.SortedDict` for the ``select``
value, not just a normal Python dictionary.
In some rare cases, you might wish to pass parameters to the SQL
fragments in ``extra(select=...)``. For this purpose, use the
``select_params`` parameter. Since ``select_params`` is a sequence and
the ``select`` attribute is a dictionary, some care is required so that
the parameters are matched up correctly with the extra select pieces.
In this situation, you should use a
:class:`django.utils.datastructures.SortedDict` for the ``select``
value, not just a normal Python dictionary.
This will work, for example::
This will work, for example::
Blog.objects.extra(
select=SortedDict([('a', '%s'), ('b', '%s')]),
select_params=('one', 'two'))
Blog.objects.extra(
select=SortedDict([('a', '%s'), ('b', '%s')]),
select_params=('one', 'two'))
The only thing to be careful about when using select parameters in
``extra()`` is to avoid using the substring ``"%%s"`` (that's *two*
percent characters before the ``s``) in the select strings. Django's
tracking of parameters looks for ``%s`` and an escaped ``%`` character
like this isn't detected. That will lead to incorrect results.
The only thing to be careful about when using select parameters in
``extra()`` is to avoid using the substring ``"%%s"`` (that's *two*
percent characters before the ``s``) in the select strings. Django's
tracking of parameters looks for ``%s`` and an escaped ``%`` character
like this isn't detected. That will lead to incorrect results.
* ``where`` / ``tables``
You can define explicit SQL ``WHERE`` clauses — perhaps to perform
non-explicit joins — by using ``where``. You can manually add tables to
the SQL ``FROM`` clause by using ``tables``.
* ``where`` / ``tables``
``where`` and ``tables`` both take a list of strings. All ``where``
parameters are "AND"ed to any other search criteria.
You can define explicit SQL ``WHERE`` clauses — perhaps to perform
non-explicit joins — by using ``where``. You can manually add tables to
the SQL ``FROM`` clause by using ``tables``.
Example::
``where`` and ``tables`` both take a list of strings. All ``where``
parameters are "AND"ed to any other search criteria.
Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
Example::
...translates (roughly) into the following SQL::
Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
...translates (roughly) into the following SQL::
Be careful when using the ``tables`` parameter if you're specifying
tables that are already used in the query. When you add extra tables
via the ``tables`` parameter, Django assumes you want that table
included an extra time, if it is already included. That creates a
problem, since the table name will then be given an alias. If a table
appears multiple times in an SQL statement, the second and subsequent
occurrences must use aliases so the database can tell them apart. If
you're referring to the extra table you added in the extra ``where``
parameter this is going to cause errors.
SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
Normally you'll only be adding extra tables that don't already appear
in the query. However, if the case outlined above does occur, there are
a few solutions. First, see if you can get by without including the
extra table and use the one already in the query. If that isn't
possible, put your ``extra()`` call at the front of the queryset
construction so that your table is the first use of that table.
Finally, if all else fails, look at the query produced and rewrite your
``where`` addition to use the alias given to your extra table. The
alias will be the same each time you construct the queryset in the same
way, so you can rely upon the alias name to not change.
Be careful when using the ``tables`` parameter if you're specifying
tables that are already used in the query. When you add extra tables
via the ``tables`` parameter, Django assumes you want that table
included an extra time, if it is already included. That creates a
problem, since the table name will then be given an alias. If a table
appears multiple times in an SQL statement, the second and subsequent
occurrences must use aliases so the database can tell them apart. If
you're referring to the extra table you added in the extra ``where``
parameter this is going to cause errors.
* ``order_by``
Normally you'll only be adding extra tables that don't already appear
in the query. However, if the case outlined above does occur, there are
a few solutions. First, see if you can get by without including the
extra table and use the one already in the query. If that isn't
possible, put your ``extra()`` call at the front of the queryset
construction so that your table is the first use of that table.
Finally, if all else fails, look at the query produced and rewrite your
``where`` addition to use the alias given to your extra table. The
alias will be the same each time you construct the queryset in the same
way, so you can rely upon the alias name to not change.
If you need to order the resulting queryset using some of the new
fields or tables you have included via ``extra()`` use the ``order_by``
parameter to ``extra()`` and pass in a sequence of strings. These
strings should either be model fields (as in the normal
:meth:`order_by()` method on querysets), of the form
``table_name.column_name`` or an alias for a column that you specified
in the ``select`` parameter to ``extra()``.
* ``order_by``
For example::
If you need to order the resulting queryset using some of the new
fields or tables you have included via ``extra()`` use the ``order_by``
parameter to ``extra()`` and pass in a sequence of strings. These
strings should either be model fields (as in the normal
:meth:`order_by()` method on querysets), of the form
``table_name.column_name`` or an alias for a column that you specified
in the ``select`` parameter to ``extra()``.
q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
q = q.extra(order_by = ['-is_recent'])
For example::
This would sort all the items for which ``is_recent`` is true to the
front of the result set (``True`` sorts before ``False`` in a
descending ordering).
q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
q = q.extra(order_by = ['-is_recent'])
This shows, by the way, that you can make multiple calls to ``extra()``
and it will behave as you expect (adding new constraints each time).
This would sort all the items for which ``is_recent`` is true to the
front of the result set (``True`` sorts before ``False`` in a
descending ordering).
* ``params``
This shows, by the way, that you can make multiple calls to ``extra()``
and it will behave as you expect (adding new constraints each time).
The ``where`` parameter described above may use standard Python
database string placeholders — ``'%s'`` to indicate parameters the
database engine should automatically quote. The ``params`` argument is
a list of any extra parameters to be substituted.
* ``params``
Example::
The ``where`` parameter described above may use standard Python
database string placeholders — ``'%s'`` to indicate parameters the
database engine should automatically quote. The ``params`` argument is
a list of any extra parameters to be substituted.
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Example::
Always use ``params`` instead of embedding values directly into
``where`` because ``params`` will ensure values are quoted correctly
according to your particular backend. For example, quotes will be
escaped correctly.
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Bad::
Always use ``params`` instead of embedding values directly into
``where`` because ``params`` will ensure values are quoted correctly
according to your particular backend. For example, quotes will be
escaped correctly.
Entry.objects.extra(where=["headline='Lennon'"])
Bad::
Good::
Entry.objects.extra(where=["headline='Lennon'"])
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Good::
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
defer
~~~~~
@ -1304,11 +1306,11 @@ are)::
This has a number of caveats though:
* The model's ``save()`` method will not be called, and the ``pre_save`` and
``post_save`` signals will not be sent.
* It does not work with child models in a multi-table inheritance scenario.
* If the model's primary key is an :class:`~django.db.models.AutoField` it
does not retrieve and set the primary key attribute, as ``save()`` does.
* The model's ``save()`` method will not be called, and the ``pre_save`` and
``post_save`` signals will not be sent.
* It does not work with child models in a multi-table inheritance scenario.
* If the model's primary key is an :class:`~django.db.models.AutoField` it
does not retrieve and set the primary key attribute, as ``save()`` does.
count
~~~~~
@ -2059,8 +2061,8 @@ Avg
Returns the mean value of the given field.
* Default alias: ``<field>__avg``
* Return type: float
* Default alias: ``<field>__avg``
* Return type: float
Count
~~~~~
@ -2069,8 +2071,8 @@ Count
Returns the number of objects that are related through the provided field.
* Default alias: ``<field>__count``
* Return type: integer
* Default alias: ``<field>__count``
* Return type: integer
Has one optional argument:
@ -2086,8 +2088,8 @@ Max
Returns the maximum value of the given field.
* Default alias: ``<field>__max``
* Return type: same as input field
* Default alias: ``<field>__max``
* Return type: same as input field
Min
~~~
@ -2096,8 +2098,8 @@ Min
Returns the minimum value of the given field.
* Default alias: ``<field>__min``
* Return type: same as input field
* Default alias: ``<field>__min``
* Return type: same as input field
StdDev
~~~~~~
@ -2106,8 +2108,8 @@ StdDev
Returns the standard deviation of the data in the provided field.
* Default alias: ``<field>__stddev``
* Return type: float
* Default alias: ``<field>__stddev``
* Return type: float
Has one optional argument:
@ -2129,8 +2131,8 @@ Sum
Computes the sum of all values of the given field.
* Default alias: ``<field>__sum``
* Return type: same as input field
* Default alias: ``<field>__sum``
* Return type: same as input field
Variance
~~~~~~~~
@ -2139,8 +2141,8 @@ Variance
Returns the variance of the data in the provided field.
* Default alias: ``<field>__variance``
* Return type: float
* Default alias: ``<field>__variance``
* Return type: float
Has one optional argument:

View File

@ -240,7 +240,7 @@ Caveats with support of certain databases
Django attempts to support as many features as possible on all database
backends. However, not all database backends are alike, and in particular many of the supported database differ greatly from version to version. It's a good idea to checkout our :doc:`notes on supported database </ref/databases>`:
- :ref:`mysql-notes`
- :ref:`sqlite-notes`
- :ref:`oracle-notes`
- :ref:`mysql-notes`
- :ref:`sqlite-notes`
- :ref:`oracle-notes`

View File

@ -14,11 +14,11 @@ Overview
The auth system consists of:
* Users
* Permissions: Binary (yes/no) flags designating whether a user may perform
a certain task.
* Groups: A generic way of applying labels and permissions to more than one
user.
* Users
* Permissions: Binary (yes/no) flags designating whether a user may perform
a certain task.
* Groups: A generic way of applying labels and permissions to more than one
user.
Installation
============
@ -26,11 +26,11 @@ Installation
Authentication support is bundled as a Django application in
``django.contrib.auth``. To install it, do the following:
1. Put ``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in
your :setting:`INSTALLED_APPS` setting.
(The :class:`~django.contrib.auth.models.Permission` model in
:mod:`django.contrib.auth` depends on :mod:`django.contrib.contenttypes`.)
2. Run the command ``manage.py syncdb``.
1. Put ``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in
your :setting:`INSTALLED_APPS` setting.
(The :class:`~django.contrib.auth.models.Permission` model in
:mod:`django.contrib.auth` depends on :mod:`django.contrib.contenttypes`.)
2. Run the command ``manage.py syncdb``.
Note that the default :file:`settings.py` file created by
:djadmin:`django-admin.py startproject <startproject>` includes
@ -303,10 +303,10 @@ Manager functions
allowed characters. (Note that the default value of ``allowed_chars``
doesn't contain letters that can cause user confusion, including:
* ``i``, ``l``, ``I``, and ``1`` (lowercase letter i, lowercase
letter L, uppercase letter i, and the number one)
* ``o``, ``O``, and ``0`` (uppercase letter o, lowercase letter o,
and zero)
* ``i``, ``l``, ``I``, and ``1`` (lowercase letter i, lowercase
letter L, uppercase letter i, and the number one)
* ``o``, ``O``, and ``0`` (uppercase letter o, lowercase letter o,
and zero)
Basic usage
-----------
@ -715,29 +715,29 @@ Sent when a user logs in successfully.
Arguments sent with this signal:
``sender``
As above: the class of the user that just logged in.
``sender``
As above: the class of the user that just logged in.
``request``
The current :class:`~django.http.HttpRequest` instance.
``request``
The current :class:`~django.http.HttpRequest` instance.
``user``
The user instance that just logged in.
``user``
The user instance that just logged in.
.. data:: django.contrib.auth.signals.user_logged_out
Sent when the logout method is called.
``sender``
As above: the class of the user that just logged out or ``None``
if the user was not authenticated.
``sender``
As above: the class of the user that just logged out or ``None``
if the user was not authenticated.
``request``
The current :class:`~django.http.HttpRequest` instance.
``request``
The current :class:`~django.http.HttpRequest` instance.
``user``
The user instance that just logged out or ``None`` if the
user was not authenticated.
``user``
The user instance that just logged out or ``None`` if the
user was not authenticated.
Limiting access to logged-in users
----------------------------------
@ -830,38 +830,38 @@ The login_required decorator
Here's what ``django.contrib.auth.views.login`` does:
* If called via ``GET``, it displays a login form that POSTs to the
same URL. More on this in a bit.
* If called via ``GET``, it displays a login form that POSTs to the
same URL. More on this in a bit.
* If called via ``POST``, it tries to log the user in. If login is
successful, the view redirects to the URL specified in ``next``. If
``next`` isn't provided, it redirects to
:setting:`settings.LOGIN_REDIRECT_URL <LOGIN_REDIRECT_URL>` (which
defaults to ``/accounts/profile/``). If login isn't successful, it
redisplays the login form.
* If called via ``POST``, it tries to log the user in. If login is
successful, the view redirects to the URL specified in ``next``. If
``next`` isn't provided, it redirects to
:setting:`settings.LOGIN_REDIRECT_URL <LOGIN_REDIRECT_URL>` (which
defaults to ``/accounts/profile/``). If login isn't successful, it
redisplays the login form.
It's your responsibility to provide the login form in a template called
``registration/login.html`` by default. This template gets passed four
template context variables:
* ``form``: A :class:`~django.forms.Form` object representing the login
form. See the :doc:`forms documentation </topics/forms/index>` for
more on ``Form`` objects.
* ``form``: A :class:`~django.forms.Form` object representing the login
form. See the :doc:`forms documentation </topics/forms/index>` for
more on ``Form`` objects.
* ``next``: The URL to redirect to after successful login. This may
contain a query string, too.
* ``next``: The URL to redirect to after successful login. This may
contain a query string, too.
* ``site``: The current :class:`~django.contrib.sites.models.Site`,
according to the :setting:`SITE_ID` setting. If you don't have the
site framework installed, this will be set to an instance of
:class:`~django.contrib.sites.models.RequestSite`, which derives the
site name and domain from the current
:class:`~django.http.HttpRequest`.
* ``site``: The current :class:`~django.contrib.sites.models.Site`,
according to the :setting:`SITE_ID` setting. If you don't have the
site framework installed, this will be set to an instance of
:class:`~django.contrib.sites.models.RequestSite`, which derives the
site name and domain from the current
:class:`~django.http.HttpRequest`.
* ``site_name``: An alias for ``site.name``. If you don't have the site
framework installed, this will be set to the value of
:attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`.
For more on sites, see :doc:`/ref/contrib/sites`.
* ``site_name``: An alias for ``site.name``. If you don't have the site
framework installed, this will be set to the value of
:attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`.
For more on sites, see :doc:`/ref/contrib/sites`.
If you'd prefer not to call the template :file:`registration/login.html`,
you can pass the ``template_name`` parameter via the extra arguments to
@ -950,31 +950,31 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``next_page``: The URL to redirect to after logout.
* ``next_page``: The URL to redirect to after logout.
* ``template_name``: The full name of a template to display after
logging the user out. Defaults to
:file:`registration/logged_out.html` if no argument is supplied.
* ``template_name``: The full name of a template to display after
logging the user out. Defaults to
:file:`registration/logged_out.html` if no argument is supplied.
* ``redirect_field_name``: The name of a ``GET`` field containing the
URL to redirect to after log out. Overrides ``next_page`` if the given
``GET`` parameter is passed.
* ``redirect_field_name``: The name of a ``GET`` field containing the
URL to redirect to after log out. Overrides ``next_page`` if the given
``GET`` parameter is passed.
**Template context:**
* ``title``: The string "Logged out", localized.
* ``title``: The string "Logged out", localized.
* ``site``: The current :class:`~django.contrib.sites.models.Site`,
according to the :setting:`SITE_ID` setting. If you don't have the
site framework installed, this will be set to an instance of
:class:`~django.contrib.sites.models.RequestSite`, which derives the
site name and domain from the current
:class:`~django.http.HttpRequest`.
* ``site``: The current :class:`~django.contrib.sites.models.Site`,
according to the :setting:`SITE_ID` setting. If you don't have the
site framework installed, this will be set to an instance of
:class:`~django.contrib.sites.models.RequestSite`, which derives the
site name and domain from the current
:class:`~django.http.HttpRequest`.
* ``site_name``: An alias for ``site.name``. If you don't have the site
framework installed, this will be set to the value of
:attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`.
For more on sites, see :doc:`/ref/contrib/sites`.
* ``site_name``: An alias for ``site.name``. If you don't have the site
framework installed, this will be set to the value of
:attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`.
For more on sites, see :doc:`/ref/contrib/sites`.
.. function:: logout_then_login(request[, login_url])
@ -984,8 +984,8 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``login_url``: The URL of the login page to redirect to.
Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
* ``login_url``: The URL of the login page to redirect to.
Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
.. function:: password_change(request[, template_name, post_change_redirect, password_change_form])
@ -995,23 +995,23 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``template_name``: The full name of a template to use for
displaying the password change form. Defaults to
:file:`registration/password_change_form.html` if not supplied.
* ``template_name``: The full name of a template to use for
displaying the password change form. Defaults to
:file:`registration/password_change_form.html` if not supplied.
* ``post_change_redirect``: The URL to redirect to after a successful
password change.
* ``post_change_redirect``: The URL to redirect to after a successful
password change.
.. versionadded:: 1.2
.. versionadded:: 1.2
* ``password_change_form``: A custom "change password" form which must
accept a ``user`` keyword argument. The form is responsible for
actually changing the user's password. Defaults to
:class:`~django.contrib.auth.forms.PasswordChangeForm`.
* ``password_change_form``: A custom "change password" form which must
accept a ``user`` keyword argument. The form is responsible for
actually changing the user's password. Defaults to
:class:`~django.contrib.auth.forms.PasswordChangeForm`.
**Template context:**
* ``form``: The password change form (see ``password_change_form`` above).
* ``form``: The password change form (see ``password_change_form`` above).
.. function:: password_change_done(request[, template_name])
@ -1021,9 +1021,9 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``template_name``: The full name of a template to use.
Defaults to :file:`registration/password_change_done.html` if not
supplied.
* ``template_name``: The full name of a template to use.
Defaults to :file:`registration/password_change_done.html` if not
supplied.
.. function:: password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect, from_email])
@ -1044,60 +1044,60 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``template_name``: The full name of a template to use for
displaying the password reset form. Defaults to
:file:`registration/password_reset_form.html` if not supplied.
* ``template_name``: The full name of a template to use for
displaying the password reset form. Defaults to
:file:`registration/password_reset_form.html` if not supplied.
* ``email_template_name``: The full name of a template to use for
generating the email with the new password. Defaults to
:file:`registration/password_reset_email.html` if not supplied.
* ``email_template_name``: The full name of a template to use for
generating the email with the new password. Defaults to
:file:`registration/password_reset_email.html` if not supplied.
* ``subject_template_name``: The full name of a template to use for
the subject of the email with the new password. Defaults
to :file:`registration/password_reset_subject.txt` if not supplied.
* ``subject_template_name``: The full name of a template to use for
the subject of the email with the new password. Defaults
to :file:`registration/password_reset_subject.txt` if not supplied.
.. versionadded:: 1.4
.. versionadded:: 1.4
* ``password_reset_form``: Form that will be used to set the password.
Defaults to :class:`~django.contrib.auth.forms.PasswordResetForm`.
* ``password_reset_form``: Form that will be used to set the password.
Defaults to :class:`~django.contrib.auth.forms.PasswordResetForm`.
* ``token_generator``: Instance of the class to check the password. This
will default to ``default_token_generator``, it's an instance of
``django.contrib.auth.tokens.PasswordResetTokenGenerator``.
* ``token_generator``: Instance of the class to check the password. This
will default to ``default_token_generator``, it's an instance of
``django.contrib.auth.tokens.PasswordResetTokenGenerator``.
* ``post_reset_redirect``: The URL to redirect to after a successful
password change.
* ``post_reset_redirect``: The URL to redirect to after a successful
password change.
* ``from_email``: A valid email address. By default Django uses
the :setting:`DEFAULT_FROM_EMAIL`.
* ``from_email``: A valid email address. By default Django uses
the :setting:`DEFAULT_FROM_EMAIL`.
**Template context:**
* ``form``: The form (see ``password_reset_form`` above) for resetting
the user's password.
* ``form``: The form (see ``password_reset_form`` above) for resetting
the user's password.
**Email template context:**
* ``email``: An alias for ``user.email``
* ``email``: An alias for ``user.email``
* ``user``: The current :class:`~django.contrib.auth.models.User`,
according to the ``email`` form field. Only active users are able to
reset their passwords (``User.is_active is True``).
* ``user``: The current :class:`~django.contrib.auth.models.User`,
according to the ``email`` form field. Only active users are able to
reset their passwords (``User.is_active is True``).
* ``site_name``: An alias for ``site.name``. If you don't have the site
framework installed, this will be set to the value of
:attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`.
For more on sites, see :doc:`/ref/contrib/sites`.
* ``site_name``: An alias for ``site.name``. If you don't have the site
framework installed, this will be set to the value of
:attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`.
For more on sites, see :doc:`/ref/contrib/sites`.
* ``domain``: An alias for ``site.domain``. If you don't have the site
framework installed, this will be set to the value of
``request.get_host()``.
* ``domain``: An alias for ``site.domain``. If you don't have the site
framework installed, this will be set to the value of
``request.get_host()``.
* ``protocol``: http or https
* ``protocol``: http or https
* ``uid``: The user's id encoded in base 36.
* ``uid``: The user's id encoded in base 36.
* ``token``: Token to check that the password is valid.
* ``token``: Token to check that the password is valid.
Sample ``registration/password_reset_email.html`` (email body template):
@ -1121,9 +1121,9 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``template_name``: The full name of a template to use.
Defaults to :file:`registration/password_reset_done.html` if not
supplied.
* ``template_name``: The full name of a template to use.
Defaults to :file:`registration/password_reset_done.html` if not
supplied.
.. function:: password_reset_confirm(request[, uidb36, token, template_name, token_generator, set_password_form, post_reset_redirect])
@ -1133,31 +1133,31 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``uidb36``: The user's id encoded in base 36. Defaults to ``None``.
* ``uidb36``: The user's id encoded in base 36. Defaults to ``None``.
* ``token``: Token to check that the password is valid. Defaults to
``None``.
* ``token``: Token to check that the password is valid. Defaults to
``None``.
* ``template_name``: The full name of a template to display the confirm
password view. Default value is :file:`registration/password_reset_confirm.html`.
* ``template_name``: The full name of a template to display the confirm
password view. Default value is :file:`registration/password_reset_confirm.html`.
* ``token_generator``: Instance of the class to check the password. This
will default to ``default_token_generator``, it's an instance of
``django.contrib.auth.tokens.PasswordResetTokenGenerator``.
* ``token_generator``: Instance of the class to check the password. This
will default to ``default_token_generator``, it's an instance of
``django.contrib.auth.tokens.PasswordResetTokenGenerator``.
* ``set_password_form``: Form that will be used to set the password.
Defaults to :class:`~django.contrib.auth.forms.SetPasswordForm`
* ``set_password_form``: Form that will be used to set the password.
Defaults to :class:`~django.contrib.auth.forms.SetPasswordForm`
* ``post_reset_redirect``: URL to redirect after the password reset
done. Defaults to ``None``.
* ``post_reset_redirect``: URL to redirect after the password reset
done. Defaults to ``None``.
**Template context:**
* ``form``: The form (see ``set_password_form`` above) for setting the
new user's password.
* ``form``: The form (see ``set_password_form`` above) for setting the
new user's password.
* ``validlink``: Boolean, True if the link (combination of uidb36 and
token) is valid or unused yet.
* ``validlink``: Boolean, True if the link (combination of uidb36 and
token) is valid or unused yet.
.. function:: password_reset_complete(request[,template_name])
@ -1168,8 +1168,8 @@ includes a few other useful built-in views located in
**Optional arguments:**
* ``template_name``: The full name of a template to display the view.
Defaults to :file:`registration/password_reset_complete.html`.
* ``template_name``: The full name of a template to display the view.
Defaults to :file:`registration/password_reset_complete.html`.
Helper functions
----------------
@ -1183,16 +1183,16 @@ Helper functions
**Required arguments:**
* ``next``: The URL to redirect to after a successful login.
* ``next``: The URL to redirect to after a successful login.
**Optional arguments:**
* ``login_url``: The URL of the login page to redirect to.
Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
* ``login_url``: The URL of the login page to redirect to.
Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
* ``redirect_field_name``: The name of a ``GET`` field containing the
URL to redirect to after log out. Overrides ``next`` if the given
``GET`` parameter is passed.
* ``redirect_field_name``: The name of a ``GET`` field containing the
URL to redirect to after log out. Overrides ``next`` if the given
``GET`` parameter is passed.
Built-in forms
--------------
@ -1354,13 +1354,13 @@ code.
The Django admin site uses permissions as follows:
* Access to view the "add" form and add an object is limited to users with
the "add" permission for that type of object.
* Access to view the change list, view the "change" form and change an
object is limited to users with the "change" permission for that type of
object.
* Access to delete an object is limited to users with the "delete"
permission for that type of object.
* Access to view the "add" form and add an object is limited to users with
the "add" permission for that type of object.
* Access to view the change list, view the "change" form and change an
object is limited to users with the "change" permission for that type of
object.
* Access to delete an object is limited to users with the "delete"
permission for that type of object.
Permissions are set globally per type of object, not per specific object
instance. For example, it's possible to say "Mary may change news stories," but
@ -1389,9 +1389,9 @@ Assuming you have an application with an
:attr:`~django.db.models.Options.app_label` ``foo`` and a model named ``Bar``,
to test for basic permissions you should use:
* add: ``user.has_perm('foo.add_bar')``
* change: ``user.has_perm('foo.change_bar')``
* delete: ``user.has_perm('foo.delete_bar')``
* add: ``user.has_perm('foo.add_bar')``
* change: ``user.has_perm('foo.change_bar')``
* delete: ``user.has_perm('foo.delete_bar')``
.. _custom-permissions:

View File

@ -92,10 +92,10 @@ Use a dot (``.``) to access attributes of a variable.
Technically, when the template system encounters a dot, it tries the
following lookups, in this order:
* Dictionary lookup
* Attribute lookup
* Method call
* List-index lookup
* Dictionary lookup
* Attribute lookup
* Method call
* List-index lookup
In the above example, ``{{ section.title }}`` will be replaced with the
``title`` attribute of the ``section`` object.
@ -129,32 +129,32 @@ them in the :ref:`built-in filter reference <ref-templates-builtins-filters>`.
To give you a taste of what's available, here are some of the more commonly
used template filters:
:tfilter:`default`
If a variable is false or empty, use given default. Otherwise, use the
value of the variable
:tfilter:`default`
If a variable is false or empty, use given default. Otherwise, use the
value of the variable
For example::
For example::
{{ value|default:"nothing" }}
{{ value|default:"nothing" }}
If ``value`` isn't provided or is empty, the above will display
"``nothing``".
If ``value`` isn't provided or is empty, the above will display
"``nothing``".
:tfilter:`length`
Returns the length of the value. This works for both strings and lists;
for example::
:tfilter:`length`
Returns the length of the value. This works for both strings and lists;
for example::
{{ value|length }}
{{ value|length }}
If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``.
If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``.
:tfilter:`striptags`
Strips all [X]HTML tags. For example::
:tfilter:`striptags`
Strips all [X]HTML tags. For example::
{{ value|striptags }}
{{ value|striptags }}
If ``value`` is ``"<b>Joel</b> <button>is</button> a
<span>slug</span>"``, the output will be ``"Joel is a slug"``.
If ``value`` is ``"<b>Joel</b> <button>is</button> a
<span>slug</span>"``, the output will be ``"Joel is a slug"``.
Again, these are just a few examples; see the :ref:`built-in filter reference
<ref-templates-builtins-filters>` for the complete list.
@ -183,40 +183,40 @@ them in the :ref:`built-in tag reference <ref-templates-builtins-tags>`. To give
you a taste of what's available, here are some of the more commonly used
tags:
:ttag:`for`
Loop over each item in an array. For example, to display a list of athletes
provided in ``athlete_list``::
:ttag:`for`
Loop over each item in an array. For example, to display a list of athletes
provided in ``athlete_list``::
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
:ttag:`if` and ``else``
Evaluates a variable, and if that variable is "true" the contents of the
block are displayed::
:ttag:`if` and ``else``
Evaluates a variable, and if that variable is "true" the contents of the
block are displayed::
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% else %}
No athletes.
{% endif %}
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% else %}
No athletes.
{% endif %}
In the above, if ``athlete_list`` is not empty, the number of athletes
will be displayed by the ``{{ athlete_list|length }}`` variable.
In the above, if ``athlete_list`` is not empty, the number of athletes
will be displayed by the ``{{ athlete_list|length }}`` variable.
You can also use filters and various operators in the :ttag:`if` tag::
You can also use filters and various operators in the :ttag:`if` tag::
{% if athlete_list|length > 1 %}
Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
Athlete: {{ athlete_list.0.name }}
{% endif %}
{% if athlete_list|length > 1 %}
Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
Athlete: {{ athlete_list.0.name }}
{% endif %}
:ttag:`block` and :ttag:`extends`
Set up `template inheritance`_ (see below), a powerful way
of cutting down on "boilerplate" in templates.
:ttag:`block` and :ttag:`extends`
Set up `template inheritance`_ (see below), a powerful way
of cutting down on "boilerplate" in templates.
Again, the above is only a selection of the whole list; see the :ref:`built-in
tag reference <ref-templates-builtins-tags>` for the complete list.
@ -344,49 +344,49 @@ tag in a parent template is always used as a fallback.
You can use as many levels of inheritance as needed. One common way of using
inheritance is the following three-level approach:
* Create a ``base.html`` template that holds the main look-and-feel of your
site.
* Create a ``base_SECTIONNAME.html`` template for each "section" of your
site. For example, ``base_news.html``, ``base_sports.html``. These
templates all extend ``base.html`` and include section-specific
styles/design.
* Create individual templates for each type of page, such as a news
article or blog entry. These templates extend the appropriate section
template.
* Create a ``base.html`` template that holds the main look-and-feel of your
site.
* Create a ``base_SECTIONNAME.html`` template for each "section" of your
site. For example, ``base_news.html``, ``base_sports.html``. These
templates all extend ``base.html`` and include section-specific
styles/design.
* Create individual templates for each type of page, such as a news
article or blog entry. These templates extend the appropriate section
template.
This approach maximizes code reuse and makes it easy to add items to shared
content areas, such as section-wide navigation.
Here are some tips for working with inheritance:
* If you use :ttag:`{% extends %}<extends>` in a template, it must be the first template
tag in that template. Template inheritance won't work, otherwise.
* If you use :ttag:`{% extends %}<extends>` in a template, it must be the first template
tag in that template. Template inheritance won't work, otherwise.
* More :ttag:`{% block %}<block>` tags in your base templates are better. Remember,
child templates don't have to define all parent blocks, so you can fill
in reasonable defaults in a number of blocks, then only define the ones
you need later. It's better to have more hooks than fewer hooks.
* More :ttag:`{% block %}<block>` tags in your base templates are better. Remember,
child templates don't have to define all parent blocks, so you can fill
in reasonable defaults in a number of blocks, then only define the ones
you need later. It's better to have more hooks than fewer hooks.
* If you find yourself duplicating content in a number of templates, it
probably means you should move that content to a ``{% block %}`` in a
parent template.
* If you find yourself duplicating content in a number of templates, it
probably means you should move that content to a ``{% block %}`` in a
parent template.
* If you need to get the content of the block from the parent template,
the ``{{ block.super }}`` variable will do the trick. This is useful
if you want to add to the contents of a parent block instead of
completely overriding it. Data inserted using ``{{ block.super }}`` will
not be automatically escaped (see the `next section`_), since it was
already escaped, if necessary, in the parent template.
* If you need to get the content of the block from the parent template,
the ``{{ block.super }}`` variable will do the trick. This is useful
if you want to add to the contents of a parent block instead of
completely overriding it. Data inserted using ``{{ block.super }}`` will
not be automatically escaped (see the `next section`_), since it was
already escaped, if necessary, in the parent template.
* For extra readability, you can optionally give a *name* to your
``{% endblock %}`` tag. For example::
* For extra readability, you can optionally give a *name* to your
``{% endblock %}`` tag. For example::
{% block content %}
...
{% endblock content %}
{% block content %}
...
{% endblock content %}
In larger templates, this technique helps you see which ``{% block %}``
tags are being closed.
In larger templates, this technique helps you see which ``{% block %}``
tags are being closed.
Finally, note that you can't define multiple :ttag:`block` tags with the same
name in the same template. This limitation exists because a block tag works in
@ -437,25 +437,25 @@ do potentially bad things. This type of security exploit is called a
To avoid this problem, you have two options:
* One, you can make sure to run each untrusted variable through the
:tfilter:`escape` filter (documented below), which converts potentially
harmful HTML characters to unharmful ones. This was the default solution
in Django for its first few years, but the problem is that it puts the
onus on *you*, the developer / template author, to ensure you're escaping
everything. It's easy to forget to escape data.
* One, you can make sure to run each untrusted variable through the
:tfilter:`escape` filter (documented below), which converts potentially
harmful HTML characters to unharmful ones. This was the default solution
in Django for its first few years, but the problem is that it puts the
onus on *you*, the developer / template author, to ensure you're escaping
everything. It's easy to forget to escape data.
* Two, you can take advantage of Django's automatic HTML escaping. The
remainder of this section describes how auto-escaping works.
* Two, you can take advantage of Django's automatic HTML escaping. The
remainder of this section describes how auto-escaping works.
By default in Django, every template automatically escapes the output
of every variable tag. Specifically, these five characters are
escaped:
* ``<`` is converted to ``&lt;``
* ``>`` is converted to ``&gt;``
* ``'`` (single quote) is converted to ``&#39;``
* ``"`` (double quote) is converted to ``&quot;``
* ``&`` is converted to ``&amp;``
* ``<`` is converted to ``&lt;``
* ``>`` is converted to ``&gt;``
* ``'`` (single quote) is converted to ``&#39;``
* ``"`` (double quote) is converted to ``&quot;``
* ``&`` is converted to ``&amp;``
Again, we stress that this behavior is on by default. If you're using Django's
template system, you're protected.