I'm intrigued by the following error I'm getting:
TypeError: Object of type 'Menu' is not JSON serializable
after all, when I go to my endpoint '/users'
, the data is there, serialized:
menu: [
{
id: 1,
created: "2019-06-24T22:24:50.811520",
items: [
{
id: 1,
name: "pasta",
created: "2019-06-24T22:24:50.850468"
},
{
id: 2,
name: "burger",
created: "2019-06-24T22:25:25.828976"
}
]
}
but the app view breaks with the serialize error above when I go to route '/edit_menu'
. Below I show the relevant code:
tables:
1) users (which is serializing)
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
restaurant = db.Column(db.String(128))
menu = db.relationship("Menu",
backref=db.backref('user'),
uselist=True)
def __init__(self, restaurant):
self.restaurant = restaurant
self.username = username
def serialize(self):
return {
'id': self.id,
'username': self.username,
'menu' : [ item.serialize() for item in self.menu],
}
2) Menu (which is not being serialized after second request)
class Menu(db.Model):
__tablename__='menu'
id = db.Column(db.Integer, primary_key=True)
created = db.Column(db.DateTime, default=func.now(), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
dishes = db.relationship('Dish',
back_populates='menu',
uselist=True)
def __init__(self, user):
self.user = user
def serialize(self):
"""Return object data in easily serializeable format"""
return { 'id' : self.id,
'created': self.created.isoformat(),
'dishes' : [ item.serialize() for item in self.dishes]}
traceback points to error at my Flask view:
File "/usr/src/app/project/api/routes/menus.py", line 192, in **edit_menu**
where 'Menu' is being called (CRITICAL CODE PROBABLY HERE):
@menus_bp.route('/edit_menu', methods=['GET', 'POST'])
def edit_menu():
response_object = {
'status': 'fail',
'message': 'Invalid payload.'
}
try:
user = User.query.filter_by(id=1).first()
if user.menu == []:
items = ['item 1', 'item 2', 'item 3', 'item 4',
'item 5', 'item 6', 'item 7', 'item 8']
template = render_template('seeds.html',
items=items)
response_object = {
'status': 'success',
'message': 'No menus yet',
'data': [{"restaurant": user.restaurant,
"seeds": user.seeds,
"content": template}]
}
else:
all = user.serialize()['menu']
items = [i['items']for i in all]
template = render_template('seeds.html',
items=items)
response_object = {
'status': 'success',
'message': 'Ready to add dishes',
'data': [{"restaurant": user.restaurant,
"seeds": user.seeds,
"menu": user.menu,
"content": template}]
}
if request.method == 'POST':
if 'item' in request.form:
add = request.form['item']
Create_or_Update_Menu(user=user)
found_playlist = Playlist.query.join(User, User.id == Playlist.user_id).filter(
and_(Playlist.title == item, User.id == 1)).first()
if not found_playlist:
filtered_tracks = filter_dataset_by_item(add)
Create_Automatic_Playlists(filtered_dataset=filtered_tracks)
return jsonify(response_object), 200
if request.method == 'POST':
if 'item2' in request.form:
add = request.form['item2']
Create_or_Update_Menu(user=user)
found_playlist = Playlist.query.join(User, User.id == Playlist.user_id).filter(
and_(Playlist.title == item, User.id == 1)).first()
if not found_playlist:
filtered_tracks = filter_dataset_by_item(add)
Create_Automatic_Playlists(filtered_dataset=filtered_tracks)
return jsonify(response_object), 200
except (exc.IntegrityError, ValueError):
db.session.rollback()
return response_object, 400
and this is the database method being called:
def Create_and_Update_Menu(user, dish):
if user.menu == []:
menu = Menu(user=user)
db.session.add(menu)
db.session.commit()
else:
menu = Menu.query.filter_by(user=user).first()
Dish = Dish(dish=dish)
db.session.add(dish)
menu.dishes.append(dish)
db.session.commit()
print ('MENU SERIAL',menu.serialize())
return {"status": True}
Full traceback:
web_1 | Traceback (most recent call last):
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
web_1 | return self.wsgi_app(environ, start_response)
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
web_1 | response = self.handle_exception(e)
web_1 | File "/usr/lib/python3.6/site-packages/flask_restful/__init__.py", line 269, in error_router
web_1 | return original_handler(e)
web_1 | File "/usr/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function
web_1 | return cors_after_request(app.make_response(f(*args, **kwargs)))
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
web_1 | reraise(exc_type, exc_value, tb)
web_1 | File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
web_1 | raise value
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
web_1 | response = self.full_dispatch_request()
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
web_1 | rv = self.handle_user_exception(e)
web_1 | File "/usr/lib/python3.6/site-packages/flask_restful/__init__.py", line 269, in error_router
web_1 | return original_handler(e)
web_1 | File "/usr/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function
web_1 | return cors_after_request(app.make_response(f(*args, **kwargs)))
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
web_1 | reraise(exc_type, exc_value, tb)
web_1 | File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
web_1 | raise value
web_1 | File "/usr/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
web_1 | rv = self.dispatch_request()
web_1 | File "/usr/lib/python3.6/site-packages/flask_debugtoolbar/__init__.py", line 125, in dispatch_request
web_1 | return view_func(**req.view_args)
web_1 | File "/usr/src/app/project/api/routes/menus.py", line 195, in edit_menu
web_1 | return jsonify(response_object), 200
web_1 | File "/usr/lib/python3.6/site-packages/flask/json/__init__.py", line 321, in jsonify
web_1 | dumps(data, indent=indent, separators=separators) + '\n',
web_1 | File "/usr/lib/python3.6/site-packages/flask/json/__init__.py", line 179, in dumps
web_1 | rv = _json.dumps(obj, **kwargs)
web_1 | File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps
web_1 | **kw).encode(obj)
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 201, in encode
web_1 | chunks = list(chunks)
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 430, in _iterencode
web_1 | yield from _iterencode_dict(o, _current_indent_level)
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
web_1 | yield from chunks
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
web_1 | yield from chunks
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
web_1 | yield from chunks
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
web_1 | yield from chunks
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 437, in _iterencode
web_1 | o = _default(o)
web_1 | File "/usr/lib/python3.6/site-packages/flask/json/__init__.py", line 81, in default
web_1 | return _json.JSONEncoder.default(self, o)
web_1 | File "/usr/lib/python3.6/json/encoder.py", line 180, in default
web_1 | o.__class__.__name__)
web_1 | TypeError: Object of type 'Menu' is not JSON serializable
Note: the first request is working. only from the second request on, the issue appears.
What am I missing here?
In the else statement in your route, you create a response_object
that contains { 'menu': user.menu }
, but this value is never serialized, so this literally is an instance of type Menu
.
Probably the first time this all works because user.menu
is assigned before calling Create_or_Update_Menu
, so the return value is None
, which is serializable. The second time, user.menu
is actually defined, and that's why the error occurs.
Additionally, you have two if statements with the same condition, but if the first is true, then you always return. Thus, the code in the second if statement is never executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With