Я пишу некоторый тест для REST API, связанного с MySQL db с помощью python + werkzeug + SQLalchemy, одним из тестов является попытка добавить "объект" с первичным ключом, отсутствующим в json, и проверить, что он терпит неудачу и не работает Вставьте что-нибудь в БД. Он отлично работал с sqlite, но я переключился на MySQLdb, и теперь я получаю FlushError (вместо IntegrityError, который я использовал для улова), и когда я пытаюсь откат после ошибки, он не вызывает никаких ошибок, но запись в база данных с первичным ключом, установленным в ''. Код выглядит так:
session = Session()
try:
res = func(*args, session=session, **kwargs)
session.commit()
except sqlalchemy.exc.SQLAlchemyError as e:
session.rollback()
return abort(422)
else:
return res
finally:
session.close()
И вот ошибка, которую я уловил во время try/except:
class 'sqlalchemy.orm.exc.FlushError': экземпляр имеет NULL идентификационный ключ. Если это автоматически сгенерированное значение, убедитесь, что таблица базы данных позволяет генерировать новые значения первичного ключа и что сопоставленный объект столбца настроен так, чтобы ожидать эти сгенерированные значения. Также убедитесь, что этот сброс() не происходит в неподходящее время, например, в событии load().
Я просто прочитал документацию о сеансе SQLalchemy и функции отката, но не понимаю, почему откат не работает для меня, поскольку это почти пример учебника из документации.
Я использую Python 2.7.13, werkzeug '0.12.2', sqlalchemy '1.1.13' и MySQLdb '1.2.3' и mysql Ver 14.14. Распространение 5.1.73!
Спасибо за вашу помощь
Похоже, проблема заключалась только в MYSQL: по умолчанию строгий режим не активирован и разрешает неверную вставку/обновление вносить изменения в базу данных (wtf?), Решение заключается в изменении sql_mode или глобально: MySQL: настройка sql_mode постоянно
Или в SQLalchemy, как описано в этом сообщении в блоге: https://www.enricozini.org/blog/2012/tips/sa-sqlmode-traditional/