related_posts.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. """
  2. Related posts plugin for Pelican
  3. ================================
  4. Adds related_posts variable to article's context
  5. """
  6. from pelican import signals
  7. from collections import Counter
  8. from itertools import chain
  9. def add_related_posts(generator):
  10. # get the max number of entries from settings
  11. # or fall back to default (5)
  12. numentries = generator.settings.get('RELATED_POSTS_MAX', 5)
  13. # Skip all posts in the same category as the article
  14. skipcategory = generator.settings.get('RELATED_POSTS_SKIP_SAME_CATEGORY', False)
  15. for article in chain(generator.articles, generator.drafts):
  16. # set priority in case of forced related posts
  17. if hasattr(article,'related_posts'):
  18. # split slugs
  19. related_posts = article.related_posts.split(',')
  20. posts = []
  21. # get related articles
  22. for slug in related_posts:
  23. i = 0
  24. slug = slug.strip()
  25. for a in generator.articles:
  26. if i >= numentries: # break in case there are max related psots
  27. break
  28. if a.slug == slug:
  29. posts.append(a)
  30. i += 1
  31. article.related_posts = posts
  32. else:
  33. # no tag, no relation
  34. if not hasattr(article, 'tags'):
  35. continue
  36. # score = number of common tags
  37. related = chain(*(generator.tags[tag] for tag in article.tags))
  38. if skipcategory:
  39. related = (other for other in related
  40. if other.category != article.category)
  41. scores = Counter(related)
  42. # remove itself
  43. scores.pop(article, None)
  44. article.related_posts = [other for other, count
  45. in scores.most_common(numentries)]
  46. def register():
  47. signals.article_generator_finalized.connect(add_related_posts)