9.2 contextmanager

1.contextmanager简单讲解

contextmanager可以简化上下文管理器,不需要我们编写__enter__和__exit__函数。他给了我们一个机会,让我们把之前一个不是上下文管理器的类变成一个上下文管理器,而不需要我们去修改这个类的源代码

其中的yield的作用,是中断当前函数执行流程,先去执行yield出去的部分的代码执行流程

下面的代码的作用,在书籍前后自动加上《》

@contextmanager
def book_mark():
    print('《', end='')
    yield
    print('》', end='')


with book_mark():
    print('钢铁',end='')

2.结合继承,contextmanager,yield,rollback来简化try-except的数据库事务代码

1.我们可以通过contextmanager实现一个上下文管理器,将try-except的代码放在contextmanager里,将具体的业务逻辑代码yield出去 2.SQLAlchemy并没有这个上下文管理器,但是我们可以做一个子类,来扩展他的功能 3.编写子类的时候,命名是非常不好起的,我们可以改变父类的名字,给子类命名为原父类的名字

models/base.py

from flask_sqlalchemy import SQLAlchemy as _SQLAlcmemy

class SQLAlchemy(_SQLAlcmemy):
    @contextmanager
    def auto_commit(self):
        try:
            yield
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e

使用auto_commit的save_to_gifts视图函数

@web.route('/gifts/book/<isbn>')
@login_required
def save_to_gifts(isbn):
    if current_user.can_save_to_list(isbn):
        with db.auto_commit():
            gift = Gift()
            gift.isbn = isbn
            gift.uid = current_user.id

            current_user.beans += current_app.config['BEANS_UPLOAD_ONE_BOOK']

            db.session.add(gift)
            db.session.add(current_user)
    else:
        flash("这本书以添加进您的赠送清单或已经存在于您的心愿清单,请不要重复添加")
    return "aaa"

使用auto_commit的register视图函数

@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)

干货:

1.遇到比较复杂的问题,应该把他单独的分离出来,在一个单独的文件里来编写一些非常简单的源码,因为业务越简单,越能够让我们去关注知识和原理本身的相关问题。 2.高级编程不是在于学习更高级的语法(学会更好),更关键的在于能够用自己所学的知识,写出更好的代码来 3.对知识的综合运用能力很重要,将单个的知识点组合在一起写出一段很好的代码来

Last updated