简体   繁体   中英

TypeError: cannot unpack non-iterable object

I'm getting "TypeError: cannot unpack non-iterable User object" when doing a post command to my flask app. I managed to manually add user to the DB. When I'm trying to create another user using the post endpoint, I'm getting the correct validation error that the email exists. But when I'm trying to post a new one, I'm getting the error: TypeError: cannot unpack non-iterable User object

I'm using Python 3.7.4 Flask 1.1.1 flask-marshmallow 0.10.1

This is my model:

class User(db.Model, UserMixin):
__tablename__ = "user"
__table_args__ = {'extend_existing': True} 


id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), index=True, unique=True, nullable=False)
password = db.Column(db.String(128), nullable=False)
stride_account_id = db.Column(db.Integer, db.ForeignKey('stride_account.id'),
                           nullable=True)



def __repr__(self):
    return '<User {} with password {}>'.format(self.email, self.password)

def set_password(self, password):
    self.password = bcrypt.generate_password_hash(password)

def check_password(self, password):
    return bcrypt.check_password_hash(self.password, password)


def generate_auth_token(self):
    """ Create a jwt token for the user to access the api """
    session_exp = datetime.utcnow() + timedelta(minutes=15)
    if current_app.config['APP_CONFIG'] != 'config.Production':
        session_exp = datetime.utcnow() + timedelta(hours=12)
    payload = {
        'sub': self.id,
        'iat': datetime.utcnow(),
        'exp': session_exp
    }
    token = jwt.encode(payload, current_app.config['SECRET_KEY'])
    return token.decode('unicode_escape')

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

This is the schema:

class UserSchema(ma.ModelSchema):

email = field_for(User, 'email', required=True, 
    validate=[
    must_not_be_blank,
    validate.Email(),
    validators.validate_email]
)

password = field_for(User, 'password', required=True,
    validate=[
    must_not_be_blank,
    validators.validate_password]   
)

class Meta:
    model = User
    load_only = ('password',)

My view

lass UserView(Resource):

def get(self):
    user = User.query.filter(id='1')
    return 'Hello World'

@data_required
def post(self):
    data = request.get_json()#json.loads(request.data)
    print('data is: ', data)

    user, errors =  serializers.UserSchema().load(data)
    print('Hoooraaay')
    # user = User(email=data['email'], password=data['password'])
    user.set_password(user.password)
    user.save()  

    return serializers.UserSchema().jsonify(user)  

The full error message is:

[2019-09-28 17:36:35,465] ERROR in app: Exception on /api/user [POST]
Traceback (most recent call last):
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask_restful/__init__.py", line 458, in wrapper
    resp = resource(*args, **kwargs)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/Users/ronshteinberg/development/stride-core/app/decorators.py", line 13, in wrapped_view
    return view(*args, **kwargs)
  File "/Users/ronshteinberg/development/stride-core/app/accounts/views.py", line 20, in post
    user, errors =  serializers.UserSchema().load(data)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/marshmallow_sqlalchemy/schema.py", line 214, in load
    return super().load(data, **kwargs)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/marshmallow/schema.py", line 720, in load
    data, many=many, partial=partial, unknown=unknown, postprocess=True
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/marshmallow/schema.py", line 898, in _do_load
    raise exc
marshmallow.exceptions.ValidationError: {'email': ['Email already exist']}
127.0.0.1 - - [28/Sep/2019 17:36:35] "POST /api/user HTTP/1.1" 500 -
data is:  {'email': 'sssss@aa.com', 'password': 'Qwert12345'}
[2019-09-28 17:36:40,644] ERROR in app: Exception on /api/user [POST]
Traceback (most recent call last):
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask_restful/__init__.py", line 458, in wrapper
    resp = resource(*args, **kwargs)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/ronshteinberg/env/stride/lib/python3.7/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/Users/ronshteinberg/development/stride-core/app/decorators.py", line 13, in wrapped_view
    return view(*args, **kwargs)
  File "/Users/ronshteinberg/development/stride-core/app/accounts/views.py", line 20, in post
    user, errors =  serializers.UserSchema().load(data)
TypeError: cannot unpack non-iterable User object

Thanks in advance

SO related above and the same issue:

in previous versions of

flask-sqlachemy OR flask-marshmallow

load function were returned 2 values

user, errors =  serializers.UserSchema().load(data)

after some updates in this source packages it started return one value, so to fix it you need to assign 1 value for response:

user =  serializers.UserSchema().load(data)

correct way to handle validation errors:

        try:
            obj = schema.load(data)
        except ValidationError as error:
            print(error.messages)

I found the issue. The code was copied from someplace and it seems that serializers.UserSchema().load(data) doesn't return a tuple,just the object So the line should be:

user =  serializers.UserSchema().load(data)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM