[PYTHON] So erstellen Sie eine Eigenschaft von Beziehungen, die durch bestimmte Bedingungen vorab abgerufen werden kann

So erstellen Sie eine Eigenschaft von Beziehungen, die durch bestimmte Bedingungen vorab abgerufen werden kann

Ich möchte eine prefetch_related-Beziehung festlegen, die unter bestimmten Bedingungen auf ein bestimmtes Modell eingegrenzt werden kann.

Einführung

Angenommen, es gibt Modelle X und Y mit einer M: N-Beziehung.

class X(models.Model):
    name = models.CharField(max_length=32, null=False, default="")
    ctime = models.DateTimeField(auto_now_add=True, null=False)
    is_valid = models.BooleanField(default=True, null=False)


class Y(models.Model):
    name = models.CharField(max_length=32, null=False, default="")
    ctime = models.DateTimeField(auto_now_add=True, null=False)
    is_valid = models.BooleanField(default=True, null=False)

    xs = models.ManyToManyField(X, related_name="ys")

Ich möchte die Beziehung von X durch die folgenden Bedingungen für ein Objekt mit Y eingrenzen lassen.

--bestellen nach -ctime --filter mit is_valid = True

Wenn Sie es direkt aufschreiben, sieht es wie folgt aus

y.xs.all().filter(is_valid=True).order_by("-ctime")

Bedarf

Wenn Sie beispielsweise die Beziehung, die die obigen Bedingungen erfüllt, als "valid_xs" bezeichnen, können Sie sie wie folgt verwenden.

#von der Instanz
y.valid_xs  # =>  [X,X,X,X]

# prefetch_related (N+1 Abfrage kann unterdrückt werden)
for y in Y.objects.all().prefetch_related("valid_xs"):
    print(y, y.valid_xs)

Implementierung

prefetch_related (" valid_xs ") war schwierig, daher ist prefetch_related (Y.prefetch_valid_xs ()) in Ordnung.

Definieren Sie die folgende Funktion.

def custom_relation_property(getter):
    name = getter.__name__
    cache_name = "_{}".format(name)

    def _getter(self):
        result = getattr(self, cache_name, None)
        if result is None:
            result = getter(self)
            setattr(self, cache_name, result)
        return result

    def _setter(self, value):
        setattr(self, cache_name, value)

    prop = property(_getter, _setter, doc=_getter.__doc__)
    return prop

Ändern Sie die Definition des Modells wie folgt

class X(models.Model):
    name = models.CharField(max_length=32, null=False, default="")
    ctime = models.DateTimeField(auto_now_add=True, null=False)
    is_valid = models.BooleanField(default=True, null=False)

    @classmethod
    def valid_set(cls, qs=None):
        if qs is None:
            qs = cls.objects.all()
        return qs.filter(is_valid=True).order_by("-ctime")

class Y(models.Model):
    name = models.CharField(max_length=32, null=False, default="")
    ctime = models.DateTimeField(auto_now_add=True, null=False)
    is_valid = models.BooleanField(default=True, null=False)

    xs = models.ManyToManyField(X, related_name="ys")

    @custom_relation_property
    def valid_xs(self):
        return X.valid_set(self.xs.all())

    @classmethod
    def prefetch_valid_xs(cls):
        return Prefetch("xs", queryset=X.valid_set(), to_attr="valid_xs")

Es kann wie folgt verwendet werden.

#von der Instanz
Y.objects.get(id=1).valid_xs  # => [X,X,X,X]

# prefetch_related (N+1 Abfrage kann unterdrückt werden)
for y in Y.objects.all().prefetch_related(Y.prefetch_valid_xs()):
    print(y, y.valid_xs)

Referenz

Es ist ein Blog, den ich selbst geschrieben habe.

Recommended Posts

