From charlesreid1

Revision as of 13:11, 23 August 2018 by Admin (talk | contribs) (→‎App)

Basics

Basic App

Run a Flask app that is bound to all network interfaces on the host, and listens on port 5000:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

If host and port are not specified, flask will only listen on the local network interface on port 5000.

if __name__ == '__main__':
    app.run(debug=True)

Routes

Simple hello world route:

@app.route('/hello')
def hello():
    return "Hello, World!"

To return HTML, we can return it in a string:

@app.route('/get_html')
def get_html():
    return "<h2>Flask Returns HTML Code</h2>"

If we are writing an API, we want routes that return JSON. we can use Flask's jsonify function:

from flask import Flask, jsonify

...

@app.route('/list')
def list():
    d = {'a' : 1, 'b' : 2, 'c' : 3}
    return jsonify(d)


RESTful API

We can use Flask to design and implement a RESTful API service. Flask will be a server and interpret between URLs and Python actions. Note that this is particularly handy if you're designing an internet-of-things thing, as you can install Flask on a RaspberryPi, and now you have a RESTful API for accessing your Raspberry Pi! If you take it a step further, you can control the GPIO pins on the Raspberry Pi, and make the Pi do things with your hardware and circuitry based on your API actions.

Hello World

Let's put our Flask hello world app in run.py:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    app.run(debug=True)

now we run it with python run.py

Return Some Data with JSON

Now let's return some data from the RESTful server to the client (perhaps a sensor on a Raspberry Pi running the RESTful API):

from flask import Flask, jsonify

app = Flask(__name__)

data = [
    {
        'sensor_id': 1,
        'time': u'2005-01-01 22:23:04',
        'temparature1': 114.15, 
        'temparature2': 132.92, 
        'alarm': False
    },
    {
        'sensor_id': 1,
        'time': u'2005-01-01 22:23:05',
        'temparature1': 118.66, 
        'temparature2': 158.41, 
        'alarm': False
    }
]

@app.route('sensor/id/1/data', methods=['GET'])
def get_tasks():
    return jsonify({'tasks': tasks})

if __name__ == '__main__':
    app.run(debug=True)

Now you can request that resource using CURL:

$ $ curl -i http://localhost:5000/sensor/id/1/data
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 294
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 04:53:53 GMT

]
{
  "data": [
    {
        'sensor_id': 1,
        'time': u'2005-01-01 22:23:04',
        'temparature1': 114.15, 
        'temparature2': 132.92, 
        'alarm': False
    },
    {
        'sensor_id': 1,
        'time': u'2005-01-01 22:23:05',
        'temparature1': 118.66, 
        'temparature2': 158.41, 
        'alarm': False
    }
  ]
}

Send Some Data with POST

You can also send some data with POST requests:

from flask import request

@app.route('/todo/api/v1.0/tasks', methods=['POST'])
def create_task():
    if not request.json or not 'title' in request.json:
        abort(400)
    task = {
        'id': tasks[-1]['id'] + 1,
        'title': request.json['title'],
        'description': request.json.get('description', ""),
        'done': False
    }
    tasks.append(task)
    return jsonify({'task': task}), 201

and the corresponding output when we POST data to the server:

$ curl -i -H "Content-Type: application/json" -X POST -d '{"title":"Read a book"}' http://localhost:5000/todo/api/v1.0/tasks
HTTP/1.0 201 Created
Content-Type: application/json
Content-Length: 104
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Mon, 20 May 2013 05:56:21 GMT

{
  "task": {
    "description": "",
    "done": false,
    "id": 3,
    "title": "Read a book"
  }
}

Packaging Flask Apps

Deploying Flask Web App as Submodule

Instructions for deploying a Flask web app as a submodule in a Python module:

First, your directory structure will look something like this:

README.md
setup.py
mymodule/
  __init__.py
  submodule1/
  submodule2/
  webapp/
    __init__.py
    additional_routes.py
    templates/
      [...]
    static/
      [...]

Next, your setup.py file will look something like this:

config = {
    'description': 'My Module',
    'install_requires': ['flask'],
    'packages': ['mymodule','mymodule.submodule1','mymodule.submodule2','mymodule.webapp'],
    'include_package_data' : True,
    'package_data' : {
        'templates' : 'mymodule/webapp/templates/*',
        'static' : 'mymodule/webapp/static/*'
        },
    'scripts': [],
    'name': 'mulch',
    'zip_safe' : False
}

setup(**config)

The key lines here are include_package_data and package_data, which will also install your non-Python template and static files with your module.

Now you can install your module with python setup.py install, and your module is available to use from anywhere.

To create an instance of your module's web app from anywhere, follow these steps:

1. Install the module

2. Import the webapp submodule:

from mymodule.webapp import *

3. Start the webapp:

app.run(debug=True)

Voila!



Resources

Basics

The Flask mega tutorial is really handy: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world

Micro blog example: https://stormpath.com/blog/build-a-flask-app-in-30-minutes

Bundling

Official flask site: patterns for distributing flask apps: http://flask.pocoo.org/docs/patterns/distribute/

Packaging a flask app: http://www.plankandwhittle.com/packaging-a-flask-web-app/

Flags