首页 > 解决方案 > Flask 应用程序启动时,如何使用从 DB 获取的数据作为 add_argument() 中的值?

问题描述

我使用以下 Flask 应用程序的项目结构flask-restx

.
├── app
│   ├── extensions.py
│   ├── __init__.py
│   └── pv_dimensioning
│       ├── controller.py
│       ├── __init__.py
│       ├── models
│       │   ├── dto.py
│       │   ├── __init__.py
│       │   └── vendor_models.py
│       ├── services
│       │   ├── calculator.py
│       │   ├── database.py
│       │   ├── data.py
│       │   ├── db_crud.py
│       │   ├── __init__.py
│       │   └── processor.py
│       └── utils
│           ├── decode_verify_jwt.py
│           ├── decorator.py
│           └── __init__.py
├── config.py
├── main.py
├── package.json
├── package-lock.json
├── Pipfile
├── Pipfile.lock
├── README.md
├── serverless.yml
└── tests
    ├── __init__.py
    ├── test_calculator.py
    ├── test_config.py
    └── test_processor.py

controller.py中,我正在添加add_argument()语句并在 api 路由中解析它们。在其中一个add_argument()声明中,我想choices为用户添加。为了获得选择,我从数据库中查询并获取list可用的值。然后我将其转换list为 a tuple,将其分配给一个变量,并将其作为choices参数传递给add_argument()

我的代码:

数据.py

from ..models.vendor_models import AdminVendor

def data(app):
    values = AdminVendor.query.all()
    v = [value.name for value in values]
    return {'v': tuple(v)}

控制器.py

from flask_restx import Resource, reqparse

parser = reqparse.RequestParser()

parser.add_argument(
    "vendor",
    choices=vendors, # <--- The values of v should be added here
    help="Select the vendor"
)

@ns.route("/")
class UserOutput(Resource):
    @ns.doc(
        "Get calculated response",
        responses={
            200: "Values returned",
            400: "Validation Error",
            403: "Not authorized"
        },
    )
    @ns.expect(parser, validation=True)
    def get(self):
        args = parser.parse_args()
        return DimensionCalculator.inputs(**args), 200

ns在哪里namespace

__init__.pyapp文件夹中的文件如下:

from flask import Flask

from .extensions import cors, db, ma

def create_app(app_config):
    app = Flask(__name__)

    app.config.from_object(app_config)

    register_blueprints(app)
    register_extensions(app)
    return app

def register_extensions(app):
    cors.init_app(app)
    db.init_app(app)
    ma.init_app(app)

def register_blueprints(app):
    from .pv_dimensioning import dimensioning_blueprint
    app.register_blueprint(dimensioning_blueprint)

该应用程序的入口点是main.py

import os

from app import create_app
from app.extensions import db
from app.pv_dimensioning.services.data import data
from config import config_by_name

config_name = os.getenv("FLASK_CONFIG") or "default"
app_config = config_by_name[config_name]
app = create_app(app_config)

db.create_all(app=app)

with app.app_context():
    v = data(app)

print(v)

的输出print(v)如下:

{'v': ('Solarmodul Canadian Solar HiKu CS3L-370MS 370Wp', 'Solarmodul Longi LR4-60HIH-370M, 370Wp', 'Solarmodul Solar Fabrik mono S3 - Halfcut 360Wp', 'Solarmodul Energetica e.Classic M HC black - 360Wp', 'Solarmodul Yingli YL280P-29b-YGE 60 Cell Series 2 - poly, 280Wp', 'Solarmodul Suntech Power STP370S-B60/Wnh, 370Wp', 'Solarmodul AXITEC AXIworldpremium X HC AC-340MH/120S, 340Wp', 'Solarmodul Longi LR4-72HIH-440M, 440Wp', 'Solarmodul Seraphim SRP-330-BMB-DG 330Wp', 'Solarmodul Sharp NU-JD 440Wp')}

我希望在参数v中使用这些值。controller.py'vendor'

我尝试通过添加来获取vfrom的值,但它显示以下错误main.pyfrom main import vcontroller.py

ImportError: cannot import name 'v' from 'main'

我在做什么错误?

标签: pythonpython-3.xflaskflask-restx

解决方案


我不是专家flask_restx,但据我了解,该choices参数采用可迭代的,因此您应该能够简单地传递data函数的返回值。

数据.py

from ..models.vendor_models import AdminVendor

def data():
    values = AdminVendor.query.all()
    v = [value.name for value in values]
    return {'v': tuple(v)}

控制器.py

from flask_restx import Resource, reqparse
from .services.data import data 

parser = reqparse.RequestParser()

parser.add_argument(
    "vendor",
    choices=data()['v'],  
    help="Select the vendor")

关于导入错误,正如 Mindslave 指出的那样,这很可能是循环导入错误,请参阅此问题以获取更多详细信息。通常,这些可以通过将导入从模块顶部移动到函数/类中来避免,例如:

from flask_restx import Resource, reqparse



def load_parser():
    from .services.data import data # avoid circular import

    parser = reqparse.RequestParser()
    parser.add_argument(
        "vendor",
        choices=data()['v'],  
        help="Select the vendor")
    return parser

parse = load_parser()

作为旁注,请注意reqparse计划从flask_restx中删除,因此可能值得考虑一个不同的选项,然后再过度嵌入它:

警告 Flask-RESTX 的整个请求解析器部分将被删除,并将被有关如何与其他可以更好地执行输入/输出内容的包(例如棉花糖)集成的文档所取代。这意味着它将保持到 2.0,但认为它已被弃用。不用担心,如果您现在有代码使用它并希望继续这样做,它不会很快消失。

来源:https ://flask-restx.readthedocs.io/en/latest/parsing.html


推荐阅读