I'm building a homepage for a django project with Zinnia installed that will show the latest entries from each category. Here, Fantomas42 suggested that registering a new templatetag that took the get_recent_entries tag and added a filter clause would be the best way to achieve this.
I tried to look at the other templatetags to gather how to write this filter clause through context clues but the tags are designed to work dynamically, rather than grab anything specifically named, so I couldn't quite parse how to write a clause that would filter for a specific category.
I'm not sure whether it'd be best to write the clause to filter for a slug (in this case, the slug for the category is political-beat), category name via string ("The Political Beat"), or via the category's position in the category tree (this would be position 1, as it's the only category registered this far -- unless it would be 0... again, I really wish I had time to step back and take a few python tutorials...).
For context, here are some of the other templatetags registered by Zinnia:
@register.inclusion_tag('zinnia/tags/dummy.html', takes_context=True)
def get_categories(context, template='zinnia/tags/categories.html'):
"""
Return the published categories.
"""
return {'template': template,
'categories': Category.published.all().annotate(
count_entries_published=Count('entries')),
'context_category': context.get('category')}
@register.inclusion_tag('zinnia/tags/dummy.html', takes_context=True)
def get_categories_tree(context,
template='zinnia/tags/categories_tree.html'):
"""
Return the categories as a tree.
"""
return {'template': template,
'categories': Category.objects.all(),
'context_category': context.get('category')}
@register.inclusion_tag('zinnia/tags/dummy.html', takes_context=True)
def get_authors(context, template='zinnia/tags/authors.html'):
"""
Return the published authors.
"""
return {'template': template,
'authors': Author.published.all().annotate(
count_entries_published=Count('entries')),
'context_author': context.get('author')}
@register.inclusion_tag('zinnia/tags/dummy.html')
def get_recent_entries(number=5,
template='zinnia/tags/entries_recent.html'):
"""
Return the most recent entries.
"""
return {'template': template,
'entries': Entry.published.all()[:number]}
@register.inclusion_tag('zinnia/tags/dummy.html')
def get_featured_entries(number=5,
template='zinnia/tags/entries_featured.html'):
"""
Return the featured entries.
"""
return {'template': template,
'entries': Entry.published.filter(featured=True)[:number]}
@register.inclusion_tag('zinnia/tags/dummy.html')
def get_draft_entries(number=5,
template='zinnia/tags/entries_draft.html'):
"""
Return the last draft entries.
"""
return {'template': template,
'entries': Entry.objects.filter(status=DRAFT)[:number]}
I'm kind of experimenting with the solution blindly, but if I happen to stumble upon it, I'll update with an answer!
EDIT: Here's a photo of the home template I'm integrating with Zinnia, in case it's helpful in clarifying the goal of creating the new templatetag(s).
This isn't the prettiest solution (mainly because you have to select your category in two places, if you want to keep your sitemap in order), but it does allow you to get recent entries based on their respective categories, and I want to share it in case somebody else who lacks thorough expertise in python is looking to implement this functionality.
And, if you are proficient with python, maybe this solution will upset you enough to post a better one :)
From the context clues I could gather from Zinnia's other templatetags, I deduced that if "Featured=True" filtered by "Featured" entries, then maybe I could extend the entry model in the admin to included other types of "Featured" checkboxes, which would correspond with the categories of the entry posted. In this case, I added "Featured_politics."
I then made changes to the following files (essentially, I searched for "featured" throughout the project, and copy/pasted the corresponding code, and changed "featured" to "featured_politics"):
zinnia/admin/entry.py
zinnia/fixtures/helloworld.json (not sure if this was necessary, but this is one excerpt from several -- that look the exact same -- changes that I made in here).
zinnia/models_bases/entry.py
And, at the bottom of models_bases/entry.py, update this list to include your new class(es):
zinnia/templatetags/zinnia.py
zinnia/xmlrpc/metaweblog.py
Don't forget that you've made changes to your models, so you need to run migrations!
And now, I can call the latest entries that I want to appear under a (in this example) "Politics" header on the homepage by using
{% get_politics_entries 3 template="homepage_latest_politics.html" %}.Not entirely relevant, but just in case it's helpful to anybody, my template for homepage_latest_politics.html is:
This is an integration of zinnia's tags with the "Card" component of Materialize, and produces this -- with the entries being the latest to have the "Featured_politics" box checked:
Hey -- I did say that it wasn't the prettiest solution, but... it works!