在Excel中打开OData服务时出错,EDMX元数据不正确

2024-10-04 03:27:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图编写一个RESTful API来发布一些数据集。在Python中这样做,并希望遵循OData标准。目标是能够从Excel中打开数据(data>;New query>;OData)

第一次尝试似乎充满希望:我已经生成了一个连接到mysql数据库并返回所需行的FlaskAPI。 不幸的是,目前还不起作用的是从Excel打开。它在元数据描述符上出错,说它遇到了一个意外的属性名“Article name”(我的数据集第一列的字母顺序),在服务文档中只需要“name”和“url”

我似乎无法找出正在生成的元数据有什么问题,因此非常感谢您的帮助

app.py:

from flask import Flask, jsonify, request, make_response
from flask_restful import Resource, Api, reqparse
import pandas as pd
import mysql.connector as sql
import ast
import xml.etree.ElementTree as ET

app = Flask(__name__)
api = Api(app, default_mediatype='application/json')

config = {
  'host': '127.0.0.1',
  'port': '3306',
  'user': '***',
  'passwd': '***',
  'database': '***',
  'charset': 'utf8mb4',
  'raise_on_warnings': True
}

class FinancieleInstrumenten(Resource):
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('begrotingsjaar', required=False)
        parser.add_argument('begrotingshoofdstuk', required=False)
        args = parser.parse_args()  # parse arguments to dictionary

        try:
            cnx = sql.connect(**config)

            # Build query depending on input variables
            if not args['begrotingsjaar'] and not args['begrotingshoofdstuk']:
                qry = "SELECT * FROM FinancieleInstrumenten LIMIT 25;"
                res = pd.read_sql(qry, cnx)
            elif not args['begrotingshoofdstuk']:
                qry = """SELECT * FROM FinancieleInstrumenten WHERE Begrotingsjaar = {} LIMIT 25;"""
                res = pd.read_sql_query(qry.format(args['begrotingsjaar']), cnx)
            elif not args['begrotingsjaar']:
                qry = """SELECT * FROM FinancieleInstrumenten WHERE Begrotingshoofdstuk = {} LIMIT 25;"""
                res = pd.read_sql_query(qry.format(args['begrotingshoofdstuk']), cnx)
            else:
                qry = """SELECT * FROM FinancieleInstrumenten WHERE Begrotingsjaar = {} AND Begrotingshoofdstuk = {} LIMIT 25;"""
                res = pd.read_sql_query(qry.format(args['begrotingsjaar'], args['begrotingshoofdstuk']), cnx)

            # Build response with OData header
            resp = make_response({
                '@odata.context': 'https://stukkenparser.gitlab-minfin.nl/financiele-instrumenten/$metadata',
                'value': res.to_dict('records')
                })
            resp.headers['OData-Version'] = '4.0'
            return resp
        except Exception as e:
            print(str(e))
        finally:
            if cnx.is_connected():
                cnx.close()

    def put(self):
        return {'message': 'Only method GET allowed.'}, 405
    def post(self):
        return {'message': 'Only method GET allowed.'}, 405
    def patch(self):
        return {'message': 'Only method GET allowed.'}, 405
    def delete(self):
        return {'message': 'Only method GET allowed.'}, 405


api.add_resource(FinancieleInstrumenten, '/financiele-instrumenten')


@app.route("/financiele-instrumenten/$metadata", methods=['GET'])
def index():
    if request.method=='GET':
        root = ET.parse('financiele-instrumenten.metadata.xml').getroot()
        return app.response_class(ET.tostring(root), mimetype='application/xml')


if __name__ == '__main__':
    app.run(debug=True, host='127.0.0.1', port=1337)

financiele-instrumenten.metadata.xml:

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
  <edmx:DataServices>
    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="NL.MinFin.OData.FinancieleInstrumenten">
      <EntityContainer Name="FinancieleInstrumentenEntities">
        <EntitySet Name="FinancieleInstrumentenSet" EntityType="NL.MinFin.OData.FinancieleInstrumenten.FinancieleInstrumentenType" />
      </EntityContainer>
      <EntityType Name="FinancieleInstrumentenType">
        <Property Name="Begrotingsjaar" Type="Edm.String" Nullable="false" />
        <Property Name="Begrotingshoofdstuk" Type="Edm.String" Nullable="false" />
        <Property Name="Begrotingsnaam" Type="Edm.String" Nullable="false" />
        <Property Name="Artikelnummer" Type="Edm.String" Nullable="true" />
        <Property Name="Artikelnaam" Type="Edm.String" Nullable="true" />
        <Property Name="Artikelonderdeel" Type="Edm.String" Nullable="true" />
        <Property Name="Instrument" Type="Edm.String" Nullable="true" />
        <Property Name="Regeling" Type="Edm.String" Nullable="true" />
        <Property Name="Ontvanger" Type="Edm.String" Nullable="true" />
        <Property Name="KvK-nummer" Type="Edm.String" Nullable="true" />
        <Property Name="Bedrag" Type="Edm.Int64" Nullable="false" />
      </EntityType>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

Tags: nameimporttrueappsqlstringtypeargs
1条回答
网友
1楼 · 发布于 2024-10-04 03:27:27

简短回答:

您的medatata不正确,因为您的entitytype缺少一个键

长答案:

发件人:https://docs.microsoft.com/en-us/odata/concepts/data-model

实体类型 实体类型是带有键的命名结构化类型。它们定义实体的命名属性和关系。实体类型可以通过单一继承从其他实体类型派生

实体类型的键由实体类型的基本属性(例如CustomerId、OrderId、LineId等)的子集构成

因此,实体的本质是,您可以唯一地标识它,以便从我们的导航属性源外部访问它。因此,您必须定义一个实体键,例如,当ODATA想要导航到其中一个时,它可以这样做,例如/FinancieleInstrumentenEntities(key)/

您的edmx应该是这样的(我猜了一下钥匙,希望它是独一无二的):

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
  <edmx:DataServices>
    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="NL.MinFin.OData.FinancieleInstrumenten">
      <EntityContainer Name="FinancieleInstrumentenEntities">
        <EntitySet Name="FinancieleInstrumentenSet" EntityType="NL.MinFin.OData.FinancieleInstrumenten.FinancieleInstrumentenType" />
      </EntityContainer>
      <EntityType Name="FinancieleInstrumentenType">
        <Key>
          <PropertyRef Name='Begrotingsjaar'/>
          <PropertyRef Name='Begrotingshoofdstuk'/>
          <PropertyRef Name='Begrotingsnaam'/>
        </Key>
        <Property Name="Begrotingsjaar" Type="Edm.String" Nullable="false" />
        <Property Name="Begrotingshoofdstuk" Type="Edm.String" Nullable="false" />
        <Property Name="Begrotingsnaam" Type="Edm.String" Nullable="false" />
        <Property Name="Artikelnummer" Type="Edm.String" Nullable="true" />
        <Property Name="Artikelnaam" Type="Edm.String" Nullable="true" />
        <Property Name="Artikelonderdeel" Type="Edm.String" Nullable="true" />
        <Property Name="Instrument" Type="Edm.String" Nullable="true" />
        <Property Name="Regeling" Type="Edm.String" Nullable="true" />
        <Property Name="Ontvanger" Type="Edm.String" Nullable="true" />
        <Property Name="KvK-nummer" Type="Edm.String" Nullable="true" />
        <Property Name="Bedrag" Type="Edm.Int64" Nullable="false" />
      </EntityType>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

如您所见,对于复合关键点,可以添加多个特性参照。你至少需要一个

用作键的属性不能为null,并且组合必须唯一。(在那种情况下我不确定)

如果没有可唯一标识的项,可以尝试使用复杂类型而不是实体,将其作为属性附加到根实体(仍需要密钥)上

相关问题 更多 >