PostgreSQL-specifika databasbegränsningarLink to this heading

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änsningLink to this heading

class ExclusionConstraint(*, name, expressions, index_type=None, condition=None, deferrable=None, include=None, violation_error_code=None, violation_error_message=None)Link to this definition

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.

namnLink to this heading

ExclusionConstraint.nameLink to this definition

Se BaseConstraint.name.

uttryckLink to this heading

ExclusionConstraint.expressionsLink to this definition

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:

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

Uttrycket OpClass() kan användas för att ange en anpassad operatorklass för begränsningsuttrycken. Till exempel:

Code
expressions = [
    (OpClass("circle", name="circle_ops"), RangeOperators.OVERLAPS),
]

skapar en uteslutningsbegränsning på circle med hjälp av circle_ops.

index_typLink to this heading

ExclusionConstraint.index_typeLink to this definition

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.

villkorLink to this heading

ExclusionConstraint.conditionLink to this definition

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.

deferrableLink to this heading

ExclusionConstraint.deferrableLink to this definition

Ange denna parameter för att skapa en uppskjutbar uteslutningsbegränsning. Accepterade värden är Deferrable.DEFERRED eller Deferrable.IMMEDIATE. Till exempel:

Code
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.

inkluderaLink to this heading

ExclusionConstraint.includeLink to this definition

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ädelseLink to this heading

ExclusionConstraint.violation_error_codeLink to this definition

Den felkod som används när ValidationError uppstår under modellvalidering. Standardvärdet är None.

avvikelse_felmeddelandeLink to this heading

Det felmeddelande som används när ValidationError uppstår under modellvalidering. Standardvärdet är BaseConstraint.violation_error_message.

ExempelLink to this heading

Följande exempel begränsar överlappande bokningar i samma rum, utan att ta hänsyn till avbokade bokningar:

Code
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:

Code
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),
            ),
        ]