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

时间:2019-06-28 16:13:46

标签: python flask sqlalchemy flask-sqlalchemy marshmallow

我在Flask-Sqlalchemy中创建了两个模型。这些模型是TicketsNamespace。两种型号均通过外键连接。我还创建了棉花糖-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

在我看来,我试图通过给定的 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})

如何在加入和过滤两个模型的同时从name模型访问Namespace属性?

当我使用/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"
    }
  ]
}

1 个答案:

答案 0 :(得分:3)

您想给模型一个relationship,而不是使用include_fk

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) 

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

请确保仅在所有SQLAlchemy模型加载后 定义棉花糖-sqlalchemy模型,因为创建模型将触发运行映射配置(其中的字符串表达式,例如"Namespace"字符串db.relationship()呼叫)已解决。您必须先创建Ticket模型,才能创建Namespace模型的棉花糖模型。

接下来,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",)参数来避免tickets对象上的Namespace关系也反映在生成的JSON中(它仅包含外键,棉花糖意识到它已经序列化了票)。您还可以将exclude添加到NamespaceSchema模型Meta中,但是全部使用该模式将排除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"
    }
  ]
}