I've been prototyping an API using starlette with SQLAlchemy and had a question about how to handle DB errors with the databases module.
# SQLAlchemy table definition
class Users(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(length=20), unique=True)
password_hash = Column(String(length=80))
# Endpoint
@validate_schema(CREATE_USER_SCHEMA)
async def create_user(request):
data = await request.json()
query = Users.__table__.insert().values(username=data["username"], password_hash=hash_password(data["password"]))
try:
await database.execute(query)
except exc.IntegrityError:
return JSONResponse({"message": "User already exists."})
return JSONResponse({"message": "Created user."})
When I try to create a user with a username that already exists, violating the UNIQUE constraint specified in the table definition, I receive a sqlite3.IntegrityError: UNIQUE constraint failed: users.username (venv/lib/python3.8/site-packages/aiosqlite/core.py:153: IntegrityError). This is not caught by the code above, which uses sqlalchemy.exc.IntegrityError.
I like to run tests in SQLite, and use Postgres in production; in other APIs I've built (with plain SQLAlchemy), sqlalchemy.exc generally does the trick regardless of the DB backend used.
Q: Is there a good way to catch errors independent of the DB used? For now, I'm catching both the SQLite and Postgres exceptions manually, but I was wondering what best practices for this case would look like using the databases module.
Thanks for creating starlette and databases, and sorry in advance if this is a duplicate.