PageRenderTime 45ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

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