Estoy usando Marshmallow para propósitos de serialización / deserialización en la API que estoy construyendo pero obtengo el error mencionado anteriormente. Aquí están mi archivo de esquema, modelo y recurso para el mismo.

Esquemas / post.py

from marshmallow import Schema, fields, validate, post_dump

from schemas.user import UserSchema

class PostSchema(Schema):
    class Meta:
        ordered = True

    id = fields.Int(dump_only=True)
    body = fields.Str(required=True, validate=[validate.Length(max=500, min=1)])
    created_at = fields.DateTime(dump_only=True)
    updated_at = fields.DateTime(dump_only=True)
    author = fields.Nested(UserSchema, attribute='user', dump_only=True, only=['id', 'username'])

    @post_dump(pass_many=True)
    def wrap_output_with_envelope(self, data, many, **kwargs):
        if many:
            return {'data': data}
        return data

Modelos / post.py

from database import db

class Post(db.Model):
    __tablename__ = 'post'

    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String, nullable=False)
    created_at = db.Column(db.DateTime(), nullable=False, server_default=db.func.now())
    updated_at = db.Column(db.DateTime(), nullable=False, server_default=db.func.now(), onupdate=db.func.now())
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    @classmethod
    def get_by_post_id(cls, id):
        return cls.query.filter_by(id=id).first()

    @classmethod
    def get_all_posts(cls):
        return cls.query.all()

    def data(self):
        return {'id': self.id, 'body': self.body, 'user_id': self.user_id}

    def save(self):
        db.session.add(self)
        db.session.commit()

    def delete(self):
        db.session.delete(self)
        db.session.commit()

Y recursos / post.py

from flask import request
from flask_restful import Resource
from http import HTTPStatus
from flask_jwt_extended import jwt_required, get_jwt_identity, jwt_optional

from models.post import Post
from schemas.post import PostSchema

post_schema = PostSchema()
post_list_schema = PostSchema(many=True)


class PostListResource(Resource):

    def get(self):
        posts = Post.get_all_posts()
        return post_list_schema.dump(posts), HTTPStatus.OK

    @jwt_required
    def post(self):
        json_data = request.get_json()
        current_user = get_jwt_identity()
        data, errors = post_schema.load(data=json_data)
        if errors:
            return {'message': "Validation errors", 'errors': errors}, HTTPStatus.BAD_REQUEST

        post = Post(**data)
        post.user_id = current_user
        post.save()

        return post_schema.dump(post), HTTPStatus.CREATED

Intento enviar el siguiente JSON: {"body": "This is some text."} y el error que obtengo es:

Traceback (most recent call last):
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask_restful\__init__.py", line 272, in error_router
    return original_handler(e)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\_compat.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask_restful\__init__.py", line 272, in error_router
    return original_handler(e)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\_compat.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask_restful\__init__.py", line 468, in wrapper
    resp = resource(*args, **kwargs)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask\views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask_restful\__init__.py", line 583, in dispatch_request
    resp = meth(*args, **kwargs)
  File "C:\Users\USER\.virtualenvs\blogposts-QxTRQ3FG\Lib\site-packages\flask_jwt_extended\view_decorators.py", line 108, in wrapper
    return fn(*args, **kwargs)
  File "D:\blogposts\resources\post.py", line 23, in post
    data, errors = post_schema.load(data=json_data)
ValueError: not enough values to unpack (expected 2, got 1)

Por favor ayuda. ¡Gracias!

0
Varun Sharma 21 ene. 2021 a las 18:41

1 respuesta

La mejor respuesta

Debes haber estado siguiendo un doc / tuto desactualizado.

Desde marshmallow 3, solo se devuelve data. Se genera un ValidationError en caso de error.

Cambio

    data, errors = post_schema.load(data=json_data)
    if errors:
        return {'message': "Validation errors", 'errors': errors}, HTTPStatus.BAD_REQUEST

En

    try:
        data = post_schema.load(data=json_data)
    except ValidationError as exc:
        return {'message': "Validation errors", 'errors': exc.messages}, HTTPStatus.BAD_REQUEST
1
Jérôme 21 ene. 2021 a las 18:43