1. 程式人生 > >django中的F和Q

django中的F和Q

價格 span UNC 條件 not 字符串 upd func opera

F查詢

Django 提供 F() 來做這樣的比較。F() 的實例可以在查詢中引用字段,來比較同一個 model 實例中兩個不同字段的值。

查詢書id大於\小於價格的書籍

1 models.Book.objects.filter(id__gt=F("price"))
2 <QuerySet []>
3 
4 models.Book.objects.filter(id__lt=F("price"))
5 <QuerySet [<Book: 書一>, <Book: 書二>, <Book: 書三>, <Book: 書四>, <Book: 書五>, <Book: 書六>]>

Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操作。

1 models.Book.objects.filter(id__lt=F("price")/2)
2 <QuerySet [<Book: 書一>, <Book: 書二>, <Book: 書三>, <Book: 書四>, <Book: 書五>]>

修改操作也可以使用F函數,比如將每一本書的價格提高30元

models.Book.objects.all().update(price=F("price")+30)

字符串使用Concat連接

from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F("title"),Value("("),Value(""),Value(")")))

Q查詢主要是用來做and, or, not 查詢的

AND查詢

將多個 Q 對象作為非關鍵參數或使用 & 聯結即可實現 AND 查詢:

>>> from django.db.models import
Q # Q(...) >>> Question.objects.filter(Q(question_text__contains=you)) [<Question: what are you doing>, <Question: what is wrong with you>, <Question: who are you>] # Q(...), Q(...) >>> Question.objects.filter(Q(question_text__contains=you), Q(question_text__contains=what)) [<Question: what are you doing>, <Question: what is wrong with you>] # Q(...) & Q(...) >>> Question.objects.filter(Q(question_text__contains=you) & Q(question_text__contains=what)) [<Question: what are you doing>, <Question: what is wrong with you>]

OR查詢

使用 | 聯結兩個 Q 對象即可實現 OR 查詢:

# Q(...) | Q(...)
>>> Question.objects.filter(Q(question_text__contains=you) | Q(question_text__contains=who))
[<Question: what are you doing>, <Question: what is wrong with you>, <Question: who are you>, <Question: who am i>]

NOT查詢

使用 ~Q(...) 客戶實現 NOT 查詢:

# ~Q(...)
>>> Question.objects.filter(~Q(question_text__contains=you))
[<Question: who am i>]

與關鍵字參數共用

記得要把 Q 對象放前面:

# Q(...), key=value
>>> Question.objects.filter(Q(question_text__contains=you), question_text__contains=who)
[<Question: who are you>]

動態構建查詢條件

比如你定義了一個包含一些 Q 對象的列表,如何使用這個列表構建 ANDOR 查詢呢? 可以使用 operatorreduce

>>> lst = [Q(question_text__contains=you), Q(question_text__contains=who)]

# OR
>>> Question.objects.filter(reduce(operator.or_, lst))
[<Question: what are you doing>, <Question: what is wrong with you>, <Question: who are you>, <Question: who am i>]

# AND
>>> Question.objects.filter(reduce(operator.and_, lst))
[<Question: who are you>]

這個列表也可能是根據用戶的輸入來構建的,比如簡單的搜索功能(搜索一個文章的標題或內容或作者名稱包含某個關鍵字):

q = request.GET.get(q, ‘‘).strip()
lst = []
if q:
    for key in [title__contains, content__contains,
                author__name__contains]:
        q_obj = Q(**{key: q})
        lst.append(q_obj)
queryset = Entry.objects.filter(reduce(operator.or_, lst))

django中的F和Q