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
BtreeGistExtensionmigreringsoperation.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),
),
]