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.
Related
I'm designing a Flask app that graphs some weather data for several cities. It makes sense to me to use a "City" class that handles the fetching and parsing of the data every time the page is loaded. However, what I'm not sure about is how Flask would handle these instances. Is Flask "smart" enough to know to release the memory for these instances after the page is served? Or will it just gradually consume more and more memory?
Alternatively, would I just be able to create a single global class instance for each city OUTSIDE of the "#app.route" functions that I could use whenever a page is requested?
The deployment server will be Windows IIS using FastCGI, in case that matters at all.
Flask is "just" a framework. It is still executed and managed by the "normal" Python interpreter so the question "how Flask would handle these instances" is nonexistent.
Define classes and use their instances as you would in any other Python project/snippet, however it might be beneficial to think where to define them.
It will not make sense inside a route since the class will be redefined every time a request is received, but the how is exactly the same.
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?
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)
I apologize in advance for asking a rather cryptic question. However, I did not understand it despite going through a lot of material. It would be great if you could shed some light on this.
What is the purpose of a request_loader in flask-login? How does it interact with the user_loader decorator?
If I am using a token based authentication system (I am planning on sending the token to my angularJS front end, storing the token there and sending that token in the authorization-token header), will I need a request_loader or will a user_loader (where I check the auth header and see if the user exists) suffice?
From the Flask-Login documentation:
Sometimes you want to login users without using cookies, such as using
header values or an api key passed as a query argument. In these cases,
you should use the request_loader callback. This callback should
behave the same as your user_loader callback, except that it accepts
the Flask request instead of a user_id.
So, to answer your question, they both serve the same function for Flask-Login. They are both used to load the user. request_loader, however, is appropriate for custom logins.
Here's a great tutorial I found that utilizes request_loader to take advantage of token based authentication (The post is not my own, I'm merely sharing the link): http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html
I need to make this clear.
This is the reason why you shoud use request_loader with flask_login.
There will be a lot of #login_required from flask_login used in your api to guard the request access.
You need to make a request to pass the check of auth.
And there will be a lot of current_user imported from flask_login,
Your app need to use them to let the request act as the identity of the current_user.
There are two ways to achieve the above with flask_login.
Using user_loader makes the request to be OK for #login_required.
It is often used for UI logins from browser.
It will store session cookies to the browser and use them to auth later.
So you need to login only once and the session will keep for a time.
Using request_loader will also be OK with #login_required.
But it is often used with api_key or basic auth.
For example used by other apps to interact with your flask app.
There will be no session cookies,
so you need to provide the auth info every time you send request.
With both user_loader and request_loader,
now you got 2 ways of auth for the same api,
protected by #login_required,
and with current_user usable,
which is really smart.
To verify users with Flask-Login's session_id for frontend requests through Angular, you must set the withCredentials configuration flag to true.
That is, if you are using Angular's $http.post(url,data [,config]) or $http.get(url [,config]), make sure the config object contains the property withCredentials set to true. This will instruct the browser to use its cookies in the same way it would for a full-on page visit.
For example,
$http.post('/api/login',{username:'myusername',password:'mypassword'},{withCredentials:true})
will post the data {username:'myusername',password:'mypassword'} to your site/app's /api/login route and, if you're using Flask-Login and are logged in, Flask will know.
You can set this behavior for all $http service requests by setting
$httpProvider.defaults.withCredentials=true
somewhere in your app. Currently, I have that line of code in my app.config block, which seems appropriate to me:
var myApp = angular.module('myApp');
myApp.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
(Since this post is about Flask, folks may want to send form data through Angular in such a way that it can be found in request.form, which has a similar solution, fyi.)
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.