MichaelM
MichaelM

Reputation: 5818

DurationField format in a ModelForm

I have a Django model that contains a duration field:

class Entry(models.Model):
    duration = models.DurationField()

And I want to render a form for this model using a ModelForm:

class EditEntryForm(forms.ModelForm):
    class Meta:
        model = Entry
        fields = ['duration']

Which is all working. However, if editing an existing model, the duration rendered in the text box is of the format HH:MM:SS

I will never be dealing with durations over an hour. How can I change how Django is formatting this field in the form to just be MM:SS?

I already have a custom template filter in use when rendering the model, I just can't figure out how to change how the form is rendered.

Thanks

Upvotes: 6

Views: 12581

Answers (2)

psychok7
psychok7

Reputation: 5473

In my case i needed to remove the milliseconds so i did what MichaelM suggested by

# -*- coding: utf-8 -*-

import datetime

from django import forms

from harvests.models import Harvest


def duration_string(duration):
    # Removing the milliseconds of the duration field
    days = duration.days
    seconds = duration.seconds
    microseconds = duration.microseconds

    minutes = seconds // 60
    seconds = seconds % 60

    hours = minutes // 60
    minutes = minutes % 60

    string = '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
    if days:
        string = '{} '.format(days) + string
    # if microseconds:
    #     string += '.{:06d}'.format(microseconds)

    return string


class CustomDurationField(forms.DurationField):
    def prepare_value(self, value):
        if isinstance(value, datetime.timedelta):
            return duration_string(value)
        return value


class HarvestForm(forms.ModelForm):
    work_time_interval = CustomDurationField()

    class Meta:
        model = Harvest
        fields = '__all__'

Upvotes: 3

solarissmoke
solarissmoke

Reputation: 31404

You should be able to do this by providing a custom widget for the field:

from django.forms.widgets import TextInput
from django.utils.dateparse import parse_duration

class DurationInput(TextInput):

    def _format_value(self, value):
        duration = parse_duration(value)

        seconds = duration.seconds

        minutes = seconds // 60
        seconds = seconds % 60

        minutes = minutes % 60

        return '{:02d}:{:02d}'.format(minutes, seconds)

and then you specify this widget on the field:

class EditEntryForm(forms.ModelForm):
    class Meta:
        model = Entry
        fields = ['duration']
        widgets = {
            'duration': DurationInput()
        }

Of course, this will cause weirdness if you do ever supply durations longer than an hour...

Upvotes: 6

Related Questions