Frage

Ich habe eine Frage zur flask restful extension.Ich habe gerade erst angefangen, es zu benutzen, und hatte ein Problem.Ich habe flask-sqlalchemy Entitäten, die in einer Viele-zu-Eins-Beziehung verbunden sind, und ich möchte, dass dieser erholsame Endpunkt die übergeordnete Entität mit allen ihren untergeordneten Elementen zurückgibt json mit Marshaller.In meinem Fall enthält Set viele Parameter.Ich schaute flaschenruhevoll zu Dokumente Es gab jedoch keine Erklärung, wie dieser Fall gelöst werden sollte.

Scheint, als würde mir etwas Offensichtliches entgehen, ich kann aber keine Lösung finden.Hier ist mein Code:

# 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>")

Wenn ich jetzt anrufe /api/set/1 Ich erhalte einen Serverfehler:

TypeError: 'Set' object is unsubscriptable

Ich brauche also eine Möglichkeit, set_marshaller korrekt zu definieren, damit der Endpunkt diesen JSON zurückgibt:

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

Ich bin für jede Hilfe dankbar.

War es hilfreich?

Lösung

Ich habe selbst eine Lösung für dieses Problem gefunden.

Nach dem Herumspielen mit flask-restful Ich stelle fest, dass ich einige Fehler gemacht habe:

zuerst set_marshaller sollte so aussehen:

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

Restless Marshaller kann die Groß- und Kleinschreibung verarbeiten, wenn der Parameter eine Liste ist und an diese gemarshallt json Liste.

Ein weiteres Problem bestand darin, dass die API-Set-Parameter verzögert geladen werden. Wenn ich also versuche, Set zu Marshallen, bekomme ich KeyError: 'parameters', also muss ich Parameter wie diesen explizit laden:

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

Oder eine andere Möglichkeit besteht darin, die Modellbeziehung zu ändern:

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

Andere Tipps

Dies ist eine Ergänzung zu Zygimantas'S Antwort:

Ich verwende Flask-RESTful und dies ist eine Lösung für das Laden der verschachtelten Eigenschaften.

Sie können dem Marshal-Dekorator ein Callable übergeben:

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

Aktualisieren Sie dann die Modelle, um die Ressourcenfelder für die eigene Entität zurückzugeben.Verschachtelte Entitäten geben daher die Ressourcenfelder für ihre Entität relativ zurück.

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

Dies ergibt die Darstellung, nach der ich suche, und würdigt das verzögerte Laden:

[
    {
        "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"
                }
            ]
    }
]

Ich mag

1) Wie dieser Ansatz es mir ermöglicht, meine Ressourcenfelder pro Entität zu definieren, und wie er für alle meine Ressourcenrouten in der App verfügbar ist.

2) wie das Gruppenargument es mir ermöglicht, die Darstellung nach meinen Wünschen anzupassen.Ich habe hier nur „flach“, aber jede Logik kann geschrieben und an tiefer verschachtelte Objekte weitergegeben werden.

3) Entitäten werden nur bei Bedarf geladen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top