how to add app object in flask's main file - flask

I want to add app object once in main.py which can be used everywhere, but route does not work in this way. What is the issue here?
main.py
from flask import Flask
app = Flask(__name__)
if __name__ == "__main__":
app.run(debug=True)
routes.py
from main import app
#app.route("/", methods = ["GET"])
def home():
return "hi"
However, if declare app = Flask(name) in routes.py and import app in main.py it is working all fine. Working scenario.
main.py
from routes import app
if __name__ == "__main__":
app.run(debug=True)
routes.py
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route("/", methods = ["GET"])
def home():
return "hi"
my objective is to define app in main.py and import it in other files, but getting issues.

main.py is not even aware that routes.py exists. Import your routes.py file after initializing your app.
# main.py
from flask import Flask
app = Flask(__name__)
import routes # needed
if __name__ == "__main__":
app.run(debug=True)
# routes.py
from __main__ import app
#app.route("/")
def home():
return "hi"

Related

Why do the routes "/login" and "/register" not work?

My Flask application is not recognizing/using the two defined routes in auth.py, how come?
File structure
Error Msg:
Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Routes
http://127.0.0.1:5000/home (WORKS)
http://127.0.0.1:5000/profile (WORKS)
http://127.0.0.1:5000/login (DOES NOT WORK)
http://127.0.0.1:5000/register (DOES NOT WORK)
app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/home")
def home():
return render_template("index.html")
#app.route("/profile")
def profile():
return render_template("profile.html")
auth.py
from flask import current_app as app, render_template
#app.route("/login")
def login():
return render_template("login.html")
#app.route("/register")
def register():
return render_template("register.html")
You can't register routes to current_app, instead you have to use a class called Blueprint which is built exactly for this purpose (splitting application into multiple files).
app.py
from flask import Flask, render_template
from auth import auth_bp
app = Flask(__name__)
# Register the blueprint
app.register_blueprint(auth_bp)
#app.route("/home")
def home():
return render_template("index.html")
#app.route("/profile")
def profile():
return render_template("profile.html")
auth.py
from flask import Blueprint, render_template
# Initialize the blueprint
auth_bp = Blueprint('auth', __name__)
#auth_bp.route("/login")
def login():
return render_template("login.html")
#auth_bp.route("/register")
def register():
return render_template("register.html")
See https://flask.palletsprojects.com/en/2.0.x/blueprints/ for more information.
It seems like you have at least two files in which you have these routes. In your app.py file you have /home and /profile, they both work. They work because you initialised the Flask application over there.
Flask offers Blueprints to split up your application. You could create a blueprint called auth for example.
There is a specific tutorial on this subject as well.
I suggest moving the initialisation of the app variable to the __init__.py file and creating a create_app() method that returns app. In this method you can register your blueprints as well.
This method would look like:
def create_app():
app = Flask(__name__)
from . import app as application, auth
app.register_blueprint(auth.bp)
app.register_blueprint(application.bp)
return app
Your auth.py file, for example, would look like:
from flask import Blueprint, render_template
bp = Blueprint('auth', __name__)
#bp.route("/login")
def login():
return render_template("login.html")
#bp.route("/register")
def register():
return render_template("register.html")

Simple Flask example with pytest and application factory does not work

I am new to flask and I have set up a simple flask example and two tests using pytest(see here). When I let run only one test it works, but if I run both tests it does not work.
Anyone knows why? I think I am missing here some basics of how flask works.
code structure:
app/__init__.py
from flask import Flask
def create_app():
app = Flask(__name__)
with app.app_context():
from app import views
return app
app/views.py
from flask import current_app as app
#app.route('/')
def index():
return 'Index Page'
#app.route('/hello')
def hello():
return 'Hello World!'
tests/conftest.py
import pytest
from app import create_app
#pytest.fixture
def client():
app = create_app()
yield app.test_client()
tests/test_app.py
from app import create_app
def test_index(client):
response = client.get("/")
assert response.data == b"Index Page"
def test_hello(client):
response = client.get("/hello")
assert response.data == b"Hello World!"
The problem is with your registration of the routes in app/views.py when you register them with current_app as app. I'm not sure how you would apply the application factory pattern without using blueprints as the pattern description in the documentation implies they are mandatory for the pattern:
If you are already using packages and blueprints for your application [...]
So I adjusted your code to use a blueprint instead:
app/main/__init__.py:
from flask import Blueprint
bp = Blueprint('main', __name__)
from app.main import views
app/views.py -> app/main/views.py:
from app.main import bp
#bp.route('/')
def index():
return 'Index Page'
#bp.route('/hello')
def hello():
return 'Hello World!'
app/__init__.py:
from flask import Flask
def create_app():
app = Flask(__name__)
# register routes with app instead of current_app:
from app.main import bp as main_bp
app.register_blueprint(main_bp)
return app
Then your tests work as intended:
$ python -m pytest tests
============================== test session starts ==============================
platform darwin -- Python 3.6.5, pytest-6.1.0, py-1.9.0, pluggy-0.13.1
rootdir: /Users/oschlueter/github/simple-flask-example-with-pytest
collected 2 items
tests/test_app.py .. [100%]
=============================== 2 passed in 0.02s ===============================

cannot import name 'serve' from 'waitress'

My Sample Flask Code (wsgitest.py):
from flask import Flask
from waitress import serve
app = Flask(__name__)
#app.route('/wait')
def index():
return ("<h3>Hello World</h3>")
if __name__ == '__main__':
serve(app, host='0.0.0.0', port=5000)
waitress
Version: 1.4.3
Error
ImportError: cannot import name 'serve' from 'waitress' (C:\.....\wsgitest.py)
if your your project has one file named waitress. Import resolves to your project file rather than waitress package
your code is ok. I copy your code to my idea, it's run successfully

Basic Flask views questions app not found

Hi I don't know why "app" is not defined. I have a very simple app and try to run it:
run.py:
from flask import Flask
app = Flask(__name__)
import views
if __name__ == "__main__":
app.run(debug=True)
views.py:
#app.route('/')
def hello():
return 'Hello, World!'
If I try to run the server via "python run.py" I get the following error:
File "XXX\a\views.py", line 1, in <module>
#app.route('/')
NameError: name 'app' is not defined
You need to put all your routes in run.py.
This is because, you have declared app in run.py and in views.py you are trying to access it.
Following works for me:
run.py
from flask import Flask
app = Flask(__name__)
import view
view.py
from run import app
#app.route('/')
def hello():
return 'Hello, World!'
On terminal execute
export FLASK_ENV=development
export FLASK_APP=run.py
then finally flask run or python -m flask run.
Also, its a good idea to switch to flask run from app.run. See this

In Flask is it possible to import views using the create_app() pattern without using Blueprints?

I have a very small Flask app that is laid out as follows:
tinker/
main.py
/my_package
init.py
views.py
When I do tinker>python main.py everything runs fine. Here are the contents of each file:
main.py:
from my_package import app
app.run()
my_package/init.py:
from flask import Flask
app = Flask(__name__)
from my_package import views
my_package/views.py:
from my_package import app
#app.route('/')
def home():
return 'Ola!!!!!'
While all the above code runs fine when I try to modify it slightly by using a a create_app() code pattern, as in the below, views.py throws the following exception: "ImportError: cannot import name 'app' from 'my_package' " Is there a way to fix the problem without using Blueprints?
main.py:
from my_package import create_app
app = create_app()
app.run()
my_package/init.py:
from flask import Flask
def create_app():
app = Flask(__name__)
from my_package import views
return app
my_package/views.py:
from my_package import app
#app.route('/')
def home():
return 'Ola!!!!!'
You import the views within application context, then in the views you can use current_app.
in mypackage/__init__.py:
def create_app():
app = Flask(__name__)
with app.app_context():
from . import views
in mypackage/views.py:
from flask import current_app
#current_app.route('/')
def index():
return 'hello, world!'
init.py needs to be renamed to __init__.py
Move app = Flask(__name__) outside of the create_app method
Change to from . import app in views.py