Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare dates in Django templates

I would like to compare a date to the current date in Django, preferably in the template, but it is also possible to do before rendering the template. If the date has already passed, I want to say "In the past" while if it is in the future, I want to give the date.

I was hoping one could do something like this:

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

With now being today's date, but this does not work. I couldn't find anything about this in the Django docs. Can anyone give some advice?

like image 574
Herman Schaaf Avatar asked Sep 26 '10 16:09

Herman Schaaf


People also ask

How to compare dates in django template?

You must show the object using DetailView. You can solve this problem by using a function that passes a boolean value to the template. However, keep in mind that in django you cannot compare a date from a SQL database with datetime. datetime.

How do you compare datetime dates?

Use the datetime Module and the < / > Operator to Compare Two Dates in Python. datetime and simple comparison operators < or > can be used to compare two dates. The datetime module provides the timedelta method to manipulate dates and times.

What does @property do in Django?

In Python, the @property decorator allows you to call custom model methods as if they were normal model attributes. For example, if you have the following greeting method, class Person: def __init__(self, first_name): self.


6 Answers

Compare date in the view, and pass something like in_the_past (boolean) to the extra_context.

Or better add it to the model as a property.

from datetime import date

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

Then in the template:

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

Basically the template is not the place for date comparison IMO.

like image 177
bx2 Avatar answered Sep 30 '22 12:09

bx2


As of Django 1.8 the following slightly distasteful construct does the job:

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

Hackish, but it avoids the need for a custom tag or context processor.

like image 42
Dirk Bergstrom Avatar answered Sep 30 '22 12:09

Dirk Bergstrom


I added date_now to my list of context processors.

So in the template there's a variable called "date_now" which is just datetime.datetime.now()

Make a context processor called date_now in the file context_processors.py

import datetime

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

And in settings.py, modify CONTEXT_PROCESSORS to include it, in my case it's

app_name.context_processors.date_now
like image 39
adiktofsugar Avatar answered Sep 30 '22 12:09

adiktofsugar


addition to @bx2 beneficial answer, if your field is a datetime field just call date() function to models datetimefield:

from datetime import date

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

EDIT: i think this could be shrunken to:

from datetime import date

@property
def is_past_due(self):
    return date.today() > self.date.date()
like image 27
Evren Kutar Avatar answered Sep 30 '22 12:09

Evren Kutar


I believe the easiest way to achieve this is by importing datetime in your views.py and passing today's date as context data.

context['today'] = datetime.date.today()

Then in the template tags you could do something like this.

 {% if listing.date < today % }

This way if you are passing a list of objects as context, you can apply the filter to each line as you output it in the HTML template. I had a list of items that I had filtered out and was using Bootstrap to stylize as I displayed them. I wanted to make overdue dates stand out and applied the filtering only if one of my dates was less than today's date.

like image 20
Sherd Avatar answered Sep 30 '22 13:09

Sherd


You can always pass datetime.datetime.now (since django models use Python's standard datetime object).

Using render_to_response, you could do something like this (after importing datetime):

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

Now that you have access to "now" inside of the template, you can compare dates just like you did in your examples.

Furthermore, if you use RequestContext in your views - you will be able to add "now" as a context_processor if you need this in multiple files. This will add "now" to any template rendered with a RequestContext.

However, it is more realistic that you simply just get the list of records that are before now in your original queryset and avoid querying for useless data in the first place:

listing.objects.filter(date__lt=datetime.datetime.now())
like image 38
monokrome Avatar answered Sep 30 '22 12:09

monokrome