2

I'm using Flask 1.0, Flask-SqlAlchemy 2 and Angular 7.

When SqlAlchemy throws an error I want to show a tailored error message in the frontend.

There is a section in the official Flask documentation about how to handle errors and also a similar question here on SO, that is related to Flask-Restless though. And yet I'm not able to connect the dots.

When SqlAlchemy throws an error, it looks something like this:

DETAIL:  Key (id)=(123) is not present in table "foo".

I'm returning the error to the route:

try:
    db.session.commit()
except Exception as error:
    db.session.flush()
    db.session.rollback()
    return error

In the route I'm checking if it is an error:

if status == True:
    return jsonify( { "success": True } ), 201
else:
    return error_response(500, str(status))

And my error_response class looks like this:

def error_response(status_code, message=None):
    payload = {"error": HTTP_STATUS_CODES.get(status_code, "Unknown error")}
    if message:
        payload["message"] = message
        response = jsonify(payload)
        response.status_code = status_code
    return response

But the response json just contains a generic error message:

"message": "Http failure response for http://127.0.0.1:5000/database/add_foo: 0 Unknown Error"

2 Answers 2

3

You can read the error object and create your own custom message out of it. for all details try printing error.\__dict__ in console.

erro.__dict__

for example:

from sqlalchemy import create_engine
from sqlalchemy import MetaData
from sqlalchemy import Table
from sqlalchemy import Column
from sqlalchemy import Integer, String

db_uri = 'sqlite:///'
engine = create_engine(db_uri)
conn = engine.connect()

# Create a metadata instance
meta = MetaData(engine)
table = Table('user', meta,
   Column('id', Integer, primary_key=True),
   Column('l_name', String),
   Column('f_name', String))
meta.create_all()
# Insert Data
conn.execute(table.insert(),[
   {'id':1,'l_name':'Hi','f_name':'bob'},
   {'id':2,'l_name':'Hello','f_name':'john'},
   {'id':3,'l_name':'yo','f_name':'bob-john'}])

result =conn.execute("SELECT * FROM user")
for res in result:
  print(res)
# Intensionally violating unique constraint
try:
  ins = table.insert().values(
      id=3,
      l_name='Hello',
      f_name='World')
# conn = engine.connect()
  conn.execute(ins)
except Exception as error:
  print(str(error.orig) + " for parameters" + str(error.params))

output will be :-

Custom Exception Message

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your help. It took me a while to figure why your solution didn't work for me (see below). Anyhow I'm sure it's helpful for other readers, so it's really appreciated!
0

Turns out the error was returned when I tried to do a bulk save:

db.session.bulk_save_objects(companies_to_add, return_defaults = True)

I was under the impression that an error would just be raised when performing either

db.session.commit()

or

db.session.flush()

Apparantly I was wrong. I now put the bulk save in a try block:

try:
    db.session.bulk_save_objects(companies_to_add, return_defaults = True)
except Exception as error:
    db.session.rollback()
    return error

Now I'm able to catch the error in the frontend.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.