views:

65

answers:

1

Can I change the default __str__() function of the datetime.datetime object? By default, it returns something like '2010-06-28 12:43:56.985790', and i need it to print something like '2010-06-28T12:44:21.241228'(which is the isoformat() function).

I need this for JSON serializing of a django model.

My model is:


class Transport(models.Model):
    user = models.ForeignKey(User)
    source = models.ForeignKey(Marker, related_name="source_marker")
    destination = models.ForeignKey(Marker, related_name="destination_marker")
    object = models.CharField(choices=possesion_choices, max_length=2**6)
    quantity = models.IntegerField()
    time_sent = models.DateTimeField()
    time_arrived = models.DateTimeField()

And when i serialize it (using the wadofstuff module), it prints something like


print serializers.serialize('json', Transport.objects.all(), relations=('source', 'destination',)  indent=4)
[
    {
        "pk": 1, 
        "model": "main.transport", 
        "fields": {
            [.. bla bla ..]
            "time_sent": "2010-06-28 12:18:05", 
            "time_arrived": "2010-06-28 12:38:36", 
            [.. bla bla ..]
        }
    }
]

+2  A: 

Django uses a field's value_to_string method to provide the string representation within a serializer. So you could define a custom field subclass that overrides this method:

class MyDateTimeField(DateTimeField)
    def value_to_string(self, obj):
        val = self._get_val_from_obj(obj)
        if val is None:
            data = ''
        else:
            data = val.isoformat()
        return data

Edited

Aargh, looks like I was looking in completely the wrong place. The serializers.python.Serializer.handle_field method actually checks for date-time fields and passes them through unchanged to the JSON encoder. So it's that encoder that we actually need to override.

class MyJSONEncoder(DjangoJSONEncoder):
    def default(self, o):
        if isinstance(o, datetime.datetime):
            return o.isoformat()
        else:
            return super(MyJSONEncoder, self).default(o)

Unfortunately, wadofstuff hardcodes the original DjangoJSONEncoder, so we'll need to override the serializer too.

from wadofstuff.django.serializers.json import Serializer
class BetterSerializer(Serializer):
    """
    Convert a queryset to JSON.
    """
    def end_serialization(self):
        """Output a JSON encoded queryset."""
        self.options.pop('stream', None)
        self.options.pop('fields', None)
        self.options.pop('excludes', None)
        self.options.pop('relations', None)
        self.options.pop('extras', None)
        simplejson.dump(self.objects, self.stream, cls=MyJSONEncoder,
            **self.options)
Daniel Roseman
Took me a while to find the documentation for this. It's here in the custom fields page - http://docs.djangoproject.com/en/1.2/howto/custom-model-fields/#converting-field-data-for-serialization
pycruft
Apparently, this does not work. The output is the same. Strange, since the documentation says it should be done like that.
Gabi Purcaru