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对象实例化来然后增加各个条件之间的关系,而且这种写法用在你不知道用户到底传入了多少个参数的时候很方便。