from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __str__(self): # __uni ...
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 的一個子類,迭代時返回字典而不是模型實例對象。
每個字典表示一個對象,鍵對應於模型對象的屬性名稱。
下麵的例子將values() 與普通的模型對象進行比較:
# 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()
並傳遞欄位的名稱,傳遞foo
或foo_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
用於你知道你只需要欄位的一小部分,而不需要用到模型實例對象的函數。只選擇用到的欄位當然更高效。
最後,要註意ValuesQuerySet
是QuerySet
的子類,它實現了大部分相同的方法。你可以對它調用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