From c61987d75ad9bc5233257f46a8246bb9d63bbbe1 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Mon, 10 Oct 2011 17:32:33 +0000 Subject: [PATCH] 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 --- docs/_ext/djangodocs.py | 22 -- docs/ref/contrib/admin/index.txt | 540 +++++++++++++------------- docs/ref/contrib/comments/example.txt | 18 +- docs/ref/contrib/localflavor.txt | 100 ++--- docs/ref/models/querysets.txt | 390 ++++++++++--------- docs/releases/1.0.txt | 6 +- docs/topics/auth.txt | 314 +++++++-------- docs/topics/templates.txt | 184 ++++----- 8 files changed, 777 insertions(+), 797 deletions(-) diff --git a/docs/_ext/djangodocs.py b/docs/_ext/djangodocs.py index 21c4716d18..d4a0512f71 100644 --- a/docs/_ext/djangodocs.py +++ b/docs/_ext/djangodocs.py @@ -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. diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 875c234f03..9c5ba2ca67 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -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 '%s %s' % (self.color_code, self.first_name, self.last_name) - colored_name.allow_tags = True + def colored_name(self): + return '%s %s' % (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 '%s' % (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 '%s' % (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 `. 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. diff --git a/docs/ref/contrib/comments/example.txt b/docs/ref/contrib/comments/example.txt index e009422b4e..8de953f1c5 100644 --- a/docs/ref/contrib/comments/example.txt +++ b/docs/ref/contrib/comments/example.txt @@ -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 `. 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 diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt index 99077be0de..0a39c31b7a 100644 --- a/docs/ref/contrib/localflavor.txt +++ b/docs/ref/contrib/localflavor.txt @@ -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 diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index 8a3d15cc05..3342e3f18c 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -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() ` (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() ` (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: ``__avg`` - * Return type: float + * Default alias: ``__avg`` + * Return type: float Count ~~~~~ @@ -2069,8 +2071,8 @@ Count Returns the number of objects that are related through the provided field. - * Default alias: ``__count`` - * Return type: integer + * Default alias: ``__count`` + * Return type: integer Has one optional argument: @@ -2086,8 +2088,8 @@ Max Returns the maximum value of the given field. - * Default alias: ``__max`` - * Return type: same as input field + * Default alias: ``__max`` + * Return type: same as input field Min ~~~ @@ -2096,8 +2098,8 @@ Min Returns the minimum value of the given field. - * Default alias: ``__min`` - * Return type: same as input field + * Default alias: ``__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: ``__stddev`` - * Return type: float + * Default alias: ``__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: ``__sum`` - * Return type: same as input field + * Default alias: ``__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: ``__variance`` - * Return type: float + * Default alias: ``__variance`` + * Return type: float Has one optional argument: diff --git a/docs/releases/1.0.txt b/docs/releases/1.0.txt index ea9e3451f6..c766c5a4f9 100644 --- a/docs/releases/1.0.txt +++ b/docs/releases/1.0.txt @@ -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:`mysql-notes` - - :ref:`sqlite-notes` - - :ref:`oracle-notes` +- :ref:`mysql-notes` +- :ref:`sqlite-notes` +- :ref:`oracle-notes` diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt index ca927d438c..fdd764eb68 100644 --- a/docs/topics/auth.txt +++ b/docs/topics/auth.txt @@ -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 ` 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 ` (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 ` (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 ` for - more on ``Form`` objects. + * ``form``: A :class:`~django.forms.Form` object representing the login + form. See the :doc:`forms documentation ` 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'] `. - 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'] `. + 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'] `. - 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'] `. + 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 ` if not supplied. + * ``login_url``: The URL of the login page to redirect to. + Defaults to :setting:`settings.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'] `. - 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'] `. + 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 ` if not supplied. + * ``login_url``: The URL of the login page to redirect to. + Defaults to :setting:`settings.LOGIN_URL ` if not supplied. - * ``redirect_field_name``: The name of a ``GET`` field containing the - URL to redirect to after log out. Overrides ``next`` if the given - ``GET`` parameter is passed. + * ``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: diff --git a/docs/topics/templates.txt b/docs/topics/templates.txt index 359f97cd21..719fc67f31 100644 --- a/docs/topics/templates.txt +++ b/docs/topics/templates.txt @@ -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 `. 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 ``"Joel a - slug"``, the output will be ``"Joel is a slug"``. + If ``value`` is ``"Joel a + slug"``, the output will be ``"Joel is a slug"``. Again, these are just a few examples; see the :ref:`built-in filter reference ` for the complete list. @@ -183,40 +183,40 @@ them in the :ref:`built-in tag reference `. 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``:: -
    - {% for athlete in athlete_list %} -
  • {{ athlete.name }}
  • - {% endfor %} -
+
    + {% for athlete in athlete_list %} +
  • {{ athlete.name }}
  • + {% endfor %} +
- :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 ` 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 %}` in a template, it must be the first template - tag in that template. Template inheritance won't work, otherwise. +* If you use :ttag:`{% extends %}` in a template, it must be the first template + tag in that template. Template inheritance won't work, otherwise. - * More :ttag:`{% 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 %}` 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 ``<`` - * ``>`` is converted to ``>`` - * ``'`` (single quote) is converted to ``'`` - * ``"`` (double quote) is converted to ``"`` - * ``&`` is converted to ``&`` +* ``<`` is converted to ``<`` +* ``>`` is converted to ``>`` +* ``'`` (single quote) is converted to ``'`` +* ``"`` (double quote) is converted to ``"`` +* ``&`` is converted to ``&`` Again, we stress that this behavior is on by default. If you're using Django's template system, you're protected.