Fixed #15309 -- reST/Sphinx cleanup on the ContentTypes Framework docs.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15544 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0577edf610
commit
e9d99c4371
|
@ -5,8 +5,8 @@ The contenttypes framework
|
||||||
.. module:: django.contrib.contenttypes
|
.. module:: django.contrib.contenttypes
|
||||||
:synopsis: Provides generic interface to installed models.
|
:synopsis: Provides generic interface to installed models.
|
||||||
|
|
||||||
Django includes a :mod:`contenttypes` application that can track all of
|
Django includes a :mod:`~django.contrib.contenttypes` application that can
|
||||||
the models installed in your Django-powered project, providing a
|
track all of the models installed in your Django-powered project, providing a
|
||||||
high-level, generic interface for working with your models.
|
high-level, generic interface for working with your models.
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
|
@ -54,34 +54,37 @@ installed; several of Django's other bundled applications require it:
|
||||||
* Django's comments system (:mod:`django.contrib.comments`) uses it to
|
* Django's comments system (:mod:`django.contrib.comments`) uses it to
|
||||||
"attach" comments to any installed model.
|
"attach" comments to any installed model.
|
||||||
|
|
||||||
|
.. currentmodule:: django.contrib.contenttypes.models
|
||||||
|
|
||||||
The ``ContentType`` model
|
The ``ContentType`` model
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
.. class:: models.ContentType
|
.. class:: ContentType
|
||||||
|
|
||||||
Each instance of :class:`~django.contrib.contenttypes.models.ContentType`
|
Each instance of :class:`~django.contrib.contenttypes.models.ContentType`
|
||||||
has three fields which, taken together, uniquely describe an installed model:
|
has three fields which, taken together, uniquely describe an installed
|
||||||
|
model:
|
||||||
|
|
||||||
.. attribute:: models.ContentType.app_label
|
.. attribute:: app_label
|
||||||
|
|
||||||
The name of the application the model is part of. This is taken from
|
The name of the application the model is part of. This is taken from
|
||||||
the :attr:`app_label` attribute of the model, and includes only the *last*
|
the :attr:`app_label` attribute of the model, and includes only the
|
||||||
part of the application's Python import path;
|
*last* part of the application's Python import path;
|
||||||
"django.contrib.contenttypes", for example, becomes an :attr:`app_label`
|
"django.contrib.contenttypes", for example, becomes an
|
||||||
of "contenttypes".
|
:attr:`app_label` of "contenttypes".
|
||||||
|
|
||||||
.. attribute:: models.ContentType.model
|
.. attribute:: model
|
||||||
|
|
||||||
The name of the model class.
|
The name of the model class.
|
||||||
|
|
||||||
.. attribute:: models.ContentType.name
|
.. attribute:: name
|
||||||
|
|
||||||
The human-readable name of the model. This is taken from the
|
The human-readable name of the model. This is taken from the
|
||||||
:attr:`verbose_name <django.db.models.fields.Field.verbose_name>`
|
:attr:`verbose_name <django.db.models.Field.verbose_name>`
|
||||||
attribute of the model.
|
attribute of the model.
|
||||||
|
|
||||||
Let's look at an example to see how this works. If you already have
|
Let's look at an example to see how this works. If you already have
|
||||||
the contenttypes application installed, and then add
|
the :mod:`~django.contrib.contenttypes` application installed, and then add
|
||||||
:mod:`the sites application <django.contrib.sites>` to your
|
:mod:`the sites application <django.contrib.sites>` to your
|
||||||
:setting:`INSTALLED_APPS` setting and run ``manage.py syncdb`` to install it,
|
:setting:`INSTALLED_APPS` setting and run ``manage.py syncdb`` to install it,
|
||||||
the model :class:`django.contrib.sites.models.Site` will be installed into
|
the model :class:`django.contrib.sites.models.Site` will be installed into
|
||||||
|
@ -89,33 +92,34 @@ your database. Along with it a new instance of
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` will be
|
:class:`~django.contrib.contenttypes.models.ContentType` will be
|
||||||
created with the following values:
|
created with the following values:
|
||||||
|
|
||||||
* :attr:`app_label` will be set to ``'sites'`` (the last part of the Python
|
* :attr:`~django.contrib.contenttypes.models.ContentType.app_label`
|
||||||
|
will be set to ``'sites'`` (the last part of the Python
|
||||||
path "django.contrib.sites").
|
path "django.contrib.sites").
|
||||||
|
|
||||||
* :attr:`model` will be set to ``'site'``.
|
* :attr:`~django.contrib.contenttypes.models.ContentType.model`
|
||||||
|
will be set to ``'site'``.
|
||||||
|
|
||||||
* :attr:`name` will be set to ``'site'``.
|
* :attr:`~django.contrib.contenttypes.models.ContentType.name`
|
||||||
|
will be set to ``'site'``.
|
||||||
|
|
||||||
.. _the verbose_name attribute: ../model-api/#verbose_name
|
.. _the verbose_name attribute: ../model-api/#verbose_name
|
||||||
|
|
||||||
Methods on ``ContentType`` instances
|
Methods on ``ContentType`` instances
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
.. class:: models.ContentType
|
Each :class:`~django.contrib.contenttypes.models.ContentType` instance has
|
||||||
|
methods that allow you to get from a
|
||||||
|
:class:`~django.contrib.contenttypes.models.ContentType` instance to the
|
||||||
|
model it represents, or to retrieve objects from that model:
|
||||||
|
|
||||||
Each :class:`~django.contrib.contenttypes.models.ContentType` instance has
|
.. method:: ContentType.get_object_for_this_type(**kwargs)
|
||||||
methods that allow you to get from a
|
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` instance to the model
|
|
||||||
it represents, or to retrieve objects from that model:
|
|
||||||
|
|
||||||
.. method:: models.ContentType.get_object_for_this_type(**kwargs)
|
|
||||||
|
|
||||||
Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the
|
Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the
|
||||||
model the :class:`~django.contrib.contenttypes.models.ContentType`
|
model the :class:`~django.contrib.contenttypes.models.ContentType`
|
||||||
represents, and does :lookup:`a get() lookup <get>` on that model,
|
represents, and does :meth:`a get() lookup <django.db.models.QuerySet.get>`
|
||||||
returning the corresponding object.
|
on that model, returning the corresponding object.
|
||||||
|
|
||||||
.. method:: models.ContentType.model_class()
|
.. method:: ContentType.model_class()
|
||||||
|
|
||||||
Returns the model class represented by this
|
Returns the model class represented by this
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` instance.
|
:class:`~django.contrib.contenttypes.models.ContentType` instance.
|
||||||
|
@ -129,7 +133,8 @@ For example, we could look up the
|
||||||
>>> user_type
|
>>> user_type
|
||||||
<ContentType: user>
|
<ContentType: user>
|
||||||
|
|
||||||
And then use it to query for a particular ``User``, or to get access
|
And then use it to query for a particular
|
||||||
|
:class:`~django.contrib.auth.models.User`, or to get access
|
||||||
to the ``User`` model class::
|
to the ``User`` model class::
|
||||||
|
|
||||||
>>> user_type.model_class()
|
>>> user_type.model_class()
|
||||||
|
@ -139,15 +144,15 @@ to the ``User`` model class::
|
||||||
|
|
||||||
Together,
|
Together,
|
||||||
:meth:`~django.contrib.contenttypes.models.ContentType.get_object_for_this_type`
|
:meth:`~django.contrib.contenttypes.models.ContentType.get_object_for_this_type`
|
||||||
and :meth:`~django.contrib.contenttypes.models.ContentType.model_class`
|
and :meth:`~django.contrib.contenttypes.models.ContentType.model_class` enable
|
||||||
enable two extremely important use cases:
|
two extremely important use cases:
|
||||||
|
|
||||||
1. Using these methods, you can write high-level generic code that
|
1. Using these methods, you can write high-level generic code that
|
||||||
performs queries on any installed model -- instead of importing and using
|
performs queries on any installed model -- instead of importing and
|
||||||
a single specific model class, you can pass an ``app_label`` and
|
using a single specific model class, you can pass an ``app_label`` and
|
||||||
``model`` into a :class:`~django.contrib.contenttypes.models.ContentType`
|
``model`` into a
|
||||||
lookup at runtime, and then work with the model class or retrieve objects
|
:class:`~django.contrib.contenttypes.models.ContentType` lookup at
|
||||||
from it.
|
runtime, and then work with the model class or retrieve objects from it.
|
||||||
|
|
||||||
2. You can relate another model to
|
2. You can relate another model to
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` as a way of
|
:class:`~django.contrib.contenttypes.models.ContentType` as a way of
|
||||||
|
@ -156,7 +161,7 @@ enable two extremely important use cases:
|
||||||
|
|
||||||
Several of Django's bundled applications make use of the latter technique.
|
Several of Django's bundled applications make use of the latter technique.
|
||||||
For example,
|
For example,
|
||||||
:class:`the permissions system <django.contrib.auth.models.Permission` in
|
:class:`the permissions system <django.contrib.auth.models.Permission>` in
|
||||||
Django's authentication framework uses a
|
Django's authentication framework uses a
|
||||||
:class:`~django.contrib.auth.models.Permission` model with a foreign
|
:class:`~django.contrib.auth.models.Permission` model with a foreign
|
||||||
key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets
|
key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets
|
||||||
|
@ -166,36 +171,40 @@ key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets
|
||||||
The ``ContentTypeManager``
|
The ``ContentTypeManager``
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
.. class:: models.ContentTypeManager
|
.. class:: ContentTypeManager
|
||||||
|
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` also has a custom
|
:class:`~django.contrib.contenttypes.models.ContentType` also has a custom
|
||||||
manager, :class:`~django.contrib.contenttypes.models.ContentTypeManager`,
|
manager, :class:`~django.contrib.contenttypes.models.ContentTypeManager`,
|
||||||
which adds the following methods:
|
which adds the following methods:
|
||||||
|
|
||||||
.. method:: models.ContentTypeManager.clear_cache()
|
.. method:: clear_cache()
|
||||||
|
|
||||||
Clears an internal cache used by
|
Clears an internal cache used by
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` to keep track
|
:class:`~django.contrib.contenttypes.models.ContentType` to keep track
|
||||||
of which models for which it has created
|
of which models for which it has created
|
||||||
:class:`django.contrib.contenttypes.models.ContentType` instances. You
|
:class:`~django.contrib.contenttypes.models.ContentType` instances. You
|
||||||
probably won't ever need to call this method yourself; Django will call
|
probably won't ever need to call this method yourself; Django will call
|
||||||
it automatically when it's needed.
|
it automatically when it's needed.
|
||||||
|
|
||||||
.. method:: models.ContentTypeManager.get_for_model(model)
|
.. method:: get_for_model(model)
|
||||||
|
|
||||||
Takes either a model class or an instance of a model, and returns the
|
Takes either a model class or an instance of a model, and returns the
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` instance
|
:class:`~django.contrib.contenttypes.models.ContentType` instance
|
||||||
representing that model.
|
representing that model.
|
||||||
|
|
||||||
The :meth:`~models.ContentTypeManager.get_for_model()` method is especially useful when you know you
|
The :meth:`~ContentTypeManager.get_for_model()` method is especially
|
||||||
need to work with a :class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't want to go to the
|
useful when you know you need to work with a
|
||||||
trouble of obtaining the model's metadata to perform a manual lookup::
|
:class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't
|
||||||
|
want to go to the trouble of obtaining the model's metadata to perform a manual
|
||||||
|
lookup::
|
||||||
|
|
||||||
>>> from django.contrib.auth.models import User
|
>>> from django.contrib.auth.models import User
|
||||||
>>> user_type = ContentType.objects.get_for_model(User)
|
>>> user_type = ContentType.objects.get_for_model(User)
|
||||||
>>> user_type
|
>>> user_type
|
||||||
<ContentType: user>
|
<ContentType: user>
|
||||||
|
|
||||||
|
.. module:: django.contrib.contenttypes.generic
|
||||||
|
|
||||||
.. _generic-relations:
|
.. _generic-relations:
|
||||||
|
|
||||||
Generic relations
|
Generic relations
|
||||||
|
@ -224,23 +233,25 @@ A simple example is a tagging system, which might look like this::
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.tag
|
return self.tag
|
||||||
|
|
||||||
A normal :class:`~django.db.models.fields.related.ForeignKey` can only "point
|
A normal :class:`~django.db.models.ForeignKey` can only "point
|
||||||
to" one other model, which means that if the ``TaggedItem`` model used a
|
to" one other model, which means that if the ``TaggedItem`` model used a
|
||||||
:class:`~django.db.models.fields.related.ForeignKey` it would have to
|
:class:`~django.db.models.ForeignKey` it would have to
|
||||||
choose one and only one model to store tags for. The contenttypes
|
choose one and only one model to store tags for. The contenttypes
|
||||||
application provides a special field type --
|
application provides a special field type which
|
||||||
:class:`django.contrib.contenttypes.generic.GenericForeignKey` -- which
|
|
||||||
works around this and allows the relationship to be with any
|
works around this and allows the relationship to be with any
|
||||||
model. There are three parts to setting up a
|
model:
|
||||||
:class:`~django.contrib.contenttypes.generic.GenericForeignKey`:
|
|
||||||
|
|
||||||
1. Give your model a :class:`~django.db.models.fields.related.ForeignKey`
|
.. class:: GenericForeignKey
|
||||||
|
|
||||||
|
There are three parts to setting up a
|
||||||
|
:class:`~django.contrib.contenttypes.generic.GenericForeignKey`:
|
||||||
|
|
||||||
|
1. Give your model a :class:`~django.db.models.ForeignKey`
|
||||||
to :class:`~django.contrib.contenttypes.models.ContentType`.
|
to :class:`~django.contrib.contenttypes.models.ContentType`.
|
||||||
|
|
||||||
2. Give your model a field that can store a primary-key value from the
|
2. Give your model a field that can store primary key values from the
|
||||||
models you'll be relating to. (For most models, this means an
|
models you'll be relating to. For most models, this means a
|
||||||
:class:`~django.db.models.fields.IntegerField` or
|
:class:`~django.db.models.PositiveIntegerField`.
|
||||||
:class:`~django.db.models.fields.PositiveIntegerField`.)
|
|
||||||
|
|
||||||
This field must be of the same type as the primary key of the models
|
This field must be of the same type as the primary key of the models
|
||||||
that will be involved in the generic relation. For example, if you use
|
that will be involved in the generic relation. For example, if you use
|
||||||
|
@ -257,7 +268,7 @@ model. There are three parts to setting up a
|
||||||
look for.
|
look for.
|
||||||
|
|
||||||
This will enable an API similar to the one used for a normal
|
This will enable an API similar to the one used for a normal
|
||||||
:class:`~django.db.models.fields.related.ForeignKey`;
|
:class:`~django.db.models.ForeignKey`;
|
||||||
each ``TaggedItem`` will have a ``content_object`` field that returns the
|
each ``TaggedItem`` will have a ``content_object`` field that returns the
|
||||||
object it's related to, and you can also assign to that field or use it when
|
object it's related to, and you can also assign to that field or use it when
|
||||||
creating a ``TaggedItem``::
|
creating a ``TaggedItem``::
|
||||||
|
@ -271,8 +282,9 @@ creating a ``TaggedItem``::
|
||||||
|
|
||||||
Due to the way :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
|
Due to the way :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
|
||||||
is implemented, you cannot use such fields directly with filters (``filter()``
|
is implemented, you cannot use such fields directly with filters (``filter()``
|
||||||
and ``exclude()``, for example) via the database API. They aren't normal field
|
and ``exclude()``, for example) via the database API. Because a
|
||||||
objects. These examples will *not* work::
|
:class:`~django.contrib.contenttypes.generic.GenericForeignKey` isn't a
|
||||||
|
normal field objects, these examples will *not* work::
|
||||||
|
|
||||||
# This will fail
|
# This will fail
|
||||||
>>> TaggedItem.objects.filter(content_object=guido)
|
>>> TaggedItem.objects.filter(content_object=guido)
|
||||||
|
@ -282,6 +294,8 @@ objects. These examples will *not* work::
|
||||||
Reverse generic relations
|
Reverse generic relations
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
.. class:: GenericRelation
|
||||||
|
|
||||||
If you know which models you'll be using most often, you can also add
|
If you know which models you'll be using most often, you can also add
|
||||||
a "reverse" generic relationship to enable an additional API. For example::
|
a "reverse" generic relationship to enable an additional API. For example::
|
||||||
|
|
||||||
|
@ -301,17 +315,20 @@ be used to retrieve their associated ``TaggedItems``::
|
||||||
>>> b.tags.all()
|
>>> b.tags.all()
|
||||||
[<TaggedItem: django>, <TaggedItem: python>]
|
[<TaggedItem: django>, <TaggedItem: python>]
|
||||||
|
|
||||||
Just as :class:`django.contrib.contenttypes.generic.GenericForeignKey`
|
Just as :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
|
||||||
accepts the names of the content-type and object-ID fields as
|
accepts the names of the content-type and object-ID fields as
|
||||||
arguments, so too does ``GenericRelation``; if the model which has the
|
arguments, so too does
|
||||||
generic foreign key is using non-default names for those fields, you
|
:class:`~django.contrib.contenttypes.generic.GenericRelation`;
|
||||||
must pass the names of the fields when setting up a
|
if the model which has the generic foreign key is using non-default names
|
||||||
``GenericRelation`` to it. For example, if the ``TaggedItem`` model
|
for those fields, you must pass the names of the fields when setting up a
|
||||||
|
:class:`.GenericRelation` to it. For example, if the ``TaggedItem`` model
|
||||||
referred to above used fields named ``content_type_fk`` and
|
referred to above used fields named ``content_type_fk`` and
|
||||||
``object_primary_key`` to create its generic foreign key, then a
|
``object_primary_key`` to create its generic foreign key, then a
|
||||||
``GenericRelation`` back to it would need to be defined like so::
|
:class:`.GenericRelation` back to it would need to be defined like so::
|
||||||
|
|
||||||
tags = generic.GenericRelation(TaggedItem, content_type_field='content_type_fk', object_id_field='object_primary_key')
|
tags = generic.GenericRelation(TaggedItem,
|
||||||
|
content_type_field='content_type_fk',
|
||||||
|
object_id_field='object_primary_key')
|
||||||
|
|
||||||
Of course, if you don't add the reverse relationship, you can do the
|
Of course, if you don't add the reverse relationship, you can do the
|
||||||
same types of lookups manually::
|
same types of lookups manually::
|
||||||
|
@ -362,37 +379,39 @@ might be tempted to try something like::
|
||||||
Bookmark.objects.aggregate(Count('tags'))
|
Bookmark.objects.aggregate(Count('tags'))
|
||||||
|
|
||||||
This will not work correctly, however. The generic relation adds extra filters
|
This will not work correctly, however. The generic relation adds extra filters
|
||||||
to the queryset to ensure the correct content type, but the ``aggregate`` method
|
to the queryset to ensure the correct content type, but the
|
||||||
doesn't take them into account. For now, if you need aggregates on generic
|
:meth:`~django.db.models.QuerySet.aggregate` method doesn't take them into
|
||||||
relations, you'll need to calculate them without using the aggregation API.
|
account. For now, if you need aggregates on generic relations, you'll need
|
||||||
|
to calculate them without using the aggregation API.
|
||||||
|
|
||||||
Generic relations in forms and admin
|
Generic relations in forms and admin
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
:mod:`django.contrib.contenttypes.generic` provides
|
The :mod:`django.contrib.contenttypes.generic` module provides
|
||||||
:class:`~django.contrib.contenttypes.generic.GenericInlineFormSet`,
|
:class:`~django.contrib.contenttypes.generic.GenericInlineFormSet`,
|
||||||
:class:`~django.contrib.contenttypes.generic.GenericTabularInline`
|
:class:`~django.contrib.contenttypes.generic.GenericTabularInline`
|
||||||
and :class:`~django.contrib.contenttypes.generic.GenericStackedInline`
|
and :class:`~django.contrib.contenttypes.generic.GenericStackedInline`
|
||||||
(the last two subclasses of :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`).
|
(the last two are subclasses of
|
||||||
|
:class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`).
|
||||||
This enables the use of generic relations in forms and the admin. See the
|
This enables the use of generic relations in forms and the admin. See the
|
||||||
:doc:`model formset </topics/forms/modelforms>` and
|
:doc:`model formset </topics/forms/modelforms>` and
|
||||||
:ref:`admin <using-generic-relations-as-an-inline>` documentation for more
|
:ref:`admin <using-generic-relations-as-an-inline>` documentation for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
.. class:: generic.GenericInlineModelAdmin
|
.. class:: GenericInlineModelAdmin
|
||||||
|
|
||||||
The :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`
|
The :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`
|
||||||
class inherits all properties from an
|
class inherits all properties from an
|
||||||
:class:`~django.contrib.admin.InlineModelAdmin` class. However,
|
:class:`~django.contrib.admin.InlineModelAdmin` class. However,
|
||||||
it adds a couple of its own for working with the generic relation:
|
it adds a couple of its own for working with the generic relation:
|
||||||
|
|
||||||
.. attribute:: generic.GenericInlineModelAdmin.ct_field
|
.. attribute:: ct_field
|
||||||
|
|
||||||
The name of the
|
The name of the
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` foreign key
|
:class:`~django.contrib.contenttypes.models.ContentType` foreign key
|
||||||
field on the model. Defaults to ``content_type``.
|
field on the model. Defaults to ``content_type``.
|
||||||
|
|
||||||
.. attribute:: generic.GenericInlineModelAdmin.ct_fk_field
|
.. attribute:: ct_fk_field
|
||||||
|
|
||||||
The name of the integer field that represents the ID of the related
|
The name of the integer field that represents the ID of the related
|
||||||
object. Defaults to ``object_id``.
|
object. Defaults to ``object_id``.
|
||||||
|
|
Loading…
Reference in New Issue