Trouble upgrading ModelField class for django 1.10

22 views
Skip to first unread message

Alexis Roda

unread,
Jun 3, 2017, 8:44:07 AM6/3/17
to django...@googlegroups.com

Hi,

I have a custom ModelField (HorariField, a simple weekly timetable) written for django 1.7 and I'm trying to upgrade it to work with django 1.10, so I have removed the SubfieldBase metaclass and added the from_db_value method. The field inherits from CharField and stores Horari instances that are serialized to/from strings like "mo,tu,we:08:00-14:00", it works like the HandField in the django docs.

After the changes I'm getting errors when serializing to json the models that have that kind of field:

TypeError: <hera_django.lib.horari.Horari object at 0x7fb3f1e619d0> is not JSON serializable

I'm not using the django serializers. The json serialization look like:

json.dumps(list(result), cls=DjangoJSONEncoder)

where result is a ValuesQuerySet.

After some debugging it seems that with the old HorariField class the json serializer already receives a serialized value, so it worked until now, but upgrading the field class the serializer receives an Horari instance.

I'm wondering if I'm missing something, some magic provided by SubfieldBase that I've no replicated in the new class, or this is how it's supposed to work and I need to take care of this in the serializer.


Here's the code for the field:

class HorariField(models.CharField):
    description = _(u"Horari")

    def __init__(self, *args, **kwargs):
        if "max_length" not in kwargs:
            kwargs["max_length"] = 188
        if "default" not in kwargs:
            kwargs["default"] = None
        super(HorariField, self).__init__(*args, **kwargs)

    def get_internal_type(self):
        return "CharField"

    def from_db_value(self, value, expression, connection, context):
        if value is None:
            return None
        return horari.Horari(value)

    def to_python(self, value):
        if isinstance(value, horari.Horari):
            return value
        return horari.Horari(value)

    def get_prep_value(self, value):
        if value is None:
            return None
        return value.to_str()

    def formfield(self, form_class=fields.HorariField, **kwargs):
        return super(HorariField, self).formfield(form_class=form_class, **kwargs)

I've tried defining the value_to_string method but I get the same error. The method it's never called. I assume that it's meant for django serializers' consumption.


TIA

Simon Charette

unread,
Jun 3, 2017, 10:27:07 AM6/3/17
to Django users
Hello Alexis,

As you've noticed Django 1.8 changed values()/values_list() to converts values returned
from the database just like any other ORM method[0].

If you want to use the json module to serialize your horari.Horari instances you'll have
to define your own JSONEncoder (or DjangoJSONEncoder) subclass.

class ToStrJSONEncoder(DjangoJSONEncoder):
    def default(o):
        if hasattr(o, 'to_str'):
            return o.to_str()
        return super().default(o)

Cheers,
Simon

Alexis Roda

unread,
Jun 3, 2017, 12:37:50 PM6/3/17
to django...@googlegroups.com
El 03/06/17 a les 16:27, Simon Charette ha escrit:
> Hello Alexis,
>
> As you've noticed Django 1.8 changed values()/values_list() to
> converts values returned
> from the database just like any other ORM method[0].
>
> If you want to use the json module to serialize your horari.Horari
> instances you'll have
> to define your own JSONEncoder (or DjangoJSONEncoder) subclass.
>
> class ToStrJSONEncoder(DjangoJSONEncoder):
> def default(o):
> if hasattr(o, 'to_str'):
> return o.to_str()
> return super().default(o)
>
> Cheers,
> Simon
>
> [0] https://docs.djangoproject.com/en/1.8/releases/1.8/#subfieldbase

Thank you Simon!

I've missed this change. I should spend some time rereading the changelogs.


Regards

Reply all
Reply to author
Forward
0 new messages