Bestellungsliste

Eine benutzerdefinierte Liste, die Index-/Positionsinformationen für enthaltene Elemente verwaltet.

Autor:

Jason Kirtland

orderinglist ist ein Helfer für mutierbare geordnete Beziehungen. Es wird Listenoperationen abfangen, die auf einer von relationship() verwalteten Sammlung durchgeführt werden, und automatisch Änderungen der Listenposition auf ein Ziel-Skalarattribut synchronisieren.

Beispiel: Eine slide-Tabelle, wobei jede Zeile auf null oder mehr Einträge in einer zugehörigen bullet-Tabelle verweist. Die Bulletpoints innerhalb einer Folie werden basierend auf dem Wert der position-Spalte in der bullet-Tabelle in Ordnung angezeigt. Wenn Einträge im Speicher neu geordnet werden, sollte der Wert des position-Attributs aktualisiert werden, um die neue Sortierreihenfolge widerzuspiegeln.

Base = declarative_base()


class Slide(Base):
    __tablename__ = "slide"

    id = Column(Integer, primary_key=True)
    name = Column(String)

    bullets = relationship("Bullet", order_by="Bullet.position")


class Bullet(Base):
    __tablename__ = "bullet"
    id = Column(Integer, primary_key=True)
    slide_id = Column(Integer, ForeignKey("slide.id"))
    position = Column(Integer)
    text = Column(String)

Das Standard-Relationship-Mapping erzeugt ein Listen-ähnliches Attribut auf jeder Slide, das alle zugehörigen Bullet-Objekte enthält, aber das Bewältigen von Änderungen der Reihenfolge wird nicht automatisch gehandhabt. Beim Anhängen eines Bullet an Slide.bullets bleibt das Bullet.position-Attribut auf "nicht gesetzt", bis es manuell zugewiesen wird. Wenn der Bullet in die Mitte der Liste eingefügt wird, müssen die folgenden Bullet-Objekte ebenfalls neu nummeriert werden.

Das OrderingList-Objekt automatisiert diese Aufgabe und verwaltet das position-Attribut auf allen Bullet-Objekten in der Sammlung. Es wird mit der ordering_list()-Fabrik konstruiert.

from sqlalchemy.ext.orderinglist import ordering_list

Base = declarative_base()


class Slide(Base):
    __tablename__ = "slide"

    id = Column(Integer, primary_key=True)
    name = Column(String)

    bullets = relationship(
        "Bullet",
        order_by="Bullet.position",
        collection_class=ordering_list("position"),
    )


class Bullet(Base):
    __tablename__ = "bullet"
    id = Column(Integer, primary_key=True)
    slide_id = Column(Integer, ForeignKey("slide.id"))
    position = Column(Integer)
    text = Column(String)

Mit der obigen Zuordnung wird das Bullet.position-Attribut verwaltet.

s = Slide()
s.bullets.append(Bullet())
s.bullets.append(Bullet())
s.bullets[1].position
>>> 1
s.bullets.insert(1, Bullet())
s.bullets[2].position
>>> 2

Der OrderingList-Konstrukt funktioniert nur mit **Änderungen** an einer Sammlung und nicht mit der initialen Ladung aus der Datenbank. Es erfordert, dass die Liste beim Laden sortiert ist. Daher stellen Sie sicher, dass Sie order_by auf dem relationship() auf das Ziel-Sortierattribut setzen, damit die Reihenfolge beim ersten Laden korrekt ist.

Warnung

