====== Flask ====== ===== Extensions ===== * [[wiki2:python:flask:sqlalchemy|Flask SQLAlchemy]] * [[wiki2:python:flask:restful|Flask RESTful]] * [[wiki2:python:flask:mongoalchemy|Flask MongoAlchemy]] * [[wiki2:python:flask:flaskmongoengine|Flask Mongo Engine]] * [[wiki2:python:flask:flasklogin|Flask Login]] * [[wiki2:python:flask:testing|Flask Testing]] * [[wiki2:python:flask:used_libraries|Flask used libraries]] ===== Some elements ===== ==== Configuration ==== There are several ways to set configuration: app = Flask(__name__) # Using app.config app.config['DEBUG'] = True # Just debug (and few more) allow to configure like this: app.debug = True # Updating multiple app.config.update( DEBUG=True, SECRET_KEY='...' ) # From a file app.config.from_object('yourapplication.default_settings') # From an environment var: # $ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg # $ python run-app.py app.config.from_envvar('YOURAPPLICATION_SETTINGS') It would be a config file: # Example configuration DEBUG = False SECRET_KEY = '?\xbf,\xb4\x8d\xa3"<\x9c\xb0@\x0f5\xab,w\xee\x8d$0\x13\x8b83' You can use a default config that is always loaded and part of the version control, and a separate configuration that overrides the values as necessary as mentioned in the example above: app = Flask(__name__) app.config.from_object('yourapplication.default_settings') app.config.from_envvar('YOURAPPLICATION_SETTINGS') If you do not want an error when load the config: app.config.from_envvar('PERSONAL_WEBPAGE_SETTINGS', silent=True) Another pattern is to use a class: class Config(object): DEBUG = False TESTING = False DATABASE_URI = 'sqlite://:memory:' class ProductionConfig(Config): DATABASE_URI = 'mysql://user@localhost/foo' class DevelopmentConfig(Config): DEBUG = True class TestingConfig(Config): TESTING = True # To enable such a config you just have to call into from_object(): app.config.from_object('configmodule.ProductionConfig') ==== Static files ==== When you locate the static files (js, css...) in ''static/'' folder you can automatically access them like ''''. \\ However you can change it providing a parameter ''static_folder'' to the application object, even changing the path with ''static_url_path'' parameter: app = Flask(__name__, static_folder='/path/to/static/folder', static_url_path='/differentstatic') Then: '''' ===== Templates ===== ==== Basic ==== @app.route('/users/') def show_users(page): users = User.query.all() return render_template('users.html', users=users) ===== Extend your application ===== ==== Structure ==== You can create an external file ''views.py'' and add there all the logic: from yourapplication import app @app.route('/') def index(): return 'Hello World!' Also you can create a global instance of your class and route your rules to it: class X(object): # Your code here INSTANCE_X = X() # Note that we are not *calling* the methods app.add_url_rule('/x/', view_func=INSTANCE_X.route1) app.add_url_rule('/y/', view_func=INSTANCE_X.route2) You can use ''view_func'': def handle_route2(): return X().route2() app.add_url_rule('/y/', view_func=handle_route2) ==== Pluggable views ==== You need to subclass flask.views.View and implement dispatch_request(), then use as_view() class method. The string you pass to that function is the name of the endpoint. from flask.views import View class ShowUsers(View): def dispatch_request(self): users = User.query.all() return render_template('users.html', objects=users) app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users')) ''add_url_rule()'' is the function to register methods. To provide methods you use the ''methods'' property: class MyView(View): methods = ['GET', 'POST'] def dispatch_request(self): if request.method == 'POST': ... ... app.add_url_rule('/myview', view_func=MyView.as_view('myview')) === MethodViews === Also you can use ''MethodView'' to implement methods: from flask.views import MethodView class UserAPI(MethodView): def get(self): users = User.query.all() ... def post(self): user = User.from_form_data(request.form) ... app.add_url_rule('/users/', view_func=UserAPI.as_view('users')) So you can implement a REST API easily: ^ URL ^ Method ^ | /users/ | GET | | /users/ | POST | | /users/ | GET | | /users/ | PUT | | /users/ | DELETE | class UserAPI(MethodView): def get(self, user_id): if user_id is None: # return a list of users pass else: # expose a single user pass def post(self): # create a new user pass def delete(self, user_id): # delete a single user pass def put(self, user_id): # update a single user pass Explicitly mention the methods for each: user_view = UserAPI.as_view('user_api') app.add_url_rule('/users/', defaults={'user_id': None}, view_func=user_view, methods=['GET',]) app.add_url_rule('/users/', view_func=user_view, methods=['POST',]) app.add_url_rule('/users/', view_func=user_view, methods=['GET', 'PUT', 'DELETE']) If you have a lot of APIs that look similar you can refactor that registration code: def register_api(view, endpoint, url, pk='id', pk_type='int'): view_func = view.as_view(endpoint) app.add_url_rule(url, defaults={pk: None}, view_func=view_func, methods=['GET',]) app.add_url_rule(url, view_func=view_func, methods=['POST',]) app.add_url_rule('%s<%s:%s>' % (url, pk_type, pk), view_func=view_func, methods=['GET', 'PUT', 'DELETE']) register_api(UserAPI, 'user_api', '/users/', pk='user_id') ==== Blueprints ==== A blueprint defines a collection of views, templates, static files and other elements that can be applied to an application. For example, let’s imagine that we have a blueprint for an admin panel. This blueprint would define the views for routes like /admin/login and /admin/dashboard. This lets us structure our app as several smaller “apps” that each do one thing. from flask import Blueprint, render_template profile = Blueprint('profile', __name__) @profile.route('/') def timeline(user_url_slug): # Do some stuff return render_template('profile/timeline.html') @profile.route('//photos') def photos(user_url_slug): # Do some stuff return render_template('profile/photos.html') @profile.route('//about') def about(user_url_slug): # Do some stuff return render_template('profile/about.html') If we were using a divisional structure, we’d want to tell Flask that the blueprint has its own template and static directories. profile = Blueprint('profile', __name__, template_folder='templates', static_folder='static') Now we only need to add it to our app: # facebook/__init__.py from flask import Flask from .views.profile import profile app = Flask(__name__) app.register_blueprint(profile) We can define the prefix in one of two places: \\ (1) when we instantiate the Blueprint() from flask import Blueprint, render_template profile = Blueprint('profile', __name__, url_prefix='/') # [...] (2) when we register it with app.register_blueprint() from flask import Flask from .views.profile import profile app = Flask(__name__) app.register_blueprint(profile, url_prefix='/') === Build blueprints URLs === If you want to link from one page to another you can use the url_for() function just like you normally would do just that you prefix the URL endpoint with the name of the blueprint and a dot (.): url_for('admin.index') Additionally if you are in a view function of a blueprint or a rendered template and you want to link to another endpoint of the same blueprint, you can use relative redirects by prefixing the endpoint with a dot only: url_for('.index') === Notes === To access the flask app from a blueprint: from flask import current_app ... if current_app.debug: ... * The url's will end with ''/''. ===== Notes ===== * **To enable debug mode** you should add ''app.debug = True''. ==== To redirect... ==== @app.route('/') def root(): register_ip(request.remote_addr) return redirect(url_for('static', filename='resume.html')) ==== url_for ==== ''url_for(folder, file)'' will return the url for that file in that folder. \\ For static files: url_for('static', filename='path/to/file') # In blueprints url_for('admin.static', filename='style.css') You also can use it in templates. In blueprints: # this blueprint -> printable function url_for('.printable') # blueprint: resume, resource FUNCTION: printable_resume url_for('resume.printable_resume') You can get the absolute url: url_for('settings', _external=True)