Flask restless

34
FLASK RESTLESS FAST AND EASY REST API’S

Transcript of Flask restless

Page 1: Flask restless

FLASK RESTLESSFAST AND EASY REST API’S

Page 2: Flask restless

Code SamplesGithub

https://github.com/mandshaw/flask_microbrewery

Page 3: Flask restless

What is Flask RestlessLibrary built around flask

Model driven

Define your models

Define their relationships

Expose your models

Specify what to expose them on (GET, POST, PUT, DELETE

Page 4: Flask restless

What is Flask Restless

Uses SQLAlchemy

Supports SQLite, Postgresql, MySQL, Oracle and many more

Built in query language (FOR FREE!)

Page 5: Flask restless

Models

What is a model?

Comes from SQLAlchemy or Flask-SQLAlchemy

Used to represent objects which will become records in a database

Page 6: Flask restless

Flask-SQLAlchemy

Abstracts away a lot of unnecessary SQLAlchemy config and makes your life easier.

Read more here

Page 7: Flask restless

Defining a Model# Define the modelsclass Beer(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Unicode, unique=True)

Will execute:

CREATE TABLE beer (

id INTEGER NOT NULL,

name VARCHAR,

PRIMARY KEY (id),

UNIQUE (name),

)

Page 8: Flask restless

Turning a Model into a API

# Create the DBdb.create_all()# Create the Flask-Restless API manager.manager = APIManager(app, flask_sqlalchemy_db=db)# Create the API endpoints from the DB Models# These will be available at /api/<tablename>manager.create_api(Beer, methods=['GET', 'POST', 'PUT', 'DELETE'])

Page 9: Flask restless

DEMO STEP/1

Page 10: Flask restless

Relationships

Page 11: Flask restless

Creating a one to many Relationship

Relationship always goes on the ‘one’ side # Define the modelsclass Beer(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Unicode, unique=True) # Create a foreign key type_id = db.Column(db.Integer, db.ForeignKey(‘type.id’)) class Type(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Unicode, unique=True) # Create a relationship beers = db.relationship('Beer', backref=db.backref('type'), lazy=‘dynamic')

Page 12: Flask restless

DEMO STEP/2

Page 13: Flask restless

Making Fields Invisible

Page 14: Flask restless

Excluding Columns

You can use exclude_columns or include_columns to hide columns in the response

manager.create_api(Beer, methods=['GET', 'POST', 'PUT', 'DELETE'], exclude_columns=['reviews', 'type'])

Page 15: Flask restless

DEMO STEP/3

Page 16: Flask restless

Pre and Post Processing

Page 17: Flask restless

Consider

On a POST or PUT for a review you want to add the date that the review was created

Do you?

Do this client side (What time zone? What format)

Do this server side

Page 18: Flask restless

Processors# Augments the request with the current db DATETIMESTAMP # When submitted def add_current_date(**kw): kw['data']['date'] = 'CURRENT_TIMESTAMP' return kw # Create the API endpoints from the DB Models# These will be available at /api/<tablename> manager.create_api( Review, methods=['GET', 'POST', 'PUT', 'DELETE'], preprocessors = { 'POST': [add_current_date], 'PUT_SINGLE': [add_current_date] })

Page 19: Flask restless

Processors

Preprocessors -> before the requests is processed

Postprocessors -> before the response is returned

Page 20: Flask restless

DEMO STEP/4

Page 21: Flask restless

Validation

Page 22: Flask restless

Validation

Not performed by Flask-Restless

Roll your own or use a combination of the SQLAlchemy validate decorator and flasks abort

Page 23: Flask restless

Validationfrom flask import Flask, abort from sqlalchemy.orm import validates

class Review(db.Model): id = db.Column(db.Integer, primary_key=True) date = db.Column(db.DateTime) stars = db.Column(db.Integer) comment = db.Column(db.Unicode) beer_id = db.Column(db.Integer, db.ForeignKey('beer.id')) author_id = db.Column(db.Integer, db.ForeignKey('reviewer.id')) @validates('stars') def validate_name(self, key, stars): if stars >= 1 and stars <=5: return stars else: return abort(400, description='A review must have a star rating of between 1 and 5')

Page 24: Flask restless

Pagination

Page 25: Flask restless

Server side Pagination

Natively uses server side pagination (default is 10 results per page)

<host>/api/<resource>?page=2 Give you page 2

Set the results_per_page attribute when creating your api to over-ride

manager.create_api(Reviewer, methods=['GET', 'POST', 'PUT', 'DELETE'], results_per_page=2)

Page 26: Flask restless

Querying data

NULL is the Chuck Norris of the database. Nothing can be compared to it. - Unknown

Page 27: Flask restless

Querying Data

Support query params on GETS

Uses Query Filters

<host>/api/<resource>/?q={“filter”:[…filters…]}

Page 28: Flask restless

Query FiltersLists of

{“name”: name, “op”: op, “val”: val}

{“name”: name, “op”: op, “field”: field}

name The field to use

op The operator to use

val The Value to use

field The field to compare name to

Page 29: Flask restless

Valid Operatorsequal ==, eq, equals, equals_to

not equal !=, neq, does_not_equal, not_equal_to

comparison >, gt, <, lt, >=, ge, gte, geq, <=, le, lte, leq

membership in, not_in

null check is_null, is_not_null

like like

has has

any any

Page 30: Flask restless

Querying Data

Extremely feature rich

Order by

Group By

Single result expected

READ THE DOCS

Page 31: Flask restless

ExamplesGet all the Hipsters

GET localhost:5000/api/reviewer?q={"filters":[{"name":"name","op": "ilike", "val":"Hipster%"}]}

Reviews with more than 3 stars

GET localhost:5000/api/review?q={"filters":[{"name":"stars","op": "gt", "val":3}]}

All reviews made by Hipster Jane

GET localhost:5000/api/review?q={"filters":[{"name":"author","op":"has","val":{"name":"name", "op":"eq", "val":"Hipster Jane”}}]}

Page 32: Flask restless

Examples

You can also use relationships in a GET

All reviews made by Hipster Jane(id=2)

GET localhost:5000/api/reviewer/2/reviews

Page 33: Flask restless

Further Reading

You can use SQLAlchemy migrate to migrate you DB revisions

Read all about it (and lots more) here

Page 34: Flask restless

QUESTIONS?