Suche…


Einführung

Mit einem F () - Ausdruck kann Django mithilfe eines Python-Objekts auf den Wert des Modellfelds oder der kommentierten Spalte in der Datenbank verweisen, ohne den Wert in den Python-Speicher ziehen zu müssen. Dadurch können Entwickler bestimmte Race-Bedingungen vermeiden und Ergebnisse basierend auf Modellfeldwerten filtern.

Syntax

  • von django.db.models importieren F

Rennbedingungen vermeiden

Sehen Sie sich diese Q & A-Frage an, wenn Sie nicht wissen, welche Wettlaufbedingungen gelten.

Der folgende Code kann Rennbedingungen unterliegen:

article = Article.objects.get(pk=69)
article.views_count += 1
article.save()

Wenn views_count gleich 1337 , führt dies zu einer solchen Abfrage:

UPDATE app_article SET views_count = 1338 WHERE id=69

Wenn zwei Clients gleichzeitig auf diesen Artikel zugreifen, kann es passieren, dass die zweite HTTP-Anforderung Article.objects.get(pk=69) ausführt, bevor die erste article.save() . Daher haben beide Anforderungen views_count = 1337 , views_count = 1337 sie und speichern views_count = 1338 in der Datenbank, während es eigentlich 1339 .

Um dies zu beheben, verwenden Sie einen F() Ausdruck:

article = Article.objects.get(pk=69)
article.views_count = F('views_count') + 1
article.save()

Dies führt andererseits zu einer solchen Abfrage:

UPDATE app_article SET views_count = views_count + 1 WHERE id=69

Abfrageset in großen Mengen aktualisieren

Nehmen wir an, wir wollen mit der ID 51 aus allen Artikeln des Autors 2 Upvotes entfernen.
Wenn Sie dies nur mit Python tun, werden N Abfragen ausgeführt ( N ist die Anzahl der Artikel im Abfrageset):

for article in Article.objects.filter(author_id=51):
    article.upvotes -= 2
    article.save()
    # Note that there is a race condition here but this is not the focus
    # of this example.

Was wäre, wenn anstatt alle Artikel in Python zu ziehen, über sie hinweg zu schleifen, die Upvotes zu verringern und jeden aktualisierten Artikel in der Datenbank zu speichern, es einen anderen Weg gab?
Mit einem F() Ausdruck können Sie dies in einer Abfrage tun:

Article.objects.filter(author_id=51).update(upvotes=F('upvotes') - 2)

Was kann in der folgenden SQL-Abfrage übersetzt werden:

UPDATE app_article SET upvotes = upvotes - 2 WHERE author_id = 51

Warum ist das besser?

  • Anstatt Python die Arbeit zu erledigen, übergeben wir die Last in die Datenbank, die für solche Abfragen fein abgestimmt ist.
  • Reduziert effektiv die Anzahl der Datenbankabfragen, die zum Erreichen des gewünschten Ergebnisses erforderlich sind.

Arithmetische Operationen zwischen Feldern ausführen

F() -Ausdrücke können verwendet werden, um arithmetische Operationen ( + , - , * usw.) zwischen Modellfeldern auszuführen, um eine algebraische Suche / Verbindung zwischen ihnen zu definieren.

  • Das Modell sei:

    class MyModel(models.Model):
        int_1 = models.IntegerField()
        int_2 = models.IntegerField()
    
  • MyModel wir nun an, dass wir alle Objekte der MyModel Tabelle int_1 int_2 Felder int_1 und int_2 dieser Gleichung entsprechen: int_1 + int_2 >= 5 . Mit annotate() und filter() wir:

    result = MyModel.objects.annotate(
                 diff=F(int_1) + F(int_2)
             ).filter(diff__gte=5)
    

    result enthält jetzt alle zuvor genannten Objekte.

Obwohl das Beispiel Integer Felder verwendet, funktioniert diese Methode für jedes Feld, auf das eine arithmetische Operation angewendet werden kann.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow