From 4fb3c88a9ff67061e4a38f30ca7b6487712913f0 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Sun, 18 Mar 2018 17:53:22 +0200 Subject: Initial REST support --- .gitignore | 2 ++ README.md | 6 +++++- app.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- requirements.txt | 23 +++++++++++++++-------- runtime.txt | 2 +- 5 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a295864 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +__pycache__ diff --git a/README.md b/README.md index 1aae83f..9724ba9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # Heroku Python Skeleton -This repository has all the base files ready for deploying a Heroku application, including a simple database model managed with flask-sqlalchemy. +This repository has all the base files ready for deploying a Python application on Heroku. It includes the following features: + + - Flask HTTP application + - SQLAlchemy model that binds to a Heroku Postgres database + - RESTful API based on Flask-RESTful and the Marshmallow serialization framework ## Usage diff --git a/app.py b/app.py index 51a1100..14841aa 100644 --- a/app.py +++ b/app.py @@ -1,12 +1,19 @@ import os from flask import Flask -from flask import render_template -from flask.ext.sqlalchemy import SQLAlchemy +from flask import render_template, request +from flask_sqlalchemy import SQLAlchemy +from flask_restful import Resource, Api +from marshmallow_sqlalchemy import ModelSchema + app = Flask(__name__) -app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL'] +app.config.update({ + 'SQLALCHEMY_DATABASE_URI': os.environ['DATABASE_URL'], + 'SQLALCHEMY_TRACK_MODIFICATIONS': False +}) db = SQLAlchemy(app) +api = Api(app) class User(db.Model): @@ -22,6 +29,40 @@ class User(db.Model): return '' % self.name +class UserSchema(ModelSchema): + class Meta: + model = User + + +class UserResource(Resource): + def get(self, user_id): + user = User.query.get(user_id) + return UserSchema().dump(user) + + def put(self, user_id): + user = User.query.get(user_id) + UserSchema().load(request.form, instance=user, session=db.session) + db.session.commit() + return 'updated' + + def delete(self, user_id): + user = User.query.get(user_id) + db.session.delete(user) + db.session.commit() + + +class UserListResource(Resource): + def get(self): + users = User.query.all() + return UserSchema(many=True).dump(users) + + def post(self): + user = UserSchema().load(request.form, session=db.session).data + db.session.add(user) + db.session.commit() + return 'created' + + @app.route('/') def home(): return render_template('index.html') @@ -33,6 +74,9 @@ def robots(): res.mimetype = 'text/plain' return res +api.add_resource(UserListResource, '/users/') +api.add_resource(UserResource, '/users//') + + if __name__ == '__main__': - port = int(os.environ.get('PORT', 5000)) - app.run(host='0.0.0.0', port=port, debug=True) + app.run(host='0.0.0.0', debug=True) diff --git a/requirements.txt b/requirements.txt index a75f7bb..a5be6dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,16 @@ -Flask==0.10.1 -Flask-SQLAlchemy==2.1 -gunicorn==19.4.5 +aniso8601==3.0.0 +click==6.7 +Flask==0.12.2 +Flask-RESTful==0.3.6 +Flask-SQLAlchemy==2.3.2 +gunicorn==19.7.1 itsdangerous==0.24 -Jinja2==2.8 -MarkupSafe==0.23 -psycopg2==2.6.1 -SQLAlchemy==1.0.12 -Werkzeug==0.11.9 +Jinja2==2.10 +MarkupSafe==1.0 +marshmallow==2.15.0 +marshmallow-sqlalchemy==0.13.2 +psycopg2==2.7.4 +pytz==2018.3 +six==1.11.0 +SQLAlchemy==1.2.5 +Werkzeug==0.14.1 diff --git a/runtime.txt b/runtime.txt index 78082e3..5c45380 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.5.1 +python-3.6.4 -- cgit v1.3.1