9.1 鱼豆

我们的鱼书有一个经济系统,在上传一本书的时候,将获取0.5个鱼豆。赠送一个本书的时候,再获取1个鱼豆。索要一本书的时候,消耗一个鱼豆,其中赠送和索要书籍是用户之间鱼豆互相加减,上传的时候是系统赠送。

基于上面的规则,我们来编写赠送鱼书的视图函数。

1.判断当前书籍是否可以加入赠送清单

    1.如果isbn编号不符合规则,不允许添加
    2.如果isbn编号对应的书籍不存在,不允许添加
    3.同一个用户,不能同时赠送同一本书籍
    4.一个用户对于一本书不能既是赠书者,又是索要者
    5.3和4合并成一条,就是一本书必须即不在心愿清单又不在赠书列表里才可以添加

并不是web编程就简单,算法就难,他们都有自己难和简单的地方,对于web编程来说,他不需要算法,数学的支撑。但是需要很强的逻辑思维能力,因为业务一直在变化,需要非常好的抽象能力来适应变化。

models/user.py

    def can_save_to_list(self, isbn):
        """
        判断可以将书籍加入心愿清单
        1.如果isbn编号不符合规则,不允许添加
        2.如果isbn编号对应的书籍不存在,不允许添加
        3.同一个用户,不能同时赠送同一本书籍
        4.一个用户对于一本书不能既是赠书者,又是索要者
        5.3和4合并成一条,就是一本书必须即不在心愿清单又不在赠书列表里才可以添加
        :param isbn:
        :return:
        """
        if not is_isbn_or_key(isbn):
            return False

        yushu_book = YuShuBook()
        yushu_book.search_by_isbn(isbn)
        if not yushu_book.first:
            return False

        gifting = Gift.query.filter_by(uid=self.id, isbn=isbn, launched=False).first()
        wishing = Wish.query.filter_by(uid=self.id, isbn=isbn, launched=False).first()
        return not wishing and not gifting

之所以要把这个逻辑判断方法加在models里而不是在form里,是因为编程是活的,要视情况而定,这个can_save_to_list加载models在使用起来更加灵活,复用性更强。

2.添加赠送清单,增加鱼豆

添加赠送清单,增加鱼豆对应了两个数据库操作,如果其中一个在执行过程中失败了,那么另一个也不能提交,这用到了数据库的事务。 给用户添加鱼豆需要获取当前用户,我们可以从flask_login的current_user获取当前用户

@web.route('/gifts/book/<isbn>')
@login_required
def save_to_gifts(isbn):
    if current_user.can_save_to_list(isbn):
        try:
            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)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e
    else:
        flash("这本书以添加进您的赠送清单或已经存在于您的心愿清单,请不要重复添加")
    return redirect(url_for('web.book_detail', isbn=isbn))

3.添加心愿清单

web/wishs.py

@web.route('/wish/book/<isbn>')
@login_required
def save_to_wish(isbn):
    if current_user.can_save_to_list(isbn):
        with db.auto_commit():
            wish = Wish()
            wish.isbn = isbn
            wish.uid = current_user.id

            db.session.add(wish)
    else:
        flash("这本书以添加进您的赠送清单或已经存在于您的心愿清单,请不要重复添加")
    return redirect(url_for('web.book_detail', isbn=isbn))

4.巧用ajax

上面我们在添加赠送书籍完成之后,由重定向回了书籍详情页面。由于我们之前就是在数据详情页面,做了一次操作以后又重定向回去了,这样的操作时非常浪费服务器资源的。我们可以用ajax异步请求来改善这个问题。

另一个消耗服务器性能的点在于书籍详情页面的模板渲染工作,所以另一种优化方案,就是将页面作为一个静态页面缓存起来,下一次重定向只需要将缓存的页面读取出来返回即可

Last updated