2010-02-04 31 views
17

como sugiere el título. Quiero agregar 30 días al campo DateField. Esto se rellena automáticamente en la creación del registro usando auto_now_add=True¿Cómo puede mi modelo django DateField agregar 30 días al valor proporcionado?

Alguna idea de cómo ir haciendo esto?

Gracias

+0

Esta es una suposición, pero las formas de Django permite llamadas a funciones en sus valores iniciales '' =. Si este es el caso también para los modelos, entonces podrías eliminar auto_add_now y reemplazarlo por 'default = lambda: datetime.now() + timedelta (days = 30)' –

Respuesta

26

// Actualización

El comentario bajo el post original me hizo pensar. Creo que esta es la mejor solución hasta el momento:

from datetime import datetime, timedelta 

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

// 2. Actualizar

Si desea definir un atributo modelo que mantiene la cantidad de días que se debe añadirse van a necesitar anular el método guardar. Hasta ahora no podría encontrar una forma más simple.

Solución:

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() 

Como ya se ha sugerido becomingGuru debe reemplazar sus modelos ahorran método.

Ejemplo:

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() 

Esta no es la mejor manera para mí ya que hay que guardar el modelo dos veces. Pero el uso de auto_now_add requiere que guarde el modelo antes de crear una instancia de fecha y hora para mydate.

Otro enfoque que requeriría una sola ahorra:

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() 

esperanza de que ayudó!

+0

¡Funciona perfectamente gracias! – dotty

+0

ACTUALIZACIÓN: Funcionó como se esperaba, sin embargo, los 30 días van a ser una variable. Podría ser 30 días, 60 días, 90 días, etc. ¿Alguna idea? ¿Debo agregar un campo 'expires_in' que contiene la cantidad de días que caduca? ¿Cómo podría usar este nuevo campo 'expires_in' para editar la línea "timedelta (days = 30)"? – dotty

+0

¿Te entiendo correctamente? ¿Desea otro campo modelo que contenga un valor que describa la cantidad de días que se agregarán? – Jens

2

Use pitones 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() 

y desde el Django documentation:

DateField
una fecha, representada en Python por una instancia datetime.date.

Si desea agregar 30 días a la creación del objeto, olvídese de auto_now_add=True y hágalo como sugiere Guru. Información sobre primordial save() también se puede encontrar en el Django documentation.

1

Sustituir el ahorrar en el modelo y mientras que el ahorro, comprobar si pk está poblada.

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

No hay necesidad de poner en práctica la costumbre guardar método.

También haciendo esto default=datetime.now()+timedelta(days=30) es absolutamente incorrecto! Se evalúa cuando inicia su instancia de django. Si usas apache, probablemente funcione, porque en algunas configuraciones apache revoca tu aplicación django en cada solicitud, pero aún así puedes encontrarte revisando tu código e intentando averiguar por qué esto no se calcula como esperabas.

La forma correcta de hacerlo es pasar un objeto invocable al argumento predeterminado. Puede ser una función datetime.today o su función personalizada. Luego se evalúa cada vez que solicita un nuevo valor predeterminado.

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

¡Utilizo esto mucho! Especialmente útil cuando desea obtener todas las publicaciones que no tienen más de 20 días o menos. Solo use 'BlogPost.objects.filter (pub_date__gt = datetime.now() - timedelta (days = 20) '. Esto se traduce en SQL y por lo tanto es muy efectivo! [Referencia en django docs] (https: //docs.djangoproject. com/en/dev/ref/models/querysets/# field-searchups) –

+0

@ mart0903 su código era justo lo que necesitaba: 'BlogPost.objects.filter (pub_date__gt = datetime.now() - timedelta (days = 20)' En otras palabras, solo los objetos con pub_date son más nuevos que hace 20 días. –

+1

default = lambda: datetime.now() + timedelta (días = 30) – exshinigami

Cuestiones relacionadas