26

Flask、Flask-SQLAlchemy、Flask-Marshmallow + marshmallow-sqlalchemy を使用して、REST API PUT メソッドを実装しようとしています。SQLA とマシュマロを使用して更新を実装するチュートリアルは見つかりませんでした。

コードは次のとおりです。

class NodeSchema(ma.Schema):
    # ...


class NodeAPI(MethodView):
    decorators = [login_required, ]
    model = Node

    def get_queryset(self):
        if g.user.is_admin:
            return self.model.query
        return self.model.query.filter(self.model.owner == g.user)

    def put(self, node_id):
        json_data = request.get_json()
        if not json_data:
            return jsonify({'message': 'Invalid request'}), 400

        # Here is part which I can't make it work for me
        data, errors = node_schema.load(json_data)
        if errors:
            return jsonify(errors), 422

        queryset = self.get_queryset()


        node = queryset.filter(Node.id == node_id).first_or_404()
        # Here I need some way to update this object
        node.update(data) #=> raises AttributeError: 'Node' object has no attribute 'update'

        # Also tried:
        # node = queryset.filter(Node.id == node_id)
        # node.update(data) <-- It doesn't if know there is any object
        # Wrote testcase, when user1 tries to modify node of user2. Node doesn't change (OK), but user1 gets status code 200 (NOT OK).

        db.session.commit()
        return jsonify(), 200
4

5 に答える 5

41

更新しました

代わりにModelSchemafromを拡張すると、次のようになります。marshmallow-sqlalchemyFlask-Marshmallow

load(data, session=None, instance=None, *args, **kwargs)

schema.load()次に、次のように、編集中のオブジェクトを のパラメーターとして渡す必要があります。

node_schema.load(json_data, instance=Node().query.get(node_id))

のすべての必須フィールドなしでロードしたい場合は、次のようにModelを追加できます。partial=True

node_schema.load(json_data, instance=Node().query.get(node_id), partial=True)

ドキュメントmarshmallow_sqlalchemy.ModelSchema.loadを参照してください

于 2016-04-05T07:04:43.260 に答える
5

私は独自のソリューションを展開しました。それが他の誰かに役立つことを願っています。ソリューションは Node モデルに update メソッドを実装します。

解決:

class Node(db.Model):
    # ...

    def update(self, **kwargs):
        # py2 & py3 compatibility do:
        # from six import iteritems
        # for key, value in six.iteritems(kwargs):
        for key, value in  kwargs.items():
            setattr(self, key, value)


class NodeAPI(MethodView):
    decorators = [login_required, ]
    model = Node

    def get_queryset(self):
        if g.user.is_admin:
            return self.model.query
        return self.model.query.filter(self.model.owner == g.user)

    def put(self, node_id):
        json_data = request.get_json()
        if not json_data:
            abort(400)

        data, errors = node_schema.load(json_data)  # validate with marshmallow
        if errors:
            return jsonify(errors), 422

        queryset = self.get_queryset()
        node = queryset.filter(self.model.id == node_id).first_or_404()
        node.update(**data)
        db.session.commit()
        return jsonify(message='Successfuly updated'), 200
于 2015-08-08T18:49:38.757 に答える