Ticket #3050: values-5383.diff

File values-5383.diff, 3.4 KB (added by Honza Král <Honza.Kral@…>, 8 years ago)

updated for current trunk (revision 5383)

  • django/db/models/query.py

     
    554554class ValuesQuerySet(QuerySet):
    555555    def __init__(self, *args, **kwargs):
    556556        super(ValuesQuerySet, self).__init__(*args, **kwargs)
    557         # select_related and select aren't supported in values().
     557        # select_related isn't supported in values().
    558558        self._select_related = False
    559         self._select = {}
    560559
    561560    def iterator(self):
    562561        try:
     
    566565
    567566        # self._fields is a list of field names to fetch.
    568567        if self._fields:
    569             columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
     568            #columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
     569            if not self._select:
     570                columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
     571            else:
     572                columns = []
     573                for f in self._fields:
     574                    if f in [field.name for field in self.model._meta.fields]:
     575                        columns.append( self.model._meta.get_field(f, many_to_many=False).column )
     576                    elif not self._select.has_key( f ):
     577                        raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
     578
    570579            field_names = self._fields
    571580        else: # Default to all fields.
    572581            columns = [f.column for f in self.model._meta.fields]
    573582            field_names = [f.attname for f in self.model._meta.fields]
    574583
    575584        select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
     585
     586        # Add any additional SELECTs.
     587        if self._select:
     588            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
     589
    576590        cursor = connection.cursor()
    577591        cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
    578592        while 1:
  • tests/modeltests/lookup/models.py

     
    131131[('headline', 'Article 7'), ('id', 7)]
    132132[('headline', 'Article 1'), ('id', 1)]
    133133
     134
     135# you can use values() even on extra fields
     136>>> for d in Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_one'):
     137...     i = d.items()
     138...     i.sort()
     139...     i
     140[('id', 5), ('id_plus_one', 6)]
     141[('id', 6), ('id_plus_one', 7)]
     142[('id', 4), ('id_plus_one', 5)]
     143[('id', 2), ('id_plus_one', 3)]
     144[('id', 3), ('id_plus_one', 4)]
     145[('id', 7), ('id_plus_one', 8)]
     146[('id', 1), ('id_plus_one', 2)]
     147
     148# however, an exception FieldDoesNotExist will still be thrown
     149# if you try to access non-existent field (field that is neither on the model nor extra)
     150>>> Article.objects.extra( select={'id_plus_one' : 'id + 1'} ).values('id', 'id_plus_two')
     151Traceback (most recent call last):
     152    ...
     153FieldDoesNotExist: Article has no field named 'id_plus_two'
     154
    134155# if you don't specify which fields, all are returned
    135156>>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}]
    136157True
Back to Top