目录
  1. 1. 基础环境说明
  2. 2. 基本查询
    1. 2.1. AND查询
    2. 2.2. OR查询
    3. 2.3. AND OR 复杂查询
    4. 2.4. NOT查询
  3. 3. 动态构建查询条件
    1. 3.1. 基本使用
    2. 3.2. 动态添加查询条件
  • 参考文章
  •  当我们使用Django查询数据库时,一般都是使用Django提供的方法。简单的数据库查询还能应付,但一旦要执行复杂查询时变无法满足要求,于是为满足用户的复杂查询需求Django提供了Q对象

    基础环境说明

     为了更方便的学习Q对象,使用Django Shell进行交互并事先创建了Model及插入了一些数据。

    • Model——pc/models.py

      1
      2
      3
      4
      5
      6
      7
      8
      class 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
      14
      mysql 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 set
    • Django 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对象列表,然后使用operatorreduceQ对象列表组合起来。

    基本使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> import operator

    #创建Q对象列表
    >>> q_list = [Q(ip='192.168.1.1'), Q(port=40004)]

    #AND查询
    >>> pcInfo.objects.filter(reduce(operator.and_, q_list))
    >>> []

    #OR查询
    >>> pcInfo.objects.filter(reduce(operator.or_, q_list))
    >>> [<pcInfo: pcInfo object>, <pcInfo: pcInfo object>]

    动态添加查询条件

    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

    >>> query = []

    #添加查询条件
    >>> query.append(('ip', '192.168.1.1'))

    >>> query.append(('port', 40004))

    >>> query.append(('port', 30002))

    #构建Q对象列表
    >>> q_list = [Q(x) for x in query]

    >>> print q_list[0]
    >>>ip', '192.168.1.1'))

    >>> print q_list[1]
    >>>port', 40004))


    >>> print q_list[2]
    >>>port', 30002))

    >>> pcInfo.objects.filter(reduce(operator.or_, q_list))
    >>> [<pcInfo: pcInfo object>, <pcInfo: pcInfo object>, <pcInfo: pcInfo object>]

    >>> result=pcInfo.objects.filter(reduce(operator.or_, q_list))
    >>> 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 0xb533ab6c>, 'port': 50000L, 'mac': u'00-E0-4C-68-6C-82', 'id': 1L}

    >>> print result[1].__dict__
    >>>t': 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 0xb533a18c>, 'port': 30002L, 'mac': u'00-E0-4C-68-41-D4', 'id': 6L}
    >>> print result[2].__dict__
    {'comment': u'modifyMinipc', 'city': u'\u6fb3\u6d32-\u5e15\u65af', 'ip': u'192.168.1.8', 'isp': u'TPG Internet', '_state': <django.db.models.base.ModelState object at 0xb533a6ec>, 'port': 40004L, 'mac': u'00-E0-4C-68-6C-A7', 'id': 8L}

    参考文章

    The power of django’s Q objects

    Powered: Hexo, Theme: Nadya remastered from NadyMain