-
Notifications
You must be signed in to change notification settings - Fork 43
/
example.py
133 lines (104 loc) · 4.32 KB
/
example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# -*- coding: utf-8 -*-
import logging
from injector import Module, Injector, inject, singleton
from flask import Flask, Request, jsonify
from flask_injector import FlaskInjector
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy import Column, String
il = logging.getLogger('injector')
il.addHandler(logging.StreamHandler())
il.level = logging.DEBUG
"""
This is an example of using Injector (https://github.com/alecthomas/injector) and Flask.
Flask provides a lot of very nice features, but also requires a lot of globals
and tightly bound code. Flask-Injector seeks to remedy this.
"""
# We use standard SQLAlchemy models rather than the Flask-SQLAlchemy magic, as
# it requires a global Flask app object and SQLAlchemy db object.
Base = declarative_base()
class KeyValue(Base):
__tablename__ = 'data'
key = Column(String, primary_key=True)
value = Column(String)
def __init__(self, key, value):
self.key = key
self.value = value
def serializable(self):
return
def configure_views(app):
@app.route('/<key>')
def get(key, db: SQLAlchemy):
try:
kv = db.session.query(KeyValue).filter(KeyValue.key == key).one()
except NoResultFound:
response = jsonify(status='No such key', context=key)
response.status = '404 Not Found'
return response
return jsonify(key=kv.key, value=kv.value)
@app.route('/')
def list(db: SQLAlchemy):
data = [i.key for i in db.session.query(KeyValue).order_by(KeyValue.key)]
return jsonify(keys=data)
@app.route('/', methods=['POST'])
def create(request: Request, db: SQLAlchemy):
kv = KeyValue(request.form['key'], request.form['value'])
db.session.add(kv)
db.session.commit()
response = jsonify(status='OK')
response.status = '201 CREATED'
return response
@app.route('/<key>', methods=['DELETE'])
def delete(db: SQLAlchemy, key):
db.session.query(KeyValue).filter(KeyValue.key == key).delete()
db.session.commit()
response = jsonify(status='OK')
response.status = '200 OK'
return response
class AppModule(Module):
def __init__(self, app):
self.app = app
"""Configure the application."""
def configure(self, binder):
# We configure the DB here, explicitly, as Flask-SQLAlchemy requires
# the DB to be configured before request handlers are called.
db = self.configure_db(self.app)
binder.bind(SQLAlchemy, to=db, scope=singleton)
def configure_db(self, app):
db = SQLAlchemy(app)
Base.metadata.create_all(db.engine)
db.session.add_all([KeyValue('hello', 'world'), KeyValue('goodbye', 'cruel world')])
db.session.commit()
return db
def main():
app = Flask(__name__)
app.config.update(DB_CONNECTION_STRING=':memory:', SQLALCHEMY_DATABASE_URI='sqlite://')
app.debug = True
# An explicit context because AppModule calls some flask-sqlalchemy's code that needs
# a context.
#
# https://github.com/pallets-eco/flask-sqlalchemy/issues/1129#issuecomment-1283219340
with app.app_context():
injector = Injector([AppModule(app)])
configure_views(app=app)
FlaskInjector(app=app, injector=injector)
client = app.test_client()
response = client.get('/')
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.post('/', data={'key': 'foo', 'value': 'bar'})
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.get('/')
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.get('/hello')
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.delete('/hello')
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.get('/')
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.get('/hello')
print('%s\n%s%s' % (response.status, response.headers, response.data))
response = client.delete('/hello')
print('%s\n%s%s' % (response.status, response.headers, response.data))
if __name__ == '__main__':
main()