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.