base.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from __future__ import annotations
  2. import typing as T
  3. from flask import abort
  4. from sqlalchemy_serializer import SerializerMixin
  5. from pycs import db
  6. from pycs.database.util import commit_on_return
  7. class BaseModel(db.Model, SerializerMixin):
  8. """ Base model class """
  9. __abstract__ = True
  10. # setup of the SerializerMixin
  11. date_format = '%s' # Unixtimestamp (seconds)
  12. datetime_format = '%d. %b. %Y %H:%M:%S'
  13. time_format = '%H:%M'
  14. id = db.Column(db.Integer, primary_key=True)
  15. serialize_only = ("id", "identifier")
  16. def identifier(self):
  17. """ alias for id attribute """
  18. return self.id
  19. def __repr__(self):
  20. attrs = self.serialize()
  21. content = ", ".join([f"{attr}={value}" for attr, value in attrs.items()])
  22. return f"<{self.__class__.__name__}: {content}>"
  23. def serialize(self) -> dict:
  24. """ default model serialization method """
  25. return self.to_dict()
  26. @commit_on_return
  27. def delete(self) -> dict:
  28. """
  29. delete this instance from the database
  30. :return: serialized self
  31. """
  32. dump = self.serialize()
  33. db.session.delete(self)
  34. return dump
  35. # do an alias
  36. remove = delete
  37. @classmethod
  38. def new(cls, commit: bool = True, **kwargs):
  39. """ creates a new object. optionally commits the created object. """
  40. obj = cls(**kwargs)
  41. db.session.add(obj)
  42. if commit:
  43. obj.commit()
  44. return obj
  45. @classmethod
  46. def get_or_create(cls, **kwargs) -> T.Tuple[BaseModel, bool]:
  47. """ get an object from the DB based on the kwargs, or create an object with these. """
  48. is_new = False
  49. obj = cls.query.filter_by(**kwargs).one_or_none()
  50. if obj is None:
  51. obj = cls.new(commit=False, **kwargs)
  52. is_new = True
  53. return obj, is_new
  54. @classmethod
  55. def get_or_404(cls, obj_id: int) -> BaseModel:
  56. """ get an object for the given id or raise 404 error if the object is not present """
  57. obj = cls.query.get(obj_id)
  58. if obj is None:
  59. abort(404, f"{cls.__name__} with ID {obj_id} could not be found!")
  60. return obj
  61. @staticmethod
  62. def commit():
  63. """ commit current session """
  64. db.session.commit()
  65. @staticmethod
  66. def flush():
  67. """ flush current session """
  68. db.session.flush()
  69. class NamedBaseModel(BaseModel):
  70. """ Extends the base model with a name attribute. """
  71. __abstract__ = True
  72. name = db.Column(db.String, nullable=False)
  73. serialize_only = BaseModel.serialize_only + ("name",)
  74. @commit_on_return
  75. def set_name(self, name: str):
  76. """ set the name attribute """
  77. self.name = name