From charlesreid1

 
(4 intermediate revisions by the same user not shown)
Line 115: Line 115:
         return "<h2>Hi there!</h2>"
         return "<h2>Hi there!</h2>"
</pre>
</pre>
===Exceptions and errors===
To write a custom exception that will return <code>abort(YYY)</code> (where YYY is an HTTP code), you can write an exception class that defines a status_code private variable:
<pre>
class InvalidUsage(Exception):
    status_code = 400
    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload
    def to_dict(self):
        rv = dict(self.payload or ())
        rv['message'] = self.message
        return rv
</pre>
Next, we need to create a handler for this type of error, and register it with our application:
<pre>
from flask import jsonify
...
class InvalidUsage(Exception):
...
@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response
</pre>
Described here in the flask documentation: http://flask.pocoo.org/docs/1.0/patterns/apierrors/


==POST Endpoints==
==POST Endpoints==
Line 155: Line 197:
=Packaging Flask Apps=
=Packaging Flask Apps=


==Deploying Flask Web App as Submodule==
[[Flask/Packaging]] - a page that covers how to bundle flask apps into a ready-to-distribute Python package


Instructions for deploying a Flask web app as a submodule in a Python module:
=Resources=
 
First, your directory structure will look something like this:
 
<pre>
README.md
setup.py
mymodule/
  __init__.py
  submodule1/
  submodule2/
  webapp/
    __init__.py
    additional_routes.py
    templates/
      [...]
    static/
      [...]
</pre>
 
Next, your setup.py file will look something like this:
 
<pre>
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)
</pre>
 
The key lines here are <code>include_package_data</code> and <code>package_data</code>, which will also install your non-Python template and static files with your module.


Now you can install your module with <code>python setup.py install</code>, and your module is available to use from anywhere.
==Flaskadillo==


To create an instance of your module's web app from anywhere, follow these steps:
I put together a tutorial on how to use Flask. This is available in the flaskadillo repo:


1. Install the module
* https://git.charlesreid1.com/charlesreid1/flaskadillo
* https://github.com/charlesreid1/flaskadillo


2. Import the webapp submodule:
<pre>
from mymodule.webapp import *
</pre>


3. Start the webapp:


<pre>
==Links==
app.run(debug=True)
</pre>
 
Voila!
 
 
 
 
=Resources=
 
==Basics==


The Flask mega tutorial is really handy: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
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
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=
=Flags=
Line 241: Line 221:
[[Category:Python]]
[[Category:Python]]
[[Category:Web]]
[[Category:Web]]
[[Category:Web Server]]
[[Category:REST API]]
[[Category:REST API]]
[[Category:Python Packaging]]

Latest revision as of 17:11, 15 November 2018

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

A simple hello world route:

from flask import Flask

...

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

Returning HTML

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

from flask import Flask

...

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

Returning JSON

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)

Rendering templates

This example shows how to take an integer variable from the URL and use it on an HTML template page:

from flask import Flask, render_template

...

@app.route('/sample/<int:sample_number>')
def sample(sample_number):
    render_template('sample.html', sample_number=sample_number)

The contents of sample.html are given below:

    <html>
    <head>
    <title>Sample {{sample_number}}</title>
    </head>
    <body>
        <h2>{{sample_number}}</h2>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula.</p>
    </body>
    </html>

Raising errors

To abort with a 400 (server error), use the abort function

from flask import Flask, abort

...

@app.route('/how_to_abort')
def how_to_abort():
    import random
    if random.random() < 0.5:
        abort(400)
    else:
        return "<h2>Hi there!</h2>"

Exceptions and errors

To write a custom exception that will return abort(YYY) (where YYY is an HTTP code), you can write an exception class that defines a status_code private variable:

class InvalidUsage(Exception):
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
        rv = dict(self.payload or ())
        rv['message'] = self.message
        return rv

Next, we need to create a handler for this type of error, and register it with our application:

from flask import jsonify

...

class InvalidUsage(Exception):

...

@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response


Described here in the flask documentation: http://flask.pocoo.org/docs/1.0/patterns/apierrors/

POST Endpoints

To deal with data sent via a POST request, use the request variable, imported from Flask, and get the POSTed data using request.json:

from flask import Flask, jsonify, abort, request

...

@app.route('/post_something',methods=['POST'])
def post_something():
    if not request.json:
        abort(400)
    post_data = request.json

    # Now render a template for the user
    # and populate the template variables
    # with data that was POSTed
    render_template('posted.html',
                        title = post_data.get('title','A Pretty Boring Title'),
                        author = post_data.get('author','Anonymous Coward'),
                        color = post_data.get('color','blue'),
    )


    # NOTE:
    # If you'd rather return json, just do
    # return jsonify({'status':'ok'}), 200

Now we can POST data to the server by adding the JSON content type to a curl request, and pass data in using the -d flag. here's the curl request:

$ curl -i -H "Content-Type: application/json" -X POST -d '{"title":"My first post", "author":"Gladys Overwith", "color":"orange"}' http://localhost:5000/post_something

Packaging Flask Apps

Flask/Packaging - a page that covers how to bundle flask apps into a ready-to-distribute Python package

Resources

Flaskadillo

I put together a tutorial on how to use Flask. This is available in the flaskadillo repo:


Links

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

Flags