Herramientas de usuario

Herramientas del sitio


wiki2:python:flask

Flask

Extensions

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 <img src='/static/images/logo.png'>.
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: <img src='/differentstatic/logo.png'>

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/<id> GET
/users/<id> PUT
/users/<id> 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/<int:user_id>', 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('/<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')

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='/<user_url_slug>')
 
# [...]

(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='/<user_url_slug>')

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.

<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap/bootstrap.min.css') }}">

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)
wiki2/python/flask.txt · Última modificación: 2020/05/09 09:25 (editor externo)