简体   繁体   English

如何使用python Flask RESTplus填充模型

[英]How to populate Models using python Flask RESTplus

I'm coming from Java background and now trying my hands on Python. 我来自Java背景,现在尝试使用Python。 I'm trying to create a RESTful web application for CRUD operations. 我正在尝试为CRUD操作创建一个RESTful Web应用程序。 I've already tried to go through the various links that provide step by step approach in achieving it using Flask RESTplus + SQLAlchemy. 我已经尝试过使用Flask RESTplus + SQLAlchemy逐步实现的各种链接。

However, I'm more keen on getting this the usual "java-way". 但是,我更渴望获得通常的“ java-way”。 Also I would like to avoid using ORM and instead use SQLAlchemy for executing raw SQL and then iterating resultsets to populate my model and then return the model. 我也想避免使用ORM,而是使用SQLAlchemy执行原始SQL,然后迭代结果集以填充我的模型,然后返回模型。

I'm taking baby steps and initially I want to see how to populate my Model with dummy data and return it back to the caller. 我正在采取一些步骤,最初我想了解如何使用虚拟数据填充模型并将其返回给调用者。 Below is what I'm trying to achieve but not able to move further: 以下是我要达到的目标,但无法进一步发展:

from flask import request
from flask import Flask
from flask import Blueprint
from flask_restplus import Resource, Api, apidoc
from flask_restplus import fields, marshal
from sqlalchemy import create_engine
from sqlalchemy.sql import text
import json

app = Flask(__name__)
blueprint = Blueprint('api', __name__, url_prefix='/edslnk/rest')
api = Api(blueprint, version='1.0', title='EDSLink ResourceSvc API',description='Set of APIs to interactively communicate with Database and HDFS')
app.register_blueprint(blueprint)

ns = api.namespace('eds-workflows', description='Operations related to EDS Workflows')

#engine = create_engine('oracle+cx_oracle://scott:tiger@tnsname')

workFlow = api.model('WorkFlow', {
    'workflowName': fields.String,
    'workflowScriptLoc': fields.String,
    'createUser': fields.String,
    'createDate': fields.String,
    'lstUpdateUser': fields.String,
    'lstUpdateDate': fields.String,
})

@ns.route('/')
class WorkflowsCollection(Resource):

    @ns.marshal_list_with(workFlow)
    def get(self):
        try:
            #connection = engine.connect()
            #result = connection.execute("select * from EDSOPERATION.EDSLNK_WORKFLOWS")
            workFlow_list = []
            for x in range(6):
                workFlow.workflowName = 'Workflow_Name'+x
                workFlow.workflowScriptLoc = 'Workflow_Script_Loc'+x
                workFlow.createUser = 'Create_User'+x
                workFlow.createDate = 'Create_Date'+x
                workFlow.lstUpdateUser = 'Lst_Modified_User'+x
                workFlow.lstUpdateDate = 'Lst_Modified_Date'+x
                workFlow_list.append(workFlow)
        finally:
            #connection.close()
            print('finally')

        #what should I return ? 'workFlow' or 'workFlow_list' ?


    @ns.response(201, 'Category successfully created.')
    def post(self):
        #create_workflow(request.json)
        pass

if __name__ == '__main__':
    app.run(debug=True)

When I trying to invoke the url curl -X GET " http://127.0.0.1:5000/edslnk/rest/eds-workflows/ " -H "accept: application/json" I get server error code 500 当我尝试调用url curl -X GET“ http://127.0.0.1:5000/edslnk/rest/eds-workflows/ ” -H“ accept:application / json”时,我得到服务器错误代码500

My total objective at this stage is to populate my model workFlow with some hardcoded data and then return list of these models as json data back to the caller. 我在此阶段的总体目标是用一些硬编码数据填充我的模型workFlow ,然后将这些模型的列表作为json数据返回给调用者。

Once I'm able to achieve this, I'll try with actual data from database by iterating the resultset and populating the resultset rows to the model. 一旦能够做到这一点,我将通过迭代结果集并将结果集行填充到模型中,尝试使用数据库中的实际数据。

Thanks in advance for any help ! 在此先感谢您的帮助!

********** UPDATE - 1 *********** ********** 更新-1 ***********

I was able to achieve some breakthrough based on below code. 根据以下代码,我能够实现一些突破。 I get expected output with below code. 我得到以下代码的预期输出。

However, I'm now ending up creating two definitions of my Model class viz., one via api.model and other via creating a normal class The model object workFlow created via api.Model is referred only for marshalling operation (in the @ns.marshal_list_with decorator) while the normal class created model objects workFlow1 and workFlow2 are used to populate the actual data and add them to the workFlow_list 但是,我现在最终要创建我的Model类的两个定义,一个是通过api.model ,另一个是通过创建普通class 。通过api.Model创建的模型对象workFlow仅用于编组操作(在@ns.marshal_list_with装饰器),而普通class创建的模型对象workFlow1workFlow2用于填充实际数据并将其添加到workFlow_list

Is it not possible to get different instances of my model object using the api.model and populate them with my data (kind-of using 'setters' as in java) ? 是否无法使用api.model获取模型对象的不同实例并用我的数据填充它们(类似于Java中的“ setters”)?

from flask import request
from flask import Flask,jsonify
from flask import Blueprint
from flask_restplus import Resource, Api, apidoc
from flask_restplus import fields, marshal
from sqlalchemy import create_engine
from sqlalchemy.sql import text
import json

app = Flask(__name__)
blueprint = Blueprint('api', __name__, url_prefix='/edslnk/rest')
api = Api(blueprint, version='1.0', title='EDSLink ResourceSvc API',description='Set of APIs to interactively communicate with Database and HDFS')
app.register_blueprint(blueprint)

ns = api.namespace('eds-workflows', description='Operations related to EDS Workflows')

#engine = create_engine('oracle+cx_oracle://scott:tiger@tnsname')

workFlow = api.model('WorkFlow', {
    'workflowName': fields.String,
    'workflowScriptLoc': fields.String,
    'createUser': fields.String,
    'createDate': fields.String,
    'lstUpdateUser': fields.String,
    'lstUpdateDate': fields.String,
})

#workFlow_list = []

class WorkFlow:
   def __init__(self, workflowName, workflowScriptLoc, createUser, createDate, lstUpdateUser, lstUpdateDate):
      self.workflowName = workflowName
      self.workflowScriptLoc = workflowScriptLoc
      self.createUser = createUser
      self.createDate = createDate
      self.lstUpdateUser = lstUpdateUser
      self.lstUpdateDate = lstUpdateDate

class MyEncoder(json.JSONEncoder):
    def default(self, o):
        return o.__dict__


@ns.route('/')
class WorkflowsCollection(Resource):

    @ns.marshal_list_with(workFlow)
    def get(self):
        try:
            #connection = engine.connect()
            #result = connection.execute("select * from EDSOPERATION.EDSLNK_WORKFLOWS")
            workFlow_list = []
            #workFlow1 = WorkFlow()
            #workFlow1.workflowName='abc'
            workFlow1 = WorkFlow('Workflow_Name', 'Workflow_Script_Loc', 'Create_User', 'Create_Date', 'Lst_Modified_User', 'Lst_Modified_Date')
            workFlow2 = WorkFlow('Workflow_Name', 'Workflow_Script_Loc', 'Create_User', 'Create_Date', 'Lst_Modified_User', 'Lst_Modified_Date')
            workFlow_list.append(workFlow1)
            workFlow_list.append(workFlow2)
            #responseString = json.dumps(workFlow_list, cls=MyEncoder)
            #print('responseString --> ' + responseString)
            #response = app.response_class(response=workFlow_list,status=200,mimetype='application/json')
#           for x in range(6):
#                workFlow.workflowName = 'Workflow_Name'+x
#                workFlow.workflowScriptLoc = 'Workflow_Script_Loc'+x
#                workFlow.createUser = 'Create_User'+x
#                workFlow.createDate = 'Create_Date'+x
#                workFlow.lstUpdateUser = 'Lst_Modified_User'+x
#                workFlow.lstUpdateDate = 'Lst_Modified_Date'+x
#                workFlow_list.append(workFlow)
        finally:
            #connection.close()
            print('finally')

        return workFlow_list

    @ns.response(201, 'Category successfully created.')
    def post(self):
        #create_workflow(request.json)
        pass

if __name__ == '__main__':
    #x = WorkflowsCollection()
    #r = x.get()
    #print(r)
    app.run(debug=True)

Flask restful models are not the appropriate tool for what you are trying to do. Flask Restful模型不适用于您要执行的操作。 They are meant to be input validation models and output serializers. 它们旨在用作输入验证模型和输出序列化器。 For validation of input, you use a decorator @ns.expect(your_model) and it will check your payload. 为了验证输入,您可以使用装饰器@ns.expect(your_model) ,它将检查您的有效负载。

Instead create a simple class like the one you made in your update for the object you are trying to model and create an array of instances of that object. 而是为要建模的对象创建一个简单的类,如您在更新中创建的类,并创建该对象的实例数组。 If you return that list from your resource get method and use the @marshal_list_with(your_model) decorator, you will get the output you want. 如果从资源get方法返回该列表,并使用@marshal_list_with(your_model)装饰器,则将获取所需的输出。

As for the model being defined in two places, the api.model one serves as an interface between your internal models and what your API calls each field or how it is structured. 至于在两个地方定义的模型, api.model一个用作内部模型与API调用每个字段或字段的结构之间的接口。 One can however create API model from sqlalchemy models if using marshmallow which is a more general purpose validation/serialization library which is what restplus intends to use in the future. 但是,如果使用棉花糖(一种更通用的验证/序列化库),则可以从sqlalchemy模型创建API模型,这是restplus将来打算使用的库。

Also I would recommend you stay away from handling the connection and specially from creating SQL statements to manipulate your objects. 我也建议您不要处理连接,尤其要避免创建SQL语句来操作对象。 Sqlalchemy is a very expressive orm and you will be missing a lot by not using it. Sqlalchemy是一个非常具有表现力的orm,如果不使用它,您将丢失很多东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM