开发者

How to compare dates in Django templates

I would like to compare a date to the current date in Django, preferably in the template,开发者_StackOverflow中文版 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?


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.


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.


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


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


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.


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


You can have 2 tasks.

  1. 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.now(), since the second option does not contain time zone information. Use django.utils.timezone.now().
  2. You must style the object from the ListView. Then I advise you to use a custom filter that you will call in the template.
@register.filter
def compare_date(date):
   if not date:
      return False
   return date < timezone.now()


If you use Django, you could use the bellow code(https://stackoverflow.com/a/3798865/17050678). In your models.py

@property
def is_past_due(self):
    today = datetime.datetime.today()
    return today > self.start_date

But it will take an error to you. like this:

can't compare offset-naive and offset-aware datetimes

So you should take the timezone type like the bellow.

import pytz
@property
def is_past_due(self):
    today =     datetime.datetime.today().astimezone(pytz.timezone('Asia/Tokyo'))
    return today > self.start_date

Then you could compare it in your template.

{% if schedule.is_past_due %}
/*your code here*/
{% endif %}


I found this question and had a similar problem. I was looking to display information if it had only occurred in the past.

Using Django's "timesince" tag in the template I was able to solve my problem. I'm not saying it's efficient, but it works for me.

In Template:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