extensions.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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) # noqa
  41. event.listen(model, 'after_{0}'.format(UPDATE_KWD), self.after_update) # noqa
  42. event.listen(model, 'after_{0}'.format(DELETE_KWD), self.after_delete) # noqa
  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),
  53. (query_class, self.query),
  54. {}
  55. )
  56. else:
  57. model.query_class = self.query
  58. else:
  59. model.query_class = self.query
  60. if self.app:
  61. wh.app = self.app
  62. return wh
  63. # Permissions Manager
  64. allows = Allows(throws=AuthorizationRequired)
  65. # Database
  66. metadata = MetaData(
  67. naming_convention={
  68. "ix": 'ix_%(column_0_label)s',
  69. "uq": "uq_%(table_name)s_%(column_0_name)s",
  70. "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
  71. "pk": "pk_%(table_name)s"
  72. }
  73. )
  74. db = SQLAlchemy(metadata=metadata)
  75. # Whooshee (Full Text Search)
  76. whooshee = FlaskBBWhooshee()
  77. # Login
  78. login_manager = LoginManager()
  79. # Mail
  80. mail = Mail()
  81. # Caching
  82. cache = Cache()
  83. # Redis
  84. redis_store = FlaskRedis()
  85. # Debugtoolbar
  86. debugtoolbar = DebugToolbarExtension()
  87. # Migrations
  88. alembic = Alembic()
  89. # Themes
  90. themes = Themes()
  91. # Babel
  92. babel = Babel()
  93. # CSRF
  94. csrf = CSRFProtect()
  95. # Rate Limiting
  96. limiter = Limiter(auto_check=False, key_func=get_remote_address)
  97. # Celery
  98. celery = Celery("flaskbb")