Ticket #5420: queryset_fields_trunk.diff
File queryset_fields_trunk.diff, 29.7 KB (added by , 17 years ago) |
---|
-
django/db/models/manager.py
101 101 def values(self, *args, **kwargs): 102 102 return self.get_query_set().values(*args, **kwargs) 103 103 104 def fields(self, *args, **kwargs): 105 return self.get_query_set().fields(*args, **kwargs) 106 104 107 class ManagerDescriptor(object): 105 108 # This class ensures managers aren't accessible via model instances. 106 109 # For example, Poll.objects works, but poll_obj.objects raises AttributeError. -
django/db/models/query.py
91 91 self._order_by = None # Ordering, e.g. ('date', '-name'). If None, use model's ordering. 92 92 self._select_related = False # Whether to fill cache for related objects. 93 93 self._max_related_depth = 0 # Maximum "depth" for select_related 94 self._fields = {} # Subset of fields of this and related models to select 95 self._modelize = True # Convert rows to models or return dictionaries 94 96 self._distinct = False # Whether the query should use SELECT DISTINCT. 95 97 self._select = {} # Dictionary of attname -> SQL. 96 98 self._where = [] # List of extra WHERE clauses to use. … … 189 191 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 190 192 191 193 fill_cache = self._select_related 192 fields = self.model._meta.fields194 fields = _get_model_fields(self.model._meta, "", self._fields, self._select) 193 195 index_end = len(fields) 194 196 has_resolve_columns = hasattr(self, 'resolve_columns') 195 197 while 1: … … 201 203 row = self.resolve_columns(row, fields) 202 204 if fill_cache: 203 205 obj, index_end = get_cached_row(klass=self.model, row=row, 204 index_start=0, max_depth=self._max_related_depth) 206 index_start=0, 207 max_depth=self._max_related_depth, 208 fields=self._fields, modelize=self._modelize) 205 209 else: 206 obj = self.model(*row[:index_end]) 210 obj = _init_model(self._modelize and self.model or None,\ 211 fields, row[:index_end]) 207 212 for i, k in enumerate(extra_select): 208 setattr(obj, k[0], row[index_end+i]) 213 if self._modelize: 214 setattr(obj, k[0], row[index_end+i]) 215 else: 216 obj[k[0]] = row[index_end+i] 209 217 yield obj 210 218 211 219 def count(self): … … 357 365 # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # 358 366 ################################################## 359 367 360 def values(self, *fields):361 return self._clone(klass=ValuesQuerySet, _fields=fields)362 363 368 def dates(self, field_name, kind, order='ASC'): 364 369 """ 365 370 Returns a list of datetime objects representing all available dates … … 415 420 "Returns a new QuerySet instance with '_select_related' modified." 416 421 return self._clone(_select_related=true_or_false, _max_related_depth=depth) 417 422 423 def fields(self, *fields, **related_fields): 424 """Returns a new QuerySet instance with '_fields' modified. 425 owner_fields is stored inside _fields with empty string key.""" 426 assert fields or related_fields, "fields() don't have sense without arguments" 427 _fields, _select_related = _merge_fields(self.model, fields, related_fields) 428 return self._clone(_modelize=True, _fields=_fields, 429 _select_related=_select_related or self._select_related) 430 431 def values(self, *fields, **related_fields): 432 """Returns a new QuerySet instance with '_fields' and '_modelize'.""" 433 if not (fields or related_fields): 434 return self._clone(_modelize=False, _fields={}) # process all fields from master model 435 _fields, _select_related = _merge_fields(self.model, fields, related_fields) 436 return self._clone(_modelize=False, _fields=_fields, 437 _select_related=_select_related or self._select_related) 438 418 439 def order_by(self, *field_names): 419 440 "Returns a new QuerySet instance with the ordering changed." 420 441 assert self._limit is None and self._offset is None, \ … … 448 469 c._order_by = self._order_by 449 470 c._select_related = self._select_related 450 471 c._max_related_depth = self._max_related_depth 472 c._fields = self._fields 473 c._modelize = self._modelize 451 474 c._distinct = self._distinct 452 475 c._select = self._select.copy() 453 476 c._where = self._where[:] … … 488 511 opts = self.model._meta 489 512 490 513 # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. 491 select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) for f in opts.fields] 514 select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) for f in \ 515 _get_model_fields(opts, "", self._fields, self._select)] 492 516 tables = [quote_only_if_word(t) for t in self._tables] 493 517 joins = SortedDict() 494 518 where = self._where[:] … … 505 529 fill_table_cache(opts, select, tables, where, 506 530 old_prefix=opts.db_table, 507 531 cache_tables_seen=[opts.db_table], 508 max_depth=self._max_related_depth )532 max_depth=self._max_related_depth, fields=self._fields) 509 533 510 534 # Add any additional SELECTs. 511 535 if self._select: … … 571 595 else: 572 596 QuerySet = _QuerySet 573 597 574 class ValuesQuerySet(QuerySet):575 def __init__(self, *args, **kwargs):576 super(ValuesQuerySet, self).__init__(*args, **kwargs)577 # select_related isn't supported in values().578 self._select_related = False579 580 def iterator(self):581 try:582 select, sql, params = self._get_sql_clause()583 except EmptyResultSet:584 raise StopIteration585 586 qn = connection.ops.quote_name587 588 # self._select is a dictionary, and dictionaries' key order is589 # undefined, so we convert it to a list of tuples.590 extra_select = self._select.items()591 592 # Construct two objects -- fields and field_names.593 # fields is a list of Field objects to fetch.594 # field_names is a list of field names, which will be the keys in the595 # resulting dictionaries.596 if self._fields:597 if not extra_select:598 fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields]599 field_names = self._fields600 else:601 fields = []602 field_names = []603 for f in self._fields:604 if f in [field.name for field in self.model._meta.fields]:605 fields.append(self.model._meta.get_field(f, many_to_many=False))606 field_names.append(f)607 elif not self._select.has_key(f):608 raise FieldDoesNotExist('%s has no field named %r' % (self.model._meta.object_name, f))609 else: # Default to all fields.610 fields = self.model._meta.fields611 field_names = [f.attname for f in fields]612 613 columns = [f.column for f in fields]614 select = ['%s.%s' % (qn(self.model._meta.db_table), qn(c)) for c in columns]615 if extra_select:616 select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) for s in extra_select])617 field_names.extend([f[0] for f in extra_select])618 619 cursor = connection.cursor()620 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)621 622 has_resolve_columns = hasattr(self, 'resolve_columns')623 while 1:624 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)625 if not rows:626 raise StopIteration627 for row in rows:628 if has_resolve_columns:629 row = self.resolve_columns(row, fields)630 yield dict(zip(field_names, row))631 632 def _clone(self, klass=None, **kwargs):633 c = super(ValuesQuerySet, self)._clone(klass, **kwargs)634 c._fields = self._fields[:]635 return c636 637 598 class DateQuerySet(QuerySet): 638 599 def iterator(self): 639 600 from django.db.backends.util import typecast_timestamp … … 829 790 raise NotImplementedError 830 791 raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type) 831 792 832 def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0 ):793 def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0, depth_path="", fields={}, modelize=True): 833 794 """Helper function that recursively returns an object with cache filled""" 834 795 835 796 # If we've got a max_depth set and we've exceeded that depth, bail now. 836 797 if max_depth and cur_depth > max_depth: 837 798 return None 838 799 839 index_end = index_start + len(klass._meta.fields) 840 obj = klass(*row[index_start:index_end]) 841 for f in klass._meta.fields: 842 if f.rel and not f.null: 843 cached_row = get_cached_row(f.rel.to, row, index_end, max_depth, cur_depth+1) 800 cur_fields = _get_model_fields(klass._meta, depth_path, fields) 801 if not cur_fields: 802 return None 803 804 index_end = index_start + len(cur_fields) 805 obj = _init_model(modelize and klass or None, cur_fields, row[index_start:index_end]) 806 for f in cur_fields: 807 if f.rel and not f.null and _get_fields(f, depth_path, fields): 808 cached_row = get_cached_row(f.rel.to, row, index_end, max_depth, cur_depth+1,\ 809 _lookup(depth_path, f.name), fields, modelize) 844 810 if cached_row: 845 811 rel_obj, index_end = cached_row 846 setattr(obj, f.get_cache_name(), rel_obj) 812 if modelize: 813 setattr(obj, f.get_cache_name(), rel_obj) 814 else: 815 obj[f.name] = rel_obj 847 816 return obj, index_end 848 817 849 def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen, max_depth=0, cur_depth=0): 818 def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen,\ 819 max_depth=0, cur_depth=0, depth_path="", fields={}): 850 820 """ 851 821 Helper function that recursively populates the select, tables and where (in 852 822 place) for select_related queries. 853 823 """ 854 855 824 # If we've got a max_depth set and we've exceeded that depth, bail now. 856 825 if max_depth and cur_depth > max_depth: 857 826 return None 858 827 859 828 qn = connection.ops.quote_name 860 for f in opts.fields:861 if f.rel and not f.null :829 for f in _get_model_fields(opts, depth_path, fields): 830 if f.rel and not f.null and _get_fields(f, depth_path, fields): 862 831 db_table = f.rel.to._meta.db_table 863 832 if db_table not in cache_tables_seen: 864 833 tables.append(qn(db_table)) … … 869 838 cache_tables_seen.append(db_table) 870 839 where.append('%s.%s = %s.%s' % \ 871 840 (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column))) 872 select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields]) 873 fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen, max_depth, cur_depth+1) 841 select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in\ 842 _get_fields(f, depth_path, fields)]) 843 fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen,\ 844 max_depth, cur_depth+1, _lookup(depth_path, f.name), fields) 874 845 846 def _lookup(depth_path, fname): 847 return depth_path and "%s__%s" % (depth_path, fname) or fname 848 849 def _split_lookup(lookup): 850 """Right split lookup on parent and child.""" 851 if LOOKUP_SEPARATOR in lookup: 852 return lookup.rsplit(LOOKUP_SEPARATOR, 1) 853 else: 854 return '', lookup 855 856 def _merge_fields(klass, fields, related_fields): 857 """Resolves child-parent relations and checks is select_related required 858 or not.""" 859 _select_related = False 860 if related_fields or [f for f in klass._meta.fields if f.name in fields and f.rel]: 861 _select_related = True 862 863 related_fields[''] = fields 864 # check that each child primary key is in parent field subset 865 for lookup in related_fields.iterkeys(): 866 if lookup: # root lookup is empty string 867 parent, child = _split_lookup(lookup) 868 if not related_fields.has_key(parent): 869 continue # a grandparent may have required field 870 parent_fields = related_fields[parent] 871 if child not in parent_fields: 872 parent_fields = list(parent_fields) + [child] 873 related_fields[parent] = parent_fields 874 875 return related_fields, _select_related 876 877 def _get_fields(field, depth_path, fields): 878 """Returns fields of field.rel model that need to be selected from db.""" 879 assert field.rel and field.rel.to, "ForeignKey is required." 880 return _get_model_fields(field.rel.to._meta, _lookup(depth_path, field.name), fields) 881 882 def _get_model_fields(meta, lookup, fields, extra_select=[]): 883 if fields: # was used fields(...), so return only specified fields 884 if fields.has_key(lookup): # we have implicit instruction for the lookup 885 fnames = fields[lookup] 886 if fnames: 887 # check that each field name is valid field name for this model and extra select 888 # actually this is optional step, but tests/modeltests/lookup.py require it 889 valid_fnames = [f.name for f in meta.fields] 890 if extra_select: 891 valid_fnames += extra_select.keys() 892 for fname in fnames: 893 if not fname in valid_fnames: 894 raise FieldDoesNotExist("%s has no field named '%s'" %\ 895 (meta.object_name, fname)) 896 return [f for f in meta.fields if f.name in fnames] 897 else: # checking parent 898 while lookup: 899 lookup, child = _split_lookup(lookup) 900 if fields.has_key(lookup): 901 # we have child defined in parent fields instead of 902 # dedicated lookup for this child, so return all fields 903 # for example BlogPost.objects.fields(('headline', 'blog')) should 904 # return only BlogPost.headline, all Blog fields and all Blog children 905 # fields (limited to _max_related_depth of course) 906 return child in fields[lookup] and meta.fields or () 907 else: 908 return meta.fields 909 910 def _init_model(klass, fields, values): 911 """If klass, return model instance, else return dictionary.""" 912 obj = dict(zip([f.attname for f in fields], values)) 913 if klass: 914 obj = klass(**obj) 915 return obj 916 875 917 def parse_lookup(kwarg_items, opts): 876 918 # Helper function that handles converting API kwargs 877 919 # (e.g. "name__exact": "tom") to SQL. -
tests/modeltests/fields/models.py
Property changes on: tests/modeltests/fields/__init__.py ___________________________________________________________________ Name: svn:keywords + Author Date Id Name: svn:eol-style + native
1 """ 2 47. Tests for fields() 3 4 ``fields()`` allows to select only fields subset from a model and its related 5 models. It change the behaviour of methods that return model 6 instances. Affects querysets with or without select_related mode. If fields() 7 isn't called for queryset, queryset behavior isn't chaged, i.e. all fields of 8 all selected models are returned. 9 """ 10 11 from django.db import models 12 13 class Author(models.Model): 14 name = models.CharField(max_length=50) 15 about = models.TextField() 16 def __unicode__(self): 17 """When self.about isn't loaded it will be shown as [].""" 18 return u"%s [%s]" % (self.name, self.about) 19 20 class Blog(models.Model): 21 name = models.CharField(max_length=50) 22 about = models.TextField() 23 author = models.ForeignKey(Author) 24 25 def __unicode__(self): 26 return u"%s [%s]" % (self.name, self.about) 27 28 class Entry(models.Model): 29 blog = models.ForeignKey(Blog) 30 headline = models.CharField(max_length=50) 31 content = models.TextField() 32 33 def __unicode__(self): 34 return u"%s [%s]" % (self.headline, self.content) 35 36 def create_world(): 37 """Helper to create test models.""" 38 etch = Author.objects.create(name="Etch", about="About Etch") 39 lenny = Author.objects.create(name="Lenny", about="About Lenny") 40 etch_blog = Blog.objects.create(name="Etch's blog", about="All about Etch", author=etch) 41 lenny_blog = Blog.objects.create(name="Lenny's blog", about="All about Lenny", author=lenny) 42 for blog in Blog.objects.select_related(): 43 for i in xrange(5): 44 headline = "%s_%d" % (blog.author.name, i) 45 Entry.objects.create(headline=headline, content="huge content", blog=blog) 46 47 48 __test__ = {'API_TESTS':""" 49 50 >>> from django.conf import settings 51 >>> old_debug = settings.DEBUG 52 >>> settings.DEBUG = True 53 >>> from django import db 54 >>> create_world() 55 >>> Author.objects.count(), Blog.objects.count(), Entry.objects.count() 56 (2, 2, 10) 57 58 # load only `id` and `headline` of a Entry 59 >>> db.reset_queries() 60 >>> p = Entry.objects.fields('id', 'headline').get(headline='Lenny_0') 61 >>> p, p.id, p.content 62 (<Entry: Lenny_0 []>, 6, '') 63 >>> len(db.connection.queries) 64 1 65 66 # load all fields of all related objects 67 >>> db.reset_queries() 68 >>> p = Entry.objects.select_related().get(headline="Etch_1") 69 >>> p, p.blog, p.blog.author 70 (<Entry: Etch_1 [huge content]>, <Blog: Etch's blog [All about Etch]>, <Author: Etch [About Etch]>) 71 >>> len(db.connection.queries) 72 1 73 74 # load only Entry.headline, Blog.name and Author.name and don't load 75 huge TextFields for Lenny's blog posts (typical task when it's need to show an object list). 76 >>> db.reset_queries() 77 >>> posts = Entry.objects.fields('headline', blog=('name',), blog__author=('name',)).filter(blog__author__name="Lenny")[:1] 78 >>> [(p, p.blog, p.blog.author) for p in posts] 79 [(<Entry: Lenny_0 []>, <Blog: Lenny's blog []>, <Author: Lenny []>)] 80 >>> p = posts[0] 81 >>> p.content == p.blog.about == p.blog.author.about == '' 82 True 83 >>> len(db.connection.queries) 84 1 85 86 # load all Entry fields and only Blog.headline and Author.name (don't load `about` fields) 87 >>> db.reset_queries() 88 >>> p = Entry.objects.fields('id','headline', 'content', blog=('name',), blog__author=('name',)).select_related().get(headline="Etch_1") 89 >>> p, p.blog, p.blog.author 90 (<Entry: Etch_1 [huge content]>, <Blog: Etch's blog []>, <Author: Etch []>) 91 >>> print p.content 92 huge content 93 >>> (p.blog.about, p.blog.author.about) 94 ('', '') 95 >>> len(db.connection.queries) 96 1 97 98 # don't load any field from Blog, but load Blog.author.name 99 >>> db.reset_queries() 100 >>> p = Entry.objects.fields('id','headline', 'content', blog=(), blog__author=('name',)).get(headline="Lenny_1") 101 >>> p, p.blog, p.blog.author 102 (<Entry: Lenny_1 [huge content]>, <Blog: []>, <Author: Lenny []>) 103 >>> len(db.connection.queries) 104 1 105 106 # select Entry.headline, all fields from Blog and only Author.name 107 >>> db.reset_queries() 108 >>> p = Entry.objects.fields('headline', 'blog', blog__author=('name',)).get(headline="Lenny_2") 109 >>> p, p.blog, p.blog.author 110 (<Entry: Lenny_2 []>, <Blog: Lenny's blog [All about Lenny]>, <Author: Lenny []>) 111 >>> len(db.connection.queries) 112 1 113 114 # check count() 115 >>> db.reset_queries() 116 >>> Entry.objects.fields('id', 'blog', blog__author=('name',)).select_related().filter(headline__contains='1').count() 117 2 118 >>> len(db.connection.queries) 119 1 120 121 # select all field from Entry, Blog and don't select Author fields because 122 # select_related(depth=1) don't touch Author table and so field limitations from 123 # fields() aren't used 124 >>> db.reset_queries() 125 >>> p = Entry.objects.fields('id','headline', 'content', 'blog', blog__author=('name',)).select_related(depth=1).get(headline="Lenny_3") 126 >>> p, p.blog, p.blog.author 127 (<Entry: Lenny_3 [huge content]>, <Blog: Lenny's blog [All about Lenny]>, <Author: Lenny [About Lenny]>) 128 >>> len(db.connection.queries) 129 2 130 131 # select Blog.name and Author.name only and check extra() 132 >>> db.reset_queries() 133 >>> b = Blog.objects.fields('name', author=('name',)).extra(select={'post_count': "SELECT COUNT(*) FROM fields_entry t WHERE t.blog_id=fields_blog.id"}).get(name="Lenny\'s blog") 134 >>> b, b.author, b.post_count 135 (<Blog: Lenny's blog []>, <Author: Lenny []>, 5) 136 >>> len(db.connection.queries) 137 1 138 139 # check extra() with collection 140 >>> db.reset_queries() 141 >>> blogs = Blog.objects.fields('id','name', author=('name',)).select_related().extra(select={'post_count': "SELECT COUNT(*) FROM fields_entry t WHERE t.blog_id=fields_blog.id"}) 142 >>> [(b, b.author, b.post_count) for b in blogs] 143 [(<Blog: Etch's blog []>, <Author: Etch []>, 5), (<Blog: Lenny's blog []>, <Author: Lenny []>, 5)] 144 >>> len(db.connection.queries) 145 1 146 147 # load Blog.name, Author.name and check extra() 148 >>> db.reset_queries() 149 >>> b = Blog.objects.fields('name', author=('name',)).select_related().extra(select={'post_count': "SELECT COUNT(*) FROM fields_entry t WHERE t.blog_id=fields_blog.id"}).get(name="Lenny\'s blog") 150 >>> b, b.author, b.post_count 151 (<Blog: Lenny's blog []>, <Author: Lenny []>, 5) 152 >>> len(db.connection.queries) 153 1 154 155 # load only Author.name without any fields from Blog 156 >>> db.reset_queries() 157 >>> b1 = Blog.objects.fields(author=('name',)).select_related().get(name="Etch\'s blog") 158 >>> b1, b1.author 159 (<Blog: []>, <Author: Etch []>) 160 >>> len(db.connection.queries) 161 1 162 163 # dive even deeper in absolute beauty, load only child fields without parent fields 164 >>> db.reset_queries() 165 >>> p3 = Entry.objects.fields(blog=(), blog__author=('id','name',)).select_related().get(headline="Etch_3") 166 >>> p3, p3.blog, p3.blog.author, p3.blog.author.id 167 (<Entry: []>, <Blog: []>, <Author: Etch []>, 1) 168 >>> len(db.connection.queries) 169 1 170 171 # check old-style values() 172 >>> d = Entry.objects.filter(blog__author__name='Lenny').values('id', 'headline')[0] 173 >>> print d['id'], d['headline'] 174 6 Lenny_0 175 >>> l = Entry.objects.values('id', 'headline').extra(select={'id_plus_1': 'id + 1'})[:2] 176 >>> [(d['id'], d['id_plus_1'], str(d['headline'])) for d in l] 177 [(1, 2, 'Etch_0'), (2, 3, 'Etch_1')] 178 179 # test models for docs/db-api.txt examples 180 >>> joe = Author.objects.create(name="Joe") 181 >>> blog = Blog.objects.create(id=1, name='Beatles Blog', about='All the latest Beatles news.', author=joe) 182 >>> entry = Entry.objects.create(headline='Joe about Beatles', content='Beatles was ...', blog=blog) 183 184 # load all fields from Entry and related models 185 >>> e = Entry.objects.select_related().get(headline='Joe about Beatles') 186 >>> e.headline, e.content, e.blog.name 187 (u'Joe about Beatles', u'Beatles was ...', u'Beatles Blog') 188 189 # don't load huge text field from Entry and only load name from related Blog 190 >>> e = Entry.objects.fields('headline', blog=('name',)).get(headline='Joe about Beatles') 191 >>> e.headline, e.content, e.blog.name 192 (u'Joe about Beatles', '', u'Beatles Blog') 193 194 >>> db.reset_queries() 195 >>> Entry.objects.values('headline', blog=('name',)).filter(headline__contains='Beatles') 196 [{'headline': u'Joe about Beatles', 'blog': {'name': u'Beatles Blog'}, 'blog_id': 1}] 197 >>> len(db.connection.queries) 198 1 199 >>> Entry.objects.values('headline', blog=('id', 'name',)).filter(headline__contains='Beatles') 200 [{'headline': u'Joe about Beatles', 'blog': {'id': 1, 'name': u'Beatles Blog'}, 'blog_id': 1}] 201 202 # Reset DEBUG to where we found it. 203 >>> settings.DEBUG = old_debug 204 """} -
AUTHORS
Property changes on: tests/modeltests/fields/models.py ___________________________________________________________________ Name: svn:keywords + Author Date Id Name: svn:eol-style + native
357 357 ymasuda@ethercube.com 358 358 Jarek Zgoda <jarek.zgoda@gmail.com> 359 359 Cheng Zhang 360 Dima Dogadaylo <http://www.mysoftparade.com/> 360 361 361 362 A big THANK YOU goes to: 362 363 -
docs/db-api.txt
536 536 However, if your query spans multiple tables, it's possible to get duplicate 537 537 results when a ``QuerySet`` is evaluated. That's when you'd use ``distinct()``. 538 538 539 `` values(*fields)``539 ``fields(*fields, **related_fields)`` 540 540 ~~~~~~~~~~~~~~~~~~~ 541 541 542 Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of 543 dictionaries instead of model-instance objects. 542 **New in Django development version** 544 543 544 Returns a ``QuerySet`` that allows to load only some of fields from this and 545 related models. 546 547 This example demonstrates effect of particular field loading:: 548 549 # load all fields from Entry and related models 550 >>> e = Entry.objects.select_related().get(headline='Joe about Beatles') 551 >>> e.headline, e.body_text, e.blog.name 552 (u'Joe about Beatles', u'Beatles was ...', u'Beatles Blog') 553 554 # don't load huge text field from Entry and only load name from related Blog 555 >>> e = Entry.objects.fields('headline', blog=('name',)).get(headline='Joe about Beatles') 556 >>> e.headline, e.body_text, e.blog.name 557 (u'Joe about Beatles', '', u'Beatles Blog') 558 559 ``fields()`` takes optional positional arguments, ``*fields``, which specify 560 field names of this model for to which the ``SELECT`` should be limited. 561 562 ``fields()`` also takes optional keyword arguments, ``**related_fields``, 563 which specify field names of related models to which the ``SELECT`` should be 564 limited. Each argument in ``**related_fields`` affects corresponding related 565 model in the same way like ``*fields`` affects master model. 566 567 You can reference related objects for any desired depth with standard Django 568 lookup syntax, for example: 569 570 Entry.objects.fields('headline', author__address__country=('name')) 571 572 The method ``fields()`` is extremelly usefull when you have models that 573 contain large text or binary fields and you don't want to load these heavy 574 fields. For example you need to show latest 10 blog posts and you only need 575 headlines of these blog posts and their author names, with ``fields`` you can 576 load only ``headline`` from ``Entry`` table and only ``name`` from ``Author`` 577 table (other fields of these 2 models will not be loaded and will have default 578 values). 579 580 With ``fields()`` you have full control on what fields will be loaded from 581 database, take this power with care. For example suppose ``Entry`` model 582 references ``Author`` model, that references ``Address`` model that have 583 foreign key to ``Country`` model. With call like 584 Entry.objects.fields('headline', author__address__country=('name')) 585 , you can load ``Entry.headline``, don't load fields from ``Author`` and 586 ``Address`` and load only name from ``Country`` assotiated with blog entry's 587 author. 588 589 ``values(*fields, **related_fields)`` 590 ~~~~~~~~~~~~~~~~~~~ 591 592 **New in Django development version** 593 594 Returns a ``QuerySet`` that evaluates to a list of dictionaries instead of 595 model-instance objects. 596 545 597 Each of those dictionaries represents an object, with the keys corresponding to 546 598 the attribute names of model objects. 547 599 … … 569 621 >>> Blog.objects.values('id', 'name') 570 622 [{'id': 1, 'name': 'Beatles Blog'}] 571 623 572 A ``ValuesQuerySet`` is useful when you know you're only going to need values 624 ``values()`` also takes optional keyword arguments, ``**related_fields``, 625 which specify field names of related models to which the ``SELECT`` should be 626 limited. Each argument in ``**related_fields`` affects corresponding related 627 model in the same way like ``*fields`` affects master model. 628 629 Example:: 630 631 >>> Entry.objects.values('headline', blog=('id', 'name',)).filter(headline__contains='Beatles') 632 [{'headline': u'Joe about Beatles', 'blog': {'name': u'Beatles Blog'}, 'blog_id': 1}] 633 >>> Entry.objects.values('headline', blog=('id', 'name',)).filter(headline__contains='Beatles') 634 [{'headline': u'Joe about Beatles', 'blog': {'id': 1, 'name': u'Beatles Blog'}, 'blog_id': 1}] 635 636 Note, when fields from related models is selected, primary keys of related 637 models also populated in parent model dictionary. 638 639 It is useful when you know you're only going to need values 573 640 from a small number of the available fields and you won't need the 574 641 functionality of a model instance object. It's more efficient to select only 575 642 the fields you need to use. 576 643 577 Finally, note a ``ValuesQuerySet`` is a subclass of ``QuerySet``, so it has all 578 methods of ``QuerySet``. You can call ``filter()`` on it, or ``order_by()``, or 644 Finally, note ``values()`` and ``fields()`` use same code for fields selecting 645 and only diferent format returned. All that you can do with ``values()`` you 646 can do with ``fields()`` and vise versa. And for sure after ``values()`` and 647 ``fields()`` you can call call ``filter()``, or ``order_by()``, or 579 648 whatever. Yes, that means these two calls are identical:: 580 649 581 650 Blog.objects.values().order_by('id')