Как мое приложение Flask может проверить, выполняется ли транзакция SQLite3?

#sqlite #flask #error-handling #transactions

Вопрос:

Я пытаюсь создать несколько интеллектуальных сообщений об ошибках с помощью функции @app.errorhandler (500). Например, мой маршрут включает команду ВСТАВКИ в базу данных:

 if request.method == "POST":
   userID = int(request.form.get("userID"))
   topicID = int(request.form.get("topicID"))
   db.execute("BEGIN TRANSACTION")
   db.execute("INSERT INTO UserToTopic (userID,topicID) VALUES (?,?)", userID, topicID)
   db.execute("COMMIT")
 

Если эта транзакция нарушает ограничение, такое как УНИКАЛЬНЫЙ или ВНЕШНИЙ ключ, я хочу поймать ошибку и отобразить удобное для пользователя сообщение. Для этого я использую Flask @app.errorhandler следующим образом:

 @app.errorhandler(500)
def internal_error(error):
    db.execute("ROLLBACK")
    return render_template('500.html'), 500
 

Команда «ОТКАТ» отлично работает, если я нахожусь в середине транзакции базы данных. Но иногда ошибка 500 не связана с базой данных, и в этих случаях сам оператор ОТКАТА вызывает ошибку, потому что вы не можете откатить транзакцию, которая никогда не запускалась. Поэтому я ищу метод, который возвращает логическое значение, которое было бы истинным, если выполняется транзакция бд, и ложным, если нет, поэтому я могу использовать его, чтобы сделать откат условным. Единственное, что я могу найти в документации SQLite3, — это интерфейс C, и я не могу заставить его работать с моим кодом Python. Есть какие-нибудь предложения?

Я знаю, что если я буду достаточно осторожен со своими формами и маршрутами, я смогу предотвратить 99% потенциальных нарушений правил БД. Но я все равно хотел бы, чтобы умный ловец ошибок защитил меня от остальных 1%.

Ответ №1:

Я не знаю, как работает транзакция в sqlite, но то, что вы пытаетесь сделать, вы можете достичь с помощью операторов try/except

  1. используйте try/за исключением внутри функции
 try:
    db.execute("ROLLBACK")
except:
    pass
return render_template('500.html'), 500
 
  1. Используйте try/за исключением случаев, когда вставляете данные.
 from flask import abort
try:
    userID = int(request.form.get("userID"))
    [...]
except:
    db.rollback()
    abort(500)
 

Я не знаком с ошибками sqlite, если вы знаете, какая конкретная ошибка возникает, за исключением этой конкретной ошибки.