mirror of
https://github.com/django/django.git
synced 2025-10-23 21:59:11 +00:00
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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user