PostgreSQL admite restricciones de integridad de datos adicionales disponibles en el django.contrib.postgres.constraints módulo. Se agregan en el modelo Meta.constraints opción.

ExclusionConstraint

class ExclusionConstraint(*, name, expressions, index_type=None, condition=None, deferrable=None, include=None, opclasses=())

Crea una restricción de exclusión en la base de datos. Internamente, PostgreSQL implementa restricciones de exclusión mediante índices. El tipo de índice predeterminado es Esencia. Para usarlos, debe activar el extensión btree_gist en PostgreSQL. Puede instalarlo usando el BtreeGistExtension operación de migración.

Si intenta insertar una nueva fila que entra en conflicto con una fila existente, IntegrityError es elevado. Del mismo modo, cuando la actualización entra en conflicto con una fila existente.

name

ExclusionConstraint.name

El nombre de la restricción.

expressions

ExclusionConstraint.expressions

Un iterable de 2 tuplas. El primer elemento es una expresión o string. El segundo elemento es un operador SQL representado como un string. Para evitar errores tipográficos, puede utilizar RangeOperators que mapea los operadores con cadenas. Por ejemplo:

expressions=[('timespan', RangeOperators.ADJACENT_TO),(F('room'), RangeOperators.EQUAL),]

Restricciones a los operadores.

Solo se pueden usar operadores conmutativos en las restricciones de exclusión.

index_type

ExclusionConstraint.index_type

El tipo de índice de la restricción. Los valores aceptados son GIST o SPGIST. La coincidencia no distingue entre mayúsculas y minúsculas. Si no se proporciona, el tipo de índice predeterminado es GIST.

condition

ExclusionConstraint.condition

A Q objeto que especifica la condición para restringir una restricción a un subconjunto de filas. Por ejemplo, condition=Q(cancelled=False).

Estas condiciones tienen las mismas restricciones de base de datos que django.db.models.Index.condition.

deferrable

ExclusionConstraint.deferrable

Nuevo en Django 3.1.

Establezca este parámetro para crear una restricción de exclusión diferible. Los valores aceptados son Deferrable.DEFERRED o Deferrable.IMMEDIATE. Por ejemplo:

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import RangeOperators
from django.db.models import Deferrable


ExclusionConstraint(
    name='exclude_overlapping_deferred',
    expressions=[('timespan', RangeOperators.OVERLAPS),],
    deferrable=Deferrable.DEFERRED,)

Por defecto, las restricciones no se aplazan. Una restricción diferida no se aplicará hasta el final de la transacción. Se aplicará una restricción inmediata inmediatamente después de cada comando.

Advertencia

Las restricciones de exclusión diferida pueden dar lugar a una penalización por desempeño.

include

ExclusionConstraint.include

Nuevo en Django 3.2.

Una lista o tupla de los nombres de los campos que se incluirán en la restricción de exclusión de cobertura como nokey columnas. Esto permite utilizar escaneos de solo índice para consultas que seleccionan solo campos incluidos (include) y filtrar solo por campos indexados (expressions).

include solo es compatible con índices GiST en PostgreSQL 12+.

opclasses

ExclusionConstraint.opclasses

Nuevo en Django 3.2.

Los nombres de la Clases de operador de PostgreSQL utilizar para esta restricción. Si necesita una clase de operador personalizada, debe proporcionar una para cada expresión de la restricción.

Por ejemplo:

ExclusionConstraint(
    name='exclude_overlapping_opclasses',
    expressions=[('circle', RangeOperators.OVERLAPS)],
    opclasses=['circle_ops'],)

crea una restricción de exclusión en circle utilizando circle_ops.

Ejemplos de

El siguiente ejemplo restringe las reservas superpuestas en la misma habitación, sin tener en cuenta las reservas canceladas:

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import DateTimeRangeField, RangeOperators
from django.db import models
from django.db.models import Q

classRoom(models.Model):
    number = models.IntegerField()classReservation(models.Model):
    room = models.ForeignKey('Room', on_delete=models.CASCADE)
    timespan = DateTimeRangeField()
    cancelled = models.BooleanField(default=False)classMeta:
        constraints =[
            ExclusionConstraint(
                name='exclude_overlapping_reservations',
                expressions=[('timespan', RangeOperators.OVERLAPS),('room', RangeOperators.EQUAL),],
                condition=Q(cancelled=False),),]

En caso de que su modelo defina un rango usando dos campos, en lugar de los tipos de rango nativos de PostgreSQL, debe escribir una expresión que use la función equivalente (p. Ej. TsTzRange()) y utilice los delimitadores del campo. La mayoría de las veces, los delimitadores serán '[)', meaning that the lower bound is inclusive and the upper bound is exclusive. You may use the RangeBoundary that provides an expression mapping for the range boundaries. For example:

from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import(
    DateTimeRangeField,
    RangeBoundary,
    RangeOperators,)from django.db import models
from django.db.models import Func, Q


classTsTzRange(Func):
    function ='TSTZRANGE'
    output_field = DateTimeRangeField()classReservation(models.Model):
    room = models.ForeignKey('Room', on_delete=models.CASCADE)
    start = models.DateTimeField()
    end = models.DateTimeField()
    cancelled = models.BooleanField(default=False)classMeta:
        constraints =[
            ExclusionConstraint(
                name='exclude_overlapping_reservations',
                expressions=((TsTzRange('start','end', RangeBoundary()), RangeOperators.OVERLAPS),('room', RangeOperators.EQUAL),),
                condition=Q(cancelled=False),),]