Skip to content

Commit

Permalink
[5.1.x] Fixed #36128 -- Clarified auto-generated unique constraint on…
Browse files Browse the repository at this point in the history
… m2m through models.

Backport of ae2736c from main.
  • Loading branch information
cliff688 authored and sarahboyce committed Mar 4, 2025
1 parent 03ace75 commit cc405e1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
7 changes: 7 additions & 0 deletions docs/ref/contrib/admin/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2635,6 +2635,13 @@ we can do this with inline admin models. Suppose we have the following models::
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)

class Meta:
constraints = [
models.UniqueConstraint(
fields=["person", "group"], name="unique_person_group"
)
]

The first step in displaying this intermediate model in the admin is to
define an inline class for the ``Membership`` model::

Expand Down
11 changes: 3 additions & 8 deletions docs/ref/models/fields.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2009,13 +2009,6 @@ that control how the relationship functions.
:ref:`extra data with a many-to-many relationship
<intermediary-manytomany>`.

.. note::

If you don't want multiple associations between the same instances, add
a :class:`~django.db.models.UniqueConstraint` including the from and to
fields. Django's automatically generated many-to-many tables include
such a constraint.

.. note::

Recursive relationships using an intermediary model can't determine the
Expand All @@ -2026,7 +2019,9 @@ that control how the relationship functions.

If you don't specify an explicit ``through`` model, there is still an
implicit ``through`` model class you can use to directly access the table
created to hold the association. It has three fields to link the models.
created to hold the association. It has three fields to link the models, a
primary key and two foreign keys. There is a unique constraint on the two
foreign keys.

If the source and target models differ, the following fields are
generated:
Expand Down
12 changes: 12 additions & 0 deletions docs/topics/db/models.txt
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,22 @@ something like this::
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)

class Meta:
constraints = [
models.UniqueConstraint(
fields=["person", "group"], name="unique_person_group"
)
]

When you set up the intermediary model, you explicitly specify foreign
keys to the models that are involved in the many-to-many relationship. This
explicit declaration defines how the two models are related.

If you don't want multiple associations between the same instances, add a
:class:`~django.db.models.UniqueConstraint` including the ``from`` and ``to``
fields. Django's automatically generated many-to-many tables include such a
constraint.

There are a few restrictions on the intermediate model:

* Your intermediate model must contain one - and *only* one - foreign key
Expand Down

0 comments on commit cc405e1

Please sign in to comment.