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:
1from gilbert.content import Content
2
3
4class TagCloud(Content):
5 pass
Next, we need to gather all the content objects and aggregate the tags.
1from collections import Counter
2
3from gilbert.content import Content
4
5
6class TagCloud(Content):
7
8 @property
9 def tag_counts(self):
10 tags = Counter()
11 for obj in self.site.content:
12 tags.update(obj.tags)
13 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.
1from collections import Counter
2
3from gilbert.content import Content
4
5class TagCloud(Content):
6 filter_by : dict = {}
7
8 @property
9 def tag_counts(self):
10 tags = Counter()
11 for obj in self.site.content.matches(self.filter_by):
12 tags.update(obj.tags)
13 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.
1from collections import Counter
2from functools import cached_property
3
4from gilbert.content import Content
5
6class TagCloud(Content):
7 filter_by : dict = {}
8
9 @cached_property
10 def tag_counts(self):
11 tags = Counter()
12 for obj in self.site.pages.matching(self.filter_by):
13 tags.update(obj.tags)
14 return tags
So here we use Python’s cached_property 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.