contenttypes.txt 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  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 ``django-admin 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. .. currentmodule:: django.contrib.contenttypes.models
  43. The ``ContentType`` model
  44. =========================
  45. .. class:: ContentType
  46. Each instance of :class:`~django.contrib.contenttypes.models.ContentType`
  47. has two fields which, taken together, uniquely describe an installed
  48. model:
  49. .. attribute:: app_label
  50. The name of the application the model is part of. This is taken from
  51. the :attr:`app_label` attribute of the model, and includes only the
  52. *last* part of the application's Python import path;
  53. ``django.contrib.contenttypes``, for example, becomes an
  54. :attr:`app_label` of ``contenttypes``.
  55. .. attribute:: model
  56. The name of the model class.
  57. Additionally, the following property is available:
  58. .. attribute:: name
  59. The human-readable name of the content type. This is taken from the
  60. :attr:`verbose_name <django.db.models.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 :mod:`~django.contrib.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 migrate`` 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:`~django.contrib.contenttypes.models.ContentType.app_label`
  71. will be set to ``'sites'`` (the last part of the Python
  72. path ``django.contrib.sites``).
  73. * :attr:`~django.contrib.contenttypes.models.ContentType.model`
  74. will be set to ``'site'``.
  75. Methods on ``ContentType`` instances
  76. ====================================
  77. Each :class:`~django.contrib.contenttypes.models.ContentType` instance has
  78. methods that allow you to get from a
  79. :class:`~django.contrib.contenttypes.models.ContentType` instance to the
  80. model it represents, or to retrieve objects from that model:
  81. .. method:: ContentType.get_object_for_this_type(using=None, **kwargs)
  82. Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the
  83. model the :class:`~django.contrib.contenttypes.models.ContentType`
  84. represents, and does
  85. :meth:`a get() lookup <django.db.models.query.QuerySet.get>`
  86. on that model, returning the corresponding object. The ``using`` argument
  87. can be used to specify a different database than the default one.
  88. .. method:: ContentType.model_class()
  89. Returns the model class represented by this
  90. :class:`~django.contrib.contenttypes.models.ContentType` instance.
  91. For example, we could look up the
  92. :class:`~django.contrib.contenttypes.models.ContentType` for the
  93. :class:`~django.contrib.auth.models.User` model:
  94. .. code-block:: pycon
  95. >>> from django.contrib.contenttypes.models import ContentType
  96. >>> user_type = ContentType.objects.get(app_label="auth", model="user")
  97. >>> user_type
  98. <ContentType: user>
  99. And then use it to query for a particular
  100. :class:`~django.contrib.auth.models.User`, or to get access
  101. to the ``User`` model class:
  102. .. code-block:: pycon
  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 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_id(id)
  143. Lookup a :class:`~django.contrib.contenttypes.models.ContentType` by ID.
  144. Since this method uses the same shared cache as
  145. :meth:`~django.contrib.contenttypes.models.ContentTypeManager.get_for_model`,
  146. it's preferred to use this method over the usual
  147. ``ContentType.objects.get(pk=id)``
  148. .. method:: get_for_model(model, for_concrete_model=True)
  149. Takes either a model class or an instance of a model, and returns the
  150. :class:`~django.contrib.contenttypes.models.ContentType` instance
  151. representing that model. ``for_concrete_model=False`` allows fetching
  152. the :class:`~django.contrib.contenttypes.models.ContentType` of a proxy
  153. model.
  154. .. method:: get_for_models(*models, for_concrete_models=True)
  155. Takes a variadic number of model classes, and returns a dictionary
  156. mapping the model classes to the
  157. :class:`~django.contrib.contenttypes.models.ContentType` instances
  158. representing them. ``for_concrete_models=False`` allows fetching the
  159. :class:`~django.contrib.contenttypes.models.ContentType` of proxy
  160. models.
  161. .. method:: get_by_natural_key(app_label, model)
  162. Returns the :class:`~django.contrib.contenttypes.models.ContentType`
  163. instance uniquely identified by the given application label and model
  164. name. The primary purpose of this method is to allow
  165. :class:`~django.contrib.contenttypes.models.ContentType` objects to be
  166. referenced via a :ref:`natural key<topics-serialization-natural-keys>`
  167. during deserialization.
  168. The :meth:`~ContentTypeManager.get_for_model()` method is especially
  169. useful when you know you need to work with a
  170. :class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't
  171. want to go to the trouble of obtaining the model's metadata to perform a manual
  172. lookup:
  173. .. code-block:: pycon
  174. >>> from django.contrib.auth.models import User
  175. >>> ContentType.objects.get_for_model(User)
  176. <ContentType: user>
  177. .. module:: django.contrib.contenttypes.fields
  178. .. _generic-relations:
  179. Generic relations
  180. =================
  181. Adding a foreign key from one of your own models to
  182. :class:`~django.contrib.contenttypes.models.ContentType` allows your model to
  183. effectively tie itself to another model class, as in the example of the
  184. :class:`~django.contrib.auth.models.Permission` model above. But it's possible
  185. to go one step further and use
  186. :class:`~django.contrib.contenttypes.models.ContentType` to enable truly
  187. generic (sometimes called "polymorphic") relationships between models.
  188. For example, it could be used for a tagging system like so::
  189. from django.contrib.contenttypes.fields import GenericForeignKey
  190. from django.contrib.contenttypes.models import ContentType
  191. from django.db import models
  192. class TaggedItem(models.Model):
  193. tag = models.SlugField()
  194. content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
  195. object_id = models.PositiveBigIntegerField()
  196. content_object = GenericForeignKey("content_type", "object_id")
  197. def __str__(self):
  198. return self.tag
  199. class Meta:
  200. indexes = [
  201. models.Index(fields=["content_type", "object_id"]),
  202. ]
  203. A normal :class:`~django.db.models.ForeignKey` can only "point
  204. to" one other model, which means that if the ``TaggedItem`` model used a
  205. :class:`~django.db.models.ForeignKey` it would have to
  206. choose one and only one model to store tags for. The contenttypes
  207. application provides a special field type (``GenericForeignKey``) which
  208. works around this and allows the relationship to be with any
  209. model:
  210. .. class:: GenericForeignKey
  211. There are three parts to setting up a
  212. :class:`~django.contrib.contenttypes.fields.GenericForeignKey`:
  213. 1. Give your model a :class:`~django.db.models.ForeignKey`
  214. to :class:`~django.contrib.contenttypes.models.ContentType`. The usual
  215. name for this field is "content_type".
  216. 2. Give your model a field that can store primary key values from the
  217. models you'll be relating to. For most models, this means a
  218. :class:`~django.db.models.PositiveBigIntegerField`. The usual name
  219. for this field is "object_id".
  220. 3. Give your model a
  221. :class:`~django.contrib.contenttypes.fields.GenericForeignKey`, and
  222. pass it the names of the two fields described above. If these fields
  223. are named "content_type" and "object_id", you can omit this -- those
  224. are the default field names
  225. :class:`~django.contrib.contenttypes.fields.GenericForeignKey` will
  226. look for.
  227. Unlike for the :class:`~django.db.models.ForeignKey`, a database index is
  228. *not* automatically created on the
  229. :class:`~django.contrib.contenttypes.fields.GenericForeignKey`, so it's
  230. recommended that you use
  231. :attr:`Meta.indexes <django.db.models.Options.indexes>` to add your own
  232. multiple column index. This behavior :ticket:`may change <23435>` in the
  233. future.
  234. .. attribute:: GenericForeignKey.for_concrete_model
  235. If ``False``, the field will be able to reference proxy models. Default
  236. is ``True``. This mirrors the ``for_concrete_model`` argument to
  237. :meth:`~django.contrib.contenttypes.models.ContentTypeManager.get_for_model`.
  238. .. admonition:: Primary key type compatibility
  239. The "object_id" field doesn't have to be the same type as the
  240. primary key fields on the related models, but their primary key values
  241. must be coercible to the same type as the "object_id" field by its
  242. :meth:`~django.db.models.Field.get_db_prep_value` method.
  243. For example, if you want to allow generic relations to models with either
  244. :class:`~django.db.models.IntegerField` or
  245. :class:`~django.db.models.CharField` primary key fields, you
  246. can use :class:`~django.db.models.CharField` for the
  247. "object_id" field on your model since integers can be coerced to
  248. strings by :meth:`~django.db.models.Field.get_db_prep_value`.
  249. For maximum flexibility you can use a
  250. :class:`~django.db.models.TextField` which doesn't have a
  251. maximum length defined, however this may incur significant performance
  252. penalties depending on your database backend.
  253. There is no one-size-fits-all solution for which field type is best. You
  254. should evaluate the models you expect to be pointing to and determine
  255. which solution will be most effective for your use case.
  256. .. admonition:: Serializing references to ``ContentType`` objects
  257. If you're serializing data (for example, when generating
  258. :class:`~django.test.TransactionTestCase.fixtures`) from a model that implements
  259. generic relations, you should probably be using a natural key to uniquely
  260. identify related :class:`~django.contrib.contenttypes.models.ContentType`
  261. objects. See :ref:`natural keys<topics-serialization-natural-keys>` and
  262. :option:`dumpdata --natural-foreign` for more information.
  263. This will enable an API similar to the one used for a normal
  264. :class:`~django.db.models.ForeignKey`;
  265. each ``TaggedItem`` will have a ``content_object`` field that returns the
  266. object it's related to, and you can also assign to that field or use it when
  267. creating a ``TaggedItem``:
  268. .. code-block:: pycon
  269. >>> from django.contrib.auth.models import User
  270. >>> guido = User.objects.get(username="Guido")
  271. >>> t = TaggedItem(content_object=guido, tag="bdfl")
  272. >>> t.save()
  273. >>> t.content_object
  274. <User: Guido>
  275. If the related object is deleted, the ``content_type`` and ``object_id`` fields
  276. remain set to their original values and the ``GenericForeignKey`` returns
  277. ``None``:
  278. .. code-block:: pycon
  279. >>> guido.delete()
  280. >>> t.content_object # returns None
  281. Due to the way :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
  282. is implemented, you cannot use such fields directly with filters (``filter()``
  283. and ``exclude()``, for example) via the database API. Because a
  284. :class:`~django.contrib.contenttypes.fields.GenericForeignKey` isn't a
  285. normal field object, these examples will *not* work:
  286. .. code-block:: pycon
  287. # This will fail
  288. >>> TaggedItem.objects.filter(content_object=guido)
  289. # This will also fail
  290. >>> TaggedItem.objects.get(content_object=guido)
  291. Likewise, :class:`~django.contrib.contenttypes.fields.GenericForeignKey`\s
  292. does not appear in :class:`~django.forms.ModelForm`\s.
  293. Reverse generic relations
  294. -------------------------
  295. .. class:: GenericRelation
  296. .. attribute:: related_query_name
  297. The relation on the related object back to this object doesn't exist by
  298. default. Setting ``related_query_name`` creates a relation from the
  299. related object back to this one. This allows querying and filtering
  300. from the related object.
  301. If you know which models you'll be using most often, you can also add
  302. a "reverse" generic relationship to enable an additional API. For example::
  303. from django.contrib.contenttypes.fields import GenericRelation
  304. from django.db import models
  305. class Bookmark(models.Model):
  306. url = models.URLField()
  307. tags = GenericRelation(TaggedItem)
  308. ``Bookmark`` instances will each have a ``tags`` attribute, which can
  309. be used to retrieve their associated ``TaggedItems``:
  310. .. code-block:: pycon
  311. >>> b = Bookmark(url="https://www.djangoproject.com/")
  312. >>> b.save()
  313. >>> t1 = TaggedItem(content_object=b, tag="django")
  314. >>> t1.save()
  315. >>> t2 = TaggedItem(content_object=b, tag="python")
  316. >>> t2.save()
  317. >>> b.tags.all()
  318. <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
  319. You can also use ``add()``, ``create()``, or ``set()`` to create
  320. relationships:
  321. .. code-block:: pycon
  322. >>> t3 = TaggedItem(tag="Web development")
  323. >>> b.tags.add(t3, bulk=False)
  324. >>> b.tags.create(tag="Web framework")
  325. <TaggedItem: Web framework>
  326. >>> b.tags.all()
  327. <QuerySet [<TaggedItem: django>, <TaggedItem: python>, <TaggedItem: Web development>, <TaggedItem: Web framework>]>
  328. >>> b.tags.set([t1, t3])
  329. >>> b.tags.all()
  330. <QuerySet [<TaggedItem: django>, <TaggedItem: Web development>]>
  331. The ``remove()`` call will bulk delete the specified model objects:
  332. .. code-block:: pycon
  333. >>> b.tags.remove(t3)
  334. >>> b.tags.all()
  335. <QuerySet [<TaggedItem: django>]>
  336. >>> TaggedItem.objects.all()
  337. <QuerySet [<TaggedItem: django>]>
  338. The ``clear()`` method can be used to bulk delete all related objects for an
  339. instance:
  340. .. code-block:: pycon
  341. >>> b.tags.clear()
  342. >>> b.tags.all()
  343. <QuerySet []>
  344. >>> TaggedItem.objects.all()
  345. <QuerySet []>
  346. Defining :class:`~django.contrib.contenttypes.fields.GenericRelation` with
  347. ``related_query_name`` set allows querying from the related object::
  348. tags = GenericRelation(TaggedItem, related_query_name="bookmark")
  349. This enables filtering, ordering, and other query operations on ``Bookmark``
  350. from ``TaggedItem``:
  351. .. code-block:: pycon
  352. >>> # Get all tags belonging to bookmarks containing `django` in the url
  353. >>> TaggedItem.objects.filter(bookmark__url__contains="django")
  354. <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
  355. If you don't add the ``related_query_name``, you can do the same types of
  356. lookups manually:
  357. .. code-block:: pycon
  358. >>> bookmarks = Bookmark.objects.filter(url__contains="django")
  359. >>> bookmark_type = ContentType.objects.get_for_model(Bookmark)
  360. >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, object_id__in=bookmarks)
  361. <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
  362. Just as :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
  363. accepts the names of the content-type and object-ID fields as
  364. arguments, so too does
  365. :class:`~django.contrib.contenttypes.fields.GenericRelation`;
  366. if the model which has the generic foreign key is using non-default names
  367. for those fields, you must pass the names of the fields when setting up a
  368. :class:`.GenericRelation` to it. For example, if the ``TaggedItem`` model
  369. referred to above used fields named ``content_type_fk`` and
  370. ``object_primary_key`` to create its generic foreign key, then a
  371. :class:`.GenericRelation` back to it would need to be defined like so::
  372. tags = GenericRelation(
  373. TaggedItem,
  374. content_type_field="content_type_fk",
  375. object_id_field="object_primary_key",
  376. )
  377. Note also, that if you delete an object that has a
  378. :class:`~django.contrib.contenttypes.fields.GenericRelation`, any objects
  379. which have a :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
  380. pointing at it will be deleted as well. In the example above, this means that
  381. if a ``Bookmark`` object were deleted, any ``TaggedItem`` objects pointing at
  382. it would be deleted at the same time.
  383. Unlike :class:`~django.db.models.ForeignKey`,
  384. :class:`~django.contrib.contenttypes.fields.GenericForeignKey` does not accept
  385. an :attr:`~django.db.models.ForeignKey.on_delete` argument to customize this
  386. behavior; if desired, you can avoid the cascade-deletion by not using
  387. :class:`~django.contrib.contenttypes.fields.GenericRelation`, and alternate
  388. behavior can be provided via the :data:`~django.db.models.signals.pre_delete`
  389. signal.
  390. Generic relations and aggregation
  391. ---------------------------------
  392. :doc:`Django's database aggregation API </topics/db/aggregation>` works with a
  393. :class:`~django.contrib.contenttypes.fields.GenericRelation`. For example, you
  394. can find out how many tags all the bookmarks have:
  395. .. code-block:: pycon
  396. >>> Bookmark.objects.aggregate(Count("tags"))
  397. {'tags__count': 3}
  398. .. module:: django.contrib.contenttypes.forms
  399. Generic relation in forms
  400. -------------------------
  401. The :mod:`django.contrib.contenttypes.forms` module provides:
  402. * :class:`BaseGenericInlineFormSet`
  403. * A formset factory, :func:`generic_inlineformset_factory`, for use with
  404. :class:`~django.contrib.contenttypes.fields.GenericForeignKey`.
  405. .. class:: BaseGenericInlineFormSet
  406. .. function:: generic_inlineformset_factory(model, form=ModelForm, formset=BaseGenericInlineFormSet, ct_field="content_type", fk_field="object_id", fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, validate_max=False, for_concrete_model=True, min_num=None, validate_min=False, absolute_max=None, can_delete_extra=True)
  407. Returns a ``GenericInlineFormSet`` using
  408. :func:`~django.forms.models.modelformset_factory`.
  409. You must provide ``ct_field`` and ``fk_field`` if they are different from
  410. the defaults, ``content_type`` and ``object_id`` respectively. Other
  411. parameters are similar to those documented in
  412. :func:`~django.forms.models.modelformset_factory` and
  413. :func:`~django.forms.models.inlineformset_factory`.
  414. The ``for_concrete_model`` argument corresponds to the
  415. :class:`~django.contrib.contenttypes.fields.GenericForeignKey.for_concrete_model`
  416. argument on ``GenericForeignKey``.
  417. .. module:: django.contrib.contenttypes.admin
  418. Generic relations in admin
  419. --------------------------
  420. The :mod:`django.contrib.contenttypes.admin` module provides
  421. :class:`~django.contrib.contenttypes.admin.GenericTabularInline` and
  422. :class:`~django.contrib.contenttypes.admin.GenericStackedInline` (subclasses of
  423. :class:`~django.contrib.contenttypes.admin.GenericInlineModelAdmin`)
  424. These classes and functions enable the use of generic relations in forms
  425. and the admin. See the :doc:`model formset </topics/forms/modelforms>` and
  426. :ref:`admin <using-generic-relations-as-an-inline>` documentation for more
  427. information.
  428. .. class:: GenericInlineModelAdmin
  429. The :class:`~django.contrib.contenttypes.admin.GenericInlineModelAdmin`
  430. class inherits all properties from an
  431. :class:`~django.contrib.admin.InlineModelAdmin` class. However,
  432. it adds a couple of its own for working with the generic relation:
  433. .. attribute:: ct_field
  434. The name of the
  435. :class:`~django.contrib.contenttypes.models.ContentType` foreign key
  436. field on the model. Defaults to ``content_type``.
  437. .. attribute:: ct_fk_field
  438. The name of the integer field that represents the ID of the related
  439. object. Defaults to ``object_id``.
  440. .. class:: GenericTabularInline
  441. .. class:: GenericStackedInline
  442. Subclasses of :class:`GenericInlineModelAdmin` with stacked and tabular
  443. layouts, respectively.
  444. .. module:: django.contrib.contenttypes.prefetch
  445. ``GenericPrefetch()``
  446. ---------------------
  447. .. class:: GenericPrefetch(lookup, querysets, to_attr=None)
  448. This lookup is similar to ``Prefetch()`` and it should only be used on
  449. ``GenericForeignKey``. The ``querysets`` argument accepts a list of querysets,
  450. each for a different ``ContentType``. This is useful for ``GenericForeignKey``
  451. with non-homogeneous set of results.
  452. .. code-block:: pycon
  453. >>> from django.contrib.contenttypes.prefetch import GenericPrefetch
  454. >>> bookmark = Bookmark.objects.create(url="https://www.djangoproject.com/")
  455. >>> animal = Animal.objects.create(name="lion", weight=100)
  456. >>> TaggedItem.objects.create(tag="great", content_object=bookmark)
  457. >>> TaggedItem.objects.create(tag="awesome", content_object=animal)
  458. >>> prefetch = GenericPrefetch(
  459. ... "content_object", [Bookmark.objects.all(), Animal.objects.only("name")]
  460. ... )
  461. >>> TaggedItem.objects.prefetch_related(prefetch).all()
  462. <QuerySet [<TaggedItem: Great>, <TaggedItem: Awesome>]>