我们的鱼书有一个经济系统,在上传一本书的时候,将获取0.5个鱼豆。赠送一个本书的时候,再获取1个鱼豆。索要一本书的时候,消耗一个鱼豆,其中赠送和索要书籍是用户之间鱼豆互相加减,上传的时候是系统赠送。
1.如果isbn编号不符合规则,不允许添加
2.如果isbn编号对应的书籍不存在,不允许添加
3.同一个用户,不能同时赠送同一本书籍
4.一个用户对于一本书不能既是赠书者,又是索要者
5.3和4合并成一条,就是一本书必须即不在心愿清单又不在赠书列表里才可以添加
并不是web编程就简单,算法就难,他们都有自己难和简单的地方,对于web编程来说,他不需要算法,数学的支撑。但是需要很强的逻辑思维能力,因为业务一直在变化,需要非常好的抽象能力来适应变化。
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在使用起来更加灵活,复用性更强。
添加赠送清单,增加鱼豆对应了两个数据库操作,如果其中一个在执行过程中失败了,那么另一个也不能提交,这用到了数据库的事务。 给用户添加鱼豆需要获取当前用户,我们可以从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))
@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))
上面我们在添加赠送书籍完成之后,由重定向回了书籍详情页面。由于我们之前就是在数据详情页面,做了一次操作以后又重定向回去了,这样的操作时非常浪费服务器资源的。我们可以用ajax异步请求来改善这个问题。