zoukankan      html  css  js  c++  java
  • django: values()与values_list()

    from django.db import models
    
    class Blog(models.Model):
        name = models.CharField(max_length=100)
        tagline = models.TextField()
    
        def __str__(self):              # __unicode__ on Python 2
            return self.name
    
    class Author(models.Model):
        name = models.CharField(max_length=50)
        email = models.EmailField()
    
        def __str__(self):              # __unicode__ on Python 2
            return self.name
    
    class Entry(models.Model):
        blog = models.ForeignKey(Blog)
        headline = models.CharField(max_length=255)
        body_text = models.TextField()
        pub_date = models.DateField()
        mod_date = models.DateField()
        authors = models.ManyToManyField(Author)
        n_comments = models.IntegerField()
        n_pingbacks = models.IntegerField()
        rating = models.IntegerField()
    
        def __str__(self):              # __unicode__ on Python 2
            return self.headline

    values

    values(*fields)
    返回一个ValuesQuerySet —— QuerySet 的一个子类,迭代时返回字典而不是模型实例对象。

    每个字典表示一个对象,键对应于模型对象的属性名称。

    # This list contains a Blog object.
    >>> Blog.objects.filter(name__startswith='Beatles')
    [<Blog: Beatles Blog>]
    
    # This list contains a dictionary.
    >>> Blog.objects.filter(name__startswith='Beatles').values()
    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]

    values() 接收可选的位置参数*fields,它指定SELECT 应该限制哪些字段。如果指定字段,每个字典将只包含指定的字段的键/值。如果没有指定字段,每个字典将包含数据库表中所有字段的键和值。

    >>> Blog.objects.values()
    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
    >>> Blog.objects.values('id', 'name')
    [{'id': 1, 'name': 'Beatles Blog'}]
    值得注意的几点:
    如果你有一个字段foo 是一个ForeignKey,默认的values() 调用返回的字典将有一个叫做foo_id 的键,因为这是保存实际的值的那个隐藏的模型属性的名称(foo 属性引用关联的模型)。当你调用values() 并传递字段的名称,传递foofoo_id 都可以,得到的结果是相同的(字典的键会与你传递的字段名匹配)。
    >>> Entry.objects.values()
    [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]
    
    >>> Entry.objects.values('blog')
    [{'blog': 1}, ...]
    
    >>> Entry.objects.values('blog_id')
    [{'blog_id': 1}, ...]
    • 当values() 与distinct() 一起使用时,注意排序可能影响最终的结果。详细信息参见distinct() 中的备注。

    • 如果values() 子句位于extra() 调用之后,extra() 中的select 参数定义的字段必须显式包含在values() 调用中。values() 调用后面的extra() 调用将忽略选择的额外的字段。

    • 在values() 之后调用only() 和defer() 不太合理,所以将引发一个NotImplementedError。

    New in Django 1.7:
    新增最后一点。以前,在values() 之后调用only() 和defer() 是允许的,但是它要么会崩溃要么返回错误的结果。

    ValuesQuerySet 用于你知道你只需要字段的一小部分,而不需要用到模型实例对象的函数。只选择用到的字段当然更高效。

    最后,要注意ValuesQuerySetQuerySet 的子类,它实现了大部分相同的方法。你可以对它调用filter()order_by() 等等。这表示下面的两个调用完全相同:

    Blog.objects.values().order_by('id')
    Blog.objects.order_by('id').values()

    Django 的作者喜欢将影响SQL 的方法放在前面,然后放置影响输出的方法(例如values()),但是实际上无所谓。这是卖弄你个性的好机会。

    你可以通过OneToOneField、ForeignKey 和 ManyToManyField 属性反向引用关联的模型的字段:

    Blog.objects.values('name', 'entry__headline')
    [{'name': 'My blog', 'entry__headline': 'An entry'},
         {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]

    警告

    因为ManyToManyField 字段和反向关联可能有多个关联的行,包含它们可能导致结果集的倍数放大。如果你在values() 查询中包含多个这样的字段将更加明显,这种情况下将返回所有可能的组合。

    values_list

    values_list(*fields, flat=False)
    与values() 类似,只是在迭代时返回的是元组而不是字典。每个元组包含传递给values_list() 调用的字段的值 —— 所以第一个元素为第一个字段,以此类推。例如:

    >>> Entry.objects.values_list('id', 'headline')
    [(1, 'First entry'), ...]

    如果只传递一个字段,你还可以传递flat 参数。如果为True,它表示返回的结果为单个值而不是元组。一个例子会让它们的区别更加清晰:

    >>> Entry.objects.values_list('id').order_by('id')
    [(1,), (2,), (3,), ...]
    
    >>> Entry.objects.values_list('id', flat=True).order_by('id')
    [1, 2, 3, ...]

    如果有多个字段,传递flat 将发生错误。

    如果你不传递任何值给values_list(),它将按照字段在模型中定义的顺序, 返回模型中的所有字段。

    注意,这个方法返回ValuesListQuerySet。这个类的行为类似列表。大部分时候它足够用了,但是如果你需要一个真实的Python 列表对象,可以对它调用list(),这将会对查询集求值。

    例如:

    School.objects.filter(school_id=1).values_list("id", "flat = true")

    上述orm解释:

    查找School表中school_id为1的id,这将返回一个id列表,而不是单个id元组列表。

    差异巨大,values_list速度更快。flat = true使得它更快,因为python不需要实例化列表中的所有对象,只返回数据库值。

    为了证明它更快,因为Django认识到我们使用查询集作为查询集的参数,因此它将它们组合到一个查询中 - 它不会首先将查询集计算values_list为列表
    有一点需要注意的是,列表理解中values / values_list的行为有所不同:

    • values / values_list将产生存储在该字段中的实际值,即,仅仅是id(不是整个对象)
    • 如果该值是一个外键,并且在模型中设置了适当的关系,则列表理解将为您提供外键引用的对象
    class Building(models.Model):  
        corporation = models.ForeignKey('company.Corporation', verbose_name=u'学校', related_name='buildings')  
        number = models.CharField(u'楼栋编号', max_length=10, unique=True, db_index=True)  
        create_time = models.DateTimeField(u'创建时间', auto_now_add=True)  

    获取Building的number字段列表

    In [1]: from apps.dormitory.models import Building  
      
    In [2]: buildings = Building.objects.values('number')  
      
    In [3]: buildings  
    Out[3]: [{'number': u'1'}, {'number': u'2'}, {'number': u'3'}, {'number': u'4'}, {'number': u'5'}]  
      
    In [4]: buildings_ = Building.objects.values_list('number')  
      
    In [5]: buildings_  
    Out[5]: [(u'1',), (u'2',), (u'3',), (u'4',), (u'5',)]  
      
    In [6]: buildings_list = Building.objects.values_list('number', flat=True)  
      
    In [7]: buildings_list  
    Out[7]: [u'1', u'2', u'3', u'4', u'5']  

    从以上代码可以看出:

    values方法可以获取number字段的字典列表。

    values_list可以获取number的元组列表。

    values_list方法加个参数flat=True可以获取number的值列表。

     
     
     

    链接:https://www.jianshu.com/p/7c7645674ae0

  • 相关阅读:
    POJ 1015 Jury Compromise【DP】
    POJ 1661 Help Jimmy【DP】
    HDU 1074 Doing Homework【状态压缩DP】
    HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
    占坑补题。。最近占的坑有点多。。。
    Codeforces 659F Polycarp and Hay【BFS】
    Codeforces 659E New Reform【DFS】
    Codeforces 659D Bicycle Race【计算几何】
    廖大python实战项目第四天
    廖大python实战项目第三天
  • 原文地址:https://www.cnblogs.com/rgxx/p/10382664.html
Copyright © 2011-2022 走看看