from flask import Blueprint, render_template errors = Blueprint('errors', __name__) @errors.app_errorhandler(404) def error_404(error): return render_template('errors/404.html'), 404 errors.app_errorhandler(403) def error_403(error): return render_template('errors/403.html'), 403 errors.app_errorhandler(500) def error_500(error): return render_template('errors/500.html'), 500
from flask import Blueprint from app.errors.handlers import exceptions bp = Blueprint('errors', __name__) bp.app_errorhandler(exceptions.ApiException)(exceptions.handle_invalid_usage)
class Dockerflow(object): """ The Dockerflow Flask extension. Set it up like this: .. code-block:: python :caption: ``myproject.py`` from flask import Flask from dockerflow.flask import Dockerflow app = Flask(__name__) dockerflow = Dockerflow(app) Or if you use the Flask application factory pattern, in an own module set up Dockerflow first: .. code-block:: python :caption: ``myproject/deployment.py`` from dockerflow.flask import Dockerflow dockerflow = Dockerflow() and then import and initialize it with the Flask application object when you create the application: .. code-block:: python :caption: ``myproject/app.py`` def create_app(config_filename): app = Flask(__name__) app.config.from_pyfile(config_filename) from myproject.deployment import dockerflow dockerflow.init_app(app) from myproject.views.admin import admin from myproject.views.frontend import frontend app.register_blueprint(admin) app.register_blueprint(frontend) return app See the parameters for a more detailed list of optional features when initializing the extension. :param app: The Flask app that this Dockerflow extension should be initialized with. :type root: ~flask.Flask or None :param db: A Flask-SQLAlchemy extension instance to be used by the built-in Dockerflow check for the database connection. :param redis: A Redis connection to be used by the built-in Dockerflow check for the Redis connection. :param migrate: A Flask-Migrate extension instance to be used by the built-in Dockerflow check for Alembic migrations. :param silenced_checks: Dockerflow check IDs to ignore when running through the list of configured checks. :type silenced_checks: list :param version_path: The filesystem path where the ``version.json`` can be found. Defaults to the parent directory of the Flask app's root path. """ def __init__(self, app=None, db=None, redis=None, migrate=None, silenced_checks=None, version_path=None, *args, **kwargs): # The Flask blueprint to add the Dockerflow signal callbacks and views self._blueprint = Blueprint('dockerflow', 'dockerflow.flask.app') # The Dockerflow specific logger to be used by internals of this # extension. self.logger = logging.getLogger('dockerflow.flask') self.logger.addHandler(logging.NullHandler()) self.logger.setLevel(logging.INFO) # The request summary logger to be used by this extension # without pre-configuration. See docs for how to set it up. self.summary_logger = logging.getLogger('request.summary') # An ordered dictionary for storing custom Dockerflow checks in. self.checks = OrderedDict() # A list of IDs of custom Dockerflow checks to ignore in case they # show up. self.silenced_checks = silenced_checks or [] # The path where to find the version JSON file. Defaults to the # parent directory of the app root path. self.version_path = version_path self._version_callback = version.get_version # Initialize the app if given. if app: self.init_app(app) # Initialize the built-in checks. if db: self.init_check(checks.check_database_connected, db) if redis: self.init_check(checks.check_redis_connected, redis) if migrate: self.init_check(checks.check_migrations_applied, migrate) def init_check(self, check, obj): """ Adds a given check callback with the provided object to the list of checks. Useful for built-ins but also advanced custom checks. """ self.logger.info('Adding extension check %s' % check.__name__) check = functools.wraps(check)(functools.partial(check, obj)) self.check(func=check) def init_app(self, app): """ Initializes the extension with the given app, registers the built-in views with an own blueprint and hooks up our signal callbacks. """ # If no version path was provided in the init of the Dockerflow # class we'll use the parent directory of the app root path. if self.version_path is None: self.version_path = os.path.dirname(app.root_path) for view in ( ('/__version__', 'version', self._version_view), ('/__heartbeat__', 'heartbeat', self._heartbeat_view), ('/__lbheartbeat__', 'lbheartbeat', self._lbheartbeat_view), ): self._blueprint.add_url_rule(*view) self._blueprint.before_app_request(self._before_request) self._blueprint.after_app_request(self._after_request) self._blueprint.app_errorhandler(HeartbeatFailure)( self._heartbeat_exception_handler) app.register_blueprint(self._blueprint) got_request_exception.connect(self._got_request_exception, sender=app) if not hasattr(app, 'extensions'): # pragma: nocover app.extensions = {} app.extensions['dockerflow'] = self def _heartbeat_exception_handler(self, error): """ An exception handler to act as a middleman to return a heartbeat view response with a 500 error code. """ return error.get_response() def _before_request(self): """ The before_request callback. """ g._request_id = str(uuid.uuid4()) g._start_timestamp = time.time() def _after_request(self, response): """ The signal handler for the request_finished signal. """ if not getattr(g, '_has_exception', False): extra = self.summary_extra() self.summary_logger.info('', extra=extra) return response def _got_request_exception(self, sender, exception, **extra): """ The signal handler for the got_request_exception signal. """ extra = self.summary_extra() extra['errno'] = 500 self.summary_logger.error(str(exception), extra=extra) g._has_exception = True def user_id(self): """ Return the ID of the current request's user """ # This needs flask-login to be installed if not has_flask_login: return # and the actual login manager installed if not hasattr(current_app, 'login_manager'): return # fail if no current_user was attached to the request context try: is_authenticated = current_user.is_authenticated except AttributeError: return # because is_authenticated could be a callable, call it if callable(is_authenticated): is_authenticated = is_authenticated() # and fail if the user isn't authenticated if not is_authenticated: return # finally return the user id try: return current_user.get_id() except UserLoadingError: # but don't fail if for some reason getting the user id # created an exception to not accidently make exception # handling worse. If sqlalchemy is used that catches # all SQLAlchemyError exceptions. pass def summary_extra(self): """ Build the extra data for the summary logger. """ out = { 'errno': 0, 'agent': request.headers.get('User-Agent', ''), 'lang': request.headers.get('Accept-Language', ''), 'method': request.method, 'path': request.path, } # set the uid value to the current user ID user_id = self.user_id() if user_id is None: user_id = '' out['uid'] = user_id # the rid value to the current request ID request_id = g.get('_request_id', None) if request_id is not None: out['rid'] = request_id # and the t value to the time it took to render start_timestamp = g.get('_start_timestamp', None) if start_timestamp is not None: # Duration of request, in milliseconds. out['t'] = int(1000 * (time.time() - start_timestamp)) return out def _version_view(self): """ View that returns the contents of version.json or a 404. """ version_json = self._version_callback(self.version_path) if version_json is None: return 'version.json not found', 404 else: return jsonify(version_json) def _lbheartbeat_view(self): """ Lets the load balancer know the application is running and available. Must return 200 (not 204) for ELB http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-healthchecks.html """ return '', 200 def _heartbeat_check_detail(self, check): errors = list( filter(lambda e: e.id not in self.silenced_checks, check())) level = max([0] + [e.level for e in errors]) return { 'status': checks.level_to_text(level), 'level': level, 'messages': {e.id: e.msg for e in errors}, } def _heartbeat_view(self): """ Runs all the registered checks and returns a JSON response with either a status code of 200 or 500 depending on the results of the checks. Any check that returns a warning or worse (error, critical) will return a 500 response. """ details = {} statuses = {} level = 0 for name, check in self.checks.items(): detail = self._heartbeat_check_detail(check) statuses[name] = detail['status'] level = max(level, detail['level']) if detail['level'] > 0: details[name] = detail payload = { 'status': checks.level_to_text(level), 'checks': statuses, 'details': details, } def render(status_code): return make_response(jsonify(payload), status_code) if level < checks.WARNING: status_code = 200 heartbeat_passed.send(self, level=level) return render(status_code) else: status_code = 500 heartbeat_failed.send(self, level=level) raise HeartbeatFailure(response=render(status_code)) def version_callback(self, func): """ A decorator to optionally register a new Dockerflow version callback and use that instead of the default of :func:`dockerflow.version.get_version`. The callback will be passed the value of the ``version_path`` parameter to the Dockerflow extension object, which defaults to the parent directory of the Flask app's root path. The callback should return a dictionary with the version information as defined in the Dockerflow spec, or None if no version information could be loaded. E.g.:: app = Flask(__name__) dockerflow = Dockerflow(app) @dockerflow.version_callback def my_version(root): return json.loads(os.path.join(root, 'acme_version.json')) """ self._version_callback = func def check(self, func=None, name=None): """ A decorator to register a new Dockerflow check to be run when the /__heartbeat__ endpoint is called., e.g.:: from dockerflow.flask import checks @dockerflow.check def storage_reachable(): try: acme.storage.ping() except SlowConnectionException as exc: return [checks.Warning(exc.msg, id='acme.health.0002')] except StorageException as exc: return [checks.Error(exc.msg, id='acme.health.0001')] or using a custom name:: @dockerflow.check(name='acme-storage-check) def storage_reachable(): # ... """ if func is None: return functools.partial(self.check, name=name) if name is None: name = func.__name__ self.logger.info('Registered Dockerflow check %s', name) @functools.wraps(func) def decorated_function(*args, **kwargs): self.logger.info('Called Dockerflow check %s', name) return func(*args, **kwargs) self.checks[name] = decorated_function return decorated_function
'message': error.description, 'id': error.id, } status_code = error.code elif isinstance(error, HTTPException): message = error.description status_code = error.code error_data = { 'message': message, 'id': "internal", 'code': status_code } else: message = "Unknown error" status_code = 500 error_data = { 'message': message, 'id': "internal", 'code': status_code } response = jsonify(status='error', error=error_data) response.status_code = status_code return response for code, _ in default_exceptions.items(): auth_bp.app_errorhandler(code)(error_handler) auth_bp.errorhandler(code)(error_handler)
from flask import Blueprint, render_template from werkzeug.exceptions import InternalServerError, NotFound from .errors import page_not_found, server_error from .model import PicBed from .utils import remove_image image = Blueprint("image", __name__, template_folder="templates") image.app_errorhandler(NotFound)(page_not_found) image.app_errorhandler(InternalServerError)(server_error) @image.route("/", methods=["GET"]) def index(): return render_template("index.html") @image.route("/remove/<string:img_id>", methods=["GET"]) def remove(img_id): resp = render_template("success.html") return remove_image(img_id, resp) @image.route("/all-images/", methods=["GET"]) def list_image(): image_list = PicBed.objects return render_template("list.html", image_list=image_list)
# @Time : 2017/7/26 14:11 # @Author : Cao jianhong # @File : urls.py # @Software: PyCharm Edu # ================================================= from flask import Blueprint from .views import (AdminIndexView, AddPostView, PostListview, DraftListView, UsersView, ChangeRoleView, DelUserView, DelPostView, CommentView) from Blog import errors site = Blueprint('admin', __name__) site.add_url_rule('/', view_func=AdminIndexView.as_view('index')) site.add_url_rule('/add_post', view_func=AddPostView.as_view('add_post')) site.add_url_rule('/edit_post/<id>', view_func=AddPostView.as_view('edit_post')) site.add_url_rule('/posts/', view_func=PostListview.as_view('posts')) site.add_url_rule('/posts/drafts/', view_func=DraftListView.as_view('drafts')) site.add_url_rule('/users/', view_func=UsersView.as_view('users')) site.add_url_rule('/change-role/<username>', view_func=ChangeRoleView.as_view('role')) site.add_url_rule('/user/<username>/delete', view_func=DelUserView.as_view('user_delete')) site.add_url_rule('/post/<id>/delete', view_func=DelPostView.as_view('post_delete')) site.add_url_rule('/posts/comments/', view_func=CommentView.as_view('comments')) site.app_errorhandler(404)(errors.page_not_found) site.app_errorhandler(401)(errors.handle_unauthorized)