I want to access to a configuration dictionnary outside of a class.
How can I do that ?
Here is the example of the webapp website.
import webapp2
config = {'foo': 'bar'}
app = webapp2.WSGIApplication(routes=[
(r'/', 'handlers.MyHandler'),
], config=config)
For instantiating the app
import webapp2
class MyHandler(webapp2.RequestHandler):
def get(self):
foo = self.app.config.get('foo')
self.response.write('foo value is %s' % foo)
For accessing the config value in a class.
So I want to use the self.app.config.get('foo') just above the class to initialize a global variable. Naturally I can't use self outside of the class so I would like to know what I must do to retrieve the value.
In my application the configuration dictionnary is in a separate file and I have multiple configuration files so I don't want to import the file and do something like config['foo'] because I need to use the configuration file that the application is using.
Thank you
I do not know if I understand your question, but you can use a utility to get the app (without self):
webapp2.get_app()
docs: http://webapp-improved.appspot.com/api/webapp2.html#utilities
Related
I use MongoEngine as an ODM in my Flask application. Depending on the passed configuration document, MongoEngine should use a different collection.
At the moment I achieve this by changing the internal meta variable model._meta['collection']. Is there an alternative for selecting the collection?
from mongoengine import connect
from api_service.model import MyModel
create_app(config):
app = Flask(__name__)
# load app.config
connect(app.config['MONGODB_DB'],
host=app.config['MONGODB_HOST'],
port=app.config['MONGODB_PORT'],
username=app.config['MONGODB_USERNAME'],
password=app.config['MONGODB_PASSWORD'],
)
MyModel._meta['collection'] = app.config['MONGODB_MYMODEL_COLLECTION']
I know that you can define the collection by meta:{} in the class body of the model (see here). But I am not in the app context there and therefore I cannot access `app.config'.
You can simply modify the meta attribute inside the class itself
class MyModel(Document):
meta = {"collection": "my_actual_collection_name"}
...
Check This for more meta attributes you can use
Solution Update
I defined a helper class that can have a provide an access the application's configurations
class AppConfigHelper:
from flask import current_app
APP_CONFIG = current_app.config
and in the document import and use that class to get the collection name.
class MyModel(Document):
meta = {'collection': AppConfigHelper.APP_CONFIG['MONGODB_MYMODEL_COLLECTION']}
...
This is not the best solution I can think of, but it does the job.
Caution: this is not gonna work if you run it separately from Flask, it is going to crash, you can run it inside the app itself, or using flask shell
I need to create a class instance (lets say backend requests session) on the app startup(runserver), and I don't want to rewrite this session after running other management command. How can I achieve this? I tried several approaches and I'm not sure why something like this doesn't work.
# app/apps.py
class MyConfig(AppConfig):
....
requests_session = None
....
def ready(self):
if MyConfig.requests_session is None:
MyConfig.requests_session = requests.Session()
Unfortunately, the condition is always met and the session is recreated. This approach is recommended in the documentation though.
Other solution for me would be to run MyConfig.ready() only after using selected subset of management commands, is that possible?
Is there completely different better way for me to store requests session?
TIA
I think it should work if you use an instance variable instead of a class variable:
# app/apps.py
class MyConfig(AppConfig):
def __init__(self, app_name, app_module):
super(MyConfig, self).__init__(app_name, app_module)
self.requests_session = None
def ready(self):
if self.requests_session is None:
self.requests_session = requests.Session()
The question now is how to access this instance variable elsewhere. You can do that like so:
from django.apps import apps
# Here myapp is the label of your app - change it as required
# This returns the instance of your app config that was initialised
# at startup.
my_app_config = apps.get_app_config('myapp')
# Use the stored request session
req = my_app_config.requests_session
Note that this instance variable only exists in the context of the current process. If you run a management command in a separate process (e.g., manage.py ...) then that will create a new instance of each app.
I am using bottle.py framework along with Jinja2 templates in a new application.
Whenever a user logs into the application I would like to add a new global Jinja2 variable with the name of the active user, so in a partial template (the header) I can display this name.
In my python (bottle) file I've tried several things according to what I googled so far, but no success yet.
This is the last thing I tried inside a function:
import jinja2
env = jinja2.Environment(loader=jinja2.FileSystemLoader('templates'))
env.globals['myglobal'] = 'My global'
#env.globals.update({'myglobal': 'My global'})
But, when putting this into the header template: {{myglobal}} it simply doesn't show up.
Since this is my first time with bottle and jinja2 anyone knows how can achieve this?
I have a similar setup, and this works for me using the BaseTemplate built into bottle:
from bottle import BaseTemplate
BaseTemplate.defaults['myglobal'] = 'My global'
In this case you need to use before_request hook, just like below:
from bottle import Jinja2Template
#hook('before_request')
def before_request():
Jinja2Template.defaults['myglobal'] = 'My global'
from bottle import Jinja2Template
Jinja2Template.defaults['foo'] = 'bar'
This is to add a variable to every rendered jinja2 templates. If you want to add a filter, here is what I did:
import functools
from bottle import jinja2_view
def foo():
return 'bar'
view = functools.partial(jinja2_view, template_settings={
'filters': {'foo': foo}})
You can set any jinja2 settings using this.
I have a series of blueprints I'm using, and I want to be able to bundle them further into a package I can use as seamlessly as possible with any number of other applications. A bundle of blueprints that provides an entire engine to an application. I sort of created my own solution, but it is manual and requires too much effort to be effective. It doesn't seem like an extension, and it is more than one blueprint(several that provide a common functionality).
Is this done? How?
(Application dispatching methods of tying together several programs might work isn't what I'm looking for)
Check this out: Nesting Blueprints → https://flask.palletsprojects.com/en/2.0.x/blueprints/#nesting-blueprints
parent = Blueprint('parent', __name__, url_prefix='/parent')
child = Blueprint('child', __name__, url_prefix='/child')
parent.register_blueprint(child)
app.register_blueprint(parent)
I wish the Blueprint object has a register_blueprint function just as the Flask object does. It would automatically place and registered blueprints under the current Blueprints' url.
The simplest way would be to create a function that takes an instance of a Flask application and registers all your blueprints on it in one go. Something like this:
# sub_site/__init__.py
from .sub_page1 import bp as sb1bp
from .sub_page2 import bp as sb2bp
# ... etc. ...
def register_sub_site(app, url_prefix="/sub-site"):
app.register_blueprint(sb1bp, url_prefix=url_prefix)
app.register_blueprint(sb2bp, url_prefix=url_prefix)
# ... etc. ...
# sub_site/sub_page1.py
from flask import Blueprint
bp = Blueprint("sub_page1", __name__)
#bp.route("/")
def sub_page1_index():
pass
Alternately, you could use something like HipPocket's autoload function (full disclosure: I wrote HipPocket) to simplify the import handling:
# sub_site/__init__.py
from hip_pocket.tasks import autoload
def register_sub_site(app,
url_prefix="/sub-site",
base_import_name="sub_site"):
autoload(app, base_import_name, blueprint_name="bp")
However, as it currently stands you couldn't use the same structure as example #1 (HipPocket assumes you are using packages for each Blueprint). Instead, your layout would look like this:
# sub_site/sub_page1/__init__.py
# This space intentionally left blank
# sub_site/sub_page1/routes.py
from flask import Blueprint
bp = Blueprint("sub_page1", __name__)
#bp.route("/")
def sub_page1_index():
pass
I have solution for myself how to load blueprints defined in configuration, so then you can have something like CORE_APPS = ('core', 'admin', 'smth') in config and when you construct app you can register those apps (of course those strings in CORE_APPS must be the names of the files you want to import in your python path).
So I'm using function to create app:
app = create_app()
def create_app():
app = Flask(__name__)
# I have class for my configs so configuring from object
app.config.from_object('configsClass')
# does a lot of different stuff but the main thing could help you:
from werkzeug.utils import import_string
for app in app.config['CORE_APPS']
real_app = import_string(app)
app.register_blueprint(real_app)
After that your blueprint should be registered. Of course you can have different format in configs to support custom url prefixes and so on and so on :)
Of course you can also do something like this in your main blueprint, so in the application creation you will need to register that one main blueprint.
I'm trying to set the namespace for all DB operations for the Google App Engine in python, but i can't get it done.
Currently my code looks something like this:
""" Set Google namespace """
if user:
namespace = thisUser.namespace
namespace_manager.set_namespace(namespace)
""" End Google namespace """
#Then i have all sorts of classes:
class MainPage(BaseHandler):
def get(self):
#code with DB operations like get and put...
class MainPage2(BaseHandler):
def get(self):
#code with DB operations like get and put...
class MainPage3(BaseHandler):
def get(self):
#code with DB operations like get and put...
app = webapp2.WSGIApplication([ ... ], debug=True, config=webapp2_config)
The problem with this is, is that in the classes all DB operations are still done on the default namespace (so as if no namespace is set). Eventhough i set the namespace in the very top of my code.
When i print the variable "namespace", which i also set in the top of the code, then i do get to see the namespace that i wish to use.
But it looks like Google App Engine somewhere resets the namespace to empty before running the code in the classes.
So now i'm wondering if there's a good way to set the namespace once somewhere.
Currently i set it like this in all "def's":
class MainPage(BaseHandler):
def get(self):
namespace_manager.set_namespace(namespace)
#code with DB operations like get and put...
class MainPage(BaseHandler):
def get(self):
namespace_manager.set_namespace(namespace)
#code with DB operations like get and put...
etc...
It's just not a very elegant solution.
You need to write a middleware that will intercept the request and will set the namespace according to your app logic.
A good solution is to add a hook. Something like that should be works.
from google.appengine.api import apiproxy_stub_map
NAMESPACE_NAME = 'noname'
def namespace_call(service, call, request, response):
if hasattr(request, 'set_name_space'):
request.set_name_space(NAMESPACE_NAME)
apiproxy_stub_map.apiproxy.GetPreCallHooks().Append(
'datastore-hooks', namespace_call, 'datastore_v3')
You can add it in your main.py or appengine_config.py. By this way the hook is configured during the loading of the instances and keeps his state.
You can use appconfig.py and define namespace_manager_default_namespace_for_request()
Have a read of https://developers.google.com/appengine/docs/python/multitenancy/multitenancy see the first section of "Setting the Current Namespace"