Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
wiki2:python:flask [2015/08/09 14:33] alfred [Pluggable views] |
wiki2:python:flask [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== Flask ====== | ====== 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 ===== | ===== Some elements ===== | ||
| Línea 123: | Línea 132: | ||
| app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users')) | app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users')) | ||
| + | </code> | ||
| + | |||
| + | ''add_url_rule()'' is the function to register methods. To provide methods you use the ''methods'' property: | ||
| + | <code python> | ||
| + | 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')) | ||
| + | </code> | ||
| + | |||
| + | === MethodViews === | ||
| + | |||
| + | Also you can use ''MethodView'' to implement methods: | ||
| + | <code python> | ||
| + | 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')) | ||
| + | </code> | ||
| + | So you can implement a REST API easily: | ||
| + | ^ URL ^ Method ^ | ||
| + | | /users/ | GET | | ||
| + | | /users/ | POST | | ||
| + | | /users/<id> | GET | | ||
| + | | /users/<id> | PUT | | ||
| + | | /users/<id> | DELETE | | ||
| + | <code python> | ||
| + | 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 | ||
| + | </code> | ||
| + | |||
| + | Explicitly mention the methods for each: | ||
| + | <code python> | ||
| + | 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/<int:user_id>', view_func=user_view, methods=['GET', 'PUT', 'DELETE']) | ||
| + | </code> | ||
| + | |||
| + | If you have a lot of APIs that look similar you can refactor that registration code: | ||
| + | <code python> | ||
| + | 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') | ||
| </code> | </code> | ||
| ==== Blueprints ==== | ==== 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. | ||
| + | <code python> | ||
| + | from flask import Blueprint, render_template | ||
| + | profile = Blueprint('profile', __name__) | ||
| + | |||
| + | @profile.route('/<user_url_slug>') | ||
| + | def timeline(user_url_slug): | ||
| + | # Do some stuff | ||
| + | return render_template('profile/timeline.html') | ||
| + | |||
| + | @profile.route('/<user_url_slug>/photos') | ||
| + | def photos(user_url_slug): | ||
| + | # Do some stuff | ||
| + | return render_template('profile/photos.html') | ||
| + | |||
| + | @profile.route('/<user_url_slug>/about') | ||
| + | def about(user_url_slug): | ||
| + | # Do some stuff | ||
| + | return render_template('profile/about.html') | ||
| + | </code> | ||
| + | If we were using a divisional structure, we’d want to tell Flask that the blueprint has its own template and static directories. | ||
| + | <code python> | ||
| + | profile = Blueprint('profile', __name__, | ||
| + | template_folder='templates', | ||
| + | static_folder='static') | ||
| + | </code> | ||
| + | Now we only need to add it to our app: | ||
| + | <code python> | ||
| + | # facebook/__init__.py | ||
| + | |||
| + | from flask import Flask | ||
| + | from .views.profile import profile | ||
| + | |||
| + | app = Flask(__name__) | ||
| + | app.register_blueprint(profile) | ||
| + | </code> | ||
| + | |||
| + | We can define the prefix in one of two places: \\ | ||
| + | (1) when we instantiate the Blueprint() | ||
| + | <code python> | ||
| + | from flask import Blueprint, render_template | ||
| + | |||
| + | profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>') | ||
| + | |||
| + | # [...] | ||
| + | </code> | ||
| + | (2) when we register it with app.register_blueprint() | ||
| + | <code python> | ||
| + | from flask import Flask | ||
| + | from .views.profile import profile | ||
| + | |||
| + | app = Flask(__name__) | ||
| + | app.register_blueprint(profile, url_prefix='/<user_url_slug>') | ||
| + | </code> | ||
| + | |||
| + | === 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 (.): | ||
| + | <code python> | ||
| + | url_for('admin.index') | ||
| + | </code> | ||
| + | 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: | ||
| + | <code python> | ||
| + | url_for('.index') | ||
| + | </code> | ||
| + | |||
| + | === Notes === | ||
| + | To access the flask app from a blueprint: | ||
| + | <code python> | ||
| + | from flask import current_app | ||
| + | ... | ||
| + | if current_app.debug: | ||
| + | ... | ||
| + | </code> | ||
| + | |||
| + | * The url's will end with ''/''. | ||
| ===== Notes ===== | ===== Notes ===== | ||
| Línea 137: | Línea 302: | ||
| return redirect(url_for('static', filename='resume.html')) | return redirect(url_for('static', filename='resume.html')) | ||
| </code> | </code> | ||
| - | ''url_for(folder, file)'' will return the url for that file in that folder. | + | |
| + | ==== url_for ==== | ||
| + | |||
| + | ''url_for(folder, file)'' will return the url for that file in that folder. \\ | ||
| + | |||
| + | For static files: | ||
| + | <code python> | ||
| + | url_for('static', filename='path/to/file') | ||
| + | # In blueprints | ||
| + | url_for('admin.static', filename='style.css') | ||
| + | </code> | ||
| + | You also can use it in templates. | ||
| + | <code> | ||
| + | <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap/bootstrap.min.css') }}"> | ||
| + | </code> | ||
| + | In blueprints: | ||
| + | <code python> | ||
| + | # this blueprint -> printable function | ||
| + | url_for('.printable') | ||
| + | # blueprint: resume, resource FUNCTION: printable_resume | ||
| + | url_for('resume.printable_resume') | ||
| + | </code> | ||
| + | You can get the absolute url: | ||
| + | <code python> | ||
| + | url_for('settings', _external=True) | ||
| + | </code> | ||