So erstellen Sie eine Eigenschaft von Beziehungen, die durch bestimmte Bedingungen vorab abgerufen werden kann
So installieren Sie die Python-Bibliothek, die von Pharmaunternehmen verwendet werden kann
Wie man einen Janken-Bot macht, der leicht bewegt werden kann (Kommentar)
So erstellen Sie einen Wrapper, der die Signatur der zu umschließenden Funktion beibehält
Ich möchte eine Prioritätswarteschlange erstellen, die mit Python (2.7) aktualisiert werden kann.
So erstellen Sie einen USB-Stick, mit dem Linux- und Win10-Installer und Winpe UEFI starten können
So extrahieren Sie Bedingungen (erwerben Sie alle Elemente der Gruppe, die die Bedingungen erfüllen) für Gruppe für Gruppe
[Python] So erstellen Sie eine Liste von Zeichenfolgen Zeichen für Zeichen
Implementieren Sie einen Thread, der durch Ausnutzen von Yield angehalten werden kann
So starten Sie einen einfachen WEB-Server, der CGI von PHP und Python ausführen kann
So richten Sie einen einfachen SMTP-Server ein, der lokal in Python getestet werden kann
So zeigen Sie Hover-Text und Text an, der ausgeführt werden kann, indem Sie mit dem Minecraft-Plug-In klicken
[Python] Ein Programm, um die Anzahl der Äpfel und Orangen zu ermitteln, die geerntet werden können
Konvertieren Sie aus SpriteUV2 exportierte Netzdaten in ein Format, das von Spine importiert werden kann
[Python] So erzwingen Sie, dass eine Methode einer Unterklasse einen bestimmten Prozess ausführt
Untersuchung der von Python steuerbaren Gleichstromversorgung
So erstellen Sie eine virtuelle Brücke
Wie erstelle ich eine Docker-Datei?
Wie erstelle ich eine große Menge an Testdaten in MySQL? ??
Vergleich von 4 Stilen, die mit set_context an seaborn übergeben werden können
[Python] Verwendung der for-Anweisung. Eine Methode zum Extrahieren durch Angabe eines Bereichs oder von Bedingungen.
So erstellen Sie eine Konfigurationsdatei
[Python] Ein Programm, das ein Paar findet, das durch einen bestimmten Wert geteilt werden kann
Erstellen Sie eine Web-App, die mit Plotly Dash einfach visualisiert werden kann
Ein Memorandum darüber, wie man Pandas schreibt, das ich persönlich oft vergesse
So erstellen Sie einen Klon aus Github
So erstellen Sie ein Repository aus Medien
Ich wollte schnell einen Mailserver erstellen, der mit postfix + dovecot auf EC2 frei verwendet werden kann
[Python3] Code, der verwendet werden kann, wenn Sie ein Bild in einer bestimmten Größe ausschneiden möchten
Hinweise zum Erstellen von Zahlen, die mit matplotlib in Zeitschriften veröffentlicht werden können
Ich habe versucht, eine Klasse zu erstellen, mit der Json in Python problemlos serialisiert werden kann
Was ich durch die Implementierung des Erstellens einer Standardbox für SSD gelernt habe
[Python] So sortieren Sie nach dem N-ten M-ten Element eines mehrdimensionalen Arrays
Ich möchte eine WEB-Anwendung mit den Daten von League of Legends ① erstellen
So erstellen Sie einen Raspberry Pi, der die Tweets eines bestimmten Benutzers spricht
Eine neue Form der App, die mit GitHub funktioniert: So erstellen Sie GitHub-Apps
So berechnen Sie die Volatilität einer Marke
Eine Menge von ganzen Zahlen, die ax + by = 1 erfüllen.
So erstellen Sie ein Funktionsobjekt aus einer Zeichenfolge
So erstellen Sie eine JSON-Datei in Python
[Hinweis] So erstellen Sie eine Ruby-Entwicklungsumgebung
So erstellen Sie ein 1-zeiliges Kivy-Eingabefeld
Verfahren zur Erstellung plattformübergreifender Apps mit kivy
So erstellen Sie eine Rest-API in Django
So zählen Sie Zahlen in einem bestimmten Bereich
[Hinweis] So erstellen Sie eine Mac-Entwicklungsumgebung
Konvertieren Sie Bilder aus dem FlyCapture SDK in ein Formular, das mit openCV verwendet werden kann
Was Sie verstehen können, weil Sie ein Anfänger sind So erstellen Sie eine Datei (erster Beitrag)
Ein Skript, das Stresstests entsprechend der Anzahl der CPU-Kerne durchführen kann
So stellen Sie pyenv unter Amazon Linux und Ubuntu ein, um eine Python 3.6.0-Umgebung zu erstellen
[Python] Einführung in das WEB-Scraping | Zusammenfassung der Methoden, die mit dem Webdriver verwendet werden können
Ich habe versucht, eine Memo-App zu erstellen, die Pomodoro sein kann, aber eine Reflexionsaufzeichnung
[Ruby] Wie ersetze ich nur einen Teil der Zeichenkette, der mit dem regulären Ausdruck übereinstimmt?
Ein Mechanismus zum Aufrufen von Ruby-Methoden aus Python, der in 200 Zeilen ausgeführt werden kann
Lesen Sie die Python-Markdown-Quelle: So erstellen Sie einen Parser
Erstellen Sie einen Datensatz mit Bildern, die für das Training verwendet werden sollen
So erstellen Sie ein Untermenü mit dem Plug-In [Blender]
[Go] So erstellen Sie einen benutzerdefinierten Fehler für Sentry