def init(cls, flask_or_import_name, project=None, directory=None, config=None, exceptions=None, compress_html=True): """ Allow to register all subclasses of Webmaster at once If a class doesn't have a route base, it will create a dasherize version of the class name. So we call it once initiating :param flask_or_import_name: Flask instance or import name -> __name__ :param project: name of the project. If the directory and config is empty, it will guess them from here :param directory: The directory containing your project's Views, Templates and Static :param config: string of config object. ie: "app.config.Dev" :param exceptions: The exceptions path to load :param compress_html: bool - If true it will use the plugin "jinja2htmlcompress" to remove white spaces off the html resul """ if isinstance(flask_or_import_name, Flask): app = flask_or_import_name else: app = Flask(flask_or_import_name) app.wsgi_app = ProxyFix(app.wsgi_app) app.url_map.converters['regex'] = RegexConverter if not directory: directory = "application/%s" % project if project else "." if not config: config = "application.config.%s" % get_env() app.config.from_object(config) # Extensions to remove extra white spaces in html if compress_html: app.jinja_env.add_extension('webmaster.htmlcompress_ext.HTMLCompress') if directory: app.template_folder = directory + "/templates" app.static_folder = directory + "/static" # Setup map base exceptions to abort() abort.map_from_module(exceptions) cls._app = app cls._setup_logger() cls._add_asset_bundle(app.static_folder) # Flask Assets cls.assets = Environment(cls._app) # Register templates if cls._template_paths: loader = [cls._app.jinja_loader] + list(cls._template_paths) cls._app.jinja_loader = jinja2.ChoiceLoader(loader) # Register static if cls._static_paths: loader = [cls._app.static_folder] + list(cls._static_paths) cls.assets.load_path = loader # init_app [_app(cls._app) for _app in cls._init_apps] # Register all views for subcls in cls.__subclasses__(): base_route = subcls.base_route if not base_route: base_route = utils.dasherize(utils.underscore(subcls.__name__)) if subcls.__name__.lower() == "index": base_route = "/" subcls.register(cls._app, base_route=base_route) # Load all bundles [cls.assets.from_yaml(a) for a in cls._asset_bundles] @cls._app.after_request def _after_request_cleanup(response): cls._global["__META__"] = cls._default_page_meta return response return cls._app
def register(cls, app, base_route=None, subdomain=None, route_prefix=None, trailing_slash=None): """Registers a FlaskView class for use with a specific instance of a Flask app. Any methods not prefixes with an underscore are candidates to be routed and will have routes registered when this method is called. :param app: an instance of a Flask application :param base_route: The base path to use for all routes registered for this class. Overrides the base_route attribute if it has been set. :param subdomain: A subdomain that this registration should use when configuring routes. :param route_prefix: A prefix to be applied to all routes registered for this class. Precedes base_route. Overrides the class' route_prefix if it has been set. """ if cls is FlaskView: raise TypeError("cls must be a subclass of FlaskView, not FlaskView itself") if base_route: cls.orig_base_route = cls.base_route cls.base_route = base_route if route_prefix: cls.orig_route_prefix = cls.route_prefix cls.route_prefix = route_prefix if not subdomain: if hasattr(app, "subdomain") and app.subdomain is not None: subdomain = app.subdomain elif hasattr(cls, "subdomain"): subdomain = cls.subdomain if trailing_slash is not None: cls.orig_trailing_slash = cls.trailing_slash cls.trailing_slash = trailing_slash members = get_interesting_members(FlaskView, cls) special_methods = ["get", "put", "patch", "post", "delete", "index"] for name, value in members: proxy = cls.make_proxy_method(name) route_name = cls.build_route_name(name) try: if hasattr(value, "_rule_cache") and name in value._rule_cache: for idx, cached_rule in enumerate(value._rule_cache[name]): rule, options = cached_rule rule = cls.build_rule(rule) sub, ep, options = cls.parse_options(options) if not subdomain and sub: subdomain = sub if ep: endpoint = ep elif len(value._rule_cache[name]) == 1: endpoint = route_name else: endpoint = "%s_%d" % (route_name, idx,) app.add_url_rule(rule, endpoint, proxy, subdomain=subdomain, **options) elif name in special_methods: if name in ["get", "index"]: methods = ["GET"] if name == "index": if hasattr(value, "_methods_cache"): methods = value._methods_cache else: methods = [name.upper()] rule = cls.build_rule("/", value) if not cls.trailing_slash: rule = rule.rstrip("/") app.add_url_rule(rule, route_name, proxy, methods=methods, subdomain=subdomain) else: methods = value._methods_cache \ if hasattr(value, "_methods_cache") \ else ["GET"] name = utils.dasherize(name) route_str = '/%s/' % name if not cls.trailing_slash: route_str = route_str.rstrip('/') rule = cls.build_rule(route_str, value) app.add_url_rule(rule, route_name, proxy, subdomain=subdomain, methods=methods) except DecoratorCompatibilityError: raise DecoratorCompatibilityError("Incompatible decorator detected on %s in class %s" % (name, cls.__name__)) if hasattr(cls, "orig_base_route"): cls.base_route = cls.orig_base_route del cls.orig_base_route if hasattr(cls, "orig_route_prefix"): cls.route_prefix = cls.orig_route_prefix del cls.orig_route_prefix if hasattr(cls, "orig_trailing_slash"): cls.trailing_slash = cls.orig_trailing_slash del cls.orig_trailing_slash