Personally, I would simply pass in the book as a context variable via the view. That way you have no need for a template tag.
Alternately, you could use the inclusion_tag decorator instead, which wraps up the idea of rendering an include template with a custom context into the current document.
But if you want to continue on the current path, the simple_tag
decorator isn't the way to go. It's for use when you need to return a string
which you want rendered directly into the template. What you're trying to do is set a template context variable. This is a bit more involved, but not too difficult. Create a node something like this:
class LastBooksNode(template.Node):
def __init__(self, category, cutoff=5, var_name='books'):
self.category = category
self.cutoff = cutoff
self.var_name = var_name
def render(self, context):
context[self.var_name] = Books.objects.filter(category=self.category)[:self.cutoff]
return ''
@register.tag(name='last_books')
def do_last_books(parser, token):
error = False
try:
tag_name, category, cutoff, _as, var_name = token.split_contents()
if _as != 'as':
error = True
except:
error = True
if error:
raise TemplateSyntaxError, 'last_books must be of the form, "last_books <category> <cutoff> as <var_name>"'
else:
return LastBooksNode(a_cat, cutoff, var_name)
You would then invoke the template tag with:
{% import <your tag library> %}
{% last_books 'category' 5 as my_books %}
{% for book in my_books %}
....
{% endfor %}
Untested, but I hope this demonstrates the idea. As mentioned above, though, passing the books directly to the view via the context or using an inclusion_tag may be easier if you don't intend to reuse this in multiple places.