PageRenderTime 156ms CodeModel.GetById 131ms app.highlight 3ms RepoModel.GetById 17ms app.codeStats 0ms

/docs/ref/contrib/contenttypes.txt

https://code.google.com/p/mango-py/
Plain Text | 453 lines | 349 code | 104 blank | 0 comment | 0 complexity | b29bc56de4788280852c88b69443194c MD5 | raw file
  1==========================
  2The contenttypes framework
  3==========================
  4
  5.. module:: django.contrib.contenttypes
  6   :synopsis: Provides generic interface to installed models.
  7
  8Django includes a :mod:`~django.contrib.contenttypes` application that can
  9track all of the models installed in your Django-powered project, providing a
 10high-level, generic interface for working with your models.
 11
 12Overview
 13========
 14
 15At the heart of the contenttypes application is the
 16:class:`~django.contrib.contenttypes.models.ContentType` model, which lives at
 17``django.contrib.contenttypes.models.ContentType``. Instances of
 18:class:`~django.contrib.contenttypes.models.ContentType` represent and store
 19information about the models installed in your project, and new instances of
 20:class:`~django.contrib.contenttypes.models.ContentType` are automatically
 21created whenever new models are installed.
 22
 23Instances of :class:`~django.contrib.contenttypes.models.ContentType` have
 24methods for returning the model classes they represent and for querying objects
 25from those models. :class:`~django.contrib.contenttypes.models.ContentType`
 26also has a :ref:`custom manager <custom-managers>` that adds methods for
 27working with :class:`~django.contrib.contenttypes.models.ContentType` and for
 28obtaining instances of :class:`~django.contrib.contenttypes.models.ContentType`
 29for a particular model.
 30
 31Relations between your models and
 32:class:`~django.contrib.contenttypes.models.ContentType` can also be used to
 33enable "generic" relationships between an instance of one of your
 34models and instances of any model you have installed.
 35
 36Installing the contenttypes framework
 37=====================================
 38
 39The contenttypes framework is included in the default
 40:setting:`INSTALLED_APPS` list created by ``django-admin.py startproject``,
 41but if you've removed it or if you manually set up your
 42:setting:`INSTALLED_APPS` list, you can enable it by adding
 43``'django.contrib.contenttypes'`` to your :setting:`INSTALLED_APPS` setting.
 44
 45It's generally a good idea to have the contenttypes framework
 46installed; several of Django's other bundled applications require it:
 47
 48    * The admin application uses it to log the history of each object
 49      added or changed through the admin interface.
 50
 51    * Django's :mod:`authentication framework <django.contrib.auth>` uses it
 52      to tie user permissions to specific models.
 53
 54    * Django's comments system (:mod:`django.contrib.comments`) uses it to
 55      "attach" comments to any installed model.
 56
 57.. currentmodule:: django.contrib.contenttypes.models
 58
 59The ``ContentType`` model
 60=========================
 61
 62.. class:: ContentType
 63
 64    Each instance of :class:`~django.contrib.contenttypes.models.ContentType`
 65    has three fields which, taken together, uniquely describe an installed
 66    model:
 67
 68    .. attribute:: app_label
 69
 70        The name of the application the model is part of. This is taken from
 71        the :attr:`app_label` attribute of the model, and includes only the
 72        *last* part of the application's Python import path;
 73        "django.contrib.contenttypes", for example, becomes an
 74        :attr:`app_label` of "contenttypes".
 75
 76    .. attribute:: model
 77
 78        The name of the model class.
 79
 80    .. attribute:: name
 81
 82        The human-readable name of the model. This is taken from the
 83        :attr:`verbose_name <django.db.models.Field.verbose_name>`
 84        attribute of the model.
 85
 86Let's look at an example to see how this works. If you already have
 87the :mod:`~django.contrib.contenttypes` application installed, and then add
 88:mod:`the sites application <django.contrib.sites>` to your
 89:setting:`INSTALLED_APPS` setting and run ``manage.py syncdb`` to install it,
 90the model :class:`django.contrib.sites.models.Site` will be installed into
 91your database. Along with it a new instance of
 92:class:`~django.contrib.contenttypes.models.ContentType` will be
 93created with the following values:
 94
 95    * :attr:`~django.contrib.contenttypes.models.ContentType.app_label`
 96      will be set to ``'sites'`` (the last part of the Python
 97      path "django.contrib.sites").
 98
 99    * :attr:`~django.contrib.contenttypes.models.ContentType.model`
