Использование 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()
Этот метод позволяет очень легко и визуально создавать остальные API, используя модели SQLalchemy.
return jsonify(result=True, id=id, page=model_Page.query.get(id))