zoukankan      html  css  js  c++  java
  • Django笔记&教程 5-2 进阶查询——Queryset

    Django 自学笔记兼学习教程第5章第2节——进阶查询——Queryset
    点击查看教程总目录

    Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-api

    0 - 数据示例

    为了方便本文后面内容举例,这里先展示下models.py和数据库表内容,
    myapp/models.py在本章第一节,如下:

    from django.db import models
    
    class Person(models.Model):
        gender = (
            ('male', '男'),
            ('female', '女'),
        )
    
        name = models.CharField(max_length=60)
        sex = models.CharField(max_length=32, choices=gender, default='男')
        age = models.IntegerField()
    

    数据库表Person如下

    id name sex age
    2 Li Hua male 20
    3 Big Shuang male 24
    4 Xiao Hong female 21
    5 Xiao Hua female 19
    6 Ellen female 20
    7 Zhang Sirui female 22
    8 Alex male 23
    9 Zhao Wen female 24
    10 Sun Wu male 18
    11 Qian Kong male 22

    可通过在Django下的交互式命令行,运行以下代码,快速生成数据库数据。

    >>> from myapp.models import Person
    >>> info_list = [
            ["Li Hua", "male", 20],
            ["Big Shuang", "male", 24],
            ["Xiao Hong", "female", 21],
            ["Xiao Hua", "female", 19],
            ["Ellen", "female", 20],
            ["Zhang Sirui", "female", 22],
            ["Alex", "male", 23],
            ["Zhao Wen", "female", 24],
            ["Sun Wu", "male", 18],
            ["Qian Kong", "male", 22],
        ]
    >>> for info in info_list:
            name, sex, age = info
            pi = Person(name=name, sex=sex, age=age)
            pi.save()
    

    1 - 查询方法

    filter

    个人最常用的查询方法是filter,可以简单理解为按条件查找(筛选),该方法返回一个Queryset对象,
    其语法为OneModel.objects.filter(**kwargs),其中OneModel为要查询的模型名,kwargs为查询条件,接受关键词(keyword)参数, 该关键字具体格式见本文第二部分。

    使用举例如下(在Django下的交互式命令行里执行代码)

    >>> from myapp.models import Person
    >>> age_20 = Person.objects.filter(age=20)
    >>> age_20
    <QuerySet [<Person: Person object (2)>, <Person: Person object (6)>]>
    >>> age_20[0]
    <Person: Person object (2)>
    >>> age_20[0].name
    'Li Hua'
    

    get

    返回与给定查找参数唯一匹配的对象,
    注意:如果查找条件能找到多个结果或者0个结果,该方法都会报错。
    其语法为OneModel.objects.get(**kwargs)

    使用举例如下(承接上文命令行中代码)

    >>> lihua = Person.objects.get(name="Li Hua")
    >>> lihua.name
    'Li Hua'
    >>> lihua.age
    20
    

    all

    获取数据库表所有数据(严格来讲,这已经不算查询方法了)。
    其语法为OneModel.objects.all()

    示例如下

    >>> persons = Person.objects.all()
    >>> for p in persons: print(p.name, p.age, end=",")
    >>> print()
    Li Hua 20,Big Shuang 24,Xiao Hong 21,Xiao Hua 19,Ellen 20,Zhang Sirui 22,Alex 23,Zhao Wen 24,Sun Wu 18,Qian Kong 22,
    

    raw

    执行一个SQL查询,并返回一个django.db.models.query.RawQuerySet实例。
    RawQuerySet实例可以像普通的QuerySet一样遍历以提供对象实例。

    示例如下

    >>> persons_above22 = Person.objects.raw("select * from myapp_person where age>22")
    >>> for p in persons_above22: print(p.id, p.name, p.sex, p.age)
    3 Big Shuang male 24
    8 Alex male 23
    9 Zhao Wen female 24
    

    2 字段查找格式(Field lookups)

    本文第一部分的filterget方法,都是接受**kwargs作为查询条件来搜索的。
    这个又称为字段查找(Field lookups),效果为指定SQL WHERE子句内容。
    第一部分只展示了最简单的查询条件:严格相等。

    如果要查找一些其他的条件,比如说年龄大于20岁,名字里面含有a字母等等。
    则需要使用某种方法标明这个条件,django里面通过字段查找类型(lookup type)实现了这种方法。

    给字段field指定查找类型lookup的语法如下
    field__lookup

    不指定时默认查找类型为精确exact,
    即以下两句效果等同

    lihua = Person.objects.get(name="Li Hua")
    lihua = Person.objects.get(name__exact="Li Hua")
    

    对应的sql为

    SELECT * from myapp_person WHERE name = 'Li Hua';
    

    这里介绍一些常用的查找类型,更多请查阅官方文档:field-lookups

    • iexact: 忽略大小写
    • contains: 查询包含指定模式的字段,(区分大小写)。
    • icontains: 查询包含指定模式的字段,(忽略大小写)。

    注:由于SQLite不支持区分大小写的LIKE操作符,所以SQLite中contains效果为icontains

    • in: 在给定的可迭代对象中,如列表、元组或查询集,还有字符串。
    • gt: 大于(记忆技巧:greater than首字母)。
    • gte: 大于或等于,(记忆技巧:greater than equal首字母)。
    • lt: 小于(记忆技巧:less than首字母)。
    • lte: 小于或等于,(记忆技巧:less than equal首字母)。
    • startswith: 开头匹配,(区分大小写)。
    • istartswith: 开头匹配,(忽略大小写)。
    • endswith: 结尾匹配,(区分大小写)。
    • iendswith: 结尾匹配,(忽略大小写)。
    • regex: 正则匹配,(区分大小写)。
    • iregex: 正则匹配,(忽略大小写)。

    注: 正则表达式语法是Python的re模块的语法。

    举例演示:

    >>> name_a = Person.objects.filter(name__icontains="a")
    >>> for p in name_a: print(p.name, end=", ")
    >>> print()
    Li Hua, Big Shuang, Xiao Hong, Xiao Hua, Zhang Sirui, Alex, Zhao Wen, Qian Kong,
    >>> age_lte_20 = Person.objects.filter(age__lte=20)
    >>> for p in age_lte_20: print(p.name, p.age, end=", ")
    >>> print()
    Li Hua 20, Xiao Hua 19, Ellen 20, Sun Wu 18,
    

    注:由于查找类型语法,是通过在字段名后面加两个下划线后声明的。
    所以Django的模型中的属性字段名不可有两个下划线。

    3 quertset 基础操作

    使用filterall方法获取到的都是一个queryset对象,
    所以我们也需要掌握该对象一些常用的方法和操作。

    首先,queryset对象是一个可迭代对象,
    这意味着它可以使用for循环遍历。
    同时queryset对象也可以使用切片操作。
    还可以使用lenlist等函数获取其对应结果。

    queryset对象常用方法:

    • order_by: 按指定字段排序,可指定多个字段(从前往后按字段来排序)。
      默认升序,在字段名前加负号则降序。

    使用示例:

    >>> persons = Person.objects.all()
    >>> persons_sorted_age = persons.order_by("age")
    >>> for p in persons_sorted_age: print(p.name, p.age, end=", ")
    >>> print()
    Sun Wu 18, Xiao Hua 19, Li Hua 20, Ellen 20, Xiao Hong 21, Zhang Sirui 22, Qian Kong 22, Alex 23, Big Shuang 24, Zhao Wen 24,
    >>> persons_sorted_age_descending = persons.order_by("-age")
    >>> for p in persons_sorted_age_descending: print(p.name, p.age, end=", ")
    >>> print()
    Big Shuang 24, Zhao Wen 24, Alex 23, Zhang Sirui 22, Qian Kong 22, Xiao Hong 21, Li Hua 20, Ellen 20, Xiao Hua 19, Sun Wu 18,
    
    • order_by: 按指定字段排序,可指定多个字段(从前往后按字段来排序)。
      默认升序,在字段名前加负号则降序。

    4 操作符

    本文第二部分介绍了字段查找的基础格式。
    且查询条件可以写多个,代表查找同时遵循这些条件的结果。

    那么有一个问题,如果要查询满足A或B的结果,那么上面写法就不够用了。

    Django实现了一个可以封装SQL表达式的对象Q,该对象在django.db.models中。
    Q可以封装一个查询条件,
    Q对象之间可以使用|(或)和&(且)符号,进行逻辑运算。
    不仅可以实现上面指出的或查询问题,还可以可以定义和重用查询条件。

    示例如下

    >>> name_contains_a = Q(name__icontains="a")
    >>> age_above_22 = Q(age__gt=22)
    >>> and_res = Person.objects.filter(name_contains_a & age_above_22)
    >>> for p in and_res: print(p.name, p.age, end=",")
    >>> print()
    Big Shuang 24,Alex 23,Zhao Wen 24,
    >>> or_res = Person.objects.filter(name_contains_a | age_above_22)
    >>> for p in or_res: print(p.name, p.age, end=",")
    >>> print()
    Li Hua 20,Big Shuang 24,Xiao Hong 21,Xiao Hua 19,Zhang Sirui 22,Alex 23,Zhao Wen 24,Qian Kong 22,
    
  • 相关阅读:
    python有哪些好的学习资料或者博客?
    运维角度浅谈MySQL数据库优化
    MySQL高可用性之Keepalived+Mysql(双主热备)
    Python 开发者节省时间的 10 个小技巧
    PHP 加密的几种方式
    17种常用的jQuery全屏焦点图代码
    13种酷炫的html5 3D图片切换代码
    14款微信小游戏源码下载
    Ext js框架模拟Windows桌面菜单管理模板
    10款 非常酷炫的网站首页焦点图 兼容ie浏览器
  • 原文地址:https://www.cnblogs.com/BigShuang/p/14285591.html
Copyright © 2011-2022 走看看