Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
210 views
in Technique[技术] by (71.8m points)

python - Extending Flask class as main App

I'm learning Flask and am a bit confused about how to structure my code. So I tried to extend Flask main class as follows:

from flask import Flask, ...

class App(Flask):
    def __init__(self, import_name, *args, **kwargs):
        super(App, self).__init__(import_name, *args, **kwargs)

Note that I am aware of that this may be a completely wrong approach.
So that when I want to start the app I do:

app = App(__name__)

if __name__ == '__main__':
    app.run()

This way I can order my methods and routes in the class, but the problem is when using self-decorators:

@route('/')
def home(self, context=None):
    context = context or dict()
    return render_template('home.html', **context)

Which raises an error as unresolved reference 'route'. I guess this is not the way I should be structuring the app. How should I do it instead or how do I get the error fixed?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Doing this doesn't make sense. You would subclass Flask to change its internal behavior, not to define your routes as class methods.

Instead, you're looking for blueprints and the app factory pattern. Blueprints divide your views into groups without requiring an app, and the factory creates and sets up the app only when called.

my_app/users/__init__.py

from flask import Blueprint

bp = Blueprint('users', __name__, url_prefix='/users')

my_app/users/views.py

from flask import render_template
from my_app.users import bp

@bp.route('/')
def index():
    return render_template('users/index.html')

my_app/__init__.py

def create_app():
    app = Flask(__name__)
    # set up the app here
    # for example, register a blueprint
    from my_app.users import bp
    app.register_blueprint(bp)
    return app

run.py

from my_app import create_app

app = create_app()

Run the dev server with:

FLASK_APP=run.py
FLASK_DEBUG=True
flask run

If you need access to the app in a view, use current_app, just like request gives access to the request in the view.

from flask import current_app
from itsdangerous import URLSafeSerializer

@bp.route('/token')
def token():
    s = URLSafeSerializer(current_app.secret_key)
    return s.dumps('secret')

If you really want to define routes as methods of a Flask subclass, you'll need to use self.add_url_rule in __init__ rather than decorating each route locally.

class MyFlask(Flask):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.add_url_rule('/', view_func=self.index)

    def index(self):
        return render_template('index.html')

The reason route (and self) won't work is because it's an instance method, but you don't have an instance when you're defining the class.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...