252

My flask application currently consists of a single test.py file with multiple routes and the main() route defined. Is there some way I could create a test2.py file that contains routes that were not handled in test.py?

@app.route('/somepath')
def somehandler():
    # Handler code here

I am concerned that there are too many routes in test.py and would like to make it such that I can run python test.py, which will also pick up the routes on test.py as if it were part of the same file. What changes to I have to make in test.py and/or include in test2.py to get this to work?

Santosh Kumar
  • 26,475
  • 20
  • 67
  • 118
Rolando
  • 58,640
  • 98
  • 266
  • 407

6 Answers6

235

You can use the usual Python package structure to divide your App into multiple modules, see the Flask docs.

However,

Flask uses a concept of blueprints for making application components and supporting common patterns within an application or across applications.

You can create a sub-component of your app as a Blueprint in a separate file:

simple_page = Blueprint('simple_page', __name__, template_folder='templates')
@simple_page.route('/<page>')
def show(page):
    # stuff

And then use it in the main part:

from yourapplication.simple_page import simple_page

app = Flask(__name__)
app.register_blueprint(simple_page)

Blueprints can also bundle specific resources: templates or static files. Please refer to the Flask docs for all the details.

pixelistik
  • 7,541
  • 3
  • 32
  • 42
118

You can use simple trick which is import flask app variable from main inside another file, like:

test_routes.py

from __main__ import app

@app.route('/test', methods=['GET'])
def test():
    return 'it works!'

and in your main files, where you declared flask app, import test-routes, like:

app.py

from flask import Flask, request, abort

app = Flask(__name__)

# import declared routes
import test_routes

It works from my side.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
Nimer Awad
  • 3,967
  • 3
  • 17
  • 31
  • 6
    It's just an example, `__main__` refers to your entry file, that's it! – Nimer Awad Jan 26 '20 at 06:49
  • 21
    Brilliant, many thanks. Blueprint or the package approach above are overkills for small apps. – VH-NZZ Jan 28 '20 at 18:01
  • 1
    Here's a link to the docs where this method is explained: [https://flask.palletsprojects.com/en/1.1.x/patterns/packages/](https://flask.palletsprojects.com/en/1.1.x/patterns/packages/) – sur.la.route Jun 24 '20 at 19:05
  • 8
    @nimeresam It worked for me but I had to learn that the `import test-routes` cannot be at the top of the `app.py` file. It crashed gunicorn but then after moving the import to the bottom of the file then it worked. _" just ensuring the module is imported and we are doing that at the bottom of the file"_ – Niklas Rosencrantz Jul 26 '20 at 19:00
  • Does flask notice when test_routes.py is updated? – Eric Duminil Nov 02 '21 at 19:52
  • Although this works, please be aware of importing from `__main__`. See https://stackoverflow.com/questions/24023601/is-it-good-practice-to-use-import-main – Govind Rai Jan 08 '22 at 01:13
  • 5
    The circular dependency doesn't look to good. https://stackoverflow.com/a/60441931/6419007 is much better IMHO. It's simple too but much cleaner. – Eric Duminil Jan 25 '22 at 20:58
  • @NimerEsam How does it works with Application Factories? – user2396640 Jul 13 '22 at 14:47
58

This task can be accomplished without blueprints and tricky imports using Centralized URL Map

app.py

import views
from flask import Flask

app = Flask(__name__)

app.add_url_rule('/', view_func=views.index)
app.add_url_rule('/other', view_func=views.other)

if __name__ == '__main__':
    app.run(debug=True, use_reloader=True)

views.py

from flask import render_template

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

def other():
    return render_template('other.html')
Bleiz
  • 591
  • 5
  • 8
  • Excellent, thanks. – Eric Duminil Jan 25 '22 at 20:57
  • 1
    Among the listed possibilities to split the app.py into multiple files, I found this approach to be the most simple and straigth forward. It's worth to mention that if you import request and session from flask, you can access the request details and the session in views.py. – Mr. Blonde Feb 07 '22 at 08:39
17

I would like to recommend flask-empty at GitHub.

It provides an easy way to understand Blueprints, multiple views and extensions.

Dušan Maďar
  • 9,269
  • 5
  • 49
  • 64
Jonathan Simon Prates
  • 1,122
  • 2
  • 12
  • 28
14

If you need split blueprint to separate files you can use snippet:

# app.py

from blueprint_module import blueprint

app = Flask(__name__)
app.register_blueprint(blueprint)
# blueprint_module\__init__.py

from flask import Blueprint

blueprint = Blueprint('my_blueprint', __name__)

from . import page
# blueprint_module\page.py

from . import blueprint

@blueprint.route("/url", methods=['GET'])
def hello():
  return 'hello world'

José Cabo
  • 6,149
  • 3
  • 28
  • 39
Ivan Bryzzhin
  • 2,009
  • 21
  • 27
6

Dividing the app into blueprints is a great idea. However, if this isn't enough, and if you want to then divide the Blueprint itself into multiple py files, this is also possible using the regular Python module import system, and then looping through all the routes that get imported from the other files.

I created a Gist with the code for doing this:

https://gist.github.com/Jaza/61f879f577bc9d06029e

As far as I'm aware, this is the only feasible way to divide up a Blueprint at the moment. It's not possible to create "sub-blueprints" in Flask, although there's an issue open with a lot of discussion about this:

https://github.com/mitsuhiko/flask/issues/593

Also, even if it were possible (and it's probably do-able using some of the snippets from that issue thread), sub-blueprints may be too restrictive for your use case anyway - e.g. if you don't want all the routes in a sub-module to have the same URL sub-prefix.

Jaza
  • 2,956
  • 2
  • 23
  • 26