How to Design a Great API (using flask) [ploneconf2017]

D
Devon BernardVP of Engineering at Enlitic en Enlitic
How	to	Design	a	Great	API
(using	Flask)
Devon	Bernard
VP	of	Engineering	@	Enlitic
Developers Users
&
Intuitive Durable Flexible
Code	That	Makes	Developers	Happy
Intuitive
Standardization	Makes	Debugging	Easier
Very	Unique Standardized
Time	Spent	Debugging
Uniqueness	of	Environment
How to Design a Great API (using flask) [ploneconf2017]
○
Are	Hard	Coded	Variables	Bad?
Yes,	here’s	why:
1. When	runtime	variables	aren’t	centralized,	they’re	harder	to	find,	
making	your	code	less	readable
2. If	the	variable	is	related	to	environment,	you’ll	likely	need	to	juggle	git
3. If	the	variable	is	supposed	to	be	private	or	secret	(e.g.	passwords)
database = 'production_url'
File.py (production)
~~ database = ’localhost_url'
++ def ban_user(email):
++ ...
File.py (local	machine)
Leaking	Passwords
Configurations	/	Environment
database: postgresql://localhost:5432/my_app
test_database: postgresql://localhost:5432/testing
flask_login_secret:
import yaml
yaml_config = yaml.load(
open(('../my-app.yaml'))
print yaml_config[’database’]
usage
my_app.yaml.example
Configurations	/	Environment	(2)
class Config(object):
DEBUG = False
CSRF_ENABLED = True
SECRET = yaml_config['flask_login_secret']
SQLALCHEMY_DATABASE_URI = yaml_config['database']
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = yaml_config['test_database’]
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
TESTING = False
app_config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig
}
app = create_app('development')
app.run()
run.py
conftest.py
@pytest.fixture(scope='session')
def mock_app():
mock = create_app(’testing')
cxt = mock.app_context()
cxt.push()
yield mock
Object	Relational	Mappers
ObjectObject
Object Object
ObjectObject
ORM Relational
Database
Object	Relational	Mappers	(2)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(Text, nullable=False)
email = Column(Text, index=True,
unique=True, nullable=False)
password = Column(Text, nullable=False)
Object	Relational	Mappers	(3)
With	ORM Without	ORM
def get_user_email(id):
return conn.query(User.email)
.get(id)
def get_user_email(id):
query = text(”””
SELECT email FROM users
WHERE id = %d LIMIT 1;”””%(id))
rows = conn.execute(query)
if rows is not None:
return rows[0][’email’]
return None
^^	Much	simpler
^^	Might	have	to	worry	about	SQL	Injection
How	to	Standardize	Database	Schemas?	
GIT	History
Database	
Migrations
(Alembic)
+
Database	Schema
=
Database	Migrations
def upgrade():
op.add_column('reports',
sa.Column(author', sa.Text())
)
def downgrade():
op.drop_column('reports', author’)
models.py alembic/version/6a9eb6b43d7d_added_report_author.py
class Report(Base):
__tablename__ = 'reports’
++ author = Column(Text)
^^	automatically	generated	for	you	by	Alembic
Default	Alembic	Behavior
$ alembic revision –-autogenerate -m “myrev”
# file_template = %%(rev)s_%%(slug)s
Terminal
Alembic.ini
Default	Alembic	Behavior	(2)
$ alembic history
69c35d0ef5bb -> 000fd728c260 (head)
b4b0fbdebf42 -> 69c35d0ef5bb
9dcf0d65e983 -> b4b0fbdebf42
ac39eb5890f4 -> 9dcf0d65e983
7054e7fae54a -> ac39eb5890f4
6a9eb6b43d7d -> 7054e7fae54a
56a1b15216da -> 6a9eb6b43d7d
dbe9911f4c0b -> 56a1b15216da
2d5f5c762653 -> dbe9911f4c0b
24f34e82e6c1 -> 2d5f5c762653
...
Terminal
8
12
3
14
5
6
9
4
7
11
13
15
10
1
2
Ideal	Alembic	Behavior
# file_template = %%(rev)s_%%(slug)s
file_template =
%%(year)d_%%(month).2d_%%(day).2d_%%(
slug)s
Alembic.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
How	to	Standardize	Database	Data?
Revision	tools	typically	only	
manage	schemas,	not	data,	you’ll	
need	to	create	a	database	seed
Why
• Go	from	0	to	standard	instantly
• Developers	are	free	to	mess	with	
their	local	database
• It’s	easy	to	test	your	back	end	
with	a	known	database	setup
How
• Dump	database	data	to	a	sql file
• Create	a	script	(.py,	.sh,	etc)	to	
reset	your	database	schema	and	
insert	the	seed	file
pg_dump --dbname=“my_app”
--file=”/PATH/TO/seed.sql”	
--data-only	--inserts
Where	Are	My	Packages?
$ python run.py
ImportError: No module named flask_sqlalchemy
$ pip install flask_sqlalchemy
$ python run.py
ImportError: No module named smtplib
$ pip install smtplib
$ python run.py
ImportError: No module named passlib
$ ... #FacePalm
Requirements.txt
$ python run.py
ImportError: No module named flask_sqlalchemy
$ pip install –r requirements.txt
Collecting flask_sqlalchemy
Collecting smtplib
Collecting passlib
...
$ python run.py
* Running on http://127.0.0.1:5000/
Flask	==	0.12
Flask-Cors==3.0.3
Flask-SQLAlchemy ==	
2.1Flask-Login==0.3.2
psycopg2	==	2.6.1
PyYAML ==	3.11
requests	==	2.10.0
SQLAlchemy ==	1.0.14
passlib==1.6.5
bcrypt==3.1.1
WTForms==2.1
...
Requirements.txt (2)
git+ssh://git@github.com/MY_USER/MY_REPO.git#egg=MY_REPO
Install	packages	from	github
git+file:///PATH/TO/MY/PROJECT
Install	packages	from	local	file	system
Why	use	these	methods?
• Ability	to	quickly	test	whether	changes	to	another	python	project	
worked	without	having	to	push	to	github
• This	flow	is	fully	local	and	keeps	your	git history	cleaner
• WARNING:	When	using	the	local	file	system	method,	your	changes	
must	be	locally	committed	otherwise	pip	will	not	notice	the	changes.
Why	aren’t	my	files	updating?
$ find . -name '*.pyc' -delete
Your	project	may	be	running	pre-compiled	.pyc files	and	not	overriding	the	old	files
Common	.pyc conflict	scenarios:
• Moved	or	renamed	python	directories
• Moved	or	renamed	python	files
• Added	or	removed	__init__.py files
• Created	a	variable	with	the	same	name	as	a	module
To	clear	out	all	.pyc files	and	start	fresh,	run	the	following:
Why	Isn’t	the	Setup	README	Working?
$ cd MyApp
$ cp config/app.yaml.example config/app.yaml
cp: No such file or directory
$ #Confused #WhatDo
Setup	Scripts
def install(dirs, args):
env = make_virtualenv(dirs['venv_dir'])
path = install_node_and_npm(dirs, env['PATH'])
env['PATH'] = path
install_bower(dirs, env)
check_call(['bower', 'install', '--force-latest'],
cwd=dirs['root_dir'], env=env)
check_call(['pip', 'install', '-q', '--upgrade', 'pip'],
cwd=dirs['root_dir'], env=env)
check_call(['pip', 'install', '-q', '-r', 'requirements.txt'],
cwd=dirs['root_dir'], env=env)
return env
setup.py
Durable
Should	We	UnitTest?
Common	Concerns
• Writing	tests	takes	time	away	from	building	features
• Slows	down	development
• Writing	tests	is	boring
Short	Answer
• Absolutely!!!
• Don’t	just	test	the	golden-path,	also	test	failure	
scenarios	like	3xx,	4xx,	or	5xx	errors
Why	UnitTests are	Awesome
Resolution	of	Time	Concern
• Requirement:	You	must	verify	
your	code	works	before	
shipping
• Would	you	prefer	to	do	that	
manually	every	time	or	
automate	that	process?
• Test	coverage	is	an	upfront	
investment	saving	time	later	on	
extra	debugging
Time	Spent	Testing
Application	Complexity
Automated Manual
Why	UnitTests are	Awesome	(2)
Resolution	of	Boring	Concern
• Writing real code (tests)
vs	being	a	click	farm
Writing	Features Writing	Tests Clicking	Thru	App
How	Boring
Global	PIP	Cache
Using	the	Wrong	Dependencies?
Project	X
(Flask==0.12)
Project	Y
(Flask==0.8)
Common	Package	Management	
Problems
• Need	to	use	different	versions	of	
the	same	package	on	another	
project	or	branch
• Project	broke	because	it	was	
using	existing	package	versions	of	
other	projects
• Requirements.txt is	missing	an	
entry	because	previous	developer	
already	had	the	package	installed
Project	
Z
Project	
W
~/.venvs/Z
~/.venvs/Y
~/.venvs/W
~/.venvs/X
Virtual	Environments
Project	X
(Flask==0.12)
Project	Y
(Flask==0.8)
Project	
Z
Project	
W
Virtual	Environments	(2)
Setup
Issues?
Just	delete	your	venv and	create	a	fresh	one
$ virtualenv ~/.venvs/X
$ source ~/.venvs/X/bin/activate
(X)$ pip install -r requirements.txt
$ rm –rf ~/.venvs/X
Clean	&	easy	dependency	
management;	especially	when	
working	on	multiple	projects
Why?
• Package	version	conflicts
• v5.0.1	!=	v5.3.0
• Dependency	contamination	
across	multiple	projects
• Testing	dependency	upgrades
Flush	vs	Commit
Flush
Reserves	a	placeholder	spot	in	database
Commit
Saves	records	into	database
Tips
• Use	flush	when	you	need	to	get	an	auto-
increment	id	back
• Use	commit	ONLY	when	you	are	100%	sure	
you	want	to	save	rows
• Every	time	you	use	`flush`	or	`commit`,	you	
are	adding	another	round-trip	request
Problem	with	always	committing
def save_test(student, answers):
for answer in answers:
conn.add(Answer(answer))
conn.commit() # SLOW!
grade = calcGrade(answers)
<< ERROR >>
conn.add(Test(student, grade))
conn.commit()
Test	will	not	get	saved,	but	every	
answer	will	still	be	in	the	database!
Flush	vs	Commit	(2)
Only	commit	once
def save_test(student, answers):
for answer in answers:
conn.add(Answer(answer))
grade = calcGrade(answers)
<< ? ERROR ? >>
conn.add(Test(student, grade))
conn.commit()
If	error,	nothing	gets	saved
If	no	error,	everything	gets	saved
Flush	(if	auto-increment	needed)
def save_test(student, answers):
for answer in answers:
conn.add(Answer(answer))
conn.flush()
### use answers[0].id
grade = calcGrade(answers)
<< ? ERROR ? >>
conn.add(Test(student, grade))
conn.commit()
Errors	&	Rollbacks
On	app	error,	rollback	session
@app.errorhandler(Exception)
def handle_error_response(error):
conn.rollback()
return jsonify(error)
After	requests,	close	sessions
@app.teardown_appcontext
def shutdown_session(exception=None):
conn.remove()
Flexible
Project	Directory	Structure
/app
/api
/models
/dbms
/utils
/config
/setup
/tests
/api
/dbms
/utils
requirements.txt
conftest.py
run.py
/app	- Contains	all	business	logic	for	run-time	usage
/config - Contains	yaml and	other	configuration	files
/setup	- Contain	scripts	and	seed	files	for	resetting	
database	and	project	dependencies
/tests	- Contains	all	unit-test,	ideally	similar	in	directory	
structure	to	/app
App	Factories
app/__init__.py
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__, instance_relative_config=True)
app.config.from_object(app_config[config_name])
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.secret_key = app.config['SECRET']
cors = CORS(app, supports_credentials=True)
db.init_app(app)
login_manager.init_app(app)
app.register_blueprint(api)
return app
App	Factories	(2)
app/__init__.py
from flask import Flask
app = Flask(__name__)
import api
import db
app/api/__init__.py
from app import app, db
import endpoint_group1
import endpoint_group2
app/db/__init__.py
from app.utils.config import config
from sqlalchemy.orm import scoped_session
conn = scoped_session(config...)
import query_group1
import query_group2
Issues:
• Circular	imports	(prevents	testing)
• Lack	of	separation	of	concerns	
between	app	module	and	app	object
Blueprints
admins = Blueprint(
’admins', __name__)
app.register_blueprint(admins)
@admins.before_request
def before_admin_req():
print ”ADMIN ROUTE REQUESTED"
@admins.route('/admin/secret',
methods=['GET'])
def admin_secret():
return jsonify({})
public = Blueprint(
’public', __name__)
app.register_blueprint(public)
@public.before_request
def before_public_req():
print ”PUBLIC ROUTE REQUESTED"
@public.route('/public/not_secret',
methods=['GET'])
def public_not_secret():
return jsonify({})
Blueprints	can	be	used	to:
• Logically	group	routes
• Selectively	apply/add	request	lifecycle	events	to	a	subset	of	routes
Extend	and	Expire	Sessions
Every	time	a	user	makes	a	request,	extend	their	session	for	30	minutes
@app.before_request
def extend_session():
session.permanent = True
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=30)
session.modified = True
Flexible	Testing	(pdb)
Typical	Python	Debugging
def my_func(objects):
print "MY_FUNC", objects
if len(objects) > 0:
print "NOT EMPTY"
new_objects = some_func(objects)
<< ERROR >>
print new_objects
else:
print "EMTPY"
new_objects = []
return new_objects
• Lots	of	print	statements
• Only	renders	prints	run	before	the	app	crashes
• Can’t	update	values
Python	Debugger
import pdb
def my_func(objects):
pdb.set_trace()
if len(objects) > 0:
new_objects = some_func(objects)
<< ERROR >>
else:
new_objects = []
return new_objects
• Sets	a	break-point	at	`.set_trace()`
• Functions	like	JS	browser	debugging	break-points
• Can	step	line-by-line	or	continue	until	next	break-point
• At	each	line,	there	is	an	interactive	terminal
• Not	only	can	print,	but	update	values
Reliable User	Friendly Fast
APIs	That	Make	Users	Happy
Reliable
How	to	maximize	up-time?
Preventative	(Before	break)
• Don’t	ship	bugs
• Unit	Tests
• Staging	servers	with	user	testing
• A/B	rollouts
• Stable	deployment	server
Quick	Detection
• System	logging	(Splunk)
• Slack	hooks
• Scheduled	health	check	pings
• E.g.	cron jobs
Quick	Diagnosis
• Failure/Exception	tracking	+	
logging
• API	playground
• Postman
Versioning
Why
• New	rollouts	won’t	break	people’s	
existing	builds
• Backwards	compatibility
• Ability	to	plan	obsolescence
How
Host	a	deployment	for	each	version
• Track	version	#	in	config files
• Prepend	version	to	routes
Host	one	big	deployment	for	all	
versions
• Duplicate	files
• Create	route	version	mapper
Analytics	on	API	Usage
Why
• Shows	what	endpoints	are	most	
frequently	used	(most	critical)
• Optimize	popular	endpoints
• Shows	what	users	are	still	using	
deprecated	endpoints
• Notify	users	to	upgrade
How
• Could	be	as	simple	as	an	
incrementing	counter	in	a	
database	table
• Could	use	deployment	tools	to	
wrap	your	API	that	provide	
analytics (DevOps	level)
User	Friendly
101	in	Endpoint	Design
Things	to	be	aware	of
• #1	rule	is	being	consistent
• No	matter	what	you	pick,	some	group	is	going	to	be	annoyed
• Their	complaints	are	likely	valid,	but	only	for	a	small	
component,	not	how	it	affects	the	whole	picture
• Common	patterns:	REST,	CRUD
• Use	more	then	just	GET	and	POST
• PUT,	DELETE,	OPTIONS,	PATCH
• Use	relevant	status	codes
• 1xx info, 2xx success, 3xx redirection,
4xx	client	errors,	5xx	server	errors
• Figure	out	if	users	are	often	instantly	re-forming	the	data	
you	send	them
101	in	Endpoint	Documentation
If	it’s	not	documented,	it’s	as	if	it	doesn’t	exist
Over	document,	biggest	complaint	is	”lack	of	
documentation”
You	only	have	to	write	it	once,	but	it	can	be	read	
millions	of	times
Interactive	docs	&	test	environments	are	great
Postman
A	great	tool	for
• Sharing	endpoints	with	your	
team	and	users	in	an	
interactive	way
• Quickly	debugging	API	issues
Pro-tip
Use	environment	and	global	
variables	to	generalize	endpoint	
usage	across	localhost,	staging,	
and	production	servers
Fast
Python	Profiling
What	lines	of	code	are	costing	you	the	most	time?
Bulk	SQL	Inserts
Three	useful	methods
• bulk_save_objects
• bulk_insert_mappings
• Mogrify
ORMs	were	not	primarily	
intended	for	bulk	usage
Using	bulk	commands	
gives	a	5-10x	speed	boost
# Without bulk
for i in range(100000):
conn.add(Employee(name="EMP #" + str(i)))
conn.commit()
# With bulk
conn.bulk_save_objects([
Employee(name="EMP #" + str(i))
for i in range(100000)
])
Caching
Store	common	responses	in-memory	for	quick	retrieval
from flask import Flask
from flask.ext.cache import Cache
app = Flask(__name__)
cache.init_app(app,
config={'CACHE_TYPE': 'simple'})
@cache.cached(timeout=50)
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
Devon	Bernard
VP	of	Engineering	@	Enlitic
" devon@enlitic.com	
# @devonwbernard
Thank	you!
Any	questions?
1 de 57

Recomendados

Lean React - Patterns for High Performance [ploneconf2017] por
Lean React - Patterns for High Performance [ploneconf2017]Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Devon Bernard
957 vistas67 diapositivas
Rest in flask por
Rest in flaskRest in flask
Rest in flaskYehor Nazarkin
3.1K vistas14 diapositivas
Web2py Code Lab por
Web2py Code LabWeb2py Code Lab
Web2py Code LabColin Su
5K vistas83 diapositivas
Scala active record por
Scala active recordScala active record
Scala active record鉄平 土佐
6.3K vistas84 diapositivas
Using web2py's DAL in other projects or frameworks por
Using web2py's DAL in other projects or frameworksUsing web2py's DAL in other projects or frameworks
Using web2py's DAL in other projects or frameworksBruno Rocha
1.9K vistas25 diapositivas
Why Every Tester Should Learn Ruby por
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyRaimonds Simanovskis
17.9K vistas25 diapositivas

Más contenido relacionado

La actualidad más candente

Why and How Powershell will rule the Command Line - Barcamp LA 4 por
Why and How Powershell will rule the Command Line - Barcamp LA 4Why and How Powershell will rule the Command Line - Barcamp LA 4
Why and How Powershell will rule the Command Line - Barcamp LA 4Ilya Haykinson
885 vistas112 diapositivas
RubyEnRails2007 - Dr Nic Williams - Keynote por
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - KeynoteDr Nic Williams
2.8K vistas81 diapositivas
Rails on Oracle 2011 por
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011Raimonds Simanovskis
16.4K vistas24 diapositivas
Node.js in action por
Node.js in actionNode.js in action
Node.js in actionSimon Su
8.7K vistas38 diapositivas
Testing Backbone applications with Jasmine por
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with JasmineLeon van der Grient
1.9K vistas23 diapositivas
Percona toolkit por
Percona toolkitPercona toolkit
Percona toolkitKarwin Software Solutions LLC
17.9K vistas84 diapositivas

La actualidad más candente(20)

Why and How Powershell will rule the Command Line - Barcamp LA 4 por Ilya Haykinson
Why and How Powershell will rule the Command Line - Barcamp LA 4Why and How Powershell will rule the Command Line - Barcamp LA 4
Why and How Powershell will rule the Command Line - Barcamp LA 4
Ilya Haykinson885 vistas
RubyEnRails2007 - Dr Nic Williams - Keynote por Dr Nic Williams
RubyEnRails2007 - Dr Nic Williams - KeynoteRubyEnRails2007 - Dr Nic Williams - Keynote
RubyEnRails2007 - Dr Nic Williams - Keynote
Dr Nic Williams2.8K vistas
Node.js in action por Simon Su
Node.js in actionNode.js in action
Node.js in action
Simon Su8.7K vistas
RubyEnRails2007 - Dr Nic Williams - DIY Syntax por Dr Nic Williams
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxRubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
Dr Nic Williams1.2K vistas
My app is secure... I think por Wim Godden
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
Wim Godden585 vistas
Custom deployments with sbt-native-packager por GaryCoady
Custom deployments with sbt-native-packagerCustom deployments with sbt-native-packager
Custom deployments with sbt-native-packager
GaryCoady2.5K vistas
Beyond PHP - it's not (just) about the code por Wim Godden
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the code
Wim Godden8.5K vistas
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter... por Domenic Denicola
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola184.2K vistas
Class-based views with Django por Simon Willison
Class-based views with DjangoClass-based views with Django
Class-based views with Django
Simon Willison2.7K vistas
Ten useful JavaScript tips & best practices por Ankit Rastogi
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
Ankit Rastogi3.5K vistas
Webinar: MongoDB Persistence with Java and Morphia por MongoDB
Webinar: MongoDB Persistence with Java and MorphiaWebinar: MongoDB Persistence with Java and Morphia
Webinar: MongoDB Persistence with Java and Morphia
MongoDB8.9K vistas
Object Oriented Exploitation: New techniques in Windows mitigation bypass por Sam Thomas
Object Oriented Exploitation: New techniques in Windows mitigation bypassObject Oriented Exploitation: New techniques in Windows mitigation bypass
Object Oriented Exploitation: New techniques in Windows mitigation bypass
Sam Thomas9.9K vistas
神に近づくx/net/context (Finding God with x/net/context) por guregu
神に近づくx/net/context (Finding God with x/net/context)神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)
guregu5.6K vistas
Why Task Queues - ComoRichWeb por Bryan Helmig
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
Bryan Helmig16.8K vistas
Morphia: Simplifying Persistence for Java and MongoDB por Jeff Yemin
Morphia:  Simplifying Persistence for Java and MongoDBMorphia:  Simplifying Persistence for Java and MongoDB
Morphia: Simplifying Persistence for Java and MongoDB
Jeff Yemin11.9K vistas
MySQL in Go - Golang NE July 2015 por Mark Hemmings
MySQL in Go - Golang NE July 2015MySQL in Go - Golang NE July 2015
MySQL in Go - Golang NE July 2015
Mark Hemmings1.1K vistas

Similar a How to Design a Great API (using flask) [ploneconf2017]

Lean Php Presentation por
Lean Php PresentationLean Php Presentation
Lean Php PresentationAlan Pinstein
13.7K vistas21 diapositivas
Dependencies Managers in C/C++. Using stdcpp 2014 por
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014biicode
4.4K vistas44 diapositivas
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi por
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiJérémy Derussé
2.6K vistas29 diapositivas
Год в Github bugbounty, опыт участия por
Год в Github bugbounty, опыт участияГод в Github bugbounty, опыт участия
Год в Github bugbounty, опыт участияdefcon_kz
308 vistas56 diapositivas
The why and how of moving to PHP 5.4/5.5 por
The why and how of moving to PHP 5.4/5.5The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5Wim Godden
9.5K vistas51 diapositivas
Symfony finally swiped right on envvars por
Symfony finally swiped right on envvarsSymfony finally swiped right on envvars
Symfony finally swiped right on envvarsSam Marley-Jarrett
750 vistas50 diapositivas

Similar a How to Design a Great API (using flask) [ploneconf2017](20)

Lean Php Presentation por Alan Pinstein
Lean Php PresentationLean Php Presentation
Lean Php Presentation
Alan Pinstein13.7K vistas
Dependencies Managers in C/C++. Using stdcpp 2014 por biicode
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014
biicode4.4K vistas
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi por Jérémy Derussé
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Jérémy Derussé2.6K vistas
Год в Github bugbounty, опыт участия por defcon_kz
Год в Github bugbounty, опыт участияГод в Github bugbounty, опыт участия
Год в Github bugbounty, опыт участия
defcon_kz308 vistas
The why and how of moving to PHP 5.4/5.5 por Wim Godden
The why and how of moving to PHP 5.4/5.5The why and how of moving to PHP 5.4/5.5
The why and how of moving to PHP 5.4/5.5
Wim Godden9.5K vistas
Debugging: Rules And Tools - PHPTek 11 Version por Ian Barber
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
Ian Barber1.5K vistas
Debugging: Rules & Tools por Ian Barber
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
Ian Barber11.8K vistas
Advanced Eclipse Workshop (held at IPC2010 -spring edition-) por Bastian Feder
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
Advanced Eclipse Workshop (held at IPC2010 -spring edition-)
Bastian Feder1.5K vistas
Heavy Web Optimization: Backend por Võ Duy Tuấn
Heavy Web Optimization: BackendHeavy Web Optimization: Backend
Heavy Web Optimization: Backend
Võ Duy Tuấn6.1K vistas
파이썬 개발환경 구성하기의 끝판왕 - Docker Compose por raccoony
파이썬 개발환경 구성하기의 끝판왕 - Docker Compose파이썬 개발환경 구성하기의 끝판왕 - Docker Compose
파이썬 개발환경 구성하기의 끝판왕 - Docker Compose
raccoony 10.7K vistas
Ruby and Rails Packaging to Production por Fabio Kung
Ruby and Rails Packaging to ProductionRuby and Rails Packaging to Production
Ruby and Rails Packaging to Production
Fabio Kung9.5K vistas
Bangpypers april-meetup-2012 por Deepak Garg
Bangpypers april-meetup-2012Bangpypers april-meetup-2012
Bangpypers april-meetup-2012
Deepak Garg528 vistas
Asian Spirit 3 Day Dba On Ubl por newrforce
Asian Spirit 3 Day Dba On UblAsian Spirit 3 Day Dba On Ubl
Asian Spirit 3 Day Dba On Ubl
newrforce1.3K vistas
Introduction to Apache Mesos por Joe Stein
Introduction to Apache MesosIntroduction to Apache Mesos
Introduction to Apache Mesos
Joe Stein19.1K vistas
PHP selber bauen por Walter Ebert
PHP selber bauenPHP selber bauen
PHP selber bauen
Walter Ebert4.7K vistas
X64服务器 lnmp服务器部署标准 new por Yiwei Ma
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 new
Yiwei Ma1.5K vistas
Effective Python Package Management [PyCon Canada 2017] por Devon Bernard
Effective Python Package Management [PyCon Canada 2017]Effective Python Package Management [PyCon Canada 2017]
Effective Python Package Management [PyCon Canada 2017]
Devon Bernard396 vistas
Python Deployment with Fabric por andymccurdy
Python Deployment with FabricPython Deployment with Fabric
Python Deployment with Fabric
andymccurdy34K vistas

Último

Airline Booking Software por
Airline Booking SoftwareAirline Booking Software
Airline Booking SoftwareSharmiMehta
5 vistas26 diapositivas
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ... por
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...Deltares
10 vistas32 diapositivas
A first look at MariaDB 11.x features and ideas on how to use them por
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use themFederico Razzoli
45 vistas36 diapositivas
ict act 1.pptx por
ict act 1.pptxict act 1.pptx
ict act 1.pptxsanjaniarun08
13 vistas17 diapositivas
HarshithAkkapelli_Presentation.pdf por
HarshithAkkapelli_Presentation.pdfHarshithAkkapelli_Presentation.pdf
HarshithAkkapelli_Presentation.pdfharshithakkapelli
11 vistas16 diapositivas
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t... por
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...Deltares
9 vistas26 diapositivas

Último(20)

Airline Booking Software por SharmiMehta
Airline Booking SoftwareAirline Booking Software
Airline Booking Software
SharmiMehta5 vistas
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ... por Deltares
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...
Deltares10 vistas
A first look at MariaDB 11.x features and ideas on how to use them por Federico Razzoli
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use them
Federico Razzoli45 vistas
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t... por Deltares
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...
DSD-INT 2023 Thermobaricity in 3D DCSM-FM - taking pressure into account in t...
Deltares9 vistas
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J... por Deltares
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...
Deltares9 vistas
Software testing company in India.pptx por SakshiPatel82
Software testing company in India.pptxSoftware testing company in India.pptx
Software testing company in India.pptx
SakshiPatel827 vistas
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI... por Marc Müller
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...
Marc Müller37 vistas
DSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - Geertsema por Deltares
DSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - GeertsemaDSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - Geertsema
DSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - Geertsema
Deltares17 vistas
FIMA 2023 Neo4j & FS - Entity Resolution.pptx por Neo4j
FIMA 2023 Neo4j & FS - Entity Resolution.pptxFIMA 2023 Neo4j & FS - Entity Resolution.pptx
FIMA 2023 Neo4j & FS - Entity Resolution.pptx
Neo4j6 vistas
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium... por Lisi Hocke
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...
Lisi Hocke28 vistas
MariaDB stored procedures and why they should be improved por Federico Razzoli
MariaDB stored procedures and why they should be improvedMariaDB stored procedures and why they should be improved
MariaDB stored procedures and why they should be improved
Federico Razzoli8 vistas
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ... por Donato Onofri
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...
Donato Onofri773 vistas
BushraDBR: An Automatic Approach to Retrieving Duplicate Bug Reports por Ra'Fat Al-Msie'deen
BushraDBR: An Automatic Approach to Retrieving Duplicate Bug ReportsBushraDBR: An Automatic Approach to Retrieving Duplicate Bug Reports
BushraDBR: An Automatic Approach to Retrieving Duplicate Bug Reports
DSD-INT 2023 Salt intrusion Modelling of the Lauwersmeer, towards a measureme... por Deltares
DSD-INT 2023 Salt intrusion Modelling of the Lauwersmeer, towards a measureme...DSD-INT 2023 Salt intrusion Modelling of the Lauwersmeer, towards a measureme...
DSD-INT 2023 Salt intrusion Modelling of the Lauwersmeer, towards a measureme...
Deltares5 vistas
Software evolution understanding: Automatic extraction of software identifier... por Ra'Fat Al-Msie'deen
Software evolution understanding: Automatic extraction of software identifier...Software evolution understanding: Automatic extraction of software identifier...
Software evolution understanding: Automatic extraction of software identifier...

How to Design a Great API (using flask) [ploneconf2017]