Publish first version
This commit is contained in:
parent
e167769041
commit
bac59704db
18 changed files with 564 additions and 1 deletions
34
app/__init__.py
Normal file
34
app/__init__.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from flask import Flask
|
||||
from flask_smorest import Api
|
||||
from flask_marshmallow import Marshmallow
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
#from flask_jwt_extended import JWTManager
|
||||
|
||||
|
||||
api = Api()
|
||||
db = SQLAlchemy()
|
||||
ma = Marshmallow()
|
||||
#jwt = JWTManager()
|
||||
|
||||
|
||||
def create_app(cfg='default'):
|
||||
from config import config
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(config[cfg])
|
||||
app.url_map.strict_slashes = False
|
||||
|
||||
config[cfg].init_app(app)
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
||||
from . import resources
|
||||
|
||||
api.init_app(app)
|
||||
db.init_app(app)
|
||||
ma.init_app(app)
|
||||
#jwt.init_app(app)
|
||||
Migrate(app, db)
|
||||
resources.register_blueprints(api)
|
||||
|
||||
return app
|
||||
|
12
app/models/impulse.py
Normal file
12
app/models/impulse.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from .. import db
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Impulse(db.Model):
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
power = db.Column(db.Integer, nullable=False)
|
||||
created_at = db.Column(db.DateTime, default=datetime.now, nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return 'Impulse {} with power of {} watts at {}'.format(self.name, self.power, self.created_at)
|
14
app/resources/__init__.py
Normal file
14
app/resources/__init__.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
def register_blueprints(api):
|
||||
from . import impulses, consumption
|
||||
|
||||
resources = (impulses, consumption, )
|
||||
|
||||
for resource_blp in (res.bp for res in resources):
|
||||
# Here we can register common handlers to all resources
|
||||
#
|
||||
# resource_blp.before_request(before_request_handler)
|
||||
# resource_blp.after_request(after_request_handler)
|
||||
|
||||
api.register_blueprint(resource_blp,
|
||||
url_prefix=f'/{resource_blp.url_prefix}')
|
||||
|
24
app/resources/consumption.py
Normal file
24
app/resources/consumption.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from .. import db
|
||||
import datetime
|
||||
from flask.views import MethodView
|
||||
from flask_smorest import Blueprint
|
||||
from ..schemas.consumption import ConsumptionSchema, ConsumptionQuerySchema
|
||||
from ..models.impulse import Impulse
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
bp = Blueprint('consumption', 'consumptions', url_prefix='consumption',
|
||||
description='Operations on consumptions')
|
||||
|
||||
|
||||
@bp.route('/')
|
||||
class Consumptions(MethodView):
|
||||
@bp.arguments(ConsumptionQuerySchema, location="query")
|
||||
@bp.response(ConsumptionSchema(many=False))
|
||||
def get(self, args):
|
||||
if "timeperiod" in args:
|
||||
timeperiod = int(args['timeperiod'])
|
||||
filterdate = datetime.datetime.now() - datetime.timedelta(seconds=timeperiod)
|
||||
consumption = db.session.query(func.sum(Impulse.power)).filter(Impulse.created_at >= filterdate).first()[0]
|
||||
else:
|
||||
consumption = db.session.query(func.sum(Impulse.power)).first()[0]
|
||||
return {'consumption': consumption}
|
35
app/resources/impulses.py
Normal file
35
app/resources/impulses.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
from .. import db
|
||||
from flask.views import MethodView
|
||||
from flask_smorest import Blueprint
|
||||
from ..schemas.impulse import ImpulseSchema, ImpulseQuerySchema
|
||||
from ..models.impulse import Impulse
|
||||
|
||||
bp = Blueprint('impulse', 'impulses', url_prefix='impulses',
|
||||
description='Operations on impulses')
|
||||
|
||||
|
||||
@bp.route('/')
|
||||
class Impulses(MethodView):
|
||||
|
||||
@bp.arguments(ImpulseQuerySchema, location="query")
|
||||
@bp.response(ImpulseSchema(many=True))
|
||||
def get(self, args):
|
||||
impulses = Impulse.query.all()
|
||||
return impulses
|
||||
|
||||
@bp.arguments(ImpulseSchema)
|
||||
@bp.response(ImpulseSchema, code=201)
|
||||
def post(self, new_impulse):
|
||||
db.session.add(new_impulse)
|
||||
db.session.commit()
|
||||
return new_impulse
|
||||
|
||||
|
||||
@bp.route('/<impulse_id>')
|
||||
class ImpulseById(MethodView):
|
||||
@bp.response(code=204)
|
||||
def delete(self, impulse_id):
|
||||
impulse = Impulse.query.filter_by(id=impulse_id).first()
|
||||
db.session.delete(impulse)
|
||||
db.session.commit()
|
||||
|
13
app/schemas/consumption.py
Normal file
13
app/schemas/consumption.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from .. import ma
|
||||
from marshmallow import fields
|
||||
|
||||
|
||||
class ConsumptionQuerySchema(ma.Schema):
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
timeperiod = fields.String()
|
||||
|
||||
|
||||
class ConsumptionSchema(ma.Schema):
|
||||
consumption = fields.Number()
|
20
app/schemas/impulse.py
Normal file
20
app/schemas/impulse.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
from .. import ma
|
||||
from ..models.impulse import Impulse
|
||||
from marshmallow import fields
|
||||
from .namespacedSchema import NamespacedSchema
|
||||
|
||||
|
||||
class ImpulseQuerySchema(ma.Schema):
|
||||
class Meta:
|
||||
strict = True
|
||||
|
||||
timeperiod = fields.String()
|
||||
|
||||
|
||||
class ImpulseSchema(NamespacedSchema):
|
||||
|
||||
class Meta:
|
||||
strict = True
|
||||
model = Impulse
|
||||
name = "impulse"
|
||||
plural_name = "impulses"
|
45
app/schemas/namespacedSchema.py
Normal file
45
app/schemas/namespacedSchema.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from marshmallow import SchemaOpts
|
||||
from marshmallow import pre_load, post_dump
|
||||
from marshmallow_sqlalchemy import ModelSchemaOpts, ModelConverter, ModelSchema
|
||||
from .. import ma
|
||||
from .. import db
|
||||
|
||||
|
||||
class NamespaceOpts(ModelSchemaOpts):
|
||||
"""Same as the default class Meta options, but adds "name" and
|
||||
"plural_name" options for enveloping.
|
||||
"""
|
||||
|
||||
def __init__(self, meta, **kwargs):
|
||||
SchemaOpts.__init__(self, meta, **kwargs)
|
||||
self.name = getattr(meta, "name", None)
|
||||
self.plural_name = getattr(meta, "plural_name", self.name)
|
||||
self.model = getattr(meta, "model", None)
|
||||
self.model_converter = getattr(meta, "model_converter", ModelConverter)
|
||||
self.include_fk = getattr(meta, "include_fk", False)
|
||||
self.transient = getattr(meta, "transient", False)
|
||||
self.sqla_session = db.session
|
||||
self.load_instance = True
|
||||
self.include_relationships = True
|
||||
|
||||
|
||||
#class NamespacedSchema(ma.SQLAlchemySchema):
|
||||
class NamespacedSchema(ModelSchema):
|
||||
OPTIONS_CLASS = NamespaceOpts
|
||||
|
||||
@pre_load(pass_many=True)
|
||||
def unwrap_envelope(self, data, many, **kwargs):
|
||||
key = self.opts.plural_name if many else self.opts.name
|
||||
if key in data:
|
||||
return data[key]
|
||||
else:
|
||||
return data
|
||||
|
||||
@post_dump(pass_many=True)
|
||||
def wrap_with_envelope(self, data, many, **kwargs):
|
||||
if 'noenvelope' in self.context and self.context['noenvelope']:
|
||||
return data
|
||||
else:
|
||||
key = self.opts.plural_name if many else self.opts.name
|
||||
return {key: data}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue