contenttypes.txt 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. .. _ref-contrib-contenttypes:
  2. ==========================
  3. The contenttypes framework
  4. ==========================
  5. .. module:: django.contrib.contenttypes
  6. :synopsis: Provides generic interface to installed models.
  7. Django includes a :mod:`contenttypes` application that can track all of
  8. the models installed in your Django-powered project, providing a
  9. high-level, generic interface for working with your models.
  10. Overview
  11. ========
  12. At the heart of the contenttypes application is the
  13. :class:`~django.contrib.contenttypes.models.ContentType` model, which lives at
  14. ``django.contrib.contenttypes.models.ContentType``. Instances of
  15. :class:`~django.contrib.contenttypes.models.ContentType` represent and store
  16. information about the models installed in your project, and new instances of
  17. :class:`~django.contrib.contenttypes.models.ContentType` are automatically
  18. created whenever new models are installed.
  19. Instances of :class:`~django.contrib.contenttypes.models.ContentType` have
  20. methods for returning the model classes they represent and for querying objects
  21. from those models. :class:`~django.contrib.contenttypes.models.ContentType`
  22. also has a :ref:`custom manager <custom-managers>` that adds methods for
  23. working with :class:`~django.contrib.contenttypes.models.ContentType` and for
  24. obtaining instances of :class:`~django.contrib.contenttypes.models.ContentType`
  25. for a particular model.
  26. Relations between your models and
  27. :class:`~django.contrib.contenttypes.models.ContentType` can also be used to
  28. enable "generic" relationships between an instance of one of your
  29. models and instances of any model you have installed.
  30. Installing the contenttypes framework
  31. =====================================
  32. The contenttypes framework is included in the default
  33. :setting:`INSTALLED_APPS` list created by ``django-admin.py startproject``,
  34. but if you've removed it or if you manually set up your
  35. :setting:`INSTALLED_APPS` list, you can enable it by adding
  36. ``'django.contrib.contenttypes'`` to your :setting:`INSTALLED_APPS` setting.
  37. It's generally a good idea to have the contenttypes framework
  38. installed; several of Django's other bundled applications require it:
  39. * The admin application uses it to log the history of each object
  40. added or changed through the admin interface.
  41. * Django's :mod:`authentication framework <django.contrib.auth>` uses it
  42. to tie user permissions to specific models.
  43. * Django's comments system (:mod:`django.contrib.comments`) uses it to
  44. "attach" comments to any installed model.
  45. The ``ContentType`` model
  46. =========================
  47. .. class:: models.ContentType
  48. Each instance of :class:`~django.contrib.contenttypes.models.ContentType`
  49. has three fields which, taken together, uniquely describe an installed model:
  50. .. attribute:: models.ContentType.app_label
  51. The name of the application the model is part of. This is taken from
  52. the :attr:`app_label` attribute of the model, and includes only the *last*
  53. part of the application's Python import path;
  54. "django.contrib.contenttypes", for example, becomes an :attr:`app_label`
  55. of "contenttypes".
  56. .. attribute:: models.ContentType.model
  57. The name of the model class.
  58. .. attribute:: models.ContentType.name
  59. The human-readable name of the model. This is taken from the
  60. :attr:`verbose_name <django.db.models.fields.Field.verbose_name>`
  61. attribute of the model.
  62. Let's look at an example to see how this works. If you already have
  63. the contenttypes application installed, and then add
  64. :mod:`the sites application <django.contrib.sites>` to your
  65. :setting:`INSTALLED_APPS` setting and run ``manage.py syncdb`` to install it,
  66. the model :class:`django.contrib.sites.models.Site` will be installed into
  67. your database. Along with it a new instance of
  68. :class:`~django.contrib.contenttypes.models.ContentType` will be
  69. created with the following values:
  70. * :attr:`app_label` will be set to ``'sites'`` (the last part of the Python
  71. path "django.contrib.sites").
  72. * :attr:`model` will be set to ``'site'``.
  73. * :attr:`name` will be set to ``'site'``.
  74. .. _the verbose_name attribute: ../model-api/#verbose_name
  75. Methods on ``ContentType`` instances
  76. ====================================
  77. .. class:: models.ContentType
  78. Each :class:`~django.contrib.contenttypes.models.ContentType` instance has
  79. methods that allow you to get from a
  80. :class:`~django.contrib.contenttypes.models.ContentType` instance to the model
  81. it represents, or to retrieve objects from that model:
  82. .. method:: models.ContentType.get_object_for_this_type(**kwargs)
  83. Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the
  84. model the :class:`~django.contrib.contenttypes.models.ContentType`
  85. represents, and does :ref:`a get() lookup <get-kwargs>` on that model,
  86. returning the corresponding object.
  87. .. method:: models.ContentType.model_class()
  88. Returns the model class represented by this
  89. :class:`~django.contrib.contenttypes.models.ContentType` instance.
  90. For example, we could look up the
  91. :class:`~django.contrib.contenttypes.models.ContentType` for the
  92. :class:`~django.contrib.auth.models.User` model::
  93. >>> from django.contrib.contenttypes.models import ContentType
  94. >>> user_type = ContentType.objects.get(app_label="auth", model="user")
  95. >>> user_type
  96. <ContentType: user>
  97. And then use it to query for a particular ``User``, or to get access
  98. to the ``User`` model class::
  99. >>> user_type.model_class()
  100. <class 'django.contrib.auth.models.User'>
  101. >>> user_type.get_object_for_this_type(username='Guido')
  102. <User: Guido>
  103. Together,
  104. :meth:`~django.contrib.contenttypes.models.ContentType.get_object_for_this_type`
  105. and :meth:`~django.contrib.contenttypes.models.ContentType.model_class`
  106. enable two extremely important use cases:
  107. 1. Using these methods, you can write high-level generic code that
  108. performs queries on any installed model -- instead of importing and using
  109. a single specific model class, you can pass an ``app_label`` and
  110. ``model`` into a :class:`~django.contrib.contenttypes.models.ContentType`
  111. lookup at runtime, and then work with the model class or retrieve objects
  112. from it.
  113. 2. You can relate another model to
  114. :class:`~django.contrib.contenttypes.models.ContentType` as a way of
  115. tying instances of it to particular model classes, and use these methods
  116. to get access to those model classes.
  117. Several of Django's bundled applications make use of the latter technique.
  118. For example,
  119. :class:`the permissions system <django.contrib.auth.models.Permission` in
  120. Django's authentication framework uses a
  121. :class:`~django.contrib.auth.models.Permission` model with a foreign
  122. key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets
  123. :class:`~django.contrib.auth.models.Permission` represent concepts like
  124. "can add blog entry" or "can delete news story".
  125. The ``ContentTypeManager``
  126. --------------------------
  127. .. class:: models.ContentTypeManager
  128. :class:`~django.contrib.contenttypes.models.ContentType` also has a custom
  129. manager, :class:`~django.contrib.contenttypes.models.ContentTypeManager`,
  130. which adds the following methods:
  131. .. method:: models.ContentTypeManager.clear_cache()
  132. Clears an internal cache used by
  133. :class:`~django.contrib.contenttypes.models.ContentType` to keep track
  134. of which models for which it has created
  135. :class:`django.contrib.contenttypes.models.ContentType` instances. You
  136. probably won't ever need to call this method yourself; Django will call
  137. it automatically when it's needed.
  138. .. method:: models.ContentTypeManager.get_for_model(model)
  139. Takes either a model class or an instance of a model, and returns the
  140. :class:`~django.contrib.contenttypes.models.ContentType` instance
  141. representing that model.
  142. The :meth:`~models.ContentTypeManager.get_for_model()` method is especially useful when you know you
  143. need to work with a :class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't want to go to the
  144. trouble of obtaining the model's metadata to perform a manual lookup::
  145. >>> from django.contrib.auth.models import User
  146. >>> user_type = ContentType.objects.get_for_model(User)
  147. >>> user_type
  148. <ContentType: user>
  149. .. _generic-relations:
  150. Generic relations
  151. =================
  152. Adding a foreign key from one of your own models to
  153. :class:`~django.contrib.contenttypes.models.ContentType` allows your model to
  154. effectively tie itself to another model class, as in the example of the
  155. :class:`~django.contrib.auth.models.Permission` model above. But it's possible
  156. to go one step further and use
  157. :class:`~django.contrib.contenttypes.models.ContentType` to enable truly
  158. generic (sometimes called "polymorphic") relationships between models.
  159. A simple example is a tagging system, which might look like this::
  160. from django.db import models
  161. from django.contrib.contenttypes.models import ContentType
  162. from django.contrib.contenttypes import generic
  163. class TaggedItem(models.Model):
  164. tag = models.SlugField()
  165. content_type = models.ForeignKey(ContentType)
  166. object_id = models.PositiveIntegerField()
  167. content_object = generic.GenericForeignKey('content_type', 'object_id')
  168. def __unicode__(self):
  169. return self.tag
  170. A normal :class:`~django.db.models.fields.related.ForeignKey` can only "point
  171. to" one other model, which means that if the ``TaggedItem`` model used a
  172. :class:`~django.db.models.fields.related.ForeignKey` it would have to
  173. choose one and only one model to store tags for. The contenttypes
  174. application provides a special field type --
  175. :class:`django.contrib.contenttypes.generic.GenericForeignKey` -- which
  176. works around this and allows the relationship to be with any
  177. model. There are three parts to setting up a
  178. :class:`~django.contrib.contenttypes.generic.GenericForeignKey`:
  179. 1. Give your model a :class:`~django.db.models.fields.related.ForeignKey`
  180. to :class:`~django.contrib.contenttypes.models.ContentType`.
  181. 2. Give your model a field that can store a primary-key value from the
  182. models you'll be relating to. (For most models, this means an
  183. :class:`~django.db.models.fields.IntegerField` or
  184. :class:`~django.db.models.fields.PositiveIntegerField`.)
  185. This field must be of the same type as the primary key of the models
  186. that will be involved in the generic relation. For example, if you use
  187. :class:`~django.db.models.fields.IntegerField`, you won't be able to
  188. form a generic relation with a model that uses a
  189. :class:`~django.db.models.fields.CharField` as a primary key.
  190. 3. Give your model a
  191. :class:`~django.contrib.contenttypes.generic.GenericForeignKey`, and
  192. pass it the names of the two fields described above. If these fields
  193. are named "content_type" and "object_id", you can omit this -- those
  194. are the default field names
  195. :class:`~django.contrib.contenttypes.generic.GenericForeignKey` will
  196. look for.
  197. This will enable an API similar to the one used for a normal
  198. :class:`~django.db.models.fields.related.ForeignKey`;
  199. each ``TaggedItem`` will have a ``content_object`` field that returns the
  200. object it's related to, and you can also assign to that field or use it when
  201. creating a ``TaggedItem``::
  202. >>> from django.contrib.auth.models import User
  203. >>> guido = User.objects.get(username='Guido')
  204. >>> t = TaggedItem(content_object=guido, tag='bdfl')
  205. >>> t.save()
  206. >>> t.content_object
  207. <User: Guido>
  208. Due to the way :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
  209. is implemented, you cannot use such fields directly with filters (``filter()``
  210. and ``exclude()``, for example) via the database API. They aren't normal field
  211. objects. These examples will *not* work::
  212. # This will fail
  213. >>> TaggedItem.objects.filter(content_object=guido)
  214. # This will also fail
  215. >>> TaggedItem.objects.get(content_object=guido)
  216. Reverse generic relations
  217. -------------------------
  218. If you know which models you'll be using most often, you can also add
  219. a "reverse" generic relationship to enable an additional API. For example::
  220. class Bookmark(models.Model):
  221. url = models.URLField()
  222. tags = generic.GenericRelation(TaggedItem)
  223. ``Bookmark`` instances will each have a ``tags`` attribute, which can
  224. be used to retrieve their associated ``TaggedItems``::
  225. >>> b = Bookmark(url='http://www.djangoproject.com/')
  226. >>> b.save()
  227. >>> t1 = TaggedItem(content_object=b, tag='django')
  228. >>> t1.save()
  229. >>> t2 = TaggedItem(content_object=b, tag='python')
  230. >>> t2.save()
  231. >>> b.tags.all()
  232. [<TaggedItem: django>, <TaggedItem: python>]
  233. Just as :class:`django.contrib.contenttypes.generic.GenericForeignKey`
  234. accepts the names of the content-type and object-ID fields as
  235. arguments, so too does ``GenericRelation``; if the model which has the
  236. generic foreign key is using non-default names for those fields, you
  237. must pass the names of the fields when setting up a
  238. ``GenericRelation`` to it. For example, if the ``TaggedItem`` model
  239. referred to above used fields named ``content_type_fk`` and
  240. ``object_primary_key`` to create its generic foreign key, then a
  241. ``GenericRelation`` back to it would need to be defined like so::
  242. tags = generic.GenericRelation(TaggedItem, content_type_field='content_type_fk', object_id_field='object_primary_key')
  243. Of course, if you don't add the reverse relationship, you can do the
  244. same types of lookups manually::
  245. >>> b = Bookmark.objects.get(url='http://www.djangoproject.com/')
  246. >>> bookmark_type = ContentType.objects.get_for_model(b)
  247. >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id,
  248. ... object_id=b.id)
  249. [<TaggedItem: django>, <TaggedItem: python>]
  250. Note that if the model with a :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
  251. that you're referring to uses a non-default value for ``ct_field`` or ``fk_field``
  252. (e.g. the :mod:`django.contrib.comments` app uses ``ct_field="object_pk"``),
  253. you'll need to pass ``content_type_field`` and ``object_id_field`` to
  254. :class:`~django.contrib.contenttypes.generic.GenericRelation`.::
  255. comments = generic.GenericRelation(Comment, content_type_field="content_type", object_id_field="object_pk")
  256. Note that if you delete an object that has a
  257. :class:`~django.contrib.contenttypes.generic.GenericRelation`, any objects
  258. which have a :class:`~django.contrib.contenttypes.generic.GenericForeignKey`
  259. pointing at it will be deleted as well. In the example above, this means that
  260. if a ``Bookmark`` object were deleted, any ``TaggedItem`` objects pointing at
  261. it would be deleted at the same time.
  262. Generic relations and aggregation
  263. ---------------------------------
  264. :ref:`Django's database aggregation API <topics-db-aggregation>`
  265. doesn't work with a
  266. :class:`~django.contrib.contenttypes.generic.GenericRelation`. For example, you
  267. might be tempted to try something like::
  268. Bookmark.objects.aggregate(Count('tags'))
  269. This will not work correctly, however. The generic relation adds extra filters
  270. to the queryset to ensure the correct content type, but the ``aggregate`` method
  271. doesn't take them into account. For now, if you need aggregates on generic
  272. relations, you'll need to calculate them without using the aggregation API.
  273. Generic relations in forms and admin
  274. ------------------------------------
  275. :mod:`django.contrib.contenttypes.generic` provides both a
  276. :class:`~django.contrib.contenttypes.generic.GenericInlineFormSet`
  277. and :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`.
  278. This enables the use of generic relations in forms and the admin. See the
  279. :ref:`model formset <topics-forms-modelforms>` and
  280. :ref:`admin <ref-contrib-admin>` documentation for more information.
  281. .. class:: generic.GenericInlineModelAdmin
  282. The :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`
  283. class inherits all properties from an
  284. :class:`~django.contrib.admin.options.InlineModelAdmin` class. However,
  285. it adds a couple of its own for working with the generic relation:
  286. .. attribute:: generic.GenericInlineModelAdmin.ct_field
  287. The name of the
  288. :class:`~django.contrib.contenttypes.models.ContentType` foreign key
  289. field on the model. Defaults to ``content_type``.
  290. .. attribute:: generic.GenericInlineModelAdmin.ct_fk_field
  291. The name of the integer field that represents the ID of the related
  292. object. Defaults to ``object_id``.