PostgreSQL-specifika databasbegränsningar¶
PostgreSQL stöder ytterligare dataintegritetsbegränsningar tillgängliga från modulen django.contrib.postgres.constraints
. De läggs till i modellen Meta.constraints
alternativ.
Uteslutningsbegränsning
¶
- class ExclusionConstraint(*, name, expressions, index_type=None, condition=None, deferrable=None, include=None, violation_error_code=None, violation_error_message=None)[source]¶
Skapar en uteslutningsbegränsning i databasen. Internt implementerar PostgreSQL uteslutningsbegränsningar med hjälp av index. Standardindextypen är GiST. För att använda dem måste du aktivera btree_gist-tillägget på PostgreSQL. Du kan installera den med hjälp av
BtreeGistExtension
migreringsoperation.Om du försöker infoga en ny rad som står i konflikt med en befintlig rad, uppstår ett
IntegrityError
. På samma sätt när en uppdatering står i konflikt med en befintlig rad.Begränsningar för uteslutning kontrolleras under modellvalidering.
namn
¶
- ExclusionConstraint.name¶
uttryck
¶
- ExclusionConstraint.expressions¶
En iterabel med 2-tuples. Det första elementet är ett uttryck eller en sträng. Det andra elementet är en SQL-operator som representeras som en sträng. För att undvika skrivfel kan du använda RangeOperators
som mappar operatörerna med strängar. Till exempel:
expressions = [
("timespan", RangeOperators.ADJACENT_TO),
(F("room"), RangeOperators.EQUAL),
]
Begränsningar för operatörer.
Endast kommutativa operatorer kan användas i uteslutningsbegränsningar.
Uttrycket OpClass()
kan användas för att ange en anpassad operatorklass för begränsningsuttrycken. Till exempel:
expressions = [
(OpClass("circle", name="circle_ops"), RangeOperators.OVERLAPS),
]
skapar en uteslutningsbegränsning på circle
med hjälp av circle_ops
.
index_typ
¶
- ExclusionConstraint.index_type¶
Indextypen för begränsningen. Accepterade värden är GIST
eller SPGIST
. Matchningen är okänslig för skiftlägesskillnader. Om det inte anges är standardindextypen GIST
.
villkor
¶
- ExclusionConstraint.condition¶
Ett Q
-objekt som anger villkoret för att begränsa en begränsning till en delmängd av rader. Till exempel:, condition=Q(cancelled=False)
.
Dessa villkor har samma databasrestriktioner som django.db.models.Index.condition
.
deferrable
¶
- ExclusionConstraint.deferrable¶
Ange denna parameter för att skapa en uppskjutbar uteslutningsbegränsning. Accepterade värden är Deferrable.DEFERRED
eller Deferrable.IMMEDIATE
. Till exempel:
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,
)
Som standard är begränsningar inte uppskjutna. En uppskjuten begränsning kommer inte att verkställas förrän i slutet av transaktionen. En omedelbar begränsning kommer att verkställas omedelbart efter varje kommando.
Varning
Uppskjutna uteslutningsbegränsningar kan leda till en ”prestandaförlust” <https://www.postgresql.org/docs/current/sql-createtable.html#id-1.9.3.85.9.4>`_.
inkludera
¶
- ExclusionConstraint.include¶
En lista eller tupel med namnen på de fält som ska ingå i det täckande uteslutningsvillkoret som icke-nyckelkolumner. Detta gör det möjligt att använda skanningar med enbart index för frågor som endast väljer inkluderade fält (include
) och endast filtrerar efter indexerade fält (expressions
).
include
stöds för GiST-index. PostgreSQL 14+ stöder också include
för SP-GiST-index.
Felkod för överträdelse
¶
- ExclusionConstraint.violation_error_code¶
Den felkod som används när ValidationError
uppstår under modellvalidering. Standardvärdet är None
.
avvikelse_felmeddelande
¶
Det felmeddelande som används när ValidationError
uppstår under modellvalidering. Standardvärdet är BaseConstraint.violation_error_message
.
Exempel¶
Följande exempel begränsar överlappande bokningar i samma rum, utan att ta hänsyn till avbokade bokningar:
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
class Room(models.Model):
number = models.IntegerField()
class Reservation(models.Model):
room = models.ForeignKey("Room", on_delete=models.CASCADE)
timespan = DateTimeRangeField()
cancelled = models.BooleanField(default=False)
class Meta:
constraints = [
ExclusionConstraint(
name="exclude_overlapping_reservations",
expressions=[
("timespan", RangeOperators.OVERLAPS),
("room", RangeOperators.EQUAL),
],
condition=Q(cancelled=False),
),
]
Om din modell definierar ett intervall med två fält, istället för de ursprungliga PostgreSQL-intervalltyperna, bör du skriva ett uttryck som använder motsvarande funktion (t.ex. `` TsTzRange() ) och använda avgränsarna för fältet. Oftast kommer avgränsarna att vara ``'[)'
, vilket innebär att den nedre gränsen är inkluderande och den övre gränsen är exkluderande. Du kan använda RangeBoundary
som tillhandahåller en uttrycksmappning för intervallgränserna. Till exempel:
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
class TsTzRange(Func):
function = "TSTZRANGE"
output_field = DateTimeRangeField()
class Reservation(models.Model):
room = models.ForeignKey("Room", on_delete=models.CASCADE)
start = models.DateTimeField()
end = models.DateTimeField()
cancelled = models.BooleanField(default=False)
class Meta:
constraints = [
ExclusionConstraint(
name="exclude_overlapping_reservations",
expressions=[
(
TsTzRange("start", "end", RangeBoundary()),
RangeOperators.OVERLAPS,
),
("room", RangeOperators.EQUAL),
],
condition=Q(cancelled=False),
),
]