2009-04-29 12 views
24

Dzięki inspectdb udało mi się uzyskać pole "interwałowe" z postgres do django. W Django był to TextField. Obiekt, który otrzymałem, był rzeczywiście obiektem timedelta!Jak umieścić timedelta w modelu django?

Teraz chcę umieścić obiekt timedelta w nowym modelu. Jaki jest najlepszy sposób na zrobienie tego? Ponieważ oddanie timedelta w TextField skutkuje wersji str przedmiotu ...

Odpowiedz

27

Można trywialnie znormalizować timedelta do pojedynczej liczby zmiennoprzecinkowej w dniach lub sekund .

Oto wersja "Normalizuj na dni".

float(timedelta.days) + float(timedelta.seconds)/float(86400) 

Możesz przeliczyć liczbę zmiennoprzecinkową na timedelta.

>>> datetime.timedelta(2.5) 
datetime.timedelta(2, 43200) 

Przechowuj więc timedelta jako spławik.

Oto wersja "Normalize to Seconds".

timedelta.days*86400+timedelta.seconds 

Oto odwrotna (używając sekund)

datetime.timedelta(someSeconds/86400) 
+1

Oczywiście masz na myśli float (timedelta.days) + float (timedelta.seconds)/float (86400) ... ale działa! –

+0

@Jack Ha: Dzięki za zauważenie problemu. –

+0

timedelta.days + timedelta.seconds/86400.0 – aehlke

7

Po pierwsze, określenie modelu:

class TimeModel(models.Model): 
    time = models.FloatField() 

Aby zapisać obiekt timedelta:

# td is a timedelta object 
TimeModel.objects.create(time=td.total_seconds()) 

Aby uzyskać obiekt timedelta z bazy danych:

# Assume the previously created TimeModel object has an id of 1 
td = timedelta(seconds=TimeModel.objects.get(id=1).time) 

Uwaga: Używam Python 2.7 dla tego przykładu.

+1

na pythonie z wersją niższą niż 2.7 może być używana formuła: 'total_seconds = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6)/10 ** 6' – Pol

+0

To jest świetne . Dziękujemy za zwięzłość i dokładność. –

3
Nie

to bilet, który sięga do lipca 2006 r to: https://code.djangoproject.com/ticket/2443

Kilka łatki zostały napisane, ale ten, który został włączony do projektu: https://github.com/johnpaulett/django-durationfield

porównaniu do wszystkich innych Odpowiedzi na ten projekt są dojrzałe i zostałyby scalone do rdzenia, z wyjątkiem tego, że jego włączenie jest obecnie uważane za "rozdęte".

Osobiście właśnie wypróbowałem kilka rozwiązań i to jest ta, która działa pięknie.

from django.db import models 
from durationfield.db.models.fields.duration import DurationField 

class Event(models.Model): 
    start = models.DateTimeField() 
    duration = DurationField() 

    @property 
    def finish(self): 
     return self.start + self.duration 

Wynik:

$ evt = Event.objects.create(start=datetime.datetime.now(), duration='1 week') 
$ evt.finish 
Out[]: datetime.datetime(2013, 6, 13, 5, 29, 29, 404753) 

A Admin:

Zmiana zdarzenia

trwania: 7 days, 0:00:00

+1

Wygląda na to, że w Django 1.8 bilet zostanie ostatecznie zamknięty, a Django będzie miał nazwę "DurationField": https://docs.djangoproject.com/en/dev/releases/1.8/# new-data-types – nnyby

2

Wyrażając to tam przyczyna może być inna droga do Rozwiąż ten problem. najpierw zainstalować tę bibliotekę: https://pypi.python.org/pypi/django-timedeltafield

wówczas:

import timedelta 

class ModelWithTimeDelta(models.Model): 
    timedeltafield = timedelta.fields.TimedeltaField() 

ciągu administratora zostaniesz poproszony o wpisanie danych do pola z następującym formacie: 3 dni, 4 godziny, 2 minuty

+0

Preferuję to rozwiązanie z Django 1.7, ponieważ jest w repozytorium pip, a nie z zewnętrznego źródła. –