User:Pathoschild/Getting started with Flask

From Wikitech
Jump to: navigation, search

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.

  1. Install prerequisites: nothing to do! They're already installed on Tool Labs by default.
  2. 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()
    
  3. 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).
  4. Set the correct file permissions from the terminal:
    chmod 755 ~/app.fcgi
    chmod 755 ~/.lighttpd.conf
    
  5. Start the server from the terminal:
    webservice start
    
  6. 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.

  1. Create ~/controllers/__init__.py with no content. (It's a Python thing.)
  2. Create ~/controllers/hello.py:
    import flask
    
    app = flask.Blueprint("hello", __name__)
    
    @app.route("/")
    def hello():
            return "hello world"
    
  3. 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()
    
  4. Restart the webservice from the terminal:
    webservice restart
    
  5. 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.

  1. 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>
    
  2. Create ~/templates/hello.html:
    {% extends "base.html" %}
    {% set page_title = 'Hello world!' %}
    {% block content %}
            <p>The server would like to say "{{message}}". :)</p>
    {% endblock %}
    
  3. 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