Building a webapp with flask could involve a couple of more advanced topics in Python, Flask and SQLAlchemy
Event and Rollback
Event and rollback are database concepts. With ORM, they are also relevant for the “Model” layer. E.g. I have some code for user registration
@web.route("/register", methods=['GET', 'POST']) def register(): form = RegisterForm(request.form) if request.method == 'POST' and form.validate(): user = User() user.set_attrs(form.data) db.session.add(user) db.session.commit() return render_template('auth/register.html', form=form)
|
Here, SQLAlchemy has secured data consistency with db.session.commit(), however rollback is missing, we may use try for some refactor
@web.route("/register", methods=['GET', 'POST']) def register(): form = RegisterForm(request.form) if request.method == 'POST' and form.validate(): try: user = User() user.set_attrs(form.data) db.session.add(user) db.session.commit() except Exception as e: db.rollback() raise e return render_template('auth/register.html', form=form)
|
Adding db.rollback() will avoid any mistakes caused by db data inconsistency here. It’s a good practice to keep here.
ContextManager and Yield
The code above we can separate into two parts: core and common part
Core Logic
To instantiate a user and save it into the db
user = User() user.set_attrs(form.data) db.session.add(user)
|
Common Part
Basically try, except part, or commit and rollback part
try: db.session.commit() except Exception as e: db.rollback() raise e
|
We can apply contextmanager and yield to rewrite the above logic as below
@contextmanager def auto_commit(db): try: yield db.session.commit() except Exception as e: db.session.rollback() raise e
with auto_commit(db): user = User() user.set_attrs(form.data) db.session.add(user)
|
Inheritance and add to SQLAlchemy
The above code can be gracefully converted to OOP by inheriting SQLAlchemy class
from contextlib import contextmanager
from flask_sqlalchemy import SQLAlchemy
class MySQLAlch(SQLAlchemy): @contextmanager def auto_commit(self): try: yield self.session.commit() except Exception as e: self.session.rollback() raise e
db = MySQLAlch()
|
To use it in the view func:
@web.route("/register", methods=['GET', 'POST']) def register(): form = RegisterForm(request.form) if request.method == 'POST' and form.validate(): with db.auto_commit(): user = User() user.set_attrs(form.data) db.session.add(user) return redirect(url_for('web.login')) return render_template('auth/register.html', form=form)
|
It’s a good example combining multiple advanced topics in Python, Flask and ORM