Как связать атрибут модели с внешним ключом в Flask sqlalchemy? - PullRequest
0 голосов
/ 28 июня 2019

Я создал две модели в Flask-Sqlalchemy.Эти модели Tickets и Namespace.Обе модели связаны с внешним ключом.Я также создал определения 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})

Как получить доступ к атрибуту name из модели Namespace при объединении и фильтрации двух моделей?

Когда я ввожу указанный выше URL с помощью /aa, я получаю только 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 Ответ

3 голосов
/ 28 июня 2019

Вместо использования 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) 

Отношения включаются автоматически, но их поле по умолчанию все еще только сериализует внешние ключи.

Обязательно определяйте только модели marshmallow-sqlalchemy после все ваши модели SQLAlchemy загрузились, так как создание моделей будет запускать запуск конфигурации сопоставления (где строковые выражения, такие как строка "Namespace" вdb.relationship() вызов) разрешены.Вы не можете создать модель Зефира модели Ticket, пока модель Namespace также не будет создана.

Далее, используйте поле Nested() , чтобы вытянуть 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 (it 'Будут содержать только внешние ключи, зефир понимает, что он уже сериализовал билеты).Вы также можете добавить 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"
    }
  ]
}
...