A flat-file CMS written in Python and Flask
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

posts.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import datetime
  2. import json
  3. import os
  4. import os.path
  5. import re
  6. import shutil
  7. import uuid
  8. from jinja2 import Environment, FileSystemLoader
  9. from markdown import markdown
  10. from yird.post import NewPostForm, Post
  11. from yird.settings import Settings
  12. class PostsService:
  13. settings = Settings()
  14. @classmethod
  15. def get_post(cls, post_id):
  16. bare_post_path = os.path.join(cls.settings.POSTS_PATH, post_id)
  17. with open(bare_post_path + '.json') as f:
  18. metadata = json.loads(f.read())
  19. with open(bare_post_path + '.md') as f:
  20. content = f.read()
  21. return Post(
  22. post_id,
  23. metadata['title'],
  24. metadata['slug'],
  25. datetime.date.fromisoformat(metadata['date']),
  26. content,
  27. metadata['changed']
  28. )
  29. @classmethod
  30. def get_posts(cls):
  31. posts_path = cls.settings.POSTS_PATH
  32. posts = []
  33. paths = os.listdir(posts_path)
  34. paths = [p for p in paths if re.search('.*(\\.json)', p)]
  35. for path in paths:
  36. post_id, extension = os.path.splitext(path)
  37. post = cls.get_post(post_id)
  38. posts.append(post)
  39. return sorted(posts, key=lambda post: post.date, reverse=True)
  40. @classmethod
  41. def generate_posts(cls):
  42. cls.__reset_public_dir()
  43. posts = cls.get_posts()
  44. template = cls.__get_post_template()
  45. for post in posts:
  46. cls.__generate_post(template, post)
  47. @classmethod
  48. def create_post(cls, post_data):
  49. id = str(uuid.uuid4())
  50. post = Post(
  51. id,
  52. post_data['title'],
  53. post_data['slug'],
  54. datetime.date.fromisoformat(post_data['date']),
  55. post_data['content'],
  56. )
  57. post.write()
  58. return post
  59. @classmethod
  60. def update_post(cls, post_id, post_data):
  61. post = Post(
  62. post_id,
  63. post_data['title'],
  64. post_data['slug'],
  65. datetime.date.fromisoformat(post_data['date']),
  66. post_data['content'],
  67. )
  68. post.write()
  69. @classmethod
  70. def get_post_form(cls, post=None):
  71. if post is None:
  72. return NewPostForm(date=datetime.date.today())
  73. return NewPostForm(
  74. title=post.title,
  75. slug=post.slug,
  76. date=post.date,
  77. content=post.content
  78. )
  79. @classmethod
  80. def __generate_post(cls, template, post):
  81. settings = cls.settings
  82. output_post_dir = os.path.join(settings.PUBLIC_PATH, post.id)
  83. metadata_path = os.path.join(settings.POSTS_PATH, post.id + '.json')
  84. os.mkdir(output_post_dir)
  85. post.content = markdown(post.content)
  86. with open(metadata_path) as f:
  87. metadata = json.loads(f.read())
  88. metadata['changed'] = False
  89. with open(metadata_path, "w") as f:
  90. f.write(json.dumps(metadata))
  91. with open(os.path.join(output_post_dir, "index.html"), "w") as f:
  92. f.write(template.render(post=post))
  93. @classmethod
  94. def __reset_public_dir(cls):
  95. shutil.rmtree(cls.settings.PUBLIC_PATH)
  96. os.mkdir(cls.settings.PUBLIC_PATH)
  97. @classmethod
  98. def __get_post_template(cls):
  99. loader = FileSystemLoader(cls.settings.TEMPLATES_PATH)
  100. env = Environment(loader=loader)
  101. return env.get_template('post.html')