User:Pathoschild/Getting started with Flask
This page helps you create a Python web application on the Tool Labs infrastructure, using Flask (a Python framework for serving web pages) and the new FastCGI webserver. The result will be a fully-functional application ready to host your tools. This guide assumes you're familiar with Python, but you don't need to be familiar with Flask or FastCGI.
Setup
Set up Flask server
First let's set up Flask using FastCGI, and make sure it works with a 'hello world' page.
- Install prerequisites: nothing to do! They're already installed on Tool Labs by default.
- Create the FastCGI application configuration (~/app.fcgi):
#!/usr/bin/python from flup.server.fcgi import WSGIServer from flask import Flask, request import time import logging # create Flask application app = Flask(__name__) # register 'hello world' page @app.route("/") def hello(): return "Hello World!" # configure Flask logging from logging import FileHandler logger = FileHandler('error.log') app.logger.setLevel(logging.DEBUG) app.logger.addHandler(logger) # log Flask events app.logger.debug(u"Flask server started " + time.asctime()) @app.after_request def write_access_log(response): app.logger.debug(u"%s %s -> %s" % (time.asctime(), request.path, response.status_code)) return response # start server if __name__ == '__main__': WSGIServer(app).run()
- Create the Lighttpd server configuration file (~/.lighttpd.conf):
fastcgi.server += ("/" => (( "socket" => "/tmp/TOOLNAME-fcgi.sock", "bin-path" => "/data/project/TOOLNAME/app.fcgi", "check-local" => "disable", "max-procs" => 1 )) ) debug.log-request-handling = "enable"
Replace TOOLNAME with your tool name (see introduction to Tool Labs). - Set the correct file permissions from the terminal:
chmod 755 ~/app.fcgi chmod 755 ~/.lighttpd.conf
- Start the server from the terminal:
webservice start
- Confirm everything worked: give the server a few moments to launch, then visit http://tools.wmflabs.org/TOOLNAME in your browser. You should see "Hello world". If not, something went wrong; make sure you correctly followed the previous steps.
Implement MVC controllers
We have our Flask application running now, but having all the pages and content in ~/app.fcgi isn't very sustainable (unless it's a very simple one-page tool). Let's convert the tool to a basic model–view–controller application.
- Create ~/controllers/__init__.py with no content. (It's a Python thing.)
- Create ~/controllers/hello.py:
import flask app = flask.Blueprint("hello", __name__) @app.route("/") def hello(): return "hello world"
- Register the controller in ~/app.fcgi like this:
#!/usr/bin/python from flup.server.fcgi import WSGIServer from flask import Flask, request import time import logging from controllers import hello # create Flask application app = Flask(__name__) app.register_blueprint(hello.app) # configure Flask logging from logging import FileHandler logger = FileHandler('error.log') app.logger.setLevel(logging.DEBUG) app.logger.addHandler(logger) # log Flask events app.logger.debug(u"Flask server started " + time.asctime()) @app.after_request def write_access_log(response): app.logger.debug(u"%s %s -> %s" % (time.asctime(), request.path, response.status_code)) return response # start server if __name__ == '__main__': WSGIServer(app).run()
- Restart the webservice from the terminal:
webservice restart
- Visit http://tools.wmflabs.org/TOOLNAME/ in your browser. If everything went well, you should see "hello world".
Implement MVC views
Our Flask application is now setup as an model–view–controller application, but our controller is still returning the raw page content. It will be easier to maintain our code if the data is separate from the representation. That's where views come in — they format your data model.
- Create ~/templates/base.html:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>{{page_title}}</title> </head> <body> <h1>{{page_title}}</h1> <div>{% block content %}{% endblock %}</div> </body> </html>
- Create ~/templates/hello.html:
{% extends "base.html" %} {% set page_title = 'Hello world!' %} {% block content %} <p>The server would like to say "{{message}}". :)</p> {% endblock %}
- Now render the template from ~/controllers/hello.py:
import flask app = flask.Blueprint("hello", __name__) @app.route("/") def hello(): return flask.render_template("hello.html", message="hi there!")
Next steps
Great! We have our fully-functional Flask MVC application running on Tool Labs. We can use it as the foundation for our tools — prettify the HTML layout, create more controllers and views, implement APIs using HTTP content negotiation, and so forth. You can read the Flask documentation and tutorials to continue from here.
See also
- Setting up Flask as a CGI application (instead of FastCGI)
- Using the MediaWiki API/OAuth from Flask