F表達式是用來優化ORM操作數據庫的。
舉個例子:我們做口罩的公司要將所有員工的薪水增加2000元,如果按照正常的流程,應該是先從數據庫中提取所有的員工的工資到Python內存中,然后使用Python代碼在員工工資的基礎上增加2000元,最后在保存到數據庫中,這里面涉及到的流程就是,首先從數據庫中提取數據到Python內存中,然后在Python內存中做完運算,之后再保存到數據庫中。示例代碼如下:
from django.db.models import F
from django.http import HttpResponse
from .models import BookOrder
# F表達式的用法詳解:F表達式並不會真正的到數據庫中查詢數據,僅僅只是起到一個標識的作用,告訴sql語句目前的值為多少。
def index2(request):
# 1. 同樣也可以先提取出所有的訂單,並且將訂單中的price減去10元,之后保存到數據庫中。
books = BookOrder.objects.all()
for book in books:
book.price -= 10
book.save()
print(connection.queries[-1])
# {
# 'sql': "UPDATE `book_order` SET `book_id` = 1, `price` = 79.0e0, `time` = '2020-02-04 01:22:43.534747' WHERE `book_order`.`id` = 7",
# 'time': '0.047'}
return HttpResponse("index2")
如果我們使用F表達式,就可以優化這個流程,他可以不需要先把數據從數據庫中提取出來,計算完成后,再保存回去 。他可以直接執行SQL語句,就將員工工資增加2000元。示例代碼如下:
from django.db.models import F
from django.http import HttpResponse
from .models import BookOrder
# F表達式的用法詳解:F表達式並不會真正的到數據庫中查詢數據,僅僅只是起到一個標識的作用,告訴sql語句目前的值為多少。
def index2(request):
# 2. 將bookorder表中預定價格降低10元
# 注意:調用的是update()方法,可以直接在數據庫層面直接調用F表達式更改數據庫中的數據信息
BookOrder.objects.update(price=F('price')-10)
# 因為connection.queries返回的是一個包含多個字典的列表,並且只有最后一個字典中的sql語句才是我們代碼中執行的sql語句
print(connection.queries[-1])
# {'sql': 'UPDATE `book_order` SET `price` = (`book_order`.`price` - 10)', 'time': '0.125'}
return HttpResponse('indes2')
其中,models.py文件中模型的定義為:
from django.db import models
# 定義圖書模型
class Book(models.Model):
name = models.CharField(max_length=100, unique=True)
pages = models.IntegerField()
price = models.FloatField()
rating = models.FloatField()
author = models.ForeignKey('Author', on_delete=models.CASCADE)
publisher = models.ForeignKey('Publisher', on_delete=models.CASCADE)
class Meta:
db_table = 'book'
def __str__(self):
return "(書名:%s,頁數:%s,價格:%s,打折:%s,作者:%s,出版社:%s)" % (self.name, self.pages, self.price, self.rating, self.author, self.publisher)
# 定義預定圖書的模型
class BookOrder(models.Model):
book = models.ForeignKey('Book', on_delete=models.CASCADE)
price = models.FloatField()
time = models.DateTimeField(auto_now_add=True, null=True)
class Meta:
db_table = 'book_order'
F表達式並不會馬上從數據庫中獲取數據,而是在生成sql語句的時候,動態的獲取傳給F表達式的值。在執行操作之前,數據庫中的數據信息如下:

執行操作之后,數據庫中信息為:
