문제

플라스크 Restful 확장에 관해 질문이 있습니다.방금 사용하기 시작했는데 한 가지 문제에 직면했습니다.나는 가지고있다 flask-sqlalchemy 다대일 관계로 연결된 엔터티가 있고 편안한 엔드포인트가 모든 하위 항목이 포함된 상위 엔터티를 반환하고 싶습니다. json 마샬러를 사용하여내 경우에는 Set에 많은 매개변수가 포함되어 있습니다.나는 플라스크-레스트풀(Flask-restful)을 보았다. 문서 하지만 이 사건을 어떻게 해결해야 할지 아무런 설명이 없었습니다.

분명한 것이 빠진 것 같지만 해결책을 찾을 수 없습니다.내 코드는 다음과 같습니다.

# entities
class Set(db.Model):
    id = db.Column("id", db.Integer, db.Sequence("set_id_seq"), primary_key=True)
    title = db.Column("title", db.String(256))

    parameters = db.relationship("Parameters", backref="set", cascade="all")


class Parameters(db.Model):
    id = db.Column("id", db.Integer, db.Sequence("parameter_id_seq"), primary_key=True)
    flag = db.Column("flag", db.String(256))
    value = db.Column("value", db.String(256))
    set_id = db.Column("set_id", db.Integer, db.ForeignKey("set.id"))


# marshallers

from flask.ext.restful import fields

parameter_marshaller = {
    "flag": fields.String,
    "value": fields.String
}

set_marshaller = {
    'id': fields.String,
    'title': fields.String,
    'parameters': fields.List(fields.Nested(parameter_marshaller))
}

# endpoint    

class SetApi(Resource):

    @marshal_with(marshallers.set_marshaller)
    def get(self, set_id):
        entity = Set.query.get(set_id)
        return entity


restful_api = Api(app)
restful_api.add_resource(SetApi, "/api/set/<int:set_id>")

이제 내가 전화할 때 /api/set/1 서버 오류가 발생합니다.

TypeError: 'Set' object is unsubscriptable

따라서 엔드포인트가 이 json을 반환하도록 set_marshaller를 올바르게 정의하는 방법이 필요합니다.

{
  "id": : "1",
  "title": "any-title",
  "parameters": [
       {"flag": "any-flag", "value": "any-value" },
       {"flag": "any-flag", "value": "any-value" },
       .....
   ]
}

도움을 주셔서 감사합니다.

도움이 되었습니까?

해결책

나는 그 문제에 대한 해결책을 스스로 찾았습니다.

가지고 놀고 난 뒤 flask-restful 나는 내가 실수를 거의 하지 않았다는 것을 알게 되었습니다.

첫째로 set_marshaller 다음과 같아야 합니다:

blob_marshaller = {
    'id': fields.String,
    'title': fields.String,
    'parameters': fields.Nested(parameter_marshaller)
}

불안한 마샬러는 매개변수가 목록이고 마샬링되는 경우 대소문자를 처리할 수 있습니다. json 목록.

또 다른 문제는 API Set 매개변수에 지연 로딩이 있다는 점이었습니다. 그래서 Set을 마샬링하려고 하면 KeyError: 'parameters', 따라서 다음과 같은 매개변수를 명시적으로 로드해야 합니다.

class SetApi(Resource):

     @marshal_with(marshallers.set_marshaller)
     def get(self, set_id):
        entity = Set.query.get(set_id)
        entity.parameters # loads parameters from db
        return entity

또는 또 다른 옵션은 모델 관계를 변경하는 것입니다.

parameters = db.relationship("Parameters", backref="set", cascade="all" lazy="joined")

다른 팁

이것은 Zygimantas 답변 :

플라스크 -LESSFIT를 사용하고 있으며 이는 중첩 된 속성을로드하는 해결책입니다.

마샬 데코레이터에 호출 할 수 있습니다.

class OrgsController(Resource):
    @marshal_with(Organization.__json__())
    def get(self):
        return g.user.member.orgs
.

그런 다음 모델을 업데이트하여 자체 엔티티에 대한 자원 필드를 반환합니다. 중첩 된 엔티티는 해당 엔티티의 자원 필드를 비교적으로 반환합니다.

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

    @staticmethod
    def __json__(group=None):
        _json = {
            'id': fields.String,
            'login': fields.String,
            'description': fields.String,
            'avatar_url': fields.String,
            'paid': fields.Boolean,
        }

        if group == 'flat':
            return _json

        from app.models import Repository
        _json['repos'] = fields.Nested(Repository.__json__('flat'))

        return _json

class Repository(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('organization.id'))
    owner = db.relationship('Organization', lazy='select', backref=db.backref('repos', lazy='select'), foreign_keys=[owner_id])
    ...

    @staticmethod
    def __json__(group=None):
        _json = {
            'id': fields.String,
            'name': fields.String,
            'updated_at': fields.DateTime(dt_format='iso8601'),
        }

        if group == 'flat':
            return _json

        from app.models import Organization
        _json['owner'] = fields.Nested(Organization.__json__('flat'))

        return _json
.

이것은 내가 찾고있는 표현을 제공하고, 게으른로드를 존중합니다 :

[
    {
        "avatar_url": "https://avatars.githubusercontent.com/u/18945?v=3",
        "description": "lorem ipsum.",
        "id": "1805",
        "login": "foobar",
        "paid": false,
        "repos":
            [
                {
                    "id": "9813",
                    "name": "barbaz",
                    "updated_at": "2014-01-23T13:51:30"
                },
                {
                    "id": "12860",
                    "name": "bazbar",
                    "updated_at": "2015-04-17T11:06:36"
                }
            ]
    }
]
.

나는 좋아한다

1)이 접근 방식은 엔티티 당 내 리소스 필드를 정의 할 수 있으며 응용 프로그램 전체의 모든 리소스 경로에서 사용할 수 있습니다.

2) 그룹 인수가 어떻게 표현을 맞춤화 할 수 있지만, 나는 원하는 방법을 욕망합니다. 여기에만 '평평한'만 있지만 모든 논리를 작성하고 깊은 중첩 된 객체로 전달할 수 있습니다.

3) 엔티티는 필요에 따라로드됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top