При использовать в проекте flask-restful удобно и необходимо возвращать в качестве результатов запросов объекты формируемые sqlalchemy моделями. Но есть одна проблема, так как очень часто эти модели содержат слишком много всяких дополнительных свойств, то встроенный сериализатор не справляется и ругается словами
is not JSON serializable
Проблема решается путём переопределения встроенного сериализатора Flask, а делается это вот так:
среди атрибутов приложения есть свойство указывающее на класс сериализатора Json, нам остаётся лишь взять базовый класс, переопределить его возможности обработкой своих типов и передать на исполнение в приложение (ниже общая схема)
from flask.json import JSONEncoder
class CustomJSONEncoder(JSONEncoder):
def default(self, obj):
# обработка собственных типов
if isinstance(obj, мои типы):
....
# стандартная обработка
return JSONEncoder.default(self, obj)app.json_encoder = CustomJSONEncoder
Чтобы научить сериализатор обрабатывать объекты sqlalchemy необходимо использовать следующую конструкцию
from sqlalchemy.ext.declarative import DeclarativeMeta
class CustomJSONEncoder(JSONEncoder):
def default(self, obj): if isinstance(obj.__class__, DeclarativeMeta):
# обрабатываем объект sqlalchemyfields = {}
obj_dict = obj.__dict__
for field in obj.__table__.columns.keys(): # получаем список полей связанной с моделью таблицы
data = obj_dict.get(field) # извлекаем данные по имени поля
try:
json.dumps(data)
fields[field] = data
except TypeError:
fields[field] = None
return fieldsreturn JSONEncoder.default(self, obj)
Собственно метод заключается в преобразование объекта sqlalchemy в обычный словарь, с последующей сериализацией полей словаря, имена которых являются полями таблицы, список которых получаем с помощью метода obj.__table__.columns.keys()
Использование такого метода позволяет очень просто и наглядно формировать rest Api с помощью sqlalchemy моделей
return jsonify(result=True, id=id, page=model_Page.query.get(id))