I have been following the flask mega tutorial form Miguel grinberg and the very first "Hello World!" program is confusing me.
More specifically it is the import of the routes module from the init.py module that is confusing me.
Below is the init.py file:
#__init__.py file:
from flask import Flask
app = Flask(__name__)
from app import routes
# above line is the source of confusion.
Below is the routes.py file
from app import app
#app.route('/')
#app.route('/index')
def index():
return "Hello, world!"
Now if I understand correctly, app is an object of class Flask. when we do "from app import app" in routes.py, I understand that we are importing the app object created in init.py file.
The code then follows is registering a route for this object.
So my question is why do we need to import this routes module in init.py?
I mean in routes module, the app object has been imported and a route has been registered on it. So this should reflect on the app object created in init.py. So why do we need to import it?
I know that it does not work if we remove the import routes statement. But want to know why.
Edit: Though I have a programming background, I am new to python. So it might be misunderstanding on how python files are executed when projects are executed. Also I think this has to do something with python being an interpreted language.
When you import anything in python, it actually runs the entire file that you are importing. The __init__.py file does not have any information about the routes so by importing it you are essentially providing that information to the app object. In addition, this routes file is never directly ran so that is the only way the views are actually created.
Hope this helps!
Related
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?
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.
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.
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')
I would like to recommend flask-empty at GitHub.
It provides an easy way to understand Blueprints, multiple views and extensions.
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'
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.
I ran into a strange issue (maybe not so strange for experienced in flask).
I have a flask application running in the context of Google App Engine's dev_appserver.py
I have a blueprint in my flask application
# rest_server.py
rest_api = Blueprint('rest_api', __name__)
app = Flask(__name__)
app.register_blueprint(rest_api, url_prefix='/api') # [1] DOESN'T WORK
#rest_api.route("/")
def hello():
return "Hello World"
app.register_blueprint(rest_api, url_prefix="/api") # [2] WORKS AS EXPECTED
I have the following in my app.yaml
-url: "/api/.*"
script: rest_server.app
When I hit localhost:8080/api/ when I register blueprint at position [1], I get an error saying there is no matching endpoint.
However, when I register bluerpint at [2], any position after the decorator, it works.
Is it required to register the blueprint after all the decorators?
Yes, it's required to register blueprints only after all their routes have been declared, at least if you want to use those routes. (If you don't mind the routes not being available, it doesn't look like there's actually any problem with declaring new routes after registering the blueprint.)
If you want to know why: basically, blueprint url rules are only registered on the application when Flask.register_blueprint is called. If you add routes after registering the blueprint, they just get added to the list of things to do when the blueprint is registered (Blueprint.deferred_functions), they don't get retroactively added to any existing applications that the blueprint was registered to in the past.
Though you have registered your blueprint, it is not actually registered!
the point is that your application is not aware of existence rest_server.py
You have to register it in the same file in which you have the following code:
app = Flask(__name__)
This should solve your problem.
I'd like to show the pattern of using blueprints I use.
(It is useful for a better organization of your code) :
Blueprint Pattern
your application can look like this:
/yourapplication
runserver.py
/application #your application is a package containing some blueprints!
__init__.py
models.py
/hello #(blueprint name)
__init__.py
views_file1.py
views_file2.py
your runserver.py should look like this:
# runserver.py
from application import app
app.run()
In this example, hello is a package and one of your blueprints:
# application/hello/__init__.py
from flask import Blueprint
hello = Blueprint('main', __name__)
# import views of this blueprint:
from application.hello import views_file1, views_file2
Import and register your blueprints in application/__ init__.py. your application/__ init__.py should look like this:
# application/__init__.py
from flask import Flask
from .hello import hello as hello_blueprint
app = Flask(__name__)
app.register_blueprint(hello_blueprint)
from application.models import * #your models (classes, or *)
This question already has answers here:
Why do circular imports seemingly work further up in the call stack but then raise an ImportError further down?
(9 answers)
Closed 6 years ago.
I learn from Larger Applications.In this document, It says: "all the view functions (the ones with a route() decorator on top) have to be imported in the init.py file. Not the object itself, but the module it is in."
I don't know why should when I do this: from . import views,It succeed.Though from views import * can also work well.
I organize these file like this:
myapplication/
runner.py
myflask/
__init__.py
views.py
templates/
static/
...
runner.py:
from testFlask import app
app.run()
myflask/__init__.py:
from flask import Flask
app = Flask(__name__)
from . import views # why this can work????
myflask/views.py:
from . import app
#app.route('/')
def index():
return 'Hello World!'
and I run it:
$ cd myapplication
$ python runner.py
It's OK to run this Flask app. However I want to know why from . import views can solve this circle import problem in flask? And why the doc says: Not the object itself, but the module it is in????
However,when I do like this:
#some_dir/
# application.py
# views.py
#application.py
from flask import Flask
app = Flask(__name__)
import views # it doesn't work
# from views import * # it works
app.run()
#views.py
from application import app
#app.route('/')
def index():
return 'Hello World!'
#run it
$ python application.py
It doesn't work.
It is a circular import. But in your case, the variable that might have been problematic (app) has already been defined in the imported script, so the import just causes the first "app" instance to be overwritten by the imported "app" instance. Which has no practical effect.
For details about this circular import situation, please read this post.
If you want to follow the pattern for a large flask application, you should look into blueprints and application factories.
It's not the specific command that solves the problem, but the order of the commands.
The trick is that you import the views after you created the app variable in your main script, so when the view script imports the main script the variable is already defined.
If you would try to import the views above declaring the app variable it would not work because it would cause an import loop and could not find the app variable.
Your project structure defines how the import would work best.
Here's an example of "A bit larger type of application" where you can use blueprints that defines a collection of views, templates, static files and other elements that can be applied to an application:
https://github.com/pallets/flask-website/tree/master/flask_website
Kind regards
So I'm trying to graduate from the single file application and organize my flask app for scalability. However, I can't even get past running the server... I tried duplicating exact stackoverflow questions that have had similar troubles before, but no luck, i.e. Structure Flask-Restful API to use SQLAlchemy, python flask-restful cannot get app access in resource class.
I got a regular flask app to work following this structure: http://flask.pocoo.org/docs/0.10/patterns/packages/, however, I have a restful extension that I'm trying to structure, and it's not working.
The error I am getting is:
from yourapplication.resources.foo import Foo
ImportError: No module named resources.foo
My directory structure is:
/myapp
runserver.py
/venv
/yourapplication
init.py
api.py
/resources
foo.py
In runserver.py, I have:
from yourapplication import app
app.run(debug=True)
For init.py, I have:
from flask import Flask
app = Flask(__name__)
import yourapplication.api
lastly, for foo.py, I have:
from flask_restful import Resource
class Foo(Resource):
def get(self):
pass
def post(self):
pass
It's so simple, yet I can't get it to work. I followed, http://flask.pocoo.org/docs/0.10/patterns/packages/, and it works for a regular flask app, but not yet found luck structuring restful extension flask apps, which is what I'm dealing with. Please help guys!
I have been learning flask/ python from this tutorial http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
This blog is pretty good and it explain very well. In the first tutorial, if you notice,
he asks us to create a init.py file, a views.py file and a main run.py file.
root
/microblog
/apps
/__init__.py
views.py
I created the two files. He asks us to create a run.py file and put it in the root file. then
chmod a+x run.py
./run.py
It says the file does not exist.
If I,
python run.py
It says App module not defined.
I cannot figure out the problem, I put the run.py file in all the files, it doesnt not work what so ever.
I will also include the code so that it would be easier to answer instead of going to the above link
init.py
from flask import Flask
app = Flask(__name__)
from app import views
views.py
from app import app
#app.route('/')
#app.route('/index')
def index():
return 'Hello world'
run.py
#!flask/bin/python
from app import app
app.run(debug = True)
My questions:
Where should I put the run.py file?
Why are we creating different files? Why cant all of them be in one
full file?
init.py -->
he is importing flask which is normal. then assigning app =
(name). why is that? Then why is he importing views from apps?
views.py -->
from app import app? is app an existing module here or the one we
just created? what does #app.route('/') or
#app.route('/index')do?
Can some one put the code together and explain it?
It says App module not defined
You misspelled package name: you have apps in your directory tree and you try to import app
Where should I put the run.py file?
Anywhere you want as long app is in PYTHONPATH. Or you can put it inside microblog directory.
he is importing flask which is normal. then assigning app = (name). why is that?
# Create reference to flask WSGI application object
app = Flask(__name__)
Why? Because you need application to run. See official docs: Flask object
Then why is he importing views from apps?
from app import views
means: From package named app import module named views
Naming convention could be probably different but if you don't see the difference you should probably spend more learning python basics before starting with more sophisticated stuff.
from app import app? is app an existing module here or the one we just created? what > does #app.route('/') or #app.route('/index')do?
#app.route('/')
def index():
return 'Hello world'
Short answer: if app receives request for url '/' responds using function foo
For more see official docs: add_url_rule and URL Route Registrations
Update
Why are we creating different files? Why cant all of them be in one full file?
Actually nothing stops you from putting everything inside one file but most of the time it is really bad idea. If you ask about reasoning in this specific example it is mostly about separating modules that have different responsibilities.