subcategory.py 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Author: Alistair Magee
  4. Adds support for subcategories on pelican articles
  5. """
  6. import os
  7. from collections import defaultdict
  8. from pelican import signals
  9. from pelican.urlwrappers import URLWrapper, Category
  10. from operator import attrgetter
  11. from functools import partial
  12. from six import text_type
  13. class SubCategory(URLWrapper):
  14. def __init__(self, name, parent, *args, **kwargs):
  15. super(SubCategory, self).__init__(name, *args, **kwargs)
  16. self.parent = parent
  17. if isinstance(self.parent, SubCategory):
  18. self.savepath = os.path.join(self.parent.savepath, self.slug)
  19. self.fullurl = '{}/{}'.format(self.parent.fullurl, self.slug)
  20. else: #parent is a category
  21. self.savepath = os.path.join(self.parent.slug, self.slug)
  22. self.fullurl = '{}/{}'.format(self.parent.slug, self.slug)
  23. def as_dict(self):
  24. d = self.__dict__
  25. d['name'] = self.name
  26. d['savepath'] = self.savepath
  27. d['fullurl'] = self.fullurl
  28. d['parent'] = self.parent
  29. return d
  30. def get_subcategories(generator, metadata):
  31. if 'SUBCATEGORY_SAVE_AS' not in generator.settings:
  32. generator.settings['SUBCATEGORY_SAVE_AS'] = os.path.join(
  33. 'subcategory', '{savepath}.html')
  34. if 'SUBCATEGORY_URL' not in generator.settings:
  35. generator.settings['SUBCATEGORY_URL'] = 'subcategory/{fullurl}.html'
  36. category_list = text_type(metadata.get('category')).split('/')
  37. category = (category_list.pop(0)).strip()
  38. category = Category(category, generator.settings)
  39. metadata['category'] = category
  40. #generate a list of subcategories with their parents
  41. sub_list = []
  42. parent = category
  43. for subcategory in category_list:
  44. subcategory.strip()
  45. subcategory = SubCategory(subcategory, parent, generator.settings)
  46. sub_list.append(subcategory)
  47. parent = subcategory
  48. metadata['subcategories'] = sub_list
  49. def organize_subcategories(generator):
  50. generator.subcategories = defaultdict(list)
  51. for article in generator.articles:
  52. subcategories = article.metadata.get('subcategories')
  53. for cat in subcategories:
  54. generator.subcategories[cat].append(article)
  55. def generate_subcategories(generator, writer):
  56. write = partial(writer.write_file,
  57. relative_urls=generator.settings['RELATIVE_URLS'])
  58. subcategory_template = generator.get_template('subcategory')
  59. for subcat, articles in generator.subcategories.items():
  60. articles.sort(key=attrgetter('date'), reverse=True)
  61. dates = [article for article in generator.dates if article in articles]
  62. write(subcat.save_as, subcategory_template, generator.context,
  63. subcategory=subcat, articles=articles, dates=dates,
  64. paginated={'articles': articles, 'dates': dates},
  65. page_name=subcat.page_name, all_articles=generator.articles)
  66. def generate_subcategory_feeds(generator, writer):
  67. for subcat, articles in generator.subcategories.items():
  68. articles.sort(key=attrgetter('date'), reverse=True)
  69. if generator.settings.get('SUBCATEGORY_FEED_ATOM'):
  70. writer.write_feed(articles, generator.context,
  71. generator.settings['SUBCATEGORY_FEED_ATOM']
  72. % subcat.fullurl)
  73. if generator.settings.get('SUBCATEGORY_FEED_RSS'):
  74. writer.write_feed(articles, generator.context,
  75. generator.settings['SUBCATEGORY_FEED_RSS']
  76. % subcat.fullurl, feed_type='rss')
  77. def generate(generator, writer):
  78. generate_subcategory_feeds(generator, writer)
  79. generate_subcategories(generator, writer)
  80. def register():
  81. signals.article_generator_context.connect(get_subcategories)
  82. signals.article_generator_finalized.connect(organize_subcategories)
  83. signals.article_writer_finalized.connect(generate)