将 flask-restful api 端点重构为单独的链接资源

Refactoring a flask-restful api endpoint into separate linked resources

我正在重构 API 上的一些代码,我不确定如何在 Flask-Restful 和 SQLAlchemy 中构建相关模型。页面中途的部分解决方案。

我基本上想做的是相当于这个 SQL

SELECT tags.name
FROM events, tags, events_tags 
WHERE events.id = events_tags.event_id 
  AND tags.id = events_tags.tag_id
  AND events.id = 1

我的路线最初有一个带有嵌套标签集的事件,api.add_resource(Events, '/events/<int:event_id>') 返回的 JSON 的结构如下:

{  
    "event_id":"1",
    "title":"Sample title",
    "tags":[
            {"name":"earthquake"},
            {"name":"infrastructure"}
           ]
}

这是 tags,我想将其分离到一个单独的端点中:

所以我们最终得到两个 JSON 输出

api.add_resource(Event, '/events/<int:event_id>')

[
    {  
        "event_id":"1",
        "title":"Sample title",
    }
]

api.add_resource(Tags, '/events/<int:event_id>/tags')

[
    {"name":"earthquake"},
    {"name":"infrastructure"}
]

当我解决这个问题时,我意识到任何给定的标签可能属于多个事件,我认为解决方案需要完成以下工作:

  1. 数据库中加入 table 的事件/标签。
  2. api
  3. 中的tag_association_table函数
  4. A TagsListModel(但我不确定这是否引用了这个 tag_association_table

欢迎任何帮助。

标签模型

class TagsListModel(db.Model):
    __tablename__ = "tags"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    events = db.relationship("EventModel", secondary=tag_association_table, backref="tag")

标签序列化器

class TagSchema(SQLAlchemyAutoSchema):
    class Meta:
        model = TagModel
        load_instance = True
        include_fk = True

    id = auto_field(load_only=True)

标签加载器

class Tags(Resource):
    # GET
    def get(self, event_id):
        schema = TagsListSchema()
        result = db.session.query(TagsListModel).filter(TagsListModel.event_id == event_id)
        return schema.dump(result, many=True), 200

    # POST
    def post(self, event_id):
        event_id = event_id
        name = request.json['name']

        tag = TagsListModel(name=name)


        db.session.add(tag)
        db.session.commit()

        data = ({'id' :tag.id,
                    'name': tag.name
                })

        #print(data)

        response = jsonify(data)
        response.status_code = 200 # or 400 or whatever
        return response

路线

# Route_1
## GET (RETURNS) A LIST OF EVENTS
## POST (CREATES) AN EVENT
api.add_resource(Events, '/events')

# Route_2
## GET (RETURNS) A SINGLE EVENT
# PUTS (UPDATES) A SINGLE EVENT
api.add_resource(Events, '/events/<int:event_id>')

# Route_3
## GET (RETURNS) ALL TAGS FOR AN EVENT
api.add_resource(Tags, '/events/<int:event_id>/tags')

部分解决方案

我已经能够在 连接 table 上检索值。这些已正确过滤并提供以下输出:

[
    {
        "tag_id": 1, 
        "event_id": 1
    }, 
    {
        "tag_id": 2,
        "event_id": 1
    }
]

端点

我用 1int:event_id 值调用以下端点:

# Route_3
## GET (RETURNS) ALL TAGS FOR AN EVENT
api.add_resource(EventTags, '/events/<int:event_id>/tags')

加载程序

class EventTags(Resource):
    # GET
    def get(self, event_id):
        schema = TagSchema()
        result = db.session.query(TagModel).filter(TagModel.event_id == event_id)
        return schema.dump(result, many=True), 200

    # POST
    def post(self, event_id):
        event_id = event_id
        tag_id = request.json['id']

        tag = TagsListModel(id=id)


        db.session.add(tag)
        db.session.commit()

        data = ({'id' :tag.id
                })

        #print(data)

        response = jsonify(data)
        response.status_code = 200 # or 400 or whatever
        return response

架构

class TagSchema(SQLAlchemyAutoSchema):
    class Meta:
        model = TagModel
        load_instance = True
        include_fk = True

    tag_id = auto_field(load_only=False)
    event_id = auto_field(load_only=False)

型号

class TagModel(db.Model):
    __tablename__ = "events_tags"

    tag_id = Column(Integer, primary_key=True)
    event_id = Column(Integer, primary_key=True)

已修复。

我不得不:

  1. 为不存在的每个 table 创建一个模型:(EventTag,Tag)
  2. 修改我的标签模式以匹配我想从 Tag table
  3. 中隐藏的值
  4. 修改我的 EventTags 加载器以过滤三个 tables
  5. 的列

型号

class TagModel(db.Model):
    __tablename__ = "tags"

    id = Column(Integer, primary_key=True)
    name = Column(db.String, nullable=False)


class EventTagModel(db.Model):
    __tablename__ = "events_tags"

    tag_id = Column(Integer, primary_key=True)
    event_id = Column(Integer, primary_key=True)

架构

class TagSchema(SQLAlchemyAutoSchema):
    class Meta:
        model = TagModel
        load_instance = True
        include_fk = True

    id = auto_field(load_only=True)  # Only one field removed so this remained pretty identical. 

装载机

result = db.session.query(TagModel)
    .filter(TagModel.id == EventTagModel.tag_id)
    .filter(EventModel.id == EventTagModel.event_id)
    .filter(EventTagModel.event_id == event_id)

#   result = db.session.query(TagModel).         # REMOVED
#       filter(TagModel.event_id == event_id).   # REMOVED