100      will be set to ``'site'``.
101
102    * :attr:`~django.contrib.contenttypes.models.ContentType.name`
103      will be set to ``'site'``.
104
105.. _the verbose_name attribute: ../model-api/#verbose_name
106
107Methods on ``ContentType`` instances
108====================================
109
110Each :class:`~django.contrib.contenttypes.models.ContentType` instance has
111methods that allow you to get from a
112:class:`~django.contrib.contenttypes.models.ContentType` instance to the
113model it represents, or to retrieve objects from that model:
114
115.. method:: ContentType.get_object_for_this_type(**kwargs)
116
117    Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the
118    model the :class:`~django.contrib.contenttypes.models.ContentType`
119    represents, and does :meth:`a get() lookup <django.db.models.QuerySet.get>`
120    on that model, returning the corresponding object.
121
122.. method:: ContentType.model_class()
123
124    Returns the model class represented by this
125    :class:`~django.contrib.contenttypes.models.ContentType` instance.
126
127For example, we could look up the
128:class:`~django.contrib.contenttypes.models.ContentType` for the
129:class:`~django.contrib.auth.models.User` model::
130
131    >>> from django.contrib.contenttypes.models import ContentType
132    >>> user_type = ContentType.objects.get(app_label="auth", model="user")
133    >>> user_type
134    <ContentType: user>
135
136And then use it to query for a particular
137:class:`~django.contrib.auth.models.User`, or to get access
138to the ``User`` model class::
139
140    >>> user_type.model_class()
141    <class 'django.contrib.auth.models.User'>
142    >>> user_type.get_object_for_this_type(username='Guido')
143    <User: Guido>
144
145Together,
146:meth:`~django.contrib.contenttypes.models.ContentType.get_object_for_this_type`
147and :meth:`~django.contrib.contenttypes.models.ContentType.model_class` enable
148two extremely important use cases:
149
150    1. Using these methods, you can write high-level generic code that
151       performs queries on any installed model -- instead of importing and
152       using a single specific model class, you can pass an ``app_label`` and
153       ``model`` into a
154       :class:`~django.contrib.contenttypes.models.ContentType` lookup at
155       runtime, and then work with the model class or retrieve objects from it.
156
157    2. You can relate another model to
158       :class:`~django.contrib.contenttypes.models.ContentType` as a way of
159       tying instances of it to particular model classes, and use these methods
160       to get access to those model classes.
161
162Several of Django's bundled applications make use of the latter technique.
163For example,
164:class:`the permissions system <django.contrib.auth.models.Permission>` in
165Django's authentication framework uses a
166:class:`~django.contrib.auth.models.Permission` model with a foreign
167key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets
168:class:`~django.contrib.auth.models.Permission` represent concepts like
169"can add blog entry" or "can delete news story".
170
171The ``ContentTypeManager``
172--------------------------
173
174.. class:: ContentTypeManager
175
176    :class:`~django.contrib.contenttypes.models.ContentType` also has a custom
177    manager, :class:`~django.contrib.contenttypes.models.ContentTypeManager`,
178    which adds the following methods:
179
180    .. method:: clear_cache()
181
182        Clears an internal cache used by
183        :class:`~django.contrib.contenttypes.models.ContentType` to keep track
184        of which models for which it has created
185        :class:`~django.contrib.contenttypes.models.ContentType` instances. You
186        probably won't ever need to call this method yourself; Django will call
187        it automatically when it's needed.
188
189    .. method:: get_for_model(model)
190
191        Takes either a model class or an instance of a model, and returns the
192        :class:`~django.contrib.contenttypes.models.ContentType` instance
193        representing that model.
194
195    .. method:: get_by_natural_key(app_label, model)
196
197        Returns the :class:`~django.contrib.contenttypes.models.ContentType`
198        instance uniquely identified by the given application label and model
199        name. The primary purpose of this method is to allow
200        :class:`~django.contrib.contenttypes.models.ContentType` objects to be
201        referenced via a :ref:`natural key<topics-serialization-natural-keys>`
202        during deserialization.
203
204The :meth:`~ContentTypeManager.get_for_model()` method is especially
205useful when you know you need to work with a
206:class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't
207want to go to the trouble of obtaining the model's metadata to perform a manual
208lookup::
209
210    >>> from django.contrib.auth.models import User
211    >>> user_type = ContentType.objects.get_for_model(User)
212    >>> user_type
213    <ContentType: user>
214
215.. module:: django.contrib.contenttypes.generic
216
217.. _generic-relations:
218
219Generic relations
220=================
221
222Adding a foreign key from one of your own models to
223:class:`~django.contrib.contenttypes.models.ContentType` allows your model to
224effectively tie itself to another model class, as in the example of the
225:class:`~django.contrib.auth.models.Permission` model above. But it's possible
226to go one step further and use
227:class:`~django.contrib.contenttypes.models.ContentType` to enable truly
228generic (sometimes called "polymorphic") relationships between models.
229
230A simple example is a tagging system, which might look like this::
231
232    from django.db import models
233    from django.contrib.contenttypes.models import ContentType
234    from django.contrib.contenttypes import generic
235
236    class TaggedItem(models.Model):
237        tag = models.SlugField()
238        content_type = models.ForeignKey(ContentType)
239        object_id = models.PositiveIntegerField()
240        content_object = generic.GenericForeignKey('content_type', 'object_id')
241
242        def __unicode__(self):
243            return self.tag
244
245A normal :class:`~django.db.models.ForeignKey` can only "point
246to" one other model, which means that if the ``TaggedItem`` model used a
247:class:`~django.db.models.ForeignKey` it would have to
248choose one and only one model to store tags for. The contenttypes
249application provides a special field type which
250works around this and allows the relationship to be with any
251model:
252
253.. class:: GenericForeignKey
254
255    There are three parts to setting up a
256    :class:`~django.contrib.contenttypes.generic.GenericForeignKey`:
257
258        1. Give your model a :class:`~django.db.models.ForeignKey`
259           to :class:`~django.contrib.contenttypes.models.ContentType`.
260
261        2. Give your model a field that can store primary key values from the
262           models you'll be relating to. For most models, this means a
263           :class:`~django.db.models.PositiveIntegerField`. The usual name
264           for this field is "object_id".
265
266        3. Give your model a
267           :class:`~django.contrib.contenttypes.generic.GenericForeignKey`, and
268           pass it the names of the two fields described above. If these fields
269           are named "content_type" and "object_id", you can omit this -- those
270           are the default field names
271           :class:`~django.contrib.contenttypes.generic.GenericForeignKey` will
272           look for.
273
274.. admonition:: Primary key type compatibility
275
276   The "object_id" field doesn't have to be the same type as the
277   primary key fields on the related models, but their primary key values
278   must be coercible to the same type as the "object_id" field by its
279   :meth:`~django.db.models.Field.get_db_prep_value` method.
280
281   For example, if you want to allow generic relations to models with either
282   :class:`~django.db.models.IntegerField` or
283   :class:`~django.db.models.CharField` primary key fields, you
284   can use :class:`~django.db.models.CharField` for the
285   "object_id" field on your model since integers can be coerced to
286   strings by :meth:`~django.db.models.Field.get_db_prep_value`.
287
288   For maximum flexibility you can use a
289   :class:`~django.db.models.TextField` which doesn't have a
290   maximum length defined, however this may incur significant performance
291   penalties depending on your database backend.
292
293   There is no one-size-fits-all solution for which field type is best. You
294   should evaluate the models you expect to be pointing to and determine
295   which solution will be most effective for your use case.
296
297.. admonition:: Serializing references to ``ContentType`` objects
298
299   If you're serializing data (for example, when generating
300   :class:`~django.test.TestCase.fixtures`) from a model that implements
301   generic relations, you should probably be using a natural key to uniquely
302   identify related :class:`~django.contrib.contenttypes.models.ContentType`
303   objects. See :ref:`natural keys<topics-serialization-natural-keys>` and
304   :djadminopt:`dumpdata --natural <--natural>` for more information.
305
306This will enable an API similar to the one used for a normal
307:class:`~django.db.models.ForeignKey`;
308each ``TaggedItem`` will have a ``content_object`` field that returns the
309object it's related to, and you can also assign to that field or use it when
310creating a ``TaggedItem``::
311
312    >>> from django.contrib.auth.models import User
313    >>> guido = User.objects.get(username='Guido')
314    >>> t = TaggedItem(content_object=guido, tag='bdfl')
315    >>> t.save()
316    >>> t.content_object
317    <User: Guido>
318
319Due to the way :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
320is implemented, you cannot use such fields directly with filters (``filter()``
321and ``exclude()``, for example) via the database API. Because a 
322:class:`~django.contrib.contenttypes.generic.GenericForeignKey` isn't a 
323normal field objects, these examples will *not* work::
324
325    # This will fail
326    >>> TaggedItem.objects.filter(content_object=guido)
327    # This will also fail
328    >>> TaggedItem.objects.get(content_object=guido)
329
330Reverse generic relations
331-------------------------
332
333.. class:: GenericRelation
334
335If you know which models you'll be using most often, you can also add
336a "reverse" generic relationship to enable an additional API. For example::
337
338    class Bookmark(models.Model):
339        url = models.URLField()
340        tags = generic.GenericRelation(TaggedItem)
341
342``Bookmark`` instances will each have a ``tags`` attribute, which can
343be used to retrieve their associated ``TaggedItems``::
344
345    >>> b = Bookmark(url='http://www.djangoproject.com/')
346    >>> b.save()
347    >>> t1 = TaggedItem(content_object=b, tag='django')
348    >>> t1.save()
349    >>> t2 = TaggedItem(content_object=b, tag='python')
350    >>> t2.save()
351    >>> b.tags.all()
352    [<TaggedItem: django>, <TaggedItem: python>]
353
354Just as :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
355accepts the names of the content-type and object-ID fields as
356arguments, so too does
357:class:`~django.contrib.contenttypes.generic.GenericRelation`;
358if the model which has the generic foreign key is using non-default names
359for those fields, you must pass the names of the fields when setting up a
360:class:`.GenericRelation` to it. For example, if the ``TaggedItem`` model
361referred to above used fields named ``content_type_fk`` and
362``object_primary_key`` to create its generic foreign key, then a
363:class:`.GenericRelation` back to it would need to be defined like so::
364
365    tags = generic.GenericRelation(TaggedItem,
366                                   content_type_field='content_type_fk',
367                                   object_id_field='object_primary_key')
368
369Of course, if you don't add the reverse relationship, you can do the
370same types of lookups manually::
371
372    >>> b = Bookmark.objects.get(url='http://www.djangoproject.com/')
373    >>> bookmark_type = ContentType.objects.get_for_model(b)
374    >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id,
375    ...                           object_id=b.id)
376    [<TaggedItem: django>, <TaggedItem: python>]
377
378Note that if the model in a
379:class:`~django.contrib.contenttypes.generic.GenericRelation` uses a
380non-default value for ``ct_field`` or ``fk_field`` in its
381:class:`~django.contrib.contenttypes.generic.GenericForeignKey` (e.g. the
382:mod:`django.contrib.comments` app uses ``ct_field="object_pk"``),
383you'll need to set ``content_type_field`` and/or ``object_id_field`` in
384the :class:`~django.contrib.contenttypes.generic.GenericRelation` to
385match the ``ct_field`` and ``fk_field``, respectively, in the
386:class:`~django.contrib.contenttypes.generic.GenericForeignKey`::
387
388    comments = generic.GenericRelation(Comment, object_id_field="object_pk")
389
390Note also, that if you delete an object that has a
391:class:`~django.contrib.contenttypes.generic.GenericRelation`, any objects
392which have a :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
393pointing at it will be deleted as well. In the example above, this means that
394if a ``Bookmark`` object were deleted, any ``TaggedItem`` objects pointing at
395it would be deleted at the same time.
396
397.. versionadded:: 1.3
398
399Unlike :class:`~django.db.models.ForeignKey`,
400:class:`~django.contrib.contenttypes.generic.GenericForeignKey` does not accept
401an :attr:`~django.db.models.ForeignKey.on_delete` argument to customize this
402behavior; if desired, you can avoid the cascade-deletion simply by not using
403:class:`~django.contrib.contenttypes.generic.GenericRelation`, and alternate
404behavior can be provided via the :data:`~django.db.models.signals.pre_delete`
405signal.
406
407Generic relations and aggregation
408---------------------------------
409
410:doc:`Django's database aggregation API </topics/db/aggregation>`
411doesn't work with a
412:class:`~django.contrib.contenttypes.generic.GenericRelation`. For example, you
413might be tempted to try something like::
414
415    Bookmark.objects.aggregate(Count('tags'))
416
417This will not work correctly, however. The generic relation adds extra filters
418to the queryset to ensure the correct content type, but the
419:meth:`~django.db.models.QuerySet.aggregate` method doesn't take them into
420account. For now, if you need aggregates on generic relations, you'll need
421to calculate them without using the aggregation API.
422
423Generic relations in forms and admin
424------------------------------------
425
426The :mod:`django.contrib.contenttypes.generic` module provides
427:class:`~django.contrib.contenttypes.generic.BaseGenericInlineFormSet`,
428:class:`~django.contrib.contenttypes.generic.GenericTabularInline`
429and :class:`~django.contrib.contenttypes.generic.GenericStackedInline`
430(the last two are subclasses of
431:class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`).
432This enables the use of generic relations in forms and the admin. See the
433:doc:`model formset </topics/forms/modelforms>` and
434:ref:`admin <using-generic-relations-as-an-inline>` documentation for more
435information.
436
437.. class:: GenericInlineModelAdmin
438
439    The :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`
440    class inherits all properties from an
441    :class:`~django.contrib.admin.InlineModelAdmin` class. However,
442    it adds a couple of its own for working with the generic relation:
443
444    .. attribute:: ct_field
445
446        The name of the
447        :class:`~django.contrib.contenttypes.models.ContentType` foreign key
448        field on the model. Defaults to ``content_type``.
449
450    .. attribute:: ct_fk_field
451
452        The name of the integer field that represents the ID of the related
453        object. Defaults to ``object_id``.