当我们使用Django查询数据库时,一般都是使用Django提供的方法。简单的数据库查询还能应付,但一旦要执行复杂查询时变无法满足要求,于是为满足用户的复杂查询需求Django提供了Q对象。
基础环境说明
为了更方便的学习Q对象,使用Django Shell进行交互并事先创建了Model及插入了一些数据。
Model——
pc/models.py
1
2
3
4
5
6
7
8class pcInfo(models.Model):
"""Q对象练习"""
mac = models.CharField(max_length=30)
port = models.IntegerField()
city = models.CharField(max_length=255)
isp = models.CharField(max_length=255)
ip = models.IPAddressField()
comment = models.CharField(max_length=255, null=True)数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14mysql pc> SELECT * FROM pc_pcInfo;
+------+-------------------+--------+-----------------+-------------------+-------------+--------------------+
| id | mac | port | city | isp | ip | comment |
|------+-------------------+--------+-----------------+-------------------+-------------+--------------------|
| 1 | 00-E0-4C-68-6C-82 | 50000 | 美国-夏威夷 | Hawaiian telcom | 192.168.1.1 | 测试 |
| 2 | 00-E0-4C-68-41-D6 | 30006 | 澳洲-悉尼 | 大马电信 | 192.168.1.2 | modifyMinipc check |
| 3 | 00-E0-4C-68-6C-A1 | 50002 | 马来西亚-吉隆坡 | Optus | 192.168.1.3 | modifyMinipc check |
| 4 | 00-E0-4C-68-5A-F2 | 30008 | 英国-伯明翰 | Virgin Media | 192.168.1.4 | |
| 5 | 00-E0-4C-68-5A-FE | 30005 | 澳洲-墨尔本 | TPG Internet | 192.168.1.5 | |
| 6 | 00-E0-4C-68-41-D4 | 30002 | 美国-拉斯维加斯 | Cox Communication | 192.168.1.6 | check |
| 7 | 00-E0-4C-68-6C-A4 | 40001 | 匈牙利 | UPC Hungary | 192.168.1.7 | test |
| 8 | 00-E0-4C-68-6C-A7 | 40004 | 澳洲-帕斯 | TPG Internet | 192.168.1.8 | modifyMinipc |
+------+-------------------+--------+-----------------+-------------------+-------------+--------------------+
8 rows in setDjango Shell
1
2
3$> python manage.py shell
>>> from pc.models import pcInfo
>>> from django.db.models import Q
基本查询
Q对象也能进行普通的查询1
2
3
4
5
6
7
8
9
10#使用普通Django objects.filter()方法
>>> result=pcInfo.objects.filter(ip__contains='192.168.1.1')
>>> print result[0].__dict__
{'comment': u' \u6d4b\u8bd5', 'city': u'\u7f8e\u56fd-\u590f\u5a01\u5937', 'ip': u'192.168.1.1', 'isp': u'Hawaiian telcom', '_state': <django.db.models.base.ModelState object at 0xb532380c>, 'port': 50000L, 'mac': u'00-E0-4C-68-6C-82', 'id': 1L}
#使用Q对象
>>> result=pcInfo.objects.filter(Q(ip__contains='192.168.1.1'))
>>> print result[0].__dict__
{'comment': u' \u6d4b\u8bd5', 'city': u'\u7f8e\u56fd-\u590f\u5a01\u5937', 'ip': u'192.168.1.1', 'isp': u'Hawaiian telcom', '_state': <django.db.models.base.ModelState object at 0xb533296c>, 'port': 50000L, 'mac': u'00-E0-4C-68-6C-82', 'id': 1L}
AND查询
AND查询有两种写法:1. Q(...) & Q(...)
;2. Q(...), Q(...)
1
2
3
4
5>>> pcInfo.objects.filter(Q(ip='192.168.1.1') & Q(port=50001))
>>> []
>>> pcInfo.objects.filter(Q(ip='192.168.1.1'), Q(port=50001))
>>> []
OR查询
OR查询使用|
1
2>>> pcInfo.objects.filter(Q(ip='192.168.1.1') | Q(port=40004))
>>> [<pcInfo: pcInfo object>, <pcInfo: pcInfo object>]
AND OR 复杂查询
实现(A OR B) AND C
1
2
3
4
5
6
7
8
9
10>>> pcInfo.objects.filter( (Q(ip='192.168.1.5') | Q(port=30002)) & Q(port__contains=300) )
>>> [<pcInfo: pcInfo object>, <pcInfo: pcInfo object>]
>>> result=pcInfo.objects.filter( (Q(ip='192.168.1.5') | Q(port=30002)) & Q(port__contains=300) )
>>> print result[0].__dict__
>>>t': u'', 'city': u'\u6fb3\u6d32-\u58a8\u5c14\u672c', 'ip': u'192.168.1.5', 'isp': u'TPG Internet', '_state': <django.db.models.base.ModelState object at 0xb5323a4c>, 'port': 30005L, 'mac': u'00-E0-4C-68-5A-FE', 'id': 5L}
>>> print result[1].__dict__
{'comment': u'check', 'city': u'\u7f8e\u56fd-\u62c9\u65af\u7ef4\u52a0\u65af', 'ip': u'192.168.1.6', 'isp': u'Cox Communication', '_state': <django.db.models.base.ModelState object at 0xb5339f2c>, 'port': 30002L, 'mac': u'00-E0-4C-68-41-D4', 'id': 6L}
NOT查询
NOT查询使用~Q()
实现1
2
3
4
5
6
7
8
9
10>>> pcInfo.objects.filter(~(Q(port__contains=3000) | Q(port__contains=4000)))
>>> [<pcInfo: pcInfo object>, <pcInfo: pcInfo object>]
>>> result=pcInfo.objects.filter(~(Q(port__contains=3000) | Q(port__contains=4000)))
>>> print result[0].__dict__
>>>t': u' \u6d4b\u8bd5', 'city': u'\u7f8e\u56fd-\u590f\u5a01\u5937', 'ip': u'192.168.1.1', 'isp': u'Hawaiian telcom', '_state': <django.db.models.base.ModelState object at 0xb5338aac>, 'port': 50000L, 'mac': u'00-E0-4C-68-6C-82', 'id': 1L}
>>> print result[1].__dict__
{'comment': u'modifyMinipc check', 'city': u'\u9a6c\u6765\u897f\u4e9a-\u5409\u9686\u5761', 'ip': u'192.168.1.3', 'isp': u'Optus', '_state': <django.db.models.base.ModelState object at 0xb5338c4c>, 'port': 50002L, 'mac': u'00-E0-4C-68-6C-A1', 'id': 3L}
动态构建查询条件
若查询条件是动态构建的,则需要先创建Q对象列表,然后使用operator
和reduce
将Q对象列表组合起来。
基本使用
1 | >>> import operator |
动态添加查询条件
1 |
|