OrderingList bietet nur begrenzte Funktionalität, wenn eine Primärschlüsselspalte oder eine eindeutige Spalte das Ziel der Sortierung ist. Vorgänge, die nicht unterstützt werden oder problematisch sind, umfassen:

  • zwei Einträge müssen ihre Werte tauschen. Dies wird nicht direkt im Fall eines Primärschlüssels oder einer eindeutigen Beschränkung unterstützt, da dies bedeutet, dass mindestens eine Zeile vorübergehend entfernt werden muss oder zu einem dritten, neutralen Wert geändert werden muss, während der Wechsel stattfindet.

  • Ein Eintrag muss gelöscht werden, um Platz für einen neuen Eintrag zu schaffen. SQLAlchemys Unit of Work führt alle INSERTs vor den DELETEs innerhalb eines einzigen Flushes aus. Im Fall eines Primärschlüssels wird ein INSERT/DELETE desselben Primärschlüssels gegen eine UPDATE-Anweisung getauscht, um die Auswirkungen dieser Einschränkung zu verringern. Dies geschieht jedoch nicht für eine UNIQUE-Spalte. Eine zukünftige Funktion wird es ermöglichen, das Verhalten "DELETE vor INSERT" zu ermöglichen, wodurch diese Einschränkung gelindert wird, obwohl diese Funktion eine explizite Konfiguration auf Mapper-Ebene für Spaltengruppen erfordert, die auf diese Weise behandelt werden sollen.

ordering_list() nimmt den Namen des Sortierattributs des zugehörigen Objekts als Argument. Standardmäßig wird der nullbasierte ganzzahlige Index der Position des Objekts in der ordering_list() mit dem Sortierattribut synchronisiert: Index 0 erhält Position 0, Index 1 Position 1, usw. Um die Nummerierung bei 1 oder einer anderen Ganzzahl zu starten, geben Sie count_from=1 an.

API-Referenz

Objektname Beschreibung

count_from_0(index, collection)

Nummerierungsfunktion: aufeinanderfolgende ganze Zahlen beginnend bei 0.

count_from_1(index, collection)

Nummerierungsfunktion: aufeinanderfolgende ganze Zahlen beginnend bei 1.

count_from_n_factory(start)

Nummerierungsfunktion: aufeinanderfolgende ganze Zahlen beginnend bei einem beliebigen Startwert.

ordering_list(attr[, count_from, ordering_func, reorder_on_append])

Bereitet eine OrderingList-Fabrik für die Verwendung in Mapper-Definitionen vor.

OrderingList

Eine benutzerdefinierte Liste, die Positionsinformationen für ihre Kinder verwaltet.

Funktion sqlalchemy.ext.orderinglist.ordering_list(attr: str, count_from: int | None = None, ordering_func: Callable[[int, Sequence[_T]], int] | None = None, reorder_on_append: bool = False) Callable[[], OrderingList]

Bereitet eine OrderingList-Fabrik für die Verwendung in Mapper-Definitionen vor.

Gibt ein Objekt zurück, das als Argument für die collection_class-Option einer Mapper-Beziehung verwendet werden kann. Z.B.

from sqlalchemy.ext.orderinglist import ordering_list


class Slide(Base):
    __tablename__ = "slide"

    id = Column(Integer, primary_key=True)
    name = Column(String)

    bullets = relationship(
        "Bullet",
        order_by="Bullet.position",
        collection_class=ordering_list("position"),
    )
Parameter:
  • attr – Name des zugeordneten Attributs zur Speicherung und zum Abruf von Ordnungsinformationen.

  • count_from – Richten Sie eine ganzzahlbasierte Ordnung ein, die bei count_from beginnt. Zum Beispiel würde ordering_list('pos', count_from=1) eine 1-basierte Liste in SQL erstellen und den Wert in der Spalte 'pos' speichern. Wird ignoriert, wenn ordering_func angegeben ist.

Zusätzliche Argumente werden an den Konstruktor von OrderingList übergeben.

Funktion sqlalchemy.ext.orderinglist.count_from_0(index, collection)

Nummerierungsfunktion: aufeinanderfolgende ganze Zahlen beginnend bei 0.

Funktion sqlalchemy.ext.orderinglist.count_from_1(index, collection)

Nummerierungsfunktion: aufeinanderfolgende ganze Zahlen beginnend bei 1.

Funktion sqlalchemy.ext.orderinglist.count_from_n_factory(start)

Nummerierungsfunktion: aufeinanderfolgende ganze Zahlen beginnend bei einem beliebigen Startwert.

Klasse sqlalchemy.ext.orderinglist.OrderingList

Eine benutzerdefinierte Liste, die Positionsinformationen für ihre Kinder verwaltet.

Das OrderingList-Objekt wird normalerweise mit der Fabrikfunktion ordering_list() eingerichtet, die in Verbindung mit der Funktion relationship() verwendet wird.

