django以字典或元組形式輸出資料庫結果集,可以選擇輸出特定列的結果
values()
¶
values
(*fields, **expressions)¶
Returns a QuerySet
that returns dictionaries, rather than model instances, when used as an iterable.
Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects.
This example compares the dictionaries ofvalues()
with the normal model objects:這個例子的意思是,在平常的查詢結果集上後加.values(),得到的結果集是一個數據字典而不是普通的model例項(Blog的例項)。# This list contains a Blog object. >>> Blog.objects.filter(name__startswith='Beatles') <QuerySet [<Blog: Beatles Blog>]> # This list contains a dictionary. >>> Blog.objects.filter(name__startswith='Beatles').values() <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
The values()
method takes optional positional arguments, *fields
, which specify field names to which the SELECT
should be limited. If you specify the fields, each dictionary will contain only the field keys/values for the fields you specify. If you don’t specify the fields, each dictionary will contain a key and value for every field in the database table.
>>> Blog.objects.values() <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]> >>> Blog.objects.values('id', 'name') <QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>The
values()
method also takes optional keyword arguments, **expressions
, which are passed through to annotate()
:values(*fields, **expressions)的引數還可以是表示式,表示式可以設定字典的key的名稱。像例子中的lower_name>>> from django.db.models.functions import Lower >>> Blog.objects.values(lower_name=Lower('name')) <QuerySet [{'lower_name': 'beatles blog'}]>
An aggregate within a values()
clause is applied before other arguments within the same values()
clause. If you need to group by another value, add it to an earlier values()
clause instead. For example:
>>> from django.db.models import Count >>> Blog.objects.values('entry__authors', entries=Count('entry')) <QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]> >>> Blog.objects.values('entry__authors').annotate(entries=Count('entry')) <QuerySet [{'entry__authors': 1, 'entries': 33}]>
A few subtleties that are worth mentioning:
If you have a field called
For example:這是外來鍵的例子,value()函式返回外來鍵在資料庫中的id,資料字典的key有兩種:blog或blog_id,但對應的值是一樣的。foo
that is aForeignKey
, the defaultvalues()
call will return a dictionary key calledfoo_id
, since this is the name of the hidden model attribute that stores the actual value (thefoo
attribute refers to the related model). When you are callingvalues()
and passing in field names, you can pass in eitherfoo
orfoo_id
and you will get back the same thing (the dictionary key will match the field name you passed in).>>> Entry.objects.values() <QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]> >>> Entry.objects.values('blog') <QuerySet [{'blog': 1}, ...]> >>> Entry.objects.values('blog_id') <QuerySet [{'blog_id': 1}, ...]>
When using
values()
together withdistinct()
, be aware that ordering can affect the results. See the note indistinct()
for details.If you use a
values()
clause after anextra()
call, any fields defined by aselect
argument in theextra()
must be explicitly included in thevalues()
call. Anyextra()
call made after avalues()
call will have its extra selected fields ignored.Calling
only()
anddefer()
aftervalues()
doesn’t make sense, so doing so will raise aNotImplementedError
.
It is useful when you know you’re only going to need values from a small number of the available fields and you won’t need the functionality of a model instance object. It’s more efficient to select only the fields you need to use.
Finally, note that you can call filter()
, order_by()
, etc. after the values()
call, that means that these two calls are identical:
Blog.objects.values().order_by('id') Blog.objects.order_by('id').values()
The people who made Django prefer to put all the SQL-affecting methods first, followed (optionally) by any output-affecting methods (such as values()
), but it doesn’t really matter. This is your chance to really flaunt your individualism.
You can also refer to fields on related models with reverse relations through OneToOneField
, ForeignKey
and ManyToManyField
attributes:
>>> Blog.objects.values('name', 'entry__headline') <QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'}, {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>
Warning
Because ManyToManyField
attributes and reverse relations can have multiple related rows, including these can have a multiplier effect on the size of your result set. This will be especially pronounced if you include multiple such fields in your values()
query, in which case all possible combinations will be returned.
Support for **expressions
was added.
values_list()
¶
values_list
(*fields, flat=False, named=False)¶
values()
except that instead of returning dictionaries, it returns tuples when iterated over. Each tuple contains the value from the respective field or expression passed into the values_list()
call — so the first item is the first field, etc. For example:values_list()函式的結果是元組,不帶key。>>> Entry.objects.values_list('id', 'headline') <QuerySet [(1, 'First entry'), ...]> >>> from django.db.models.functions import Lower >>> Entry.objects.values_list('id', Lower('headline')) <QuerySet [(1, 'first entry'), ...]>If you only pass in a single field, you can also pass in the
flat
parameter. If True
, this will mean the returned results are single values, rather than one-tuples. An example should make the difference clearer:甚至可以是去掉元組的陣列。>>> Entry.objects.values_list('id').order_by('id') <QuerySet[(1,), (2,), (3,), ...]> >>> Entry.objects.values_list('id', flat=True).order_by('id') <QuerySet [1, 2, 3, ...]>
It is an error to pass in flat
when there is more than one field.
You can pass named=True
to get results as a namedtuple()
:
>>> Entry.objects.values_list('id', 'headline', named=True) <QuerySet [Row(id=1, headline='First entry'), ...]>
Using a named tuple may make use of the results more readable, at the expense of a small performance penalty for transforming the results into a named tuple.
If you don’t pass any values to values_list()
, it will return all the fields in the model, in the order they were declared.
A common need is to get a specific field value of a certain model instance. To achieve that, use values_list()
followed by a get()
call:
>>> Entry.objects.values_list('headline', flat=True).get(pk=1) 'First entry'
values()
and values_list()
are both intended as optimizations for a specific use case: retrieving a subset of data without the overhead of creating a model instance. This metaphor falls apart when dealing with many-to-many and other multivalued relations (such as the one-to-many relation of a reverse foreign key) because the “one row, one object” assumption doesn’t hold.
For example, notice the behavior when querying across a ManyToManyField
:
>>> Author.objects.values_list('name', 'entry__headline') <QuerySet [('Noam Chomsky', 'Impressions of Gaza'), ('George Orwell', 'Why Socialists Do Not Believe in Fun'), ('George Orwell', 'In Defence of English Cooking'), ('Don Quixote', None)]>
Authors with multiple entries appear multiple times and authors without any entries have None
for the entry headline.
Similarly, when querying a reverse foreign key, None
appears for entries not having any author:
>>> Entry.objects.values_list('authors') <QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>Changed in Django 1.11:
Support for expressions in *fields
was added.
The named
parameter was added.