import os import flask import flask_cors import flask_restful import flask_restful.fields import flask_restful.reqparse import flask_sqlalchemy import sqlalchemy DB_PATH = os.path.expandvars('$HOME/quotes/quotes.db') app = flask.Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_PATH}' app.config['ERROR_404_HELP'] = False db = flask_sqlalchemy.SQLAlchemy(app) db.create_all() api = flask_restful.Api(app) flask_cors.CORS(app) class Quote(db.Model): __tablename__ = 'quotes' id = db.Column(db.Integer, primary_key=True) video_id = db.Column(db.Integer) date = db.Column(db.Date) game = db.Column(db.String) text = db.Column(db.String) created_at = db.Column(db.DateTime) updated_at = db.Column(db.DateTime) quote_fields = { 'id': flask_restful.fields.Integer(), 'video_id': flask_restful.fields.Integer(), 'date': flask_restful.fields.DateTime(dt_format='iso8601'), 'game': flask_restful.fields.String(), 'text': flask_restful.fields.String(), 'created_at': flask_restful.fields.DateTime(dt_format='iso8601'), 'updated_at': flask_restful.fields.DateTime(dt_format='iso8601'), } quote_parser = flask_restful.reqparse.RequestParser() quote_parser.add_argument('id', type=int) quote_parser.add_argument('video_id', type=int) quote_parser.add_argument('date', type=flask_restful.inputs.date, required=True) quote_parser.add_argument('game', type=str, required=True) quote_parser.add_argument('text', type=str, required=True) filter_parser = flask_restful.reqparse.RequestParser() filter_parser.add_argument('filter', type=str) filter_parser.add_argument('sort_by', type=str) filter_parser.add_argument('sort_order', type=str) filter_parser.add_argument('page_number', type=int) filter_parser.add_argument('page_size', type=int) class QuoteResource(flask_restful.Resource): @flask_restful.marshal_with(quote_fields) def get(self, id): q = db.session.query(Quote).filter(Quote.id == id) quote = q.first() if not quote: flask_restful.abort(404, message='Quote {0} does not exist'.format(id)) return quote, 200 @flask_restful.marshal_with(quote_fields) def put(self, id): args = quote_parser.parse_args() now = sqlalchemy.func.now() q = db.session.query(Quote).filter(Quote.id == id) quote = q.first() if not quote: quote = Quote(id=id, created_at=now) quote.video_id = args['video_id'] # FIXME: NULL quote.date = args['date'] quote.game = args['game'] quote.text = args['text'] quote.updated_at = now db.session.add(quote) db.session.commit() return quote, 200 def delete(self, id): q = db.session.query(Quote).filter(Quote.id == id) quote = q.first() if not quote: flask_restful.abort(404, message='Quote {0} does not exist'.format(id)) db.session.delete(quote) db.session.commit() return None, 204 class QuotesResource(flask_restful.Resource): @flask_restful.marshal_with(quote_fields) def get(self): args = filter_parser.parse_args() q = db.session.query(Quote) if args['filter']: q = q.filter(Quote.text.ilike('%{}%'.format(args['filter']))) count = q.count() if args['sort_by']: col = getattr(Quote, args['sort_by'], None) if col: if args['sort_order']: order_by = getattr(col, args['sort_order'], None) if order_by: q = q.order_by(order_by()) else: q = q.order_by(col) if args['page_size']: q = q.limit(args['page_size']) if args['page_number'] and args['page_size']: q = q.offset(args['page_number'] * args['page_size']) quotes = q.all() return quotes, 200, {'X-Total-Count': count} @flask_restful.marshal_with(quote_fields) def post(self): args = quote_parser.parse_args() if not args['id']: flask_restful.abort(400, message='Missing required parameter id') now = sqlalchemy.func.now() q = db.session.query(Quote).filter(Quote.id == args['id']) quote = q.first() if not quote: quote = Quote(id=args['id'], created_at=now) quote.video_id = args['video_id'] # FIXME: NULL quote.date = args['date'] quote.game = args['game'] quote.text = args['text'] quote.updated_at = now db.session.add(quote) db.session.commit() url = api.url_for(QuoteResource, id=quote.id, _external=True, _scheme='https') return quote, 201, {'Location': url} api.add_resource(QuoteResource, '/quotes/') api.add_resource(QuotesResource, '/quotes')