• ORM(三)QuerySet查询字段操作


    这里的环境还是用上次的环境:

    Django项目:orm_practice

    app/models.py中有如下几个类:

    models.py

    publishing表内容如下:

    pid    name
    1    机械工业出版社
    2    电子工业出版社
    3    人民出版社
    4    图灵出版社
    5    科学出版社
    app_publishing

    app_books表内容如下:

    bid   name            price    pid_id
    1     雪山飞狐         40       3
    2     三国演义         50       1
    3     天龙八部         60       3
    4     红楼梦           50       2
    5     C语言程序设计     80       4
    6     水浒传           50       5
                    

    app_author表内容如下:

    aid   name          
    1     金庸            
    2     罗贯中        
    3     曹雪芹        
    4     施耐庵        
    5     丹尼斯里奇      
        

    app_author_books表内容如下:

    id     author_id       books_id
    1      1                1
    2      1                3
    3      2                2
    4      3                4
    5      4                6
    6      5                5

    有了以上的表后,下面进行字段操作,在进行操作之前我们先创建一个脚本,用于运行ORM的语句。

    脚本内容:

    import os
    
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
        import django
        django.setup()
    orm运行脚本

    这里新建一个script的目录,在该目录下新建一个script.py的Python文件,在里面添加上面的脚本头,最后看起来像下面这个样子:

    1、表的查询QuerySet

    all():以列表的形式返回表中所有字段信息。

    语法:models.表名.objects.all()

    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
        import django
        django.setup()
    
    from app import models
    obj = models.Publishing.objects.all()   # 获取Publishing表中所有字段信息
    print(obj,type(obj))    # 打印publishing表总所有字段
    
    # 打印内容如下
    <QuerySet [<Publishing: Publishing object>, <Publishing: Publishing object>, <Publishing: Publishing object>,
    <Publishing: Publishing object>, <Publishing: Publishing object>]> <class 'django.db.models.query.QuerySet'>

     可能结果我们返回的字段类型class 'django.db.models.query.QuerySet' ,并且打印的内容也不是很友好,这是因为我们没有处理字段如何显示(也就是没有处理表中的属性如何显示),我们在创建publishing类时继承了models.Model类,class Publishing(models.Model):由于我们没有处理字段显示,所以就到父类中去寻找显示字段的方法,而父类models.Model为我们定义了__str__方法用于显示字段,所以我们看到的字段信息是继承了父类的显示方法。

     

     既然我们知道了字段显示方法,那么我们就可以自己定义字段显示方法__str__()。

    再次打印publishing表的字段信息,为便于查看结果,这回使用for循环的方式打印:

    obj_all = models.Publishing.objects.all()
    for obj in obj_all:
        print(obj.pid,obj.name)
    print(type(obj_all))
    
    # 打印内容如下
    1 机械工业出版社
    2 电子工业出版社
    3 人民出版社
    4 图灵出版社
    5 科学出版社
    <class 'django.db.models.query.QuerySet'>

    fileter(*args, **kwargs):如果不写参数,默认返回所有表字段信息。关键字参数kwargs用于设置查询条件,返回QuerySet类型列表。

    语法:models.表名.objects.filter(关键字参数)

    obj_list = models.Publishing.objects.filter()  # 没有设置查找条件,默认打印表中所有内容
    for obj in obj_list:
        print(obj.pid,obj.name)
    
    # 打印内容如下
    1 机械工业出版社
    2 电子工业出版社
    3 人民出版社
    4 图灵出版社
    5 科学出版社

    查找pid = 3的出版社。

    obj_list = models.Publishing.objects.filter(pid=3)
    print(obj_list[0].pid,obj_list[0].name,type(obj_list))  # filter返回的是一个QuerySet类型的列表,这里需要注意下。
    
    # 打印内容如下
    3 人民出版社 <class 'django.db.models.query.QuerySet'>

    这里需要注意的是filter(条件)返回的是QuerySet类型的列表的所有符合条件的字段信息,还有一个地方就是Django为我们将主键位置封装了一个类似别名pk,这样我们在使用主键作为条件查找时,如果不记得主键名称可以使用pk来代替主键。如下pk=3将得到和上面一样的结果:

    # obj_list = models.Publishing.objects.filter(pid=3)
    obj_list = models.Publishing.objects.filter(pk=3)  # 这里使用pk作为主键进行查找
    print(obj_list[0].pid,obj_list[0].name,type(obj_list))
    
    # 打印内容如下
    3 人民出版社 <class 'django.db.models.query.QuerySet'>

    exclude(*args, **kwargs):如果不写参数,会显示所有字段信息。指定排除条件kwargs,返回与条件不匹配的QuerySet类型列表。

    语法:models.表名.objects.exclude(关键字参数)

    obj_list = models.Publishing.objects.exclude(pk=2)  # 这里排除主键是2的对象
    for obj in obj_list:
        print(obj.pid,obj.name)
    
    # 打印内容如下
    1 机械工业出版社
    3 人民出版社
    4 图灵出版社
    5 科学出版社

    order_by(*field_names):根据字段名就行排序。

    obj_all = models.Publishing.objects.all().order_by("pk")  # 升序
    for obj in obj_all:
        print(obj.pid,obj.name)
    
    # 打印内容如下
    1 机械工业出版社
    2 电子工业出版社
    3 人民出版社
    4 图灵出版社
    5 科学出版社

    下面是降序:

    obj_all = models.Publishing.objects.all().order_by("-pk")  # 在字段前加一个负号代表降序
    for obj in obj_all:
        print(obj.pid,obj.name)
    
    # 打印内容如下
    5 科学出版社
    4 图灵出版社
    3 人民出版社
    2 电子工业出版社
    1 机械工业出版社

    reverse():将列表对象颠倒,必须要和order_by配合使用,否则不生效

    obj_all = models.Publishing.objects.all().order_by("pk")
    for obj in obj_all[:3]:    # 打印列表的前三个对象
        print(obj.pid,obj.name)
    print("-"*20)
    for obj in obj_all.reverse()[:3]: # 颠倒后打印列表的前三个对象
        print(obj.pid,obj.name)
    
    # 打印内容如下
    1 机械工业出版社
    2 电子工业出版社
    3 人民出版社
    --------------------
    5 科学出版社
    4 图灵出版社
    3 人民出版社

    values(*fields, **expressions):将QuerySet类型列表中的对象转换成字典。可指定*fields只查看要显示的字段。

    obj_all = models.Publishing.objects.all().values()  
    print(obj_all,type(obj_all))
    
    # 打印内容如下
    <QuerySet [{'pid': 1, 'name': '机械工业出版社'}, 
    {'pid': 2, 'name': '电子工业出版社'}, {'pid': 3, 'name': '人民出版社'}, {'pid': 4, 'name': '图灵出版社'}, 
    {'pid': 5, 'name': '科学出版社'}]> <class 'django.db.models.query.QuerySet'>

    指定*fields只查看书籍的bid、name、price字段:

    obj_all = models.Books.objects.all().values("bid","name","price")  # 只查看书籍的bid、name、price字段
    for obj in obj_all:
        print(list(obj.items()))  # 使用items()查看字典中的值
    
    # 打印内容如下
    [('bid', 1), ('name', '雪山飞狐'), ('price', 40)]
    [('bid', 2), ('name', '三国演义'), ('price', 50)]
    [('bid', 3), ('name', '天龙八部'), ('price', 60)]
    [('bid', 4), ('name', '红楼梦'), ('price', 50)]
    [('bid', 5), ('name', 'C语言程序设计'), ('price', 80)]
    [('bid', 6), ('name', '水浒传'), ('price', 50)]

    distinct(*field_names):去除重复行,需要注意的是参数field_names在PostgreSQL中可以用,在mysql不能使用该值。

    obj_all = models.Books.objects.all().values("price")
    for obj in obj_all:  # 打印所有价格
        print(list(obj.items()))  
    print("-"*20)
    for obj in obj_all.distinct():  # 去掉重复价格
        print(list(obj.items())) 
    
    # 打印内容如下
    [('price', 40)]
    [('price', 50)]
    [('price', 60)]
    [('price', 50)]
    [('price', 80)]
    [('price', 50)]
    --------------------
    [('price', 40)]
    [('price', 50)]
    [('price', 60)]
    [('price', 80)]

    values_list(*fields, **kwargs):fields用于指定字段显示,以元组的形式返回结果,kwargs有一个参数flat用于将数据转换成原数据类型,但只能转换一个值。

    指定"bid","name","price"字段打印内容:

    obj_all = models.Books.objects.all().values_list("bid","name","price")
    for obj in obj_all:  # 打印所有价格
        print(obj)
    
    # 打印内容如下
    (1, '雪山飞狐', 40)
    (2, '三国演义', 50)
    (3, '天龙八部', 60)
    (4, '红楼梦', 50)
    (5, 'C语言程序设计', 80)
    (6, '水浒传', 50)

    指定"name"字段使用flat=True打印"name"的原数据类型。

    obj_all = models.Books.objects.all().values_list("name",flat=True)
    for obj in obj_all:  # 打印所有价格
        print(obj)
    
    # 打印内容如下
    雪山飞狐
    三国演义
    天龙八部
    红楼梦
    C语言程序设计
    水浒传

    dates(field_name, kind, order='ASC')

    field_name:字段名

    kind:取值范围是"year", "month", "day"

            year:返回该字段的所有不同年份值的列表。

       month:返回该字段的所有不同年/月值的列表。

       day:返回该字段的所有不同年/月/日值的列表。

    order:"ASC","DESC"

    我们在书籍字段中插入一列日期记录,插入后的表如下:

    bid    name               pid_id    price     date
    1      雪山飞狐             3        40        2019-04-10
    2      三国演义             1        50        2019-04-09
    3      天龙八部             3        60        2018-04-10
    4      红楼梦               2        50        2017-04-10
    5      C语言程序设计         4        80        2019-02-10
    6      水浒传               5        50        2019-04-10

    下面分别对去除重复的年,月,日:

    obj_year = models.Books.objects.dates("date","year")    # 去掉相同年份的
    obj_month = models.Books.objects.dates("date","month")  # 去掉同年同月
    obj_day = models.Books.objects.dates("date","day")      # 去掉同年同月同日生
    for obj in obj_year:  # 去掉相同年份的
        print(obj)
    print("-"*20)
    for obj in obj_month:  # 去掉同年同月
        print(obj)
    print("-"*20)
    for obj in obj_day:  # 去掉同年同月同日生
        print(obj)
    
    # 打印内容如下
    2017-01-01
    2018-01-01
    2019-01-01
    --------------------
    2017-04-01
    2018-04-01
    2019-02-01
    2019-04-01
    --------------------
    2017-04-10
    2018-04-10
    2019-02-10
    2019-04-09
    2019-04-10

    datetimes(field_name, kind, order='ASC', tzinfo=None):与dates()类似,这里不演示了。

    ield_name:字段名

    kind:取值范围是"year", "month", "day"

            year:返回该字段的所有不同年份值的列表。

       month:返回该字段的所有不同年/月值的列表。

       day:返回该字段的所有不同年/月/日值的列表。

      "hour":返回该字段的所有不同年/月/日 小时值的列表。

      "minute":返回该字段的所有不同年/月/日 小时:分钟值的列表。

      "second"::返回该字段的所有不同年/月/日 小时:分钟:秒值的列表。

    order:"ASC","DESC"

    none():将创建一个永远不会返回任何对象的查询集,并且在访问结果时不会执行任何查询。

    obj_all = models.Books.objects.all().none()
    print(obj_all)
    
    # 打印内容如下
    <QuerySet []>

    exists():如果获取到结果返回True,否则返回False。

    obj_list = models.Books.objects.filter(pk=1).exists()  # 表中存在的主键
    obj_list2 = models.Books.objects.filter(pk=10).exists()  # 表中不存在的主键
    print(obj_list)
    print(obj_list2)
    
    # 打印内容如下
    True
    False

    first()、last():获取第一个和获取最后一个对象。

    obj_list = models.Books.objects.all()
    
    print(obj_list.first())  # 获取第一个对象
    print(obj_list.last())  # 获取最后一个对象
    
    # 打印内容如下
    雪山飞狐 - 40
    水浒传 - 50

    上面只显示书籍名字,和价格的原因是。我们在Books表中的显示方式只指定了name和price

    count():获取对象个数。

    obj_num = models.Books.objects.all().count()
    print(obj_num)
    
    # 打印内容如下
    6

    get(*args, **kwargs):必须给定查找条件,如果不指定查找条件会报错,并且查找条件的匹配结果必须是只有一条记录,如果返回多条记录也会报错,如果查找条件没有匹配的结果也会报错。所以在使用get时必须非常确根据条件肯定能获取到结果,且结果只有一条记录。否则会报错。get是直接返回查找到的记录(也就是类的对象)。

    obj = models.Publishing.objects.get(pk=4)
    print(obj.name,type(obj))
    
    # 打印内容如下
    图灵出版社 <class 'app.models.Publishing'>

    参考网址:https://docs.djangoproject.com/en/1.11/ref/models/querysets/

  • 相关阅读:
    Java设计模式——装饰器模式
    Java设计模式——观察者模式
    Java设计模式——代理模式
    Java设计模式——适配器模式
    Java设计模式——建造者模式
    Java项目——聊天器
    Java设计模式——抽象工厂模式
    JDBC操作(总结)
    JDBC操作(大纲)
    JavaScript事件委托的技术原理
  • 原文地址:https://www.cnblogs.com/caesar-id/p/10685497.html
Copyright © 2020-2023  润新知