Plugins¶
In this tutorial we’re going to build a Tag Cloud content object. It will provide a way to inject counts of how many times tags appear on selected objects.
We start by creating a plugins.py
in our project, and declaring
TagCloud
as a sub-class of gilbert.content.Content:
1 2 3 4 5 | from gilbert.content import Content class TagCloud(Content): pass |
Next, we need to gather all the content objects and aggregate the tags.
1 2 3 4 5 6 7 8 9 10 11 12 13 | from collections import Counter from gilbert.content import Content class TagCloud(Content): @property def tag_counts(self): tags = Counter() for obj in self.site.content: tags.update(obj.tags) return tags |
And that’s it! We can create a content object with content_type: TagCloud,
and access it in our templates by looking it up in site.content[]
, and
accessing its tag_counts
property.
Oh, but wait - maybe we don’t want to count all the objects? Let’s add a filter.
1 2 3 4 5 6 7 8 9 10 11 12 13 | from collections import Counter from gilbert.content import Content class TagCloud(Content): filter_by : dict = {} @property def tag_counts(self): tags = Counter() for obj in self.site.content.matches(self.filter_by): tags.update(obj.tags) return tags |
Now our users can declare a filter using Object Queries to limit which objects will be scanned.
This is nice, but as our site grows, collecting these each time we render will start to get expensive.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from collections import Counter from gilbert.content import Content from gilbert.utils import oneshot class TagCloud(Content): filter_by : dict = {} @oneshot def tag_counts(self): tags = Counter() for obj in self.site.pages.matching(self.filter_by): tags.update(obj.tags) return tags |
So here we introduce the oneshot
utility decorator, which works like
property
but caches the result so it only invokes the function once,
saving the result on the instance; future accesses are super fast as they’re
handled internally within Python.