Klassensignatur

class sqlalchemy.ext.orderinglist.OrderingList (builtins.list, typing.Generic)

Methode sqlalchemy.ext.orderinglist.OrderingList.__init__(ordering_attr: str | None = None, ordering_func: Callable[[int, Sequence[_T]], int] | None = None, reorder_on_append: bool = False)

Eine benutzerdefinierte Liste, die Positionsinformationen für ihre Kinder verwaltet.

OrderingList ist eine Listenimplementierung vom Typ collection_class, die die Position in einer Python-Liste mit einem Positionsattribut auf den gemappten Objekten synchronisiert.

Diese Implementierung basiert darauf, dass die Liste in der richtigen Reihenfolge beginnt. Stellen Sie also **sicher**, dass Sie einen order_by für Ihre Beziehung angeben.

Parameter:
  • ordering_attr – Name des Attributs, das die Reihenfolge des Objekts in der Beziehung speichert.

  • ordering_func

    Optional. Eine Funktion, die die Position in der Python-Liste auf einen Wert abbildet, der im ordering_attr gespeichert werden soll. Die zurückgegebenen Werte sind normalerweise (müssen aber nicht!) ganze Zahlen.

    Eine ordering_func wird mit zwei Positionsargumenten aufgerufen: dem Index des Elements in der Liste und der Liste selbst.

    Wenn weggelassen, werden die Indizes der Python-Liste für die Attributwerte verwendet. Zwei grundlegende vordefinierte Nummerierungsfunktionen sind in diesem Modul enthalten: count_from_0 und count_from_1. Für exotischere Beispiele wie schrittweise Nummerierung, alphabetische und Fibonacci-Nummerierung siehe die Unit-Tests.

  • reorder_on_append

    Standardmäßig False. Wenn ein Objekt mit einem vorhandenen (nicht-None-)Ordnungswert angehängt wird, wird dieser Wert unverändert gelassen, es sei denn, reorder_on_append ist true. Dies ist eine Optimierung, um eine Vielzahl gefährlicher unerwarteter Datenbankaktualisierungen zu vermeiden.

    SQLAlchemy fügt Instanzen beim Laden Ihres Objekts über append() zur Liste hinzu. Wenn aus irgendeinem Grund die Ergebnismenge aus der Datenbank einen Schritt in der Reihenfolge überspringt (z. B. Zeile '1' fehlt, aber Sie erhalten '2', '3' und '4'), würde reorder_on_append=True die Elemente sofort in '1', '2', '3' neu nummerieren. Wenn mehrere Sitzungen Änderungen vornehmen, von denen einige diese Sammlung auch nur im Vorbeigehen laden, würden alle Sitzungen versuchen, die Nummerierung bei ihren Commits zu "bereinigen", was dazu führen könnte, dass alle außer einer mit einem Fehler bei gleichzeitiger Änderung fehlschlagen.

    Es wird empfohlen, dies beim Standardwert von False zu belassen und nur reorder() aufzurufen, wenn Sie append()-Operationen mit zuvor geordneten Instanzen durchführen oder wenn Sie einige Wartungsarbeiten nach manuellen SQL-Operationen durchführen.

Methode sqlalchemy.ext.orderinglist.OrderingList.append(entity)

Objekt am Ende der Liste anhängen.

Methode sqlalchemy.ext.orderinglist.OrderingList.insert(index, entity)

Objekt vor dem Index einfügen.

Methode sqlalchemy.ext.orderinglist.OrderingList.pop(index=-1)

Element am Index entfernen und zurückgeben (standardmäßig das letzte).

Löst IndexError aus, wenn die Liste leer ist oder der Index außerhalb des Bereichs liegt.

Methode sqlalchemy.ext.orderinglist.OrderingList.remove(entity)

Erstes Vorkommen des Werts entfernen.

Löst ValueError aus, wenn der Wert nicht vorhanden ist.

Methode sqlalchemy.ext.orderinglist.OrderingList.reorder() None

Ordnung für die gesamte Sammlung synchronisieren.

Durchläuft die Liste und stellt sicher, dass jedes Objekt über genaue Ordnungsinformationen verfügt.