mirror of
https://github.com/django/django.git
synced 2025-07-06 02:39:12 +00:00
queryset-refactor: Made the use of values() for ForeignKey fields consistent
and documented this feature. Refs #4358. git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6516 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4c4341f012
commit
70d5e32e13
@ -391,17 +391,22 @@ class ValuesQuerySet(QuerySet):
|
||||
# 'fields' is used to configure the query, whilst field_names is stored
|
||||
# in this object for use by iterator().
|
||||
if self._fields:
|
||||
opts = self.model._meta
|
||||
all = dict([(field.column, field) for field in opts.fields])
|
||||
all.update([(field.name, field) for field in opts.fields])
|
||||
if not self.query.extra_select:
|
||||
fields = [self.model._meta.get_field(f, many_to_many=False)
|
||||
for f in self._fields]
|
||||
try:
|
||||
fields = [all[f] for f in self._fields]
|
||||
except KeyError, e:
|
||||
raise FieldDoesNotExist('%s has no field named %r'
|
||||
% (opts.object_name, e.args[0]))
|
||||
field_names = self._fields
|
||||
else:
|
||||
fields = []
|
||||
field_names = []
|
||||
for f in self._fields:
|
||||
if f in [field.name for field in self.model._meta.fields]:
|
||||
fields.append(self.model._meta.get_field(f,
|
||||
many_to_many=False))
|
||||
if f in all:
|
||||
fields.append(all[f])
|
||||
field_names.append(f)
|
||||
elif not self.query.extra_select.has_key(f):
|
||||
raise FieldDoesNotExist('%s has no field named %r'
|
||||
|
@ -583,6 +583,30 @@ Example::
|
||||
>>> Blog.objects.values('id', 'name')
|
||||
[{'id': 1, 'name': 'Beatles Blog'}]
|
||||
|
||||
A couple of subtleties that are worth mentioning:
|
||||
|
||||
* The ``values()`` method does not return anything for ``ManyToManyField``
|
||||
attributes and will raise an error if you try to pass in this type of
|
||||
field to it.
|
||||
* If you have a field called ``foo`` that is a ``ForeignKey``, the default
|
||||
``values()`` call will return a dictionary key called ``foo_id``, since
|
||||
this is the name of the hidden model attribute that stores the actual
|
||||
value (the ``foo`` attribute refers to the related model). When you are
|
||||
calling ``values()`` and passing in field names, you can pass in either
|
||||
``foo`` or ``foo_id`` and you will get back the same thing (the
|
||||
dictionary key will match the field name you passed in).
|
||||
|
||||
For example::
|
||||
|
||||
>>> Entry.objects.values()
|
||||
[{'blog_id: 1, 'headline': u'First Entry', ...}, ...]
|
||||
|
||||
>>> Entry.objects.values('blog')
|
||||
[{'blog': 1}, ...]
|
||||
|
||||
>>> Entry.objects.values('blog_id')
|
||||
[{'blog_id': 1}, ...]
|
||||
|
||||
A ``ValuesQuerySet`` 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
|
||||
|
@ -334,5 +334,24 @@ Bug #3037
|
||||
Bug #5321
|
||||
>>> Note.objects.values('misc').distinct().order_by('note', '-misc')
|
||||
[{'misc': u'foo'}, {'misc': u'bar'}]
|
||||
|
||||
Bug #4358
|
||||
If you don't pass any fields to values(), relation fields are returned as
|
||||
"foo_id" keys, not "foo". For consistency, you should be able to pass "foo_id"
|
||||
in the fields list and have it work, too. We actually allow both "foo" and
|
||||
"foo_id".
|
||||
|
||||
# The *_id version is returned by default.
|
||||
>>> 'note_id' in ExtraInfo.objects.values()[0]
|
||||
True
|
||||
|
||||
# You can also pass it in explicitly.
|
||||
>>> ExtraInfo.objects.values('note_id')
|
||||
[{'note_id': 1}, {'note_id': 2}]
|
||||
|
||||
# ...or use the field name.
|
||||
>>> ExtraInfo.objects.values('note')
|
||||
[{'note': 1}, {'note': 2}]
|
||||
|
||||
"""}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user