Ricerca…


introduzione

Un'espressione F () è un modo per Django di utilizzare un oggetto Python per fare riferimento al valore del campo del modello o della colonna annotata nel database senza dover inserire il valore nella memoria di Python. Ciò consente agli sviluppatori di evitare determinate condizioni di gara e di filtrare i risultati in base ai valori del campo del modello.

Sintassi

  • da django.db.models import F

Evitare le condizioni di gara

Vedi questa domanda Q & A se non sai quali sono le condizioni di gara.

Il seguente codice può essere soggetto a condizioni di gara:

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

Se views_count è uguale a 1337 , ciò comporterà una query di questo tipo:

UPDATE app_article SET views_count = 1338 WHERE id=69

Se due client accedono contemporaneamente a questo articolo, ciò che potrebbe accadere è che la seconda richiesta HTTP esegua Article.objects.get(pk=69) prima che il primo esegua article.save() . Pertanto, entrambe le richieste avranno views_count = 1337 , incrementarlo e salvare views_count = 1338 nel database, mentre in realtà dovrebbe essere 1339 .

Per risolvere questo problema, usa un'espressione F() :

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

Questo, d'altra parte, si tradurrà in tale query:

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

Aggiornamento di queryset in blocco

Supponiamo di voler rimuovere 2 upvotes da tutti gli articoli dell'autore con id 51 .
Farlo solo con Python eseguirà N query ( N è il numero di articoli nel queryset):

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.

Cosa succede se invece di trascinare tutti gli articoli in Python, passandoci sopra, diminuendo gli upvotes e salvando ogni aggiornato nel database, c'era un altro modo?
Usando un'espressione F() , puoi farlo in una query:

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

Quale può essere tradotto nella seguente query SQL:

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

Perché è meglio?

  • Invece di fare il lavoro in Python, passiamo il carico nel database che è messo a punto per fare queste domande.
  • Riduce efficacemente il numero di query del database necessarie per ottenere il risultato desiderato.

Esegui operazioni aritmetiche tra i campi

F() espressioni F() possono essere utilizzate per eseguire operazioni aritmetiche ( + , - , * ecc.) Tra i campi del modello, al fine di definire una ricerca / connessione algebrica tra di esse.

  • Lascia che il modello sia:

    class MyModel(models.Model):
        int_1 = models.IntegerField()
        int_2 = models.IntegerField()
    
  • Ora lascia supporre che vogliamo recuperare tutti gli oggetti di MyModel tabella che di int_1 e int_2 campi soddisfano questa equazione: int_1 + int_2 >= 5 . Utilizzando annotate() e filter() otteniamo:

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

    result ora contiene tutti gli oggetti di cui sopra.

Sebbene l'esempio utilizzi i campi Integer , questo metodo funzionerà su ogni campo in cui è possibile applicare un'operazione aritmetica.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow