summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Gama <53076065+cliff688@users.noreply.github.com>2024-10-17 16:39:40 +0200
committerNatalia <124304+nessita@users.noreply.github.com>2024-10-17 11:42:54 -0300
commit9a5eae0ad8054e9e9d8a43505c52313eecddbc8e (patch)
tree3927f135be79d150f8e7ccd56becd1d447751746
parent8ce0039cee6fba82c261037523c5f81a28212341 (diff)
[5.1.x] Fixed #26322 -- Consolidated lazy relationships details in docs/ref/models/fields.txt.
Reorganized docs to list and explain the types of lazy relationships that can be defined in related fields. Co-authored-by: Natalia <124304+nessita@users.noreply.github.com> Backport of 65f3cfce59395131f318cf1ecba144530ed6609e from main.
-rw-r--r--docs/ref/models/fields.txt195
1 files changed, 127 insertions, 68 deletions
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
index 069ecdbabb..0ceb620a9f 100644
--- a/docs/ref/models/fields.txt
+++ b/docs/ref/models/fields.txt
@@ -1634,80 +1634,25 @@ Django also defines a set of fields that represent relations.
.. class:: ForeignKey(to, on_delete, **options)
A many-to-one relationship. Requires two positional arguments: the class to
-which the model is related and the :attr:`~ForeignKey.on_delete` option.
-
-.. _recursive-relationships:
-
-To create a recursive relationship -- an object that has a many-to-one
-relationship with itself -- use ``models.ForeignKey('self',
-on_delete=models.CASCADE)``.
-
-.. _lazy-relationships:
-
-If you need to create a relationship on a model that has not yet been defined,
-you can use the name of the model, rather than the model object itself::
-
- from django.db import models
-
-
- class Car(models.Model):
- manufacturer = models.ForeignKey(
- "Manufacturer",
- on_delete=models.CASCADE,
- )
- # ...
-
-
- class Manufacturer(models.Model):
- # ...
- pass
-
-Relationships defined this way on :ref:`abstract models
-<abstract-base-classes>` are resolved when the model is subclassed as a
-concrete model and are not relative to the abstract model's ``app_label``:
-
-.. code-block:: python
- :caption: ``products/models.py``
-
- from django.db import models
-
-
- class AbstractCar(models.Model):
- manufacturer = models.ForeignKey("Manufacturer", on_delete=models.CASCADE)
-
- class Meta:
- abstract = True
-
-.. code-block:: python
- :caption: ``production/models.py``
+which the model is related and the :attr:`~ForeignKey.on_delete` option::
from django.db import models
- from products.models import AbstractCar
class Manufacturer(models.Model):
- pass
-
-
- class Car(AbstractCar):
- pass
-
+ name = models.TextField()
- # Car.manufacturer will point to `production.Manufacturer` here.
-
-To refer to models defined in another application, you can explicitly specify
-a model with the full application label. For example, if the ``Manufacturer``
-model above is defined in another application called ``production``, you'd
-need to use::
class Car(models.Model):
- manufacturer = models.ForeignKey(
- "production.Manufacturer",
- on_delete=models.CASCADE,
- )
+ manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
-This sort of reference, called a lazy relationship, can be useful when
-resolving circular import dependencies between two applications.
+The first positional argument can be either a concrete model class or a
+:ref:`lazy reference <lazy-relationships>` to a model class.
+:ref:`Recursive relationships <recursive-relationships>`, where a model has a
+relationship with itself, are also supported.
+
+See :attr:`ForeignKey.on_delete` for details on the second positional
+argument.
A database index is automatically created on the ``ForeignKey``. You can
disable this by setting :attr:`~Field.db_index` to ``False``. You may want to
@@ -1720,9 +1665,9 @@ Database Representation
Behind the scenes, Django appends ``"_id"`` to the field name to create its
database column name. In the above example, the database table for the ``Car``
-model will have a ``manufacturer_id`` column. (You can change this explicitly by
-specifying :attr:`~Field.db_column`) However, your code should never have to
-deal with the database column name, unless you write custom SQL. You'll always
+model will have a ``manufacturer_id`` column. You can change this explicitly by
+specifying :attr:`~Field.db_column`, however, your code should never have to
+deal with the database column name (unless you write custom SQL). You'll always
deal with the field names of your model object.
.. _foreign-key-arguments:
@@ -2272,6 +2217,120 @@ accepted by :class:`ForeignKey`, plus one extra argument:
See :doc:`One-to-one relationships </topics/db/examples/one_to_one>` for usage
examples of ``OneToOneField``.
+.. _lazy-relationships:
+
+Lazy relationships
+------------------
+
+Lazy relationships allow referencing models by their names (as strings) or
+creating recursive relationships. Strings can be used as the first argument in
+any relationship field to reference models lazily. A lazy reference can be
+either :ref:`recursive <recursive-relationships>`,
+:ref:`relative <relative-relationships>` or
+:ref:`absolute <absolute-relationships>`.
+
+.. _recursive-relationships:
+
+Recursive
+~~~~~~~~~
+
+To define a relationship where a model references itself, use ``"self"`` as the
+first argument of the relationship field::
+
+ from django.db import models
+
+
+ class Manufacturer(models.Model):
+ name = models.TextField()
+ suppliers = models.ManyToManyField("self", symmetrical=False)
+
+
+When used in an :ref:`abstract model <abstract-base-classes>`, the recursive
+relationship resolves such that each concrete subclass references itself.
+
+.. _relative-relationships:
+
+Relative
+~~~~~~~~
+
+When a relationship needs to be created with a model that has not been defined
+yet, it can be referenced by its name rather than the model object itself::
+
+ from django.db import models
+
+
+ class Car(models.Model):
+ manufacturer = models.ForeignKey(
+ "Manufacturer",
+ on_delete=models.CASCADE,
+ )
+
+
+ class Manufacturer(models.Model):
+ name = models.TextField()
+ suppliers = models.ManyToManyField("self", symmetrical=False)
+
+Relationships defined this way on :ref:`abstract models
+<abstract-base-classes>` are resolved when the model is subclassed as a
+concrete model and are not relative to the abstract model's ``app_label``:
+
+.. code-block:: python
+ :caption: ``products/models.py``
+
+ from django.db import models
+
+
+ class AbstractCar(models.Model):
+ manufacturer = models.ForeignKey("Manufacturer", on_delete=models.CASCADE)
+
+ class Meta:
+ abstract = True
+
+.. code-block:: python
+ :caption: ``production/models.py``
+
+ from django.db import models
+ from products.models import AbstractCar
+
+
+ class Manufacturer(models.Model):
+ name = models.TextField()
+
+
+ class Car(AbstractCar):
+ pass
+
+In this example, the ``Car.manufacturer`` relationship will resolve to
+``production.Manufacturer``, as it points to the concrete model defined
+within the ``production/models.py`` file.
+
+.. admonition:: Reusable models with relative references
+
+ Relative references allow the creation of reusable abstract models with
+ relationships that can resolve to different implementations of the
+ referenced models in various subclasses across different applications.
+
+.. _absolute-relationships:
+
+Absolute
+~~~~~~~~
+
+Absolute references specify a model using its ``app_label`` and class name,
+allowing for model references across different applications. This type of lazy
+relationship can also help resolve circular imports.
+
+For example, if the ``Manufacturer`` model is defined in another application
+called ``thirdpartyapp``, it can be referenced as::
+
+ class Car(models.Model):
+ manufacturer = models.ForeignKey(
+ "thirdpartyapp``.Manufacturer",
+ on_delete=models.CASCADE,
+ )
+
+Absolute references always point to the same model, even when used in an
+:ref:`abstract model <abstract-base-classes>`.
+
Field API reference
===================