Slide 1

Slide 1 text

Creating a REST API with Python and Flask Miguel Grinberg @miguelgrinberg

Slide 2

Slide 2 text

About Me OpenStack Engineer @ Rackspace Author of the O’Reilly book “Flask Web Development” Author of Flask-SocketIO, Flask-Migrate, Flask- HTTPAuth and a few more Flask extensions My blog: http://blog.miguelgrinberg.com

Slide 3

Slide 3 text

What is an API?

Slide 4

Slide 4 text

API A set of rules and protocols by which two components agree to communicate.

Slide 5

Slide 5 text

Fat Server API Model Client ● User interaction Server ● Application logic ● Rendering ● User input handling ● Data management

Slide 6

Slide 6 text

Fat Client API Model Client ● User interaction ● Application logic ● Rendering ● User input handling Server ● Data management

Slide 7

Slide 7 text

What is REST?

Slide 8

Slide 8 text

REST An architectural style for highly scalable networked applications that typically run on top of the HTTP protocol.

Slide 9

Slide 9 text

The Six REST Principles ● Client-Server ● Uniform Interface ○ Identification of Resources ○ Manipulation of Resources Through Representations ○ Self-Descriptive Messages ○ Hypermedia as the Engine of Application State (HATEOAS) ● Stateless ● Layered System ● Cacheable ● Code-on-Demand (optional) Watch my PyCon 2015 talk “Is your REST API RESTful?” to learn what these are.

Slide 10

Slide 10 text

Resources ● Resources represent the entities in the application’s domain ○ Customers, Invoices, Products, Players, Games, etc. ○ Can also represent physical objects: Garage doors, cameras, sensors, etc. ● Each resource or collection of resources has a unique URL ○ https://api.example.com/customers ○ https://api.example.com/customers/123 ○ https://api.example.com/customers/123/invoices ● Clients work with resource representations ○ JSON {“first”: “Susan”, “last”: “Smith”, “phone”: “503-111-2222”} ○ XML SusanSmith503-111-2222

Slide 11

Slide 11 text

● The client sends a HTTP request to the server ○ The request method specifies the action to perform. Examples: GET(read), POST(create), PUT(edit), DELETE ○ The URL specifies the target resource ○ The request body specifies a resource representation (POST and PUT only) ○ The request headers contain metadata (content types, caching details, etc.) ● The server sends a HTTP response back to the client ○ The status code specifies the result of the operation 200 (OK), 201 (Created), 202 (Accepted), 400 (Bad Request), 404 (Not Found), etc. ○ The response body specifies a resource representation ○ The response headers contain metadata Requests and Responses

Slide 12

Slide 12 text

Why Flask?

Slide 13

Slide 13 text

What Would you rather Have? I take the tub, thank you very much!

Slide 14

Slide 14 text

What’s in the (Flask) Box? ● Built in development server and debugger ● Integrated unit testing support ● RESTful request dispatching ● Uses Jinja2 templating ● Support for secure cookies (client side sessions) ● 100% WSGI 1.0 compliant ● Unicode based ● Extensively documented ● Built in development server and debugger ● Integrated unit testing support ● RESTful request dispatching ● Uses Jinja2 templating ● Support for secure cookies (client side sessions) ● 100% WSGI 1.0 compliant ● Unicode based ● Extensively documented

Slide 15

Slide 15 text

@app.route('/customers', methods=['GET']) def a_function(): pass RESTful Request Dispatching @app.route('/customers', methods=['POST']) def another_function(): pass @app.route('/customers', methods=['GET']) @app.route('/customers', methods=['GET']) @app.route('/customers/', methods=['DELETE']) def yet_another_function(id): pass

Slide 16

Slide 16 text

Creating REST APIs with Flask

Slide 17

Slide 17 text

The 90-90 Rule The first 90% of the code accounts for 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time. Tom Cargill, Bell Labs

Slide 18

Slide 18 text

● Use Flask’s native dispatching to implement your base API endpoints ● Manage the actual resources: the choice is yours! ○ Database resources: SQLAlchemy, Peewee, direct DB access, etc. ○ Physical devices: Use the appropriate Python package to control the device ● Handle resource representations ○ Manually through dictionaries and the native JSON/XML packages ○ Using more sophisticated third party packages: Flask-RESTful, Marshmallow, etc. ● Add token based authentication ○ Flask-HTTPAuth wraps authentication at the HTTP protocol level ● Return appropriate error responses ● Encapsulate resources in Python modules to keep things organized The First 90%

Slide 19

Slide 19 text

● Filtering ● Sorting ● Pagination ● Asynchronous requests ● Caching ● Rate Limiting ● Hypermedia ● … WTF??? None of these things are directly related to specific resources in your application, so they should not clutter your resources! The Other 90%

Slide 20

Slide 20 text

@api.route('/customers//invoices', methods=['GET']) @etag @json @collection(Invoice) def get_customer_invoices(id): return Customer.query.get_or_404(id).invoices Decorators To The Rescue! @api.route('/cameras//movies', methods=['POST']) @async def capture_movie(id): camera = get_camera_from_id(id) movie_id = camera.start_recording() return url_for('get_movie', id=movie_id)

Slide 21

Slide 21 text

Questions? Miguel Grinberg @miguelgrinberg