Вопрос

Problem

I am building an app on Flask, Flask-SQLAlchemy, and Flask-Restless. I have used restless to generate an API for a parent-child-grandchild relationship*. A GET on my child will correctly fetch the grandchild, but a GET on the parent will not fetch the grandchild for each child.

*In fact, the parent-child relationship is a many-to-many, but same premise.

Models

class Grandchild(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)

    parent = db.relationship('Child', backref='grandchild')

parent_child = db.Table('parent_child', 
    db.Column('parent_id', db.Integer, db.ForeignKey('parent.id')),
    db.Column('child_id', db.Integer, db.ForeignKey('child.id')),
    db.Column('number', db.SmallInteger)
)

class Child(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)

    grandchild_id = db.Column(db.Integer, db.ForeignKey('grandchild.id'), nullable=False)

class Parent(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)

    children = db.relationship('Child', secondary=parent_child)

api.create_api(Child, exclude_columns=['grandchild_id'])
api.create_api(Parent)

GET: /api/child response

{
  "num_results": 1, 
  "objects": [
    {
      "id": 1, 
      "name": "test"
      "grandchild": {
        "id": 1, 
        "name": "test"
      }
    }
  ], 
  "page": 1, 
  "total_pages": 1
}

GET: /api/parent response

{
  "num_results": 1, 
  "objects": [
    {
      "children": [
        {
          "id": 1, 
          "name": "test", 
          "grandchild_id": 1
        }
      ],
      "id": 1, 
      "name": "test"
    }], 
  "page": 1, 
  "total_pages": 1
}
Это было полезно?

Решение

postprocessors can be used to fetch grandchild.

def parent_post_get_many(result=None, search_params=None, **kw):
   for object in result['objects']:
      for child in object['children']:
         grandchild = Grandchild.query.get(child['grand_child_id'])
         child.update({'grandchild': grandchild})

api.create_api(Parent, postprocessors={'GET_MANY': [parent_post_get_many]})

Другие советы

After looking at this for a few hours I'm going to give the best answer I have at the moment. I've tried a number of approaches and haven't been able to get anything to successfully render the grandchild, so I turned to the flask-restless issues tracker to see what I could find:

https://github.com/jfinkels/flask-restless/pull/222#issuecomment-31326359 and @jfinkels response seem to indicate that what you want is currently not possible in flask-restless.

Assuming my assessment of the state of issues is correct, you may want to look into either designing around this issue, or using a different package to serve your API (perhaps Flask-restful, though I admit I haven't used it and don't know if it's suitable).

FWIW, I've been using Flask-Classy to build a json API for a project I'm working on. The process is a little more involved than I suspect you want, but it also comes with enough freedom to better control what queries are used and how the results are serialized.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top