mirror of
https://github.com/django/django.git
synced 2025-03-06 23:42:33 +00:00
Fixed #36075 -- Documented how to introspect composite primary keys.
Document _meta.pk_fields and interactions between Field.primary_key and CompositePrimaryKey. Thanks Mariusz for the review.
This commit is contained in:
parent
f2a1dcaa53
commit
e580926d74
@ -542,18 +542,20 @@ cross-site scripting attack.
|
|||||||
|
|
||||||
If ``True``, this field is the primary key for the model.
|
If ``True``, this field is the primary key for the model.
|
||||||
|
|
||||||
If you don't specify ``primary_key=True`` for any field in your model, Django
|
If you don't specify ``primary_key=True`` for any field in your model and have
|
||||||
will automatically add a field to hold the primary key, so you don't need to
|
not defined a composite primary key, Django will automatically add a field to
|
||||||
set ``primary_key=True`` on any of your fields unless you want to override the
|
hold the primary key. So, you don't need to set ``primary_key=True`` on any of
|
||||||
default primary-key behavior. The type of auto-created primary key fields can
|
your fields unless you want to override the default primary-key behavior. The
|
||||||
be specified per app in :attr:`AppConfig.default_auto_field
|
type of auto-created primary key fields can be specified per app in
|
||||||
<django.apps.AppConfig.default_auto_field>` or globally in the
|
:attr:`AppConfig.default_auto_field <django.apps.AppConfig.default_auto_field>`
|
||||||
:setting:`DEFAULT_AUTO_FIELD` setting. For more, see
|
or globally in the :setting:`DEFAULT_AUTO_FIELD` setting. For more, see
|
||||||
:ref:`automatic-primary-key-fields`.
|
:ref:`automatic-primary-key-fields`.
|
||||||
|
|
||||||
``primary_key=True`` implies :attr:`null=False <Field.null>` and
|
``primary_key=True`` implies :attr:`null=False <Field.null>` and
|
||||||
:attr:`unique=True <Field.unique>`. Only one primary key is allowed on an
|
:attr:`unique=True <Field.unique>`. Only one field per model can set
|
||||||
object.
|
``primary_key=True``. Composite primary keys must be defined using
|
||||||
|
:class:`CompositePrimaryKey` instead of setting this flag to ``True`` for all
|
||||||
|
fields to maintain this invariant.
|
||||||
|
|
||||||
The primary key field is read-only. If you change the value of the primary
|
The primary key field is read-only. If you change the value of the primary
|
||||||
key on an existing object and then save it, a new object will be created
|
key on an existing object and then save it, a new object will be created
|
||||||
@ -562,6 +564,10 @@ alongside the old one.
|
|||||||
The primary key field is set to ``None`` when
|
The primary key field is set to ``None`` when
|
||||||
:meth:`deleting <django.db.models.Model.delete>` an object.
|
:meth:`deleting <django.db.models.Model.delete>` an object.
|
||||||
|
|
||||||
|
.. versionchanged:: 5.2
|
||||||
|
|
||||||
|
The ``CompositePrimaryKey`` field was added.
|
||||||
|
|
||||||
``unique``
|
``unique``
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -13,10 +13,11 @@ understand the capabilities of each model. The API is accessible through
|
|||||||
the ``_meta`` attribute of each model class, which is an instance of an
|
the ``_meta`` attribute of each model class, which is an instance of an
|
||||||
``django.db.models.options.Options`` object.
|
``django.db.models.options.Options`` object.
|
||||||
|
|
||||||
Methods that it provides can be used to:
|
Methods and attributes that it provides can be used to:
|
||||||
|
|
||||||
* Retrieve all field instances of a model
|
* Retrieve all field instances of a model
|
||||||
* Retrieve a single field instance of a model by name
|
* Retrieve a single field instance of a model by name
|
||||||
|
* Retrieve all fields that compose the primary key of a model
|
||||||
|
|
||||||
.. _model-meta-field-api:
|
.. _model-meta-field-api:
|
||||||
|
|
||||||
@ -118,3 +119,42 @@ Retrieving all field instances of a model
|
|||||||
<django.db.models.fields.DateTimeField: date_joined>,
|
<django.db.models.fields.DateTimeField: date_joined>,
|
||||||
<django.db.models.fields.related.ManyToManyField: groups>,
|
<django.db.models.fields.related.ManyToManyField: groups>,
|
||||||
<django.db.models.fields.related.ManyToManyField: user_permissions>)
|
<django.db.models.fields.related.ManyToManyField: user_permissions>)
|
||||||
|
|
||||||
|
Retrieving fields composing the primary key of a model
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 5.2
|
||||||
|
|
||||||
|
.. attribute:: Options.pk_fields
|
||||||
|
|
||||||
|
Returns a list of the fields composing the primary key of a model.
|
||||||
|
|
||||||
|
When a :class:`composite primary key <django.db.models.CompositePrimaryKey>`
|
||||||
|
is defined on a model it will contain all the
|
||||||
|
:class:`fields <django.db.models.Field>` referenced by it.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class TenantUser(models.Model):
|
||||||
|
pk = models.CompositePrimaryKey("tenant_id", "id")
|
||||||
|
tenant_id = models.IntegerField()
|
||||||
|
id = models.IntegerField()
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> TenantUser._meta.pk_fields
|
||||||
|
[
|
||||||
|
<django.db.models.fields.IntegerField: tenant_id>,
|
||||||
|
<django.db.models.fields.IntegerField: id>
|
||||||
|
]
|
||||||
|
|
||||||
|
Otherwise it will contain the single field declared as the
|
||||||
|
:attr:`primary key <django.db.models.Field.primary_key>` of the model.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> User._meta.pk_fields
|
||||||
|
[<django.db.models.fields.AutoField: id>]
|
||||||
|
@ -185,3 +185,52 @@ field :exc:`.FieldError`.
|
|||||||
This is also true of composite primary keys. Hence, you may want to set
|
This is also true of composite primary keys. Hence, you may want to set
|
||||||
:attr:`.Field.editable` to ``False`` on all primary key fields to exclude
|
:attr:`.Field.editable` to ``False`` on all primary key fields to exclude
|
||||||
them from ModelForms.
|
them from ModelForms.
|
||||||
|
|
||||||
|
Building composite primary key ready applications
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
Prior to the introduction of composite primary keys, the single field composing
|
||||||
|
the primary key of a model could be retrieved by introspecting the
|
||||||
|
:attr:`primary key <django.db.models.Field.primary_key>` attribute of its
|
||||||
|
fields:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> pk_field = None
|
||||||
|
>>> for field in Product._meta.get_fields():
|
||||||
|
... if field.primary_key:
|
||||||
|
... pk_field = field
|
||||||
|
... break
|
||||||
|
...
|
||||||
|
>>> pk_field
|
||||||
|
<django.db.models.fields.AutoField: id>
|
||||||
|
|
||||||
|
Now that a primary key can be composed of multiple fields the
|
||||||
|
:attr:`primary key <django.db.models.Field.primary_key>` attribute can no
|
||||||
|
longer be relied upon to identify members of the primary key as it will be set
|
||||||
|
to ``False`` to maintain the invariant that at most one field per model will
|
||||||
|
have this attribute set to ``True``:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> pk_fields = []
|
||||||
|
>>> for field in OrderLineItem._meta.get_fields():
|
||||||
|
... if field.primary_key:
|
||||||
|
... pk_fields.append(field)
|
||||||
|
...
|
||||||
|
>>> pk_fields
|
||||||
|
[]
|
||||||
|
|
||||||
|
In order to build application code that properly handles composite primary
|
||||||
|
keys the :attr:`_meta.pk_fields <django.db.models.options.Options.pk_fields>`
|
||||||
|
attribute should be used instead:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> Product._meta.pk_fields
|
||||||
|
[<django.db.models.fields.AutoField: id>]
|
||||||
|
>>> OrderLineItem._meta.pk_fields
|
||||||
|
[
|
||||||
|
<django.db.models.fields.ForeignKey: product>,
|
||||||
|
<django.db.models.fields.ForeignKey: order>
|
||||||
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user