On Sun, 2007-11-04 at 04:08 +0100, Stefan Foulis[spiderware gmbh] wrote: > Hi > I've tried to create a custom Field for the database to store > Timedelta objects. Since I only need exactness to the minute and won't > have any large timedeltas I'm using a simple Integer to store it in > the database. Maybe I'll make this configurable later. > > this is the code: > ============ > from django.db.models.fields import IntegerField, Field > from django.core import validators > import datetime > from contrib.numeric_utilities import timedelta2minutes > > class TimedeltaField(IntegerField): > def to_python(self, value): > # turns the integer saved in the database to a python > timedelta object > if value is None: > return value > if isinstance(value, datetime.timedelta): > return value > validators.isInteger(str(value), None) > try: > return datetime.timedelta(minutes=int(value)) > except (TypeError, ValueError): > raise validators.ValidationError, u"This value must be an > integer (it gets converted to a Timedelta)" > def get_db_prep_save(self, value): > # Turns the input into a integer of minutes for save in db > if isinstance(value, datetime.timedelta): > value = timedelta2minutes(int(value)) > return Field.get_db_prep_save(self, value) > def get_internal_type(self): > return "IntegerField" > ========= > timedelta2minutes is a simple function that returns an integer. > > > On the commandline: > ================= > >>> from mytest.models import *; > >>> t = MyTest.objects.all()[0] > >>> t.a_timedelta > 2342 > >>> type(t.a_timedelta) > <type 'int'> > >>> t.validate() > {} > >>> t.a_timedelta > datetime.timedelta(0, 39960) > >>> type(t.a_timedelta) > <type 'datetime.timedelta'> > ========== > > So... until I run validate()
Firstly, don't rely on validate() at the moment. It doesn't fully work (which is why, for example, it's not documented or advertised at all). > at least once the field returns the int > from the database instead of the converted value from to_python(). I > ran some tests with print statements in the to_python methods... they > never get called until validate() is run. The same for the built-in > DateField, but there the value still gets magically returned as a > datetime.date object. What is stored in the model attributes is exactly what the database gives us back, at the moment. There's nothing magical about datetime objects -- all the database wrappers convert datetime columns into Python datetime objects. What needs to be changed for field subclassing -- and I keep meaning to finish this work, along with my 5 other highest priorities -- is that for custom fields (only!) we install attributes as part of contribute to class so that, via Python's descriptor protocol (__set__ and __get__) conversion automatically happens. You can actually do that manually now, it's just not as easy as it could be. To see how to do it now, have a look at the Django OSCON 2007 slides (see [1]). Jeremy Dunck presented some stuff there about field subclassing (starting at slide 107) that includes discussion of the descriptor protocol. [1] http://toys.jacobian.org/presentations/2007/oscon/tutorial/ All we'll add to Django to make that stuff easier is probably a metaclass that you can use so that you only need to implement to_python() and a few other things and it will automatically do the contribute_to_class() portion and set up __set__() and __get__() for you. So no extra functionality, just a nicer wrapper. Regards, Malcolm -- Why be difficult when, with a little bit of effort, you could be impossible. http://www.pointy-stick.com/blog/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---