first commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
*.pyc
|
||||||
|
config.py
|
||||||
|
venv/
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Photowall API 2
|
||||||
|
|
||||||
|
Provides a REST API to Photowall database.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
`$ pip install -r requirements.txt`
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
First copy config.sample.py to config.py. This file will be read by the application on startup.
|
||||||
|
|
||||||
|
List of available configuration options:
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ---- | ----------- |
|
||||||
|
| `SQLALCHEMY_DATABASE_URI` | Database connection string. e.g: `postgresql://user:password@localhost/photowall`
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
Starting the application:
|
||||||
|
|
||||||
|
`$ python run.py`
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
from flask import Flask, jsonify
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from api.helpers import JSONEncoder
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_object('config')
|
||||||
|
|
||||||
|
# enable this when json encoding works
|
||||||
|
# app.json_encoder = JSONEncoder
|
||||||
|
|
||||||
|
def on_404(e):
|
||||||
|
return jsonify(dict(error='Not found')), 404
|
||||||
|
|
||||||
|
app.errorhandler(404)(on_404)
|
||||||
|
|
||||||
|
#SQLAlchemy
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
|
from api.views import designers
|
||||||
|
app.register_blueprint(designers.mod)
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
data = {
|
||||||
|
"info": {
|
||||||
|
"api_version": "0.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonify(data)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from json import JSONEncoder, JsonSerializer
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
from flask.json import JSONEncoder as BaseJSONEncoder
|
||||||
|
|
||||||
|
|
||||||
|
class JSONEncoder(BaseJSONEncoder):
|
||||||
|
"""Custom :class:`JSONEncoder` which respects objects that include the
|
||||||
|
:class:`JsonSerializer` mixin.
|
||||||
|
"""
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, JsonSerializer):
|
||||||
|
return obj.to_json()
|
||||||
|
return super(JSONEncoder, self).default(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class JsonSerializer(object):
|
||||||
|
"""A mixin that can be used to mark a SQLAlchemy model class which
|
||||||
|
implements a :func:`to_json` method. The :func:`to_json` method is used
|
||||||
|
in conjuction with the custom :class:`JSONEncoder` class. By default this
|
||||||
|
mixin will assume all properties of the SQLAlchemy model are to be visible
|
||||||
|
in the JSON output. Extend this class to customize which properties are
|
||||||
|
public, hidden or modified before being being passed to the JSON serializer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__json_public__ = None
|
||||||
|
__json_hidden__ = None
|
||||||
|
__json_modifiers__ = None
|
||||||
|
|
||||||
|
def get_field_names(self):
|
||||||
|
for p in self.__mapper__.iterate_properties:
|
||||||
|
yield p.key
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
field_names = self.get_field_names()
|
||||||
|
|
||||||
|
public = self.__json_public__ or field_names
|
||||||
|
hidden = self.__json_hidden__ or []
|
||||||
|
modifiers = self.__json_modifiers__ or dict()
|
||||||
|
|
||||||
|
rv = dict()
|
||||||
|
for key in public:
|
||||||
|
rv[key] = getattr(self, key)
|
||||||
|
for key, modifier in modifiers.items():
|
||||||
|
value = getattr(self, key)
|
||||||
|
rv[key] = modifier(value, self)
|
||||||
|
for key in hidden:
|
||||||
|
rv.pop(key, None)
|
||||||
|
return rv
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from designer import Designer
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
from api import db
|
||||||
|
from api.helpers import JsonSerializer
|
||||||
|
|
||||||
|
class Designer(JsonSerializer, db.Model):
|
||||||
|
__tablename__ = 'designers'
|
||||||
|
|
||||||
|
designerid = db.Column('designerid', db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(100), nullable=False)
|
||||||
|
path = db.Column(db.String(100), nullable=False)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
from flask import Blueprint, request, jsonify
|
||||||
|
from api import db
|
||||||
|
from api.models import Designer
|
||||||
|
|
||||||
|
mod = Blueprint('designers', __name__, url_prefix='/designers')
|
||||||
|
|
||||||
|
@mod.route("/", methods=["GET"])
|
||||||
|
def list():
|
||||||
|
designers = Designer.query.all()
|
||||||
|
return jsonify(designers=[d.to_json() for d in designers])
|
||||||
|
|
||||||
|
@mod.route("/", methods=["POST"])
|
||||||
|
def create():
|
||||||
|
data = request.json
|
||||||
|
designer = Designer(**data)
|
||||||
|
db.session.add(designer)
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify(designer.to_json())
|
||||||
|
|
||||||
|
|
||||||
|
@mod.route("/<int:id>", methods=["GET"])
|
||||||
|
def show(id):
|
||||||
|
designer = Designer.query.get_or_404(id)
|
||||||
|
return jsonify(designer.to_json())
|
||||||
|
|
||||||
|
@mod.route("/<id>", methods=["PUT"])
|
||||||
|
def update(id):
|
||||||
|
designer = Designer.query.get_or_404(id)
|
||||||
|
data = request.json
|
||||||
|
for k, v in data.iteritems():
|
||||||
|
setattr(designer, k, v)
|
||||||
|
db.session.add(designer)
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify(designer.to_json())
|
||||||
|
|
||||||
|
@mod.route("/<id>", methods=["DELETE"])
|
||||||
|
def delete(id):
|
||||||
|
designer = Designer.query.get_or_404(id)
|
||||||
|
db.session.delete(designer)
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify({"status": "ok"})
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password@host/db_name'
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
from flask.ext.script import Manager, prompt_bool
|
||||||
|
from api import app, db
|
||||||
|
from api.models import Designer
|
||||||
|
|
||||||
|
manager = Manager(app)
|
||||||
|
|
||||||
|
@manager.command
|
||||||
|
def initdb():
|
||||||
|
db.create_all()
|
||||||
|
print 'All tables created'
|
||||||
|
|
||||||
|
@manager.command
|
||||||
|
def dropdb():
|
||||||
|
if prompt_bool("Are you sure you want to lose all your data"):
|
||||||
|
db.drop_all()
|
||||||
|
print 'All tables dropped'
|
||||||
|
|
||||||
|
@manager.command
|
||||||
|
def seed():
|
||||||
|
print 'Adding sample data %s' % db.engine.url
|
||||||
|
designer = Designer(name="Martin", path='/martin', username='martin', password='secret')
|
||||||
|
db.session.add(designer)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
manager.run()
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Flask==0.10.1
|
||||||
|
Flask-SQLAlchemy==2.1
|
||||||
|
Flask-Script==2.0.5
|
||||||
|
Jinja2==2.8
|
||||||
|
MarkupSafe==0.23
|
||||||
|
SQLAlchemy==1.0.12
|
||||||
|
Werkzeug==0.11.8
|
||||||
|
argparse==1.2.1
|
||||||
|
itsdangerous==0.24
|
||||||
|
psycopg2==2.6.1
|
||||||
|
wsgiref==0.1.2
|
||||||
Reference in New Issue
Block a user