I want to create a blueprint; not an issue with the current blueprint I have. I can do this.
But, say I wanted to use a flask extension in my application (for my case I want to integrate flask-Cache)?
Everything I've done so far has errored:
cache = Cache(my_blueprint)
importing Cache and various parts of Cache in varying guises
so something like flask-cache is simple enough to wrap around my app:
from flask.ext.cache import Cache
cache = Cache(app)
but using this in a blueprint or using with a blueprint I don't quite understand how right now.
EDIT: the less obvious solution was to crib from the extension and build my own library to import into the blueprint, but it is more work and I'm not quite done yet. extensions / blueprints don't seem to be compatible from my level of understanding right now.
In order to avoid circular imports you will want to create your cache instance separate from your application instance (you may want to consider switching to the app factory module if you are building something more complex).
cache.py
from flask_cache import Cache
cache = Cache()
foo.py
from flask import Blueprint
from cache import cache
mod = Blueprint(...)
#mod.route("/")
#cache.cached(timeout=50)
def index():
return datetime.now().strfmtime("%Y-%m-%d %H:%M:%S")
app.py
from flask import Flask
from yourapp.cache import cache
from yourapp.foo import mod
app = Flask("yourapp")
# ... snip ...
cache.init_app(app)
# ... snip ...
app.register_blueprint(mod)
The only thing the application needs access to is the app-instance to create a cache.
Let's assume your code: cache = Cache(app) is in foo.py. But you wanna use the cache in bar.py which uses a Blueprint to register the routes.
foo.py:
from flask.ext.cache import Cache
cache = Cache(app)
from bar import mod
app.register_blueprint(mod)
The only thing you have to do in bar.py is importing the cache from foo.py and use it:
bar.py:
from foo import chache
mod = Blueprint(...)
#mod.route('/')
#cache.cached(timeout=50)
def index():
return str(datetime.now())
Flask Cache Docs and Examples
EDIT: The example above has a problem with circiular imports. The way to go here is separate the app from the cache:
pack/__init__.py:
app = Flask(__name__)
from pack.views.general import mod
app.register_blueprint(mod)
pack/cache.py:
from flask.ext.cache import Cache
from pack import app
cache = Cache(app)
pack/views/general.py:
from flask import Blueprint
from pack.chache import chache
mod = Blueprint(...)
#mod.route('/')
#cache.cached(timeout=50)
def index():
return str(datetime.now())
Related
I'm confused about import of custom modules. As you can see in the code below, in main I first import all libraries needed by everything AND that I duplicated those imports in my i_setup_functions.py file. Leaving any of them out of either file created errors. Same with duplication of "app = Flask(name)". I really hope that redundancy is not correct and there is some simple way to fix this. All I want to do is include setup for sessions, email, data connection, etc. Only showing sessions here for simplicity sake.
BTW: The entire app worked bug-free until I tried to modularize.
Error message:
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
That error message points to a line in a function in the middle of main.py that tries to create a session.
Thanks for any ideas you all can share!
main.py:
from flask import session
import random
from datetime import datetime, timedelta
from i_setup_functions import setup_sessions
app = Flask(__name__)
# is the following line even necessary in either module?
application = app
setup_sessions()
setup_mail()
setup_logging()
[snip]
# Error here:
​session["id_user"] = id_user
i_setup_functions.py
from flask import session
import random
from datetime import datetime, timedelta
from i_setup_functions import setup_sessions
app = Flask(__name__)
application = app
def setup_sessions():
random.seed(datetime.now())
app.config['SECRET_KEY'] = str(random.randint(1, 500)) + "jibber" + str(random.randint(1, 500)) + "jabber"
app.permanent_session_lifetime = timedelta(days=30)
return True
You are creating two (or more?) separate apps and setting the SECRET_KEY to the one that isn't serving your application.
To fix this remove all app = Flask(__name__) calls from all modules except main.py. Then, pass the app you create in main.py to all the places you need it.
from flask import session
import random
from datetime import datetime, timedelta
from i_setup_functions import setup_sessions
app = Flask(__name__)
setup_sessions(app)
setup_mail(app)
setup_logging(app)
[snip]
​session["id_user"] = id_user
Initial note: I know there are many of these type posts for python but I've tried many of the solutions and they have not worked for me.
File structure:
/nickdima
__init__.py
/test_pong
__init__.py
pong.py
/nickdima/__init__.py:
from flask_socketio import Socketio
socker = SocketIO()
from test_pong import pong
def create_app():
app = Flask(__name__)
socker.init_app(app)
return app
/nickdima/test_pong/pong.py
from __main__ import socker
#socker.on('connect')
def handle_connect():
print('connected')
When I run this code on Heroku I get the error:
from __main__ import socker
ImportError: cannot import name 'socker'
I'm fairly certain this is related to a circular import but I cannot solve it.
I've tried putting: from test_pong import pong
inside the create_app() function to "delay the import" locally but to no avail and I get the same error cannot import name 'socker'
Ok, so after further inspection here's what I suggest:
/nickdima
__init__.py
socker.py
/test_pong
__init__.py
pong.py
/nickdima/socker.py
from flask_socketio import Socketio
socker = SocketIO()
/nickdima/__init__.py:
from nickidima.socker import socker
from nickidima.test_pong import pong
def create_app():
app = Flask(__name__)
socker.init_app(app)
return app
/nickdima/test_pong/pong.py
from nickidima.socker import socker
#socker.on('connect')
def handle_connect():
print('connected')
This way you no longer have circular dependencies!
Imports are relative to the root directory where nickidima is placed. I'm not sure how Heroku works with this kind of importing (actually I've never used Heroku) but I hope you get the idea and will be able to tweak it to your needs.
The most important lesson: circular dependencies are almost always a sign of a bad design and almost always can be replaced with non-circular dependencies. And when they can: do it.
Side note: I'm following your naming convention (socker?) but seriously, you should fix it. :)
I am writing unit tests for the api, which connects to MongoDB. In my API module it looks like this:
from flask import Flask, jsonify
from MyApp import MongoData
api = Flask(__name__)
DB_CONN = MongoData()
#api.route('/bla', methods=['GET'])
def alive():
return jsonify({'response': true})
I have a problem while importing this module in my unittest. I want to mock collection from MongoData() with special mock class, which uses mongomock. The problem is that I cannot mock DB_CONN while importing in tests:
from MyApp import api
I was trying to do this with mock:
DB_CONN = MockMongoData()
with mock.patch('MyApp.api.DB_CONN', DB_CONN):
from MyApp import api
but it still tries to connect to the database as specified in the config file.
Any advice how to mock DB_CONN from MyApp.api module?
Thanks in advance!
EDIT:
This will work:
import sys
from MyApp import MongoData, MockMongoData
sys.modules['MyApp'].MongoData = MockMongoData
from MyApp import api
But is there a better (more pythonic) way to do this?
Import the module first, then monkeypatch its members:
DB_CONN = MockMongoData()
from MyApp import api
with mock.patch('MyApp.api.DB_CONN', DB_CONN):
api.run()
I'm having a problem with Flask wherein routes declared in imported modules are not be registered and always result in a 404. I am running the latest version Flask on Python 2.7.
I have the following directory structure:
run.py has the following code:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
import views.home
if __name__ == '__main__':
app.run()
home.py has the following code:
from run import app
#app.route('/test')
def test():
return "test"
When I run run.py the route declared in home.py (http://localhost:5000/test) always returns a 404 even though run.py imports views.home. The root view (http://localhost:5000) declared in run.py works fine.
I have written a function that prints out all the registered routes and /test is not in there (get a list of all routes defined in the app).
Any idea why?
I have discovered that switching the import statement in run.py from
import views.home
to
from views.home import *
makes everything work, which gave me the clue as to why the modules are not being registered using import views.home.
Basically, when run.py is run as a script it is given the name __main__ and this is the name given to the module in sys.modules (Importing modules: __main__ vs import as module)
Then when I import app from run.py in views.home.py a new instance of run.py is registered in sys.modules with the name run. As this point, the reference to app in run.py and views.home.py are two different references hence the routes not being registered.
The solution was to move the creation of the app variable out of run.py and in to a separate python file (I called it web_app.py) that is imported into run.py. This guarantees that the Flask app variable declared inside web_app.py is the always referenced correctly wherever web_app.py is imported.
So run.py now looks like this:
from web_app import app
if __name__ == '__main__':
app.run()
and web_app.py looks like this:
from flask import Flask
app = Flask(__name__)
import view.home
You can do it by reorganizing your code as it is described here Larger Applications, but it is more recommended to divide them into smaller groups where each group is implemented with the help of a blueprint. For a gentle introduction into this topic refer to the Modular Applications with Blueprints chapter of the documentation.
Modular Applications with Blueprints
I can't get it to work to use one module that creates the Flask application object and runs it, and one module that implements the views (routes and errorhandlers). The modules are not contained in a Python package.
app.py
from flask import Flask
app = Flask('graphlog')
import config
import views
if __name__ == '__main__':
app.run(host=config.host, port=config.port, debug=config.debug)
views.py
from app import app
#app.route('/')
def index():
return 'Hello!'
config.py
host = 'localhost'
port = 8080
debug = True
I always get Flask's default "404 Not Found" page. If I move the contents of view.py to app.py however, it works. What's the problem here?
You have four modules here:
__main__, the main script, the file you gave to the Python command to run.
config, loaded from the config.py file.
views, loaded from the views.py file.
app, loaded from app.py when you use import app.
Note that the latter is separate from the first! The initial script is not loaded as app and Python sees it as different. You have two Flask objects, one referenced as __main__.app, the other as app.app.
Create a separate file to be the main entry point for your script; say run.py:
from app import app
import config
if __name__ == '__main__':
app.run(host=config.host, port=config.port, debug=config.debug)
and remove the import config line from app.py, as well as the last two lines.
Alternatively (but much uglier), use from __main__ import app in views.py.