Flask-sqlalchemy: Как сериализовать объекты с помощью специального конструктора из существующей базы данных? - PullRequest
0 голосов
/ 01 июля 2018

Я пытаюсь научиться создавать основанные на Python фоны из некоторых существующих данных, которые я собрал. Я пришел к выводу, что я определенно хочу использовать sqlalchemy, и эта фляжка кажется хорошей библиотекой. Моя проблема в том, что даже после многих часов чтения документации sqlalchemy и просмотра различных ответов на stackexchange, я все еще не понимаю, как я могу преобразовать данные из существующей таблицы в объект с совершенно другой структурой.

Трансформация, которую я хочу сделать, очень конкретна. Я хочу перейти от этой структуры в моей таблице MariaDB:

Столбцы: название компании, дата, показатели (1 ... 23)

К этому выводу json, сгенерированному из сериализованного объекта класса:

{
  "company_name[1]": 
    {
      "indicator_name[1]":
        {
          "date[1]": "indicator_name[1].value[1]",
          "date[2]": "indicator_name[1].value[2]",
          "date[3]": "indicator_name[1].value[3]",
          "date[4]": "indicator_name[1].value[4]",
          "date[5]": "indicator_name[1].value[5]"
        },
      "indicator_name[2]":
        {
          "date[1]": "indicator_name[2].value[1]",
          "date[2]": "indicator_name[2].value[2]",
          "date[3]": "indicator_name[2].value[3]",
          "date[4]": "indicator_name[2].value[4]",
          "date[5]": "indicator_name[2].value[5]"
        },

Я нашел отличный учебник, с помощью которого я могу выводить всю запись таблицы по записи, но структура - это не то, что мне нужно, и я не думаю, что создание желаемой структуры на внешнем интерфейсе имеет смысл в этом случае.

Вот код, который выводит всю таблицу в json-запись по записи:

from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy 
from sqlalchemy import PrimaryKeyConstraint
from sqlalchemy import orm
from sqlalchemy import select, func
from sqlalchemy import Column, Integer, String, ForeignKey
from flask_marshmallow import Marshmallow
import decimal
import flask.json

class MyJSONEncoder(flask.json.JSONEncoder): # Enables decimal queries for the API
    def default(self, obj):
        if isinstance(obj, decimal.Decimal):
            # Convert decimal instances to strings.
            return str(obj)
        return super(MyJSONEncoder, self).default(obj)

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://USER:PASS@localhost:3306/kl_balance_sheets'

app.json_encoder = MyJSONEncoder
db = SQLAlchemy(app)
ma = Marshmallow(app)

# Bind declarative base to engine
db.Model.metadata.reflect(db.engine)


class CompanyData(db.Model):
    __table__ = db.Model.metadata.tables['kl_balance_sheets']

class CompanyDataSchema(ma.ModelSchema):
    class Meta:
        model = CompanyData

@app.route('/')
def index():
    company_data = CompanyData.query.all()
    company_data_schema = CompanyDataSchema(many=True)
    output = company_data_schema.dump(company_data).data
    return jsonify({'company_data' : output})

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

Мой главный вопрос: как мне отредактировать этот код, чтобы получить желаемый JSON?

То, что я должен сделать, - это создать собственный конструктор и затем передать его в функцию индекса, но я не могу понять, как конкретно это сделать. Два варианта, с которыми я столкнулся:

@orm.reconstructor
def init_on_load(self):
    #do custom stuff

или

class Foo(db.Model):
# ...
def __init__(**kwargs):
super(Foo, self).__init__(**kwargs)
# do custom stuff

Мне кажется, что это обычная операция, которую каждый пользователь фляги-зефира будет делать регулярно. Может кто-нибудь объяснить, как данные SQL обычно вставляются в объект с новой структурой, а затем сериализуются? В моем случае, нужно ли мне что-то менять в основном на уровне метаданных, объектов или зефира? Я удивлен, что не могу найти хороших примеров этого.

...