Django                
            Wyrażenia F ()
        
        
            
    Szukaj…
Wprowadzenie
Wyrażenie F () jest sposobem na użycie przez Django obiektu Python w celu odniesienia się do wartości pola modelu lub kolumny z adnotacjami w bazie danych bez konieczności pobierania wartości do pamięci Python. Dzięki temu programiści mogą unikać określonych warunków wyścigu, a także filtrować wyniki na podstawie wartości pola modelu.
Składnia
- z importu django.db.models F
Unikanie warunków wyścigu
Zobacz to pytanie, jeśli nie wiesz, jakie są warunki wyścigu.
Poniższy kod może podlegać warunkom wyścigu:
article = Article.objects.get(pk=69)
article.views_count += 1
article.save()
 Jeśli liczba views_count jest równa 1337 , spowoduje to takie zapytanie: 
UPDATE app_article SET views_count = 1338 WHERE id=69
 Jeśli dwóch klientów uzyskuje dostęp do tego artykułu w tym samym czasie, może się zdarzyć, że drugie żądanie HTTP wykona Article.objects.get(pk=69) przed pierwszym uruchomieniem article.save() . Zatem oba żądania będą miały wartość views_count = 1337 , views_count = 1337 ją i views_count = 1338 w bazie danych, podczas gdy faktycznie powinna to być 1339 . 
 Aby to naprawić, użyj wyrażenia F() : 
article = Article.objects.get(pk=69)
article.views_count = F('views_count') + 1
article.save()
To z kolei spowoduje takie zapytanie:
UPDATE app_article SET views_count = views_count + 1 WHERE id=69
Zbiorcza aktualizacja zestawu zapytań
 Załóżmy, że chcemy usunąć 2 głosy poparcia ze wszystkich artykułów autora o id 51 . 
 Wykonanie tego tylko przy użyciu Pythona spowodowałoby wykonanie N zapytań ( N oznacza liczbę artykułów w zestawie zapytań): 
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.
 Co jeśli zamiast wciągania wszystkich artykułów do Pythona, zapętlania ich, zmniejszania głosów pozytywnych i zapisywania każdego zaktualizowanego z powrotem do bazy danych, istnieje inny sposób? 
 Używając wyrażenia F() , możesz to zrobić w jednym zapytaniu: 
Article.objects.filter(author_id=51).update(upvotes=F('upvotes') - 2)
Które można przetłumaczyć w następującym zapytaniu SQL:
UPDATE app_article SET upvotes = upvotes - 2 WHERE author_id = 51
Dlaczego to jest lepsze?
- Zamiast wykonywać pracę w Pythonie, przekazujemy obciążenie do bazy danych, która jest dostosowana do wykonywania takich zapytań.
- Skutecznie zmniejsza liczbę zapytań do bazy danych potrzebnych do osiągnięcia pożądanego rezultatu.
Wykonuj operacje arytmetyczne między polami
 F() można używać do wykonywania operacji arytmetycznych ( + , - , * itd.) Między polami modelu, w celu zdefiniowania wyszukiwania algebraicznego / połączenia między nimi. 
- Niech model będzie: - class MyModel(models.Model): int_1 = models.IntegerField() int_2 = models.IntegerField()
- Załóżmy teraz, że chcemy pobrać wszystkie obiekty tabeli - MyModelktóre są- int_1i- int_2spełniają to równanie:- int_1 + int_2 >= 5. Używając- annotate()i- filter()otrzymujemy:- result = MyModel.objects.annotate( diff=F(int_1) + F(int_2) ).filter(diff__gte=5)- resultzawiera teraz wszystkie wyżej wymienione obiekty.
 Chociaż w przykładzie wykorzystano pola Integer , ta metoda będzie działać na każdym polu, na którym można zastosować operację arytmetyczną.