【发布时间】:2020-12-27 13:29:48
【问题描述】:
我已经使用 SQLAlchemy 成功设置了一个 API 端点。新的目标是让 json 与 tag 对象的嵌套数组一起返回。所以我最终会得到这样的结果:
{
"favourite": "0",
"location": {
"urbanisation": "Montreal",
"province": "Quebec"
},
"tags":[{
"name":"celebration"
},
{
"name":"national holiday"
},
],
"count_articles": 5,
"scheduled": "1",
"title": "TEST TITLE",
"count_video": 5,
"id": 1,
"date": "2020-09-08",
"count_audio": 5,
"summary": "TEST DESCRIPTION"
}
尝试 1:
我知道我可以创建一个 many to many relationship in SQLAlchemy 并修改了我的 python 和数据库以适应这种变化。
这是连接表的处理方式
#JOINING TABLE FOR EVENTS AND TAGS
tag_association_table = Table('events_tags', db.metadata,
db.Column('event_id', db.Integer, db.ForeignKey('events.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tags.id'))
)
这是完整的代码:
from flask import Flask, request, jsonify
from flask_restful import Resource, Api
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine, Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from json import dumps
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, fields, auto_field
from flask_cors import CORS
from sqlalchemy.ext.declarative import declarative_base
import mysql.connector
#SQLAlchemy Docs: https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:password@localhost/news'
CORS(app, resources={r"/*": {"origins": "*"}})
db = SQLAlchemy(app)
api = Api(app)
#JOINING TABLE FOR EVENTS AND TAGS
tag_association_table = Table('events_tags', db.metadata,
db.Column('event_id', db.Integer, db.ForeignKey('events.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tags.id'))
)
#MODELS FOR EVENTS RESOURCE
class EventModel(db.Model):
__tablename__ = "events"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
summary = db.Column(db.String, nullable=False)
date = db.Column(db.String, nullable=True)
scheduled = db.Column(db.String, nullable=True)
favourite = db.Column(db.String, nullable=True)
count_audio = db.Column(db.Integer, nullable=False)
count_video = db.Column(db.Integer, nullable=False)
count_articles = db.Column(db.Integer, nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'), nullable=False)
location = db.relationship("LocationModel")
tags = db.relationship("TagModel",secondary=tag_association_table)
class LocationModel(db.Model):
__tablename__ = "location"
id = db.Column(db.Integer, primary_key=True)
province = db.Column(db.String, nullable=True)
urbanisation = db.Column(db.String, nullable=True)
class TagModel(db.Model):
__tablename__ = "tags"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
#SERIALISER CLASSES
class EventSchema(SQLAlchemyAutoSchema):
class Meta:
model = EventModel
load_instance = True
include_fk = False
location = fields.Nested('LocationSchema', many=False)
id = auto_field(load_only=False)
class LocationSchema(SQLAlchemyAutoSchema):
class Meta:
model = LocationModel
load_instance = True
include_fk = False
id = auto_field(load_only=True)
class TagSchema(SQLAlchemyAutoSchema):
class Meta:
model = TagModel
load_instance = True
include_fk = False
id = auto_field(load_only=True)
#LOADER
class Events(Resource):
def get(self):
schema = EventSchema()
result = db.session.query(EventModel).all()
return schema.dump(result, many=True), 200
api.add_resource(Events, '/events') # Route_1
#api.add_resource(Entries, '/events/event_id/entries>') # Route_2
if __name__ == '__main__':
app.run(port='5002')
应用程序运行,但标签根本不返回。 JSON 输出完全缺少标签数组。有什么想法吗?
尝试 2:
我还尝试将我的课程组织为suggested here。这也可以运行,但不提供标签列表。在这种情况下,我们有一个连接模型,而不是连接表:
class EventsTagsLink(db.Model):
__tablename__ = 'events_tags'
event_id = db.Column(db.Integer, ForeignKey('events.id'), primary_key = True)
tag_id = db.Column(db.Integer, ForeignKey('tags.id'), primary_key = True)
每个事件和标签模型都有一个之前定义的关系
class EventModel(db.Model):
__tablename__ = "events"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
summary = db.Column(db.String, nullable=False)
date = db.Column(db.String, nullable=True)
scheduled = db.Column(db.String, nullable=True)
favourite = db.Column(db.String, nullable=True)
count_audio = db.Column(db.Integer, nullable=False)
count_video = db.Column(db.Integer, nullable=False)
count_articles = db.Column(db.Integer, nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'), nullable=False)
location = db.relationship("LocationModel")
tags = db.relationship("TagModel",secondary='events_tags')
class TagModel(db.Model):
__tablename__ = "tags"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
events = db.relationship("EventModel",secondary='events_tags')
【问题讨论】:
-
我知道这不是直接回答你的问题,但你可能看过 sqlacodegen 吗? pypi.org/project/sqlacodegen 我用它来进行数据转换,并使用它从模式中生成的代码。如果你有一些多对多的关系,看看它是如何处理它的?
-
谢谢,我会试一试
-
顺便说一句:顾名思义,这是一个基于 SQL 的 -vs JSON db.. 但是如果你有类似 Northwind 或 Oracle 示例数据库之类的东西,你可以看到它是如何建模的.
标签: json python-3.x sqlalchemy