Объектно-ориентированный Python с Flask Server?
Я использую Flask, чтобы выставить некоторый хрустящий код в качестве веб-сервиса.
Я хотел бы иметь некоторые переменные класса, к которым могут обращаться мои функции Flask.
Позвольте мне провести вас туда, где я застрял:
from flask import Flask
app = Flask(__name__)
class MyServer:
def __init__(self):
globalData = json.load(filename)
@app.route('/getSomeData')
def getSomeData():
return random.choice(globalData) #select some random data to return
if __name__ == "__main__":
app.run(host='0.0.0.0')
Когда я запускаю getSomeData()
вне Flask, он работает нормально. Но, когда я запускаю это с помощью Flask, я получаю 500 internal server error
. Здесь нет волшебства, и Флакс не знает, что он должен инициализировать объект MyServer
. Как я могу передать экземпляр MyServer команде app.run()
?
Я мог бы признать поражение и поместить globalData
в базу данных. Но есть ли другой путь?
Ответы
Ответ 1
Вы можете создать экземпляр MyServer
только за пределами ваших конечных точек и получить доступ к его атрибутам. Это сработало для меня:
class MyServer:
def __init__(self):
self.globalData = "hello"
from flask import Flask
app = Flask(__name__)
my_server = MyServer()
@app.route("/getSomeData")
def getSomeData():
return my_server.globalData
if __name__ == "__main__":
app.run(host="0.0.0.0")
Ответ 2
Наименее связанное решение заключается в применении маршрутов во время выполнения (а не во время загрузки):
def init_app(flask_app, database_interface, filesystem_interface):
server = MyServer(database_interface, filesystem_interface)
flask_app.route('get_data', methods=['GET'])(server.get_data)
Это очень легко проверить - просто вызовите init_app()
в тестовом коде с помощью фальшивых/поддельных зависимостей (database_interface
и filesystem_interface
) и флеш-приложение, настроенное для тестирования (app.config["TESTING"]=True
или что-то вроде это), и вы все готовы писать тесты, которые охватывают все ваше приложение (включая маршрутизацию фляжек).
Единственный недостаток - это не очень "Flasky" (или так мне сказали); идиома Flask должна использовать @app.route()
, которая применяется во время загрузки и обязательно жестко связана, потому что зависимости жестко закодированы в реализации вместо того, чтобы впрыскиваться в какой-либо конструктор или метод factory (и, следовательно, сложно тестировать).
Ответ 3
немного поздно, но это быстрый вариант, который я использую для регистрации маршрутов во время init
from flask import Flask,request,render_template
from functools import partial
registered_routes = {}
def register_route(route=None):
#simple decorator for class based views
def inner(fn):
registered_routes[route] = fn
return fn
return inner
class MyServer(Flask):
def __init__(self,*args,**kwargs):
if not args:
kwargs.setdefault('import_name',__name__)
Flask.__init__(self,*args ,**kwargs)
# register the routes from the decorator
for route,fn in registered_routes.items():
partial_fn = partial(fn,self)
partial_fn.__name__ = fn.__name__
self.route(route)(partial_fn)
@register_route("/")
def index(self):
return render_template("my_template.html")
if __name__ == "__main__":
MyServer(template_folder=os.path.dirname(__file__)).run(debug=True)
Ответ 4
если вы хотите подойти к классу MyServer как ресурс
Я считаю, что flask_restful может вам помочь:
from flask import Flask
from flask_restful import Resource, Api
import json
import numpy as np
app = Flask(__name__)
api = Api(app)
class MyServer(Resource):
def __init__(self):
self.globalData = json.load(filename)
def get(self):
return np.random.choice(self.globalData)
api.add_resource(MyServer, '/')
if __name__ == '__main__':
app.run()
Ответ 5
Вы можете наследовать свой класс из Flask, чтобы вы могли добавить к нему функциональные возможности:
class MyServer(Flask):
def __init__(self, name):
self.globalData = "hello"
Flask.__init__(self, name)
def getSomeData(self):
return self.globalData
my_server = MyServer(__name__)
@my_server.route("/getSomeData")
def getSomeData():
return my_server.getSomeData()
my_server.run(host="0.0.0.0")
Теперь я пытаюсь использовать декоратор маршрута для метода моего класса MyServer, но пока не могу понять.
Ответ 6
Попробуй флягу
Я только начал с этого, и это именно то, что я искал.
http://flask-classful.teracy.org/#
Ответ 7
Я знаю, что это поздний ответ, но я столкнулся с этим вопросом, когда столкнулся с аналогичной проблемой. Я нашел классную колбу действительно хорошей. Вы наследуете свой класс от FlaskView и регистрируете приложение Flask в своем классе MyServer.
http://flask-classful.teracy.org/#
В этом случае с классом flask ваш код будет выглядеть так:
from flask import Flask
from flask-classful import FlaskView, route
app = Flask(__name__)
class MyServer(FlaskView):
def __init__(self):
globalData = json.load(filename)
@route('/getSomeData')
def getSomeData():
return random.choice(globalData) #select some random data to return
MyServer.register(app, base_route="/")
if __name__ == "__main__":
app.run(host='0.0.0.0')