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
-~----------~----~----~----~------~----~------~--~---

Reply via email to