2010-09-26 66 views
33

Me gustaría comparar una fecha con la fecha actual en Django, preferiblemente en la plantilla, pero también es posible hacerlo antes de representar la plantilla. Si la fecha ya ha pasado, quiero decir "En el pasado", mientras que si es en el futuro, quiero dar la fecha.Cómo comparar fechas en Django

Tenía la esperanza de que se podría hacer algo como esto:

{% if listing.date <= now %} 
    In the past 
{% else %} 
    {{ listing.date|date:"d M Y" }} 
{% endif %} 

siendo ahora la fecha de hoy, pero esto no funciona. No pude encontrar nada sobre esto en los documentos de Django. ¿Alguien puede dar un consejo?

Respuesta

72

Compare la fecha en la vista y pase algo como in_the_past (booleano) al contexto_extra.

O mejor agrégalo a la modelo como una propiedad.

from datetime import date 

@property 
def is_past_due(self): 
    return date.today() > self.date 

A continuación, en la vista:

{% if listing.is_past_due %} 
    In the past 
{% else %} 
    {{ listing.date|date:"d M Y" }} 
{% endif %} 

Básicamente la plantilla no es el lugar para la comparación fecha de la OMI.

+0

Sí, estoy de acuerdo en que las plantillas no son el lugar para la comparación de fechas, pero en esta situación parecía mucho más elegante. En cualquier caso, finalmente implementé un método en my django Model, inPast(), que compara la fecha con la fecha actual y devuelve True si está en el pasado y de lo contrario es falso. Esto luego se llama desde la plantilla. Tu solución funciona igual de bien o mejor, solo tenía curiosidad por saber si había una forma de hacerlo en la plantilla. –

+2

No lo creo :(También desde el estilo de codificación y la refactorización de POV, es mucho mejor poder reproducir 'is_past_due' como una propiedad más avanzada, es decir, en otras plantillas; de lo contrario, tendrías que copiar y pegar el mismo código de plantilla una y otra vez. – bx2

+1

Si de verdad quieres guardar las fechas en la plantilla, debes pasar la fecha actual como extra_context y luego usar la etiqueta estándar 'if', pero esta no es una solución elegante. – bx2

0

Siempre puede pasar datetime.datetime.now (ya que los modelos django usan el objeto datetime estándar de Python).

Usando render_to_response, se podría hacer algo como esto (después de la importación de fecha y hora):

return render_to_response('template.html', {'now': datetime.datetime.now()}) 

Ahora que tiene acceso a "ahora" dentro de la plantilla, se puede comparar fechas al igual que lo hizo en su ejemplos.

Además, si usa RequestContext en sus vistas, podrá agregar "ahora" como context_processor si necesita esto en varios archivos. Esto agregará "ahora" a cualquier plantilla procesada con un RequestContext.

Sin embargo, es más realista que simplemente acaba de obtener la lista de registros que se encuentran hasta ahora en su queryset original y evitar la consulta de datos inútiles en el primer lugar:

listing.objects.filter(date__lt=datetime.datetime.now()) 
+0

El filtrado sería recomendable en la mayoría de las situaciones, pero en mi situación este no es el efecto deseado: tengo una lista de elementos con ciertas fechas de lanzamiento, y Quisiera diferenciar entre los artículos que ya se han lanzado y los que aún están por lanzar, pero ambos son relevantes para la búsqueda. Por alguna razón, la variable 'ahora', como usted propuso, no funcionó para mí. ssumed el problema fue el mayor que la comparación en la declaración if, aparentemente eso no está disponible en todas las versiones de Django. –

+0

Es necesario tener fecha y hora importada con este código: fecha y hora de importación Si ha utilizado: de fecha y hora de importación de fecha y hora Entonces sería el método adecuado, datetime.now() en lugar de datetime.datetime.now() Esto debería funcionar en todas las versiones de django. ¿Qué versión está utilizando? – monokrome

9

añadí date_now a mi lista de procesadores de contexto.

Así que en la plantilla hay una variable llamada "date_now", que es sólo datetime.datetime.now()

Hacer un procesador de contexto llamada date_now en el archivo context_processors.py

import datetime 

def date_now(request): 
    return {'date_now':datetime.datetime.now()} 

Y en settings.py, modificar CONTEXT_PROCESSORS incluirlo, en mi caso es

app_name.context_processors.date_now 
1

Además @ bx2 respuesta beneficiosa, si el campo es un campo de fecha y hora sólo llame d comió() para modelos DateTimeField:

from datetime import date 

@property 
def is_past_due(self): 
    if date.today() > self.date.date(): 
     return True 
    return False 
0

me encontré con esta pregunta y tenía un problema similar. Estaba buscando mostrar información si solo había ocurrido en el pasado.

Usando la etiqueta "timesince" de Django en la plantilla, pude resolver mi problema. No digo que sea eficiente, pero funciona para mí.

En Plantilla:

{% if model_name.date_time|timesince >= "1 min" %} 
    <p>In the past</p> 
{% else %} 
    <p>{{ model_name.date_time }}</p> 
{% endif %} 
+0

Eso ni siquiera se recomienda como una solución rápida, ya que está comparando cadenas. Después de un día estás comparando '" 1 día "> =" 1 min "' que es 'False' mientras esperas' True' – blacklwhite

7

A partir de Django 1.8 el siguiente constructo poco de mal gusto se encarga del trabajo:

{% now "Y-m-d" as todays_date %} 
{% if todays_date < someday|date:"Y-m-d" %} 
    <h1>It's not too late!</h1> 
{% endif %} 

hacker, pero evita la necesidad de una etiqueta personalizada o procesador de contexto.