python-3.x - 如何正确地将依赖项注入(inject) Flask?

标签 python-3.x flask dependency-injection

我正在编写我的第一个 Flask 应用程序。到目前为止,我已经通过这样做让一切正常工作(请注意,这段代码将分布在多个文件中):

class AppDefinition:

    def __init__(self):
        self.App = Flask(__name__, instance_relative_config = True)
        self.PlacesProvider = GooglePlacesSearchProvider(
            'https://maps.googleapis.com/maps/api/place/findplacefromtext/json',
            'my_api_key')

app = AppDefinition()

@app.App.route('/search/phone/<phone>/<language>')
def search_with_phone_number(phone: str, language: str):
    resp = app.PlacesProvider.get_by_phone_number(phone, language)
    return from_response(resp)

@app.App.route('/search/address/<address>/<language>')
def search_with_address(address: str, language: str):
    resp = app.PlacesProvider.get_by_address(address, language)
    return from_response(resp)

def from_response(resp: Response):
    return json.dumps(resp.json(), ensure_ascii = False)

if __name__ == '__main__':
    HOST = 'localhost'
    PORT = 5000
    app.App.run(HOST, PORT)

但是,我对这段代码不是特别满意。 Controller 方法没有被封装到合适的类中,依赖项没有被正确注入(inject),似乎没有办法封装 Controller 方法。所有这些问题似乎都与核心的依赖注入(inject)有关,所以这可能是真正的问题,恕我直言。鉴于此,在这种情况下我将如何进行依赖注入(inject)?

最佳答案

使用Dependency Injector .以下是您的应用程序的外观。

application.py list :

import json

from dependency_injector import containers, providers
from dependency_injector.ext import flask
from flask import Flask


# Services

class Response:

    def __init__(self, data):
        self.data = data

    def json(self):
        return self.data


class GooglePlacesSearchProvider:

    def __init__(self, url, api_key):
        ...

    def get_by_phone_number(self, phone, language):
        return Response({'result': 'phone-number-lookup-result'})

    def get_by_address(self, phone, language):
        return Response({'result': 'address-lookup-result'})


# Views

def search_with_phone_number(phone: str, language: str, places_provider: GooglePlacesSearchProvider):
    resp = places_provider.get_by_phone_number(phone, language)
    return from_response(resp)


def search_with_address(address: str, language: str, places_provider: GooglePlacesSearchProvider):
    resp = places_provider.get_by_address(address, language)
    return from_response(resp)


def from_response(resp: Response):
    return json.dumps(resp.json(), ensure_ascii=False)


# Container

class ApplicationContainer(containers.DeclarativeContainer):
    """Application container."""

    app = flask.Application(Flask, __name__, instance_relative_config=True)

    config = providers.Configuration()

    places_provider = providers.Factory(
        GooglePlacesSearchProvider,
        config.services.places.url,
        config.services.places.api_key,
    )

    search_with_phone_number_view = flask.View(
        search_with_phone_number,
        places_provider=places_provider,
    )

    search_with_address_view = flask.View(
        search_with_address,
        places_provider=places_provider,
    )


# Application factory

def create_app():
    container = ApplicationContainer()
    container.config.from_yaml('config.yml')
    container.config.services.places.api_key.from_env('PLACES_API_KEY')

    app = container.app()
    app.container = container

    app.add_url_rule(
        '/search/phone/<phone>/<language>',
        view_func=container.search_with_phone_number_view.as_view(),
    )
    app.add_url_rule(
        '/search/address/<address>/<language>',
        view_func=container.search_with_address_view.as_view(),
    )

    return app


if __name__ == '__main__':
    HOST = 'localhost'
    PORT = 5000
    app = create_app()
    app.run(HOST, PORT)

config.yml list :

services:
  places:
    url: "https://maps.googleapis.com/maps/api/place/findplacefromtext/json"

并且您需要在运行应用程序时提供 API key 作为环境变量:

PLACES_API_KEY=key python -m application

我建议将其拆分为多个文件。查看依赖注入(inject)器 Flask tutorial .

关于python-3.x - 如何正确地将依赖项注入(inject) Flask?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53621724/

相关文章:

java - CDI 和 EJB 与 glassfish 3.1 混合

jakarta-ee - 在另一只耳朵中注入(inject)无接口(interface) ejb

python - 使用变量作为参数的 SQL 更新错误

python - 如何使用 Flask-SQLAlchemy 仅选择数据库中的某些列?

flask - Jinja - 在 for 循环中显示两个不同的值

java - Android:Dagger 2 和构造函数注入(inject)

python 返回列表中的重复项

python - 循环遍历文本,一次 3 个字符

python - 服务器如何启动与客户端的连接

python , flask : How to set response header for all responses