Python-模型類-F()對象和Q()對象詳解


定義模型
from django.db import models
from django.db.models import F, Q

class Publisher(models.Model):
    """出版社"""
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    country = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name


class Author(models.Model):
    """作家"""
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)


class Book(models.Model):
    """書"""
    title = models.CharField(max_length=100)
    publisher = models.ForeignKey(Publisher)
    price = models.IntegerField(default=0)

    def __unicode__(self):
        return self.title
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
一、F對象:
需求:
  • 當一般的查詢語句已經無法滿足我們的需求時,Django為我們提供了F和Q復雜查詢語句。比如在我定義的這個模型類中, 書的價格飛漲,從以前的20元,漲到了21元。我們應該怎么辦?這個時候F對象是最佳首選。
>>> Book.objects.all().first().price  # 簡單的查詢了 數據庫中書的價格
>>> # 返回的是 20 
>>> # 下面我想將價格飛速的上漲到21元
>>> Book.objects.update(price=F("price")+1)
>>> Book.objects.all().first().price
>>> 返回的結果是 21 
>>> # 這本書的價格又發生了改變,降到了 6塊錢
>>> Book.objects.update(price=F("price")-15)
(0.003) UPDATE `apps_book` SET `price` = (`apps_book`.`price` - 15); args=(15,)
>>> # 返回的結果是6元
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 接下來讓我們查看一下SQL語句:
(0.003) UPDATE `apps_book` SET `price` = (`apps_book`.`price` + 1); args=(1,)
  • 1
  • 2
  • F查詢專門對對象中某劣值的操作,不可以使用雙下划線("__")
二、Q對象:
  • Q查詢可以組合使用“&”,“|” 操作符,當一個操作符是用於兩個Q的對象,它產生一個新的Q對象,Q對象可以用 “~” 操作符放在前面表示否定,也可允許否定與不否定形式的組合。Q對象可以與關鍵字參數查詢一起使用,不過一定要把Q對象放在關鍵字參數查詢的前面
    • 接下來filter()里面一個Q對象的情況下:
from django.db.models import Q
# 使用Q對象,返回的是QuerySet通過[0]下標來獲取值(一般情況下不使用下標的方式,獲取不到會報錯)
>>> Book.objects.filter(Q(id=3))[0]
(0.000) SELECT `apps_book`.`id`, `apps_book`.`title`, `apps_book`.`publisher_id`, `apps_book`.`price` FROM `apps_book` WHERE `apps_book`.`id` = 3 LIMIT 1; args=(3,)
<Book: cow>
# 返回QuerySet最好使用first()來獲取第一個對象而不用下標的方式[0]
>>> Book.objects.filter(Q(id=3)).first()
(0.000) SELECT `apps_book`.`id`, `apps_book`.`title`, `apps_book`.`publisher_id`, `apps_book`.`price` FROM `apps_book` WHERE `apps_book`.`id` = 3 ORDER BY `apps_book`.`id` ASC LIMIT
 1; args=(3,)
<Book: cow>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
* 接下來filter()里面二個Q對象的情況下:
  • 1
# 看到了 | 是代表或的意思 只要一個條件滿足就會返回數據;顯然數據庫里面title字段沒有jave,所以返回的是id=2的對象
>>> Book.objects.filter(Q(id=2) | Q(title="java")).first()
(0.001) SELECT `apps_book`.`id`, `apps_book`.`title`, `apps_book`.`publisher_id`, `apps_book`.`price` FROM `apps_book` WHERE (`apps_book`.`id` = 2 OR `apps_book`.`title` = 'jave') O
RDER BY `apps_book`.`id` ASC LIMIT 1; args=(2, 'jave')
<Book: python>
# 我們在來做一個比較:
# 數據庫里面沒有id=4的對象,正好title的字段里面有"python" 所以返回的是python對應的對象
>>> Book.objects.filter(Q(id=4)|Q(title="python")).first()
(0.000) SELECT `apps_book`.`id`, `apps_book`.`title`, `apps_book`.`publisher_id`, `apps_book`.`price` FROM `apps_book` WHERE (`apps_book`.`id` = 4 OR `apps_book`.`title` = 'python')
 ORDER BY `apps_book`.`id` ASC LIMIT 1; args=(4, 'python')
<Book: python>
# 接下來查詢一個復雜一些的:價格大於等於6元的,或者id大於等於1的對象
>>> Book.objects.filter(Q(price__gte=6)|Q(id__gt=1)).first()
(0.001) SELECT `apps_book`.`id`, `apps_book`.`title`, `apps_book`.`publisher_id`, `apps_book`.`price` FROM `apps_book` WHERE (`apps_book`.`price` >= 6 OR `apps_book`.`id` > 1) ORDER
 BY `apps_book`.`id` ASC LIMIT 1; args=(6, 1)
<Book: python>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 接下來告訴大家~Q()的玩法
# ~Q:就是代表非的意思
>>> Book.objects.filter(Q(price__gte=6) | ~Q(id__gt=1)).first()
(0.001) SELECT `apps_book`.`id`, `apps_book`.`title`, `apps_book`.`publisher_id`, `apps_book`.`price` FROM `apps_book` WHERE (`apps_book`.`price` >= 6 OR `apps_book`.`id` > 1) ORDER
 BY `apps_book`.`id` ASC LIMIT 1; args=(6, 1)
<Book: python>
  • 1
  • 2
  • 3
  • 4
  • 5

其實默認的情況下filter()里面每個字段的連接都是& ,我們使用Q對象通常都是讓它變成|,來進行查詢
* 接下來我們來一個更復雜的Q對象查詢:

from django.db.models import Q

query = Q()
q1 = Q()
q1.connector = "AND"  # 連接的條件是AND 代表就是& 
q1.children.append(("email", "280773872@qq.com")) # email代表的是數據庫的字段
q1.children.append(("password", "666"))
 # 等同於:email="280773872@qq.com" & password="666"
q2 = Q()
q2.connector = "AND"  # 同樣q2對象連接條件也是AND 
q2.children.append(("username", "fe_cow")) # 同樣數據庫里username字段
q2.children.append(("password", "fe_cow666"))
 # 等同於:username="fe_cow" & password="fe_cow666"
query.add(q1, "OR") 
query.add(q2, "OR")
 # query目前里面的符合條件結果就是: (email="280773872@qq.com" & password="666") | (username="fe_cow" & password="fe_cow666")
userinfo_obj = models.UserInfo.objects.filter(query).first()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Q對象實例化來然后增加各個條件之間的關系,而且這種寫法用在你不知道用戶到底傳入了多少個參數的時候很方便


免責聲明!

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



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