Django provides quite a few built-in template filters right out of the box. However, eventually you might need them to work in a specific way that isn't quite the default behavior. In my case, the django date filter worked great, but I needed something specific:
By default, the date filter takes a value, along with a formatting argument, and returns a "rendered" string:
{{ value|date:"F d, Y P" }}
This would render as:
January 18, 2009 1:30 p.m.
However, what happens if time information is entered for some datetime's and not for others? We end up with stuff like "January 18, 2009 midnight". Not what I wanted.
Turns out it's quite easy to not only implement your own custom filters, but also to tap the power of the built-in filters as well. To achieve the functionality I was looking for, my custom filter needed to...
- Work just like the default date filter, taking an argument of format
- Check if there was no time information on the datetime
- Remove the time formatting if so
Starting out, here's the base custom filter, along with the code to remove time arguments from the formatting argument:
import re
@register.filter
def smart_date(value, arg):
if value.hour == 0 and value.minute == 0 and value.second == 0:
arg = re.sub(r'[aAfgGhHijlLPOsTZ]', '', arg)
What I did not want to do was re-implement the functionality of the date filter. However, it's easy to bring that functionality into your custom filter by simply importing it (yeah, it's really that easy).
Here's my completed "smart_date" tag:
import re
from django.template.defaultfilters import date as date_filter
@register.filter
def smart_date(value, arg):
if not value.time():
# remove all time-related formatting
arg = re.sub(r'[aAfgGhHijlLPOsTZ]', '', arg)
return date_filter(value, arg)