2010-02-04 15 views
17

come suggerisce il titolo. Voglio aggiungere 30 giorni al campo DateField. Questo viene popolato automaticamente alla creazione del record utilizzando auto_now_add=TrueCome può il mio modello Datejeld modello django aggiungere 30 giorni al valore fornito?

Qualche idea su come procedere?

Grazie

+0

Questa è una supposizione, ma le forme Django consentono chiamate di funzione nelle loro '' valori iniziali =. Se questo è il caso anche per i modelli, puoi rimuovere auto_add_now e sostituirlo con 'default = lambda: datetime.now() + timedelta (days = 30)' –

risposta

26

// Aggiornamento

Il commento sotto il post originale mi ha fatto pensare. Credo che questa sia la soluzione migliore finora:

from datetime import datetime, timedelta 

class MyModel(models.Model): 
    mydate = models.DateTimeField(default=datetime.now()+timedelta(days=30)) 

// 2. Aggiornare

Se si desidera definire un attributo di modello che contiene la quantità di giorni che si dovrebbe essere aggiunto sarà necessario sovrascrivere il metodo di salvataggio. Finora non sono riuscito a trovare un modo più semplice.

Soluzione:

class MyModel(models.Model): 
    mydate = models.DateTimeField(editable=False) 
    daysadded = models.IntegerField() 

    def save(self): 
    from datetime import datetime, timedelta 
    d = timedelta(days=self.daysadded) 

    if not self.id: 
     self.mydate = datetime.now() + d 
     super(MyModel, self).save() 

Come becomingGuru già suggerito si dovrebbe ignorare i vostri modelli di risparmiare metodo.

Esempio:

class MyModel(models.Model): 
    mydate = models.DateTimeField(auto_now_add=True)  

    def save(self): 
    from datetime import timedelta 
    d = timedelta(days=30) 

    // only add 30 days if it's the first time the model is saved 
    if not self.id: 
     // not saving the model before adding the timedelta gave me errors 
     super(MyModel, self).save() 

     self.mydate += d 

     // final save 
     super(MyModel, self).save() 

questo non è il modo migliore per me dal momento che è necessario salvare il modello due volte. Tuttavia, utilizzando auto_now_add è necessario salvare il modello prima di creare un'istanza datetime per mydate.

Un altro approccio che richiederebbe un solo risparmiare:

class MyModel(models.Model): 
    mydate = models.DateTimeField(editable=False) // editable=False to hide in admin 

    def save(self): 
    from datetime import datetime, timedelta 
    d = timedelta(days=30) 

    // only add 30 days if it's the first time the model is saved 
    if not self.id: 
     self.mydate = datetime.now() + d 
     super(MyModel, self).save() 

Speranza che ha aiutato!

+0

Funziona perfettamente grazie! – dotty

+0

AGGIORNAMENTO: funzionato come previsto, tuttavia i 30 giorni diventeranno una variabile. Potrebbero essere 30 giorni, 60 giorni, 90 giorni, ecc. Qualche idea? Dovrei aggiungere un campo 'expires_in' che contiene il numero di giorni in cui scade? Come potrei usare questo nuovo campo 'expires_in' per modificare la riga "timedelta (days = 30)"? – dotty

+0

Ho capito bene? Vuoi un altro campo modello che contiene un valore che descrive quanti giorni verranno aggiunti? – Jens

2

Utilizzare Pythons timedelta:

from datetime import timedelta 
d = timedelta(days=30) 

# object is your current instance of the model 
object.yourdatefield += d 
# or this because I am not sure whether the previous works 
object.yourdatefield = object.yourdatefield + d 

object.save() 

E dal Django documentation:

DateField
una data, rappresentati in Python da un'istanza datetime.date.

Se si desidera aggiungere 30 giorni sulla creazione dell'oggetto, dimenticare auto_now_add=True e fare come suggerisce becomingGuru. Le informazioni relative alla sostituzione di save() si possono trovare anche nello Django documentation.

1

Ignorare il salvataggio sul modello e durante il salvataggio, controllare se popk è popolato.

>>> from datetime import datetime 
>>> from datetime import timedelta 
>>> cur_date = datetime.now() 
>>> cur_date 
datetime.datetime(2010, 2, 4, 5, 0, 24, 437405) 
>>> cur_date+timedelta(days=30) 
datetime.datetime(2010, 3, 6, 5, 0, 24, 437405) 
42

Non è necessario implementare il metodo di salvataggio personalizzato.

Anche questo default=datetime.now()+timedelta(days=30) è assolutamente sbagliato! Viene valutato quando si avvia l'istanza di Django. Se usi apache probabilmente funzionerà, perché su alcune configurazioni Apache revoca la tua applicazione django ad ogni richiesta, ma puoi comunque trovarti un giorno a guardare il tuo codice e cercare di capire perché questo viene calcolato non come ti aspetti.

Il modo giusto per farlo è passare un oggetto chiamabile all'argomento predefinito. Può essere una funzione datetime.today o una funzione personalizzata. Quindi viene valutato ogni volta che si richiede un nuovo valore predefinito.

def get_deadline(): 
    return datetime.today() + timedelta(days=20) 

class Bill(models.Model): 
    name = models.CharField(max_length=50) 
    customer = models.ForeignKey(User, related_name='bills') 
    date = models.DateField(default=datetime.today) 
    deadline = models.DateField(default=get_deadline) 
+3

Io uso questo molto! Particolarmente utile quando si desidera ottenere tutti i post che non sono più vecchi di 20 giorni o giù di lì. Basta usare 'BlogPost.objects.filter (pub_date__gt = datetime.now() - timedelta (days = 20) '. Questo si traduce in SQL ed è quindi molto efficace! [Riferimento in django docs] (https: //docs.djangoproject. it/it/dev/ref/models/querysets/# field-lookups) –

+0

@ mart0903 il tuo codice era proprio quello di cui avevo bisogno: 'BlogPost.objects.filter (pub_date__gt = datetime.now() - timedelta (days = 20)' In altre parole, solo oggetti con pub_date più recente di 20 giorni fa. –

+1

default = lambda: datetime.now() + timedelta (giorni = 30) – exshinigami

Problemi correlati