Storing passages of time

by Marty Alchin on November 3, 2007 about Django

One thing I need for VGMix is the ability to store the length of a song in a Django model. There are date and time features, but nothing for just a length of time, unrelated to any particular point in time. I did a bit of searching and found a ticket to add an IntervalField to Django, but no patches were provided.

So naturally, I decided to investigate and write a patch for it. The result is attached to that ticket, and does the job fairly well. It’s not quite finished yet, but there’s been some interest in this feature, so I thought I’d document what I’ve done so far.

Please note that I haven’t provided this separately yet, so if you want to try this out before it gets into trunk, you’ll have to copy the code out of the patch and put it into a module in your project and use it from there. Please don’t go patching your Django source.

Basically, this patch just adds a DurationField to Django, both for models and newforms. It validates user input and converts it to a Python timedelta object.

Models

Using DurationField in a model is as simple as anything else. Just include a line like the following in your model and enjoy the benefits:

class Song(models.Model):
    title = models.CharField(maxlength=255)
    length = models.DurationField()

This will store the value in the database the same way as a DecimalField, but this allows it to maintain all the precision that a timedelta supports. Unfortunately, the admin presents it the same as a DecimalField as well, since the existing admin is a bit difficult to extend in that way. So editing it in the admin will require entering values as the number of seconds to be saved.

If you’re using newforms-admin, it will use the newforms widget described below.

Forms

You can also use DurationField in any newforms form, by using the same code described above:

class Song(forms.Form):
    title = forms.CharField()
    length = forms.DurationField()

This will automatically use an improved widget, which presents the value as a set of input fields in the following format:

days, : : .

This is the same format timedelta uses when displaying its string equivalent, and seemed the most straightforward to me. The biggest downfall to the patch as it stands is that you must supply a value for each portion of the field. If you don’t need to include days, for instance, just supply a 0 instead. It’s unfortunate, and will be fixed in the future, but it’s not there yet.

Going forward

This will be improved and polished up in the near future, so things will get better. However, there’s no telling how long it will be before it’s ready to make it into Django proper. If I get it finished up fairly soon, I may make it available as a separate download for use until it gets in the main distribution.