Sam Odio
Sam Odio

Reputation: 3037

values_list does not use to_python in custom model fields?

I seem to have stumbled across a quirk in Django custom model fields. I have the following custom modelfield:

class PriceField(models.DecimalField):
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        try:
            return Price(super(PriceField, self).to_python(value))
        except (TypeError, AttributeError):
            return None

    def get_db_prep_value(self, value):
        return super(PriceField, self).get_db_prep_value(value.d if value else value)

    def value_to_string(self, instance):
        return 'blah'

Which should always return the custom Price class in python. This works as expected:

>>> PricePoint.objects.all()[0].price
Price('1.00')

However when retrieving prices in the form of a values_list I get decimals back:

>>> PricePoint.objects.all().values_list('price')
[(Decimal('1'),)]

Then if I change the DB type to foat and try again I get a float:

>>> PricePoint.objects.all().values_list('price')
[(1.0,)]
>>> type(PricePoint.objects.all().values_list('price')[0][0])
<type 'float'>

This makes me think that values_list does not rely on to_python at all and instead just returns the type as defined in the database. Is that correct? Is there any way to return a custom type through values_list?

Upvotes: 4

Views: 745

Answers (2)

Barry Hurley
Barry Hurley

Reputation: 577

Just to note that this was resolved in Django 1.8 with the addition of the from_db_value method on custom fields.

See https://docs.djangoproject.com/en/1.8/howto/custom-model-fields/#converting-values-to-python-objects

Upvotes: 0

Sam Odio
Sam Odio

Reputation: 3037

Answered my own question: This apparently is a Django bug. values_list does not deserialize the database data.

It's being tracked here: https://code.djangoproject.com/ticket/9619 and is pending a design decision.

Upvotes: 3

Related Questions