Keeping DRY with custom Django templatetags
I have an existing templatetag, show_next_event
:
def show_next_event():
try:
e = Event.objects.filter(published='1').order_by('date').filter(date__gte=datetime.date.today())[0]
except IndexError:
e = ''
return {'event': e}
register.inclusion_tag('events/next_event.html')(show_next_event)
I'd like to abstract the template. First thing that comes to mind is to change show_next_event
to just next_event
and then add two new functions; show_next_event
and show_next_event_badge
. Im hoping I can do something like the following but it doesn't work as-is:
def next_event():
try:
e = Event.objects.filter(p开发者_如何学运维ublished='1').order_by('date').filter(date__gte=datetime.date.today())[0]
except IndexError:
e = ''
return {'event': e}
def show_next_event():
next_event
register.inclusion_tag('events/next_event.html')(show_next_event)
def show_next_event_badge():
next_event
register.inclusion_tag('events/next_event_badge.html')(show_next_event_badge)
Or is there an even better solution?
Django is Python, not Ruby. You can't call a function just by specifying its name: you need to use the calling parentheses. And Python doesn't automatically return the value of the last expression in the function: you need to use the return
statement.
So, this should work:
@register.inclusion_tag('events/next_event_badge.html')
def show_next_event_badge():
return next_event()
Also, note that I've used the decorator syntax to register the tag.
After following @Daniel suggestions, you could do this to avoid the def
s (DRY!) :
show_next_event = next_event
show_next_event_badge = next_event
EDIT:
It would be like this:
def next_event():
try:
e = Event.objects.filter(published='1').order_by('date').filter(date__gte=datetime.date.today())[0]
except IndexError:
e = ''
return {'event': e}
show_next_event = next_event
show_next_event_badge = next_event
register.inclusion_tag('events/next_event.html')(show_next_event)
register.inclusion_tag('events/next_event_badge.html')(show_next_event_badge)
精彩评论