如何在 Flask sqlalchemy 中获取与外键链接的模型属性?

How to get model attribute linked with foreign key in Flask sqlalchemy?

我在 Flask-Sqlalchemy 中创建了两个模型。这些模型是 TicketsNamespace。两种模型都与外键连接。我还创建了 marshmallow-sqlalchemy ModelSchema 定义以在 RESTful API.

中使用
class Ticket(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    namespace = db.Column(
        db.Integer, db.ForeignKey('namespace.id'), nullable=False)
    title = db.Column(db.String)
    description = db.Column(db.Text)
    status = db.Column(db.String)
    severity = db.Column(db.String)


class TicketSchema(ma.ModelSchema):
    class Meta:
        model = Ticket
        include_fk = True
class Namespace(db.Model):

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


class NamespaceSchema(ma.ModelSchema):
    class Meta:
        model = Namespace

在我看来,我正在尝试通过给定的 命名空间 过滤所有票证。这是我的查询:

@app.route("/<string:name>", methods=["GET"])
def get_tickets_by_namespace(name):

    tickets_query = Ticket.query.join(Namespace).filter(Namespace.name == name)
    result = TicketSchema(many=True).dump(tickets_query).data

    return jsonify({"tickets": result})

如何在连接和过滤两个模型时从 Namespace 模型访问 name 属性?

当我使用 /aa 输入上面的 URL 时,我只得到 namespace_id,我还想看到命名空间的名称:

{
  "tickets": [
    {
      "description": "xcv",
      "id": 1,
      "namespace": 1,
      "severity": "xcvbn",
      "status": "xcvb",
      "title": "xc"
    },
    {
      "description": "xcv",
      "id": 3,
      "namespace": 1,
      "severity": "xcvbnb",
      "status": "axcvb",
      "title": "axcb"
    },
    {
      "description": "xcv",
      "id": 4,
      "namespace": 1,
      "severity": "bnb",
      "status": "axcvb",
      "title": "aaaxcb"
    }
  ]
}

而不是使用 include_fk,你想给你的模型一个 relationship:

class Ticket(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    namespace_id = db.Column(
        'namespace',
        db.Integer,
        db.ForeignKey('namespace.id'),
        nullable=False
    )
    namespace = db.relationship("Namespace", backref="tickets")

    title = db.Column(db.String)
    description = db.Column(db.Text)
    status = db.Column(db.String)
    severity = db.Column(db.String) 

自动包含关系,但它们的默认字段仍然只序列化外键。

确保只定义 marshmallow-sqlalchemy 模型 所有 SQLAlchemy 模型加载后,因为创建模型将触发映射配置 运行 (其中字符串db.relationship() 调用中的 "Namespace" 字符串等表达式)被解析。在 Namespace 模型也已创建之前,您无法创建 Ticket 模型的 Marshmallow 模型。

接下来,use a Nested() field 拉入您想要的 Namespace 属性:

class TicketSchema(ma.ModelSchema):
    class Meta:
        model = Ticket

    # don't include 'tickets' when including a namespace schema.
    # you can also put this on the NestedSchema model.
    namespace = ma.Nested("NamespaceSchema", exclude=("tickets",))

在上面的例子中,需要 exclude=("tickets",) 参数来避免 Namespace 对象上的 tickets 关系也反映在结果 JSON 中(它' ll 只包含外键,Marshmallow 意识到它已经序列化了票证)。您还可以将 exclude 添加到 NamespaceSchema 模型 Meta,但随后 all 使用该架构将排除 tickets 字段.

通过上述更改,您的路由输出:

{
  "tickets": [
    {
      "description": "xcv",
      "id": 1,
      "namespace": {
        "id": 1,
        "name": "aa"
      },
      "severity": "xcvbn",
      "status": "xcvb",
      "title": "xc"
    },
    {
      "description": "xcv",
      "id": 3,
      "namespace": {
        "id": 1,
        "name": "aa"
      },
      "severity": "xcvbnb",
      "status": "axcvb",
      "title": "axcb"
    },
    {
      "description": "xcv",
      "id": 4,
      "namespace": {
        "id": 1,
        "name": "aa"
      },
      "severity": "bnb",
      "status": "axcvb",
      "title": "aaaxcb"
    }
  ]
}