Django 之 models的 F() 和 Q() 函數


前提:

app名稱為core,models.py 如下:

 1 #coding: utf8
 2 import datetime
 3 from django.db import models
 4 
 5 class Order(models.Model):
 6     orderid     = models.CharField(max_length=64, unique=True)
 7     desc        = models.CharField(max_length=512)
 8     product     = models.CharField(max_length=512, null=True)
 9     amount      = models.IntegerField()
10     userid      = models.CharField(max_length=512, null=True)
11     create_time = models.DateTimeField(db_index=True)

1. F() ---- 專門取對象中某列值的操作

F()允許Django在未實際鏈接數據的情況下具有對數據庫字段的值的引用。通常情況下我們在更新數據時需要先從數據庫里將原數據取出后方在內存里,然后編輯某些屬性,最后提交。例如

1 order = Order.objects.get(orderid='123456789')
2 order.amount += 1
3 order.save()

上述方法生成的sql語句為(可以使用connection.queries查看http://www.cnblogs.com/liuq/p/5946166.html):

UPDATE `core_order` SET ..., `amount` = 22 WHERE `core_order`.`orderid` = '123456789' # ...表示Order中的其他值,在這里會重新賦一遍值; 22表示為計算后的結果

其實想生成的sql語句為:

UPDATE `core_order` SET ..., `amount` = `amount` + 1 WHERE `core_order`.`orderid` = '123456789'

這時就可以使用F()方法,代碼如下:

1 from django.db.models import F 2 from core.models import Order
3  
4 order = Order.objects.get(orderid='123456789')
5 order.amount = F('amount') - 1
6 order.save()

查看生成的sql:

UPDATE `core_order` SET ..., `amount` = `core_order`.`amount` - 1 WHERE `core_order`.`orderid` = '123456789' # 和預計的一樣

當Django程序中出現F()時,Django會使用SQL語句的方式取代標准的Python操作。

上述代碼中不管 order.amount 的值是什么,Python都不曾獲取過其值,python做的唯一的事情就是通過Django的F()函數創建了一條SQL語句然后執行而已。

需要注意的是在使用上述方法更新過數據之后需要重新加載數據來使數據庫中的值與程序中的值對應

  order = Order.objects.get(pk=order.pk)

或者使用更加簡單的方法:

order.refresh_from_db()
這里只做引子,詳細參考如下:

 

2. Q() ---- 對對象的復雜查詢

 Q對象(django.db.models.Q)可以對關鍵字參數進行封裝,從而更好地應用多個查詢。可以組合使用 &(and),|(or),~(not)操作符,當一個操作符是用於兩個Q的對象,它產生一個新的Q對象。
Order.objects.get(
    Q(desc__startswith='Who'),
    Q(create_time=date(2016, 10, 2)) | Q(create_time=date(2016, 10, 6))
)

轉換成sql語句,大致如下:

SELECT * from core_order WHERE desc LIKE 'Who%' AND (create_time = '2016-10-02' OR create_time = '2016-10-06')

 

Q對象可以與關鍵字參數查詢一起使用,不過一定要把Q對象放在關鍵字參數查詢的前面

正確寫法:

Order.objects.get(
    Q(create_time=date(2016, 10, 2)) | Q(create_time=date(2016, 10, 6)) desc__startswith='Who',
)

錯誤寫法:

Order.objects.get(
    desc__startswith='Who', Q(create_time=date(2016, 10, 2)) | Q(create_time=date(2016, 10, 6))
)

詳細內容可查看下面地址:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM