django/django

View on GitHub
docs/ref/models/constraints.txt

Summary

Maintainability
Test Coverage
=====================
Constraints reference
=====================

.. module:: django.db.models.constraints

.. currentmodule:: django.db.models

The classes defined in this module create database constraints. They are added
in the model :attr:`Meta.constraints <django.db.models.Options.constraints>`
option.

.. admonition:: Referencing built-in constraints

    Constraints are defined in ``django.db.models.constraints``, but for
    convenience they're imported into :mod:`django.db.models`. The standard
    convention is to use ``from django.db import models`` and refer to the
    constraints as ``models.<Foo>Constraint``.

.. admonition:: Constraints in abstract base classes

    You must always specify a unique name for the constraint. As such, you
    cannot normally specify a constraint on an abstract base class, since the
    :attr:`Meta.constraints <django.db.models.Options.constraints>` option is
    inherited by subclasses, with exactly the same values for the attributes
    (including ``name``) each time. To work around name collisions, part of the
    name may contain ``'%(app_label)s'`` and ``'%(class)s'``, which are
    replaced, respectively, by the lowercased app label and class name of the
    concrete model. For example ``CheckConstraint(condition=Q(age__gte=18),
    name='%(app_label)s_%(class)s_is_adult')``.

.. admonition:: Validation of Constraints

    Constraints are checked during the :ref:`model validation
    <validating-objects>`.

``BaseConstraint``
==================

.. class:: BaseConstraint(* name, violation_error_code=None, violation_error_message=None)

    Base class for all constraints. Subclasses must implement
    ``constraint_sql()``, ``create_sql()``, ``remove_sql()`` and
    ``validate()`` methods.

    .. deprecated:: 5.0

        Support for passing positional arguments is deprecated.

All constraints have the following parameters in common:

``name``
--------

.. attribute:: BaseConstraint.name

The name of the constraint. You must always specify a unique name for the
constraint.

``violation_error_code``
------------------------

.. versionadded:: 5.0

.. attribute:: BaseConstraint.violation_error_code

The error code used when ``ValidationError`` is raised during
:ref:`model validation <validating-objects>`. Defaults to ``None``.

``violation_error_message``
---------------------------

.. attribute:: BaseConstraint.violation_error_message

The error message used when ``ValidationError`` is raised during
:ref:`model validation <validating-objects>`. Defaults to
``"Constraint ā€œ%(name)sā€ is violated."``.

``validate()``
--------------

.. method:: BaseConstraint.validate(model, instance, exclude=None, using=DEFAULT_DB_ALIAS)

Validates that the constraint, defined on ``model``, is respected on the
``instance``. This will do a query on the database to ensure that the
constraint is respected. If fields in the ``exclude`` list are needed to
validate the constraint, the constraint is ignored.

Raise a ``ValidationError`` if the constraint is violated.

This method must be implemented by a subclass.

``CheckConstraint``
===================

.. class:: CheckConstraint(*, condition, name, violation_error_code=None, violation_error_message=None)

    Creates a check constraint in the database.

``condition``
-------------

.. attribute:: CheckConstraint.condition

A :class:`Q` object or boolean :class:`~django.db.models.Expression` that
specifies the conditional check you want the constraint to enforce.

For example, ``CheckConstraint(condition=Q(age__gte=18), name='age_gte_18')``
ensures the age field is never less than 18.

.. admonition:: Expression order

    ``Q`` argument order is not necessarily preserved, however the order of
    ``Q`` expressions themselves are preserved. This may be important for
    databases that preserve check constraint expression order for performance
    reasons. For example, use the following format if order matters::

        CheckConstraint(
            condition=Q(age__gte=18) & Q(expensive_check=condition),
            name="age_gte_18_and_others",
        )

.. admonition:: Oracle < 23c

    Checks with nullable fields on Oracle < 23c must include a condition
    allowing for ``NULL`` values in order for :meth:`~BaseConstraint.validate`
    to behave the same as check constraints validation. For example, if ``age``
    is a nullable field::

        CheckConstraint(condition=Q(age__gte=18) | Q(age__isnull=True), name="age_gte_18")

.. deprecated:: 5.1

    The ``check`` attribute is deprecated in favor of ``condition``.

``UniqueConstraint``
====================

.. class:: UniqueConstraint(*expressions, fields=(), name=None, condition=None, deferrable=None, include=None, opclasses=(), nulls_distinct=None, violation_error_code=None, violation_error_message=None)

    Creates a unique constraint in the database.

``expressions``
---------------

.. attribute:: UniqueConstraint.expressions

Positional argument ``*expressions`` allows creating functional unique
constraints on expressions and database functions.

For example::

    UniqueConstraint(Lower("name").desc(), "category", name="unique_lower_name_category")

creates a unique constraint on the lowercased value of the ``name`` field in
descending order and the ``category`` field in the default ascending order.

Functional unique constraints have the same database restrictions as
:attr:`Index.expressions`.

``fields``
----------

.. attribute:: UniqueConstraint.fields

A list of field names that specifies the unique set of columns you want the
constraint to enforce.

For example, ``UniqueConstraint(fields=['room', 'date'],
name='unique_booking')`` ensures each room can only be booked once for each
date.

``condition``
-------------

.. attribute:: UniqueConstraint.condition

A :class:`Q` object that specifies the condition you want the constraint to
enforce.

For example::

    UniqueConstraint(fields=["user"], condition=Q(status="DRAFT"), name="unique_draft_user")

ensures that each user only has one draft.

These conditions have the same database restrictions as
:attr:`Index.condition`.

``deferrable``
--------------

.. attribute:: UniqueConstraint.deferrable

Set this parameter to create a deferrable unique constraint. Accepted values
are ``Deferrable.DEFERRED`` or ``Deferrable.IMMEDIATE``. For example::

    from django.db.models import Deferrable, UniqueConstraint

    UniqueConstraint(
        name="unique_order",
        fields=["order"],
        deferrable=Deferrable.DEFERRED,
    )

By default constraints are not deferred. A deferred constraint will not be
enforced until the end of the transaction. An immediate constraint will be
enforced immediately after every command.

.. admonition:: MySQL, MariaDB, and SQLite.

    Deferrable unique constraints are ignored on MySQL, MariaDB, and SQLite as
    neither supports them.

.. warning::

    Deferred unique constraints may lead to a `performance penalty
    <https://www.postgresql.org/docs/current/sql-createtable.html#id-1.9.3.85.9.4>`_.

``include``
-----------

.. attribute:: UniqueConstraint.include

A list or tuple of the names of the fields to be included in the covering
unique index as non-key columns. This allows index-only scans to be used for
queries that select only included fields (:attr:`~UniqueConstraint.include`)
and filter only by unique fields (:attr:`~UniqueConstraint.fields`).

For example::

    UniqueConstraint(name="unique_booking", fields=["room", "date"], include=["full_name"])

will allow filtering on ``room`` and ``date``, also selecting ``full_name``,
while fetching data only from the index.

Unique constraints with non-key columns are ignored for databases besides
PostgreSQL.

Non-key columns have the same database restrictions as :attr:`Index.include`.


``opclasses``
-------------

.. attribute:: UniqueConstraint.opclasses

The names of the `PostgreSQL operator classes
<https://www.postgresql.org/docs/current/indexes-opclass.html>`_ to use for
this unique index. If you require a custom operator class, you must provide one
for each field in the index.

For example::

    UniqueConstraint(
        name="unique_username", fields=["username"], opclasses=["varchar_pattern_ops"]
    )

creates a unique index on ``username`` using ``varchar_pattern_ops``.

``opclasses`` are ignored for databases besides PostgreSQL.

``nulls_distinct``
------------------

.. versionadded:: 5.0

.. attribute:: UniqueConstraint.nulls_distinct

Whether rows containing ``NULL`` values covered by the unique constraint should
be considered distinct from each other. The default value is ``None`` which
uses the database default which is ``True`` on most backends.

For example::

    UniqueConstraint(name="ordering", fields=["ordering"], nulls_distinct=False)

creates a unique constraint that only allows one row to store a ``NULL`` value
in the ``ordering`` column.

Unique constraints with ``nulls_distinct`` are ignored for databases besides
PostgreSQL 15+.

``violation_error_code``
------------------------

.. versionadded:: 5.0

.. attribute:: UniqueConstraint.violation_error_code

The error code used when ``ValidationError`` is raised during
:ref:`model validation <validating-objects>`. Defaults to ``None``.

This code is *not used* for :class:`UniqueConstraint`\s with
:attr:`~UniqueConstraint.fields` and without a
:attr:`~UniqueConstraint.condition`. Such :class:`~UniqueConstraint`\s have the
same error code as constraints defined with :attr:`.Field.unique` or in
:attr:`Meta.unique_together <django.db.models.Options.constraints>`.

``violation_error_message``
---------------------------

.. attribute:: UniqueConstraint.violation_error_message

The error message used when ``ValidationError`` is raised during
:ref:`model validation <validating-objects>`. Defaults to
:attr:`.BaseConstraint.violation_error_message`.

This message is *not used* for :class:`UniqueConstraint`\s with
:attr:`~UniqueConstraint.fields` and without a
:attr:`~UniqueConstraint.condition`. Such :class:`~UniqueConstraint`\s show the
same message as constraints defined with
:attr:`.Field.unique` or in
:attr:`Meta.unique_together <django.db.models.Options.constraints>`.