model.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. from abc import ABCMeta, abstractmethod
  2. import datetime
  3. import mistune
  4. import peewee
  5. from typing import Optional
  6. import slugify
  7. import by.config as c
  8. import by.error as e
  9. import by.view as v
  10. class Model(peewee.Model):
  11. class Meta:
  12. database = c.db
  13. class User(Model):
  14. name = peewee.TextField(unique=True)
  15. passhash = peewee.TextField()
  16. class Contents(Model):
  17. source = peewee.TextField()
  18. class Page(Model):
  19. slug = peewee.TextField(unique=True)
  20. title = peewee.TextField()
  21. @staticmethod
  22. def new_page(title: str, contents: str) -> "Page":
  23. p = Page.create(
  24. slug=slugify.slugify(title),
  25. title=title,
  26. )
  27. p.update_page(contents)
  28. p.update_references()
  29. return p
  30. def update_page(self, source: str):
  31. now = datetime.datetime.now()
  32. c = Contents.create(source=source)
  33. r = Revision.create(
  34. modified=now,
  35. contents=c,
  36. page=self,
  37. )
  38. def update_references(self):
  39. Ref.delete().where(Ref.parent == self)
  40. @staticmethod
  41. def id_from_slug(slug: str) -> Optional[int]:
  42. if (p := Page.get_or_none(Page.slug == slug)):
  43. return p.id
  44. return None
  45. @staticmethod
  46. def view_from_slug(slug: str) -> v.Page:
  47. query = list(Revision.select()
  48. .join(Page, on=(Revision.page == Page.id))
  49. .join(Contents, on=(Revision.contents == Contents.id))
  50. .where(Page.slug == slug)
  51. .order_by(-Revision.modified)
  52. .limit(1))
  53. if len(query) != 1:
  54. raise e.PageNotFound()
  55. q = query[0]
  56. return v.Page(
  57. title=q.page.title,
  58. slug=q.page.slug,
  59. modified=q.modified,
  60. source=q.contents.source,
  61. rendered=mistune.html(q.contents.source),
  62. )
  63. class Revision(Model):
  64. modified = peewee.DateTimeField()
  65. contents = peewee.ForeignKeyField(Contents)
  66. page = peewee.ForeignKeyField(Page)
  67. class Ref(Model):
  68. parent = peewee.ForeignKeyField(Page)
  69. target = peewee.ForeignKeyField(Page)
  70. MODELS = [
  71. User,
  72. Page,
  73. Ref,
  74. Revision,
  75. Contents,
  76. ]
  77. def create_tables():
  78. c.db.create_tables(MODELS, safe=True)