Why can't I use flask.g after a request comes? - python

According to the Flask 0.12 docs:
flask.g
...... Starting with Flask 0.10 this is stored on the application
context and no longer on the request context which means it becomes
available if only the application context is bound and not yet a
request.
As far as I know, when a request comes, a application context will be created, if there isn't one. So shouldn't flask.g be available after a request has come, since the request ensures the existence of an application context?
As a bouns question: why should I store database connections on g instead of request? I know creating a application context is less "expensive" than creating a request context, but when a request comes, a request context will be created anyway.

The wording there is a little awkward. The g object is available during a request as well. A request context is nested inside an application context.
You should store a database connection in the g object because it'll be available *even when there is no request, such as in the flask shell command, and any custom command-line commands. You'll need this when initialising your database, for example.
Next, there are advanced use-cases where you may want to create an 'internal' request, calling another route on your Flask app as if it came from outside. This nested request would re-use the existing app context.
There is never a request context without an application context.

Answering bonus question from Flask documentation:
For instance, the request variable is the request object associated
with the current request, whereas g is a general purpose variable
associated with the current application context.

flask.g is bound to the session of current request. That means that you have different g's for different requests. For example, I store a user in g object for easier access to it (it's not good, but fast to access and easy to use)

Related

Python: pipe request to blueprint endpoint through another endpoint

I have a Flask application that inherits a library with some blueprints already defined (that I can't change). Now I need to be able to filter out some of the requests that goes to one of the pre-defined endpoints.
The endpoint /updateuser is defined in the blueprint, but now I need to stop certain requests from getting to that endpoint, and instead return a message in my application.
I've figured out how to overwrite an endpoint in a blueprint, but that's not what I want. I'd like to add this /updateuser endpoint in my flask application, and either return a message OR send them to the original endpoint that's defined in the library, without the user being exposed to this extra layer.
Is there any good way to achieve this?

Flask tutorial: Why do we use the app context for the DB connection?

I'm studying the Flask tutorial and am confused about the usage of the app context for connecting to the database. On the page, the author says:
Creating and closing database connections all the time is very
inefficient, so you will need to keep it around for longer. Because
database connections encapsulate a transaction, you will need to make
sure that only one request at a time uses the connection.
However, it seems that creating and closing the connection is exactly what is accomplished by the code. We have a view get_db that connects to the database, returns a connection object, and adds it to the app context if not present. We also have a close_db view that closes the connection object when the app context is torn down.
My understanding of what's happening here is as follows: A user connects to the app's home page, establishing a connection with the database and then closing it. Each time the user makes a request to the page (e.g., posting a new blog entry), a new connection is established with the database and then closed when the request is completed. So what's the value of using the app context at all? Why not just directly create and close a connection for each request?
Maybe I am misunderstanding something here -- any insight appreciated!
It's badly documented. But basically the whole point of the app context is to abstract app-specific-but-persistent-across-request data objects (ostensibly to allow multi-tenant applications that are all separate instances of Flask without tying everything to request context). In any case, flask.g is the app context-specific dict for the current app context. This way you can call get_db() on the very first request, shove the resulting connection object into g and then use g.dbconn later on in the app, which doesn't get killed on each request (presumably you want to use the same connection on each page access). I like to think of flask.g is like a class (well the app, in this case) instance of globals().
See also: http://flask.pocoo.org/docs/0.12/appcontext/#app-context

How to keep a request context in a celery task, in Python Flask?

Is there a way to copy the request to a celery task in Flask in such a manner that the task executes inside the request context which initiated the task?
I need to access the flask security current user in a celery task, but since the task is outside the request context, I can not do that. I need additional information from the request, so just forwarding the current user to the task would not do the trick.
My task does inserts on the database. It needs the current user to save the id of the user which creates the row. Passing the user object to the task would solve the problem. However, the application logic is such that every insert/delete/update is logged via before flush event, which logs the user who did the modification, his IP, original url, the data it inserts...)
Log event is done like I said before flush, and it works in 99% scenarios.
But when I have one lengthy task which I want to be a celery task, the request
data is not available, nor is the current user (since it is outside the original request context)
The is no out-of-the-box way to pass the request or current_user objects to the celery task as they are non serializable. But people have worked around this by creating a wrapper to call the celery task in the request context.
The Celery task in a Flask request context blog post explores this topic in detail. The gists by Xion and derived one by aviaryan with the Request Context wrapper.

How can I share a dict between two different http requests

The Django application loads data from a file to a Python dict, process it and sends it as http response. Now say n number of request are received on the web server then this Django app would run n times and load data from a file to a Python dict n times. I was wondering if somehow I can make this data being loaded to the dict only once while n http response could be served.
An example view.py file for the problem situation can be as followed:
from django.http import HttpResponse
from django.http import HttpRequest
def hello(request):
data = open("abc").readlines()
return HttpResponse(data[0])
Binding the dictionary to a global name will make it persist for as long as the Django project runs. Note that each Django process (some WSGI containers, e.g. mod_wsgi, can run multiple processes for an app) will have its own independent copy of the dictionary.
If the data is relevant to the user, you can use djanog's session framework to persist data across requests. If the data needs to be shared between numerous users, you can use the cache.
This is a job for the Django Middleware. Add it to your settings and it will persist across your request. Its a better option then persistence and definitely a lot better than using a global object.
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input and/or output. Each middleware component is responsible for doing some specific function. For example, Django includes a middleware component, XViewMiddleware, that adds an "X-View" HTTP header to every response to a HEAD request.

Flask for Python - architectural question regarding the system

I've been using Django and Django passes in a request object to a view when it's run. It looks like (from first glance) in Flask the application owns the request and it's imported (as if it was a static resource). I don't understand this and I'm just trying to wrap my brain around WSGI and Flask, etc. Any help is appreciated.
In Flask request is a thread-safe global, so you actually do import it:
from flask import request
I'm not sure this feature is related to WSGI as other WSGI micro-frameworks do pass request as a view function argument. "Global" request object is a feature of Flask. Flask also encourages to store user's data which is valid for a single request in a similar object called flask.g:
To share data that is valid for one
request only from one function to
another, a global variable is not good
enough because it would break in
threaded environments. Flask provides
you with a special object that ensures
it is only valid for the active
request and that will return different
values for each request. In a
nutshell: it does the right thing,
like it does for request and session.

Categories

Resources