Después de mucho batallar pudimos hallar la solución de esta escollo que tantos lectores de esta web presentan. Si tienes alguna información que aportar no dejes de aportar tu conocimiento.
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),),]
Reseñas y valoraciones del tutorial
Al final de la página puedes encontrar las críticas de otros usuarios, tú asimismo tienes la libertad de mostrar el tuyo si te apetece.