extensions.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.extensions
  4. ~~~~~~~~~~~~~~~~~~
  5. The extensions that are used by FlaskBB.
  6. :copyright: (c) 2014 by the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. from inspect import isclass
  10. from celery import Celery
  11. from flask_alembic import Alembic
  12. from flask_allows import Allows
  13. from flask_babelplus import Babel
  14. from flask_caching import Cache
  15. from flask_debugtoolbar import DebugToolbarExtension
  16. from flask_limiter import Limiter
  17. from flask_limiter.util import get_remote_address
  18. from flask_login import LoginManager
  19. from flask_mail import Mail
  20. from flask_redis import FlaskRedis
  21. from flask_sqlalchemy import BaseQuery, SQLAlchemy
  22. from flask_themes2 import Themes
  23. from flask_whooshee import (DELETE_KWD, INSERT_KWD, UPDATE_KWD, Whooshee,
  24. WhoosheeQuery)
  25. from flask_wtf.csrf import CSRFProtect
  26. from flaskbb.exceptions import AuthorizationRequired
  27. from sqlalchemy import MetaData, event
  28. from sqlalchemy.orm import Query as SQLAQuery
  29. class FlaskBBWhooshee(Whooshee):
  30. def register_whoosheer(self, wh):
  31. """This will register the given whoosher on `whoosheers`, create the
  32. neccessary SQLAlchemy event listeners, replace the `query_class` with
  33. our own query class which will provide the search functionality
  34. and store the app on the whoosheer, so that we can always work
  35. with that.
  36. :param wh: The whoosher which should be registered.
  37. """
  38. self.whoosheers.append(wh)
  39. for model in wh.models:
  40. event.listen(model, 'after_{0}'.format(INSERT_KWD), self.after_insert)
  41. event.listen(model, 'after_{0}'.format(UPDATE_KWD), self.after_update)
  42. event.listen(model, 'after_{0}'.format(DELETE_KWD), self.after_delete)
  43. query_class = getattr(model, 'query_class', None)
  44. if query_class is not None and isclass(query_class):
  45. # already a subclass, ignore it
  46. if issubclass(query_class, self.query):
  47. pass
  48. # ensure there can be a stable MRO
  49. elif query_class not in (BaseQuery, SQLAQuery, WhoosheeQuery):
  50. query_class_name = query_class.__name__
  51. model.query_class = type(
  52. "Whooshee{}".format(query_class_name), (query_class, self.query), {}
  53. )
  54. else:
  55. model.query_class = self.query
  56. else:
  57. model.query_class = self.query
  58. if self.app:
  59. wh.app = self.app
  60. return wh
  61. # Permissions Manager
  62. allows = Allows(throws=AuthorizationRequired)
  63. # Database
  64. metadata = MetaData(
  65. naming_convention={
  66. "ix": 'ix_%(column_0_label)s',
  67. "uq": "uq_%(table_name)s_%(column_0_name)s",
  68. "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
  69. "pk": "pk_%(table_name)s"
  70. }
  71. )
  72. db = SQLAlchemy(metadata=metadata)
  73. # Whooshee (Full Text Search)
  74. whooshee = FlaskBBWhooshee()
  75. # Login
  76. login_manager = LoginManager()
  77. # Mail
  78. mail = Mail()
  79. # Caching
  80. cache = Cache()
  81. # Redis
  82. redis_store = FlaskRedis()
  83. # Debugtoolbar
  84. debugtoolbar = DebugToolbarExtension()
  85. # Migrations
  86. alembic = Alembic()
  87. # Themes
  88. themes = Themes()
  89. # Babel
  90. babel = Babel()
  91. # CSRF
  92. csrf = CSRFProtect()
  93. # Rate Limiting
  94. limiter = Limiter(auto_check=False, key_func=get_remote_address)
  95. # Celery
  96. celery = Celery("flaskbb")