我被以下错误所吸引:
TypeError: Object of type 'Menu' is not JSON serializable
毕竟,当我转到端点'/users'
时,数据已经存在,并进行了序列化:
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"
}
]
}
但是当我转到路由'/edit_menu'
时,应用程序视图因上面的序列化错误而中断。下面我显示了相关代码:
表格:
1)用户(正在序列化)
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)菜单(第二个请求后未序列化 )
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]}
回溯指向我的Flask视图中的错误:
File "/usr/src/app/project/api/routes/menus.py", line 192, in **edit_menu**
正在调用“菜单”的地方(此处可能是关键代码):
@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
这是被称为的数据库方法:
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}
完整追溯:
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
注意:第一个请求正在运行。仅从第二个请求开始,问题就会出现。
我在这里想念什么?
答案 0 :(得分:6)
在您路线中的else语句中,创建一个包含response_object
的{{1}},但是此值从未被序列化,因此,它实际上是类型{ 'menu': user.menu }
的实例。
这可能是第一次全部起作用,因为在调用Menu
之前分配了user.menu
,所以返回值为Create_or_Update_Menu
,该值是可序列化的。第二次实际定义None
,这就是发生错误的原因。
此外,您有两个条件相同的if语句,但是如果第一个为true,则始终返回。因此,第二条if语句中的代码永远不会执行。