How would you access the Django authentication framework from a Flask app?
I have a Django app and Flask app running in parallel on a server. Both are hosted behind the same domain, but behind different paths, so they should be able to see each other's cookies.
I'm using Flask to run a simple API microservice, where using Django would be overkill. However, to prevent abuse, I still want Flask to check the request's cookies to see if they're from a user who's still authenticated in the Django application. I don't want to re-implement an authentication framework in Flask.
Access Django settings from inside Flask is relatively simple. I just put something like this at the top of my Flask script to set the path to my Django settings module:
sys.path.insert(0, <path to Django project>)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mydjangoproject.settings")
from django.conf import settings
However, I'm unsure how to update a Flask request handler to pull the correct cookies from a request and verify them with Django's authentication backend. How would I do this?
Digging through the Django interals for the session and authentication middleware, it looks like it's pretty easy to fed Flask's native request instance to them. This seems to do it for me:
from importlib import import_module
from django.conf import settings
from django.contrib.auth.middleware import get_user
engine = import_module(settings.SESSION_ENGINE)
SessionStore = engine.SessionStore
session_key = request.cookies.get(settings.SESSION_COOKIE_NAME)
request.session = SessionStore(session_key)
user = get_user(request)
print(user.is_authenticated)
Related
In a flask app I'm developing, I have some web views, which return a normal web page content and an API blueprint. For development configuration, I turn on debug, which is handy to see the backtrace in a browser:
DEBUG = True
However, this also applies to the API blueprint. Dumping HTML content into the console when doing a request through httpie is not very nice. Is there a way to have debug only for the web views and not for the APIs?
I am writing a flask application with angularjs frontend. Templates aren't rendered from flask yet, they are delivered as static files. My api endpoint is as following:
#route('/projects', method=['GET'])
def rest_projects(self):
"""TODO: CRUD operation
"""
Project = Model.get('project.project')
return jsonify([project.serialize() for project in Project.search([])])
url_for works perfect with above endpoint but is there any way it can build urls for js templates also?. Say if url has api prefixed ie: /api/tasks, it comes to this handler otherwise deliver template. Right now I am using nginx to achieve that but is there anything wrong in my design which is restricting me to do this from flask only.
Flask is not intended to serve static files and you are better off keeping your files served by nginx for performance reasons. You can serve static files however using send_static_file() or send_from_directory methods.
http://flask.pocoo.org/docs/0.10/api/
I am running Flask and Eve on localhost at a same time. The Flask app serves static files and makes requests to the Eve app to get some data. I want to run Eve only, without a separate Flask app. How can I serve static files with Eve?
A better approach will be to prefix the /api for all REST APIs. This can be done by adding URL_PREFIX="api" in settings.py.
By doing this whenever there is request to /, Eve(Flask) will not return the resource catalog instead returns the page as given in run.py.
To serve static content add route decorators accordingly in run.py,
#app.route('/')
def index():
return app.send_static_file('index.html')
app.run(host="0.0.0.0", debug=True)
Eve is a Flask application (a subclass) so as a general rule everything that works with Flask works with Eve too. You could register a blueprint, or add new routes.
Also see this answer for a link to a working example: Servicing html requests with Eve
try set import_name arg for Eve:
app = Eve(import_name=__name__)
I have an application that is constructed as follows:
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(frontend.create_app(), {
'/api': api.create_app()
})
app.config['DATABASE'] = db
I want to access the same database in both the frontend and api apps, but when I run something like current_app.config['DATABASE'] in Blueprints registered to api, that raises KeyError: 'DATABASE'. Is it possible to inherit configurations so that tests, etc. need only modify the top-level abstraction? Thanks.
Simply change your create_app methods on frontend and api to take a configuration dictionary and use flask.Config to create a configuration with all the properties of app.config (loadable from environmental variables, etc.):
from flask import Config
from werkzeug.wsgi import DispatcherMiddlware
config = Config()
config.from_envvar("YOUR_PROGRAM_CONFIG")
app = DispatcherMiddlware(frontend.create_app(config), {
'/api': api.create_app(config)
})
Then you can merge the provided config with each of your app's configurations:
def create_app(config):
app = Flask(__name__)
app.config.update(config)
# Potentially, load another config
app.config.from_envvar("YOUR_PROGRAM_CONFIG_FRONTEND", silent=True)
return app
Note that there is no need to create an app to route to other apps - the dispatcher middleware can already do that for you.
Also note that if you are already using blueprints it may make more sense to simply ship the blueprints and compose them on a single application, rather than using dispatcher middleware (depending, of course on how complex your apps are).
I am trying to run a django app and a webapp2 app together in one python interpreter. I'm using werkzeug for that as described here.
Here's my sample code.
from werkzeug.wsgi import DispatcherMiddleware
from django_app import application as djangoapp
from webapp2_app import application as webapp2app
application = DispatcherMiddleware(djangoapp, {
'/backend': webapp2app
})
After doing this, I would expect all requests to /backend should be treated by the webapp2 app as /. But it treats the requests as /backend. This work fines with other WSGI apps using django or flask. The problem only appears with webapp2 apps. Does anyone have any suggestions how to overcome this? Is there any other way I can achieve my purpose without using werkzeug for serving multiple WSGI apps under one domain?
DispatcherMiddleware fabricates environments for your apps and especially SCRIPT_NAME. Django can deal with it with configuration varibale FORCE_SCRIPT_NAME = '' (docs).
With Webapp2 it's slightly more complicated. You can create subclass of webapp2.WSGIApplication and override __call__() method and force SCRIPT_NAME to desired value. So in your webapp2_app.py it could be like this
import webapp2
class WSGIApp(webapp2.WSGIApplication):
def __call__(self, environ, start_response):
environ['SCRIPT_NAME'] = ''
return super(WSGIApp, self).__call__(environ, start_response)
# app = WSGIApp(...)