1
0
mirror of https://github.com/django/django.git synced 2025-01-03 06:55:47 +00:00

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>
This commit is contained in:
Clifford Gama 2024-10-17 16:39:40 +02:00 committed by GitHub
parent bd3b1dfa24
commit 65f3cfce59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1628,80 +1628,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::
which the model is related and the :attr:`~ForeignKey.on_delete` option::
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
"Manufacturer",
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
name = models.TextField()
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):
pass
class Car(AbstractCar):
pass
# 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
@ -1714,9 +1659,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:
@ -2266,6 +2211,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
===================