交互式烧瓶提示

时间:2016-02-23 20:25:09

标签: python rest flask interactive

我正在使用Flask应用来管理图书馆。我遇到的一个问题与添加新书有关。在许多情况下,存在“作者碰撞”;本书中添加了一本带有“John Smith”的书,然后添加了另一本以“John Smith”作为作者的书籍添加到数据库中。第一本书的作者“约翰史密斯”是否与第二本书的作者“约翰史密斯”相同?

我对此问题的解决方案是使用模态对话框,其中向用户呈现作者姓名形式的“作者碰撞”,以及当前在数据库中归属于所述作者的书籍列表。问题是我不知道如何实现这一点。我的第一个想法是重定向到另一个页面,用户将在新页面中回答这些问题。问题在于,这需要一些看似不合时宜的设计,比如保存状态数据(用户已经输入的其余书籍元数据)。

我在想我应该做的是在LoanBook(MethodView)中实现某种“Post方法”,产生一系列模态对话框(每个作者碰撞一个,因为书籍可以有多个作者),提交只有当每个碰撞都用“是”或“否”解决时。

理想情况下,我希望能够暂停Post方法(在标记为# ??? yield ???的位置),等待用户的响应,然后根据响应运行代码。然后在必要时重复。我不知道是否有一些Flask扩展或方法使这成为可能,或者甚至可能。我应该采取另一种方法吗?有没有人有任何建议?

class LoanBook(MethodView):
    decorators = [login_required]
    form = None

    def __init__(self):
        self.book = None
        self.form = self.prep_form()

    @permissions_required(Permission.CHECK_OUT_BOOK)
    def get(self):
        return render_template("library/loan_book.html", form=self.form)

    @permissions_required(Permission.CHECK_OUT_BOOK)
    def post(self):        
        if self.form.validate_on_submit():
            if self.form.fill_ISBN.data:
                # User has hit the fill data from ISBN button
                pass
            else:
                try:
                    self.__make_book__()
                    db.session.add(self.book)
                    db.session.commit()
                except InvalidRequestError:
                    db.session.rollback()
                    db.session.flush()
                    flash(FlashMessage.not_saved, FlashMessage.failure)
                else:
                    auths = None
                    if len(loanedBook.authors) > 1:
                        auths = oxford_commatize(
                                [a.full_name() for a in loanedBook.authors]
                            )
                    else:
                        auths = loanedBook.authors[0].full_name()
                    flash(
                        FlashMessage.saved.format(loanedBook.title, auths), 
                        FlashMessage.failure
                    )
                return redirect(url_for("library.main"))
        elif self.form.author_collisions:
            uri_auth = []
            for auth in self.form.author_collisions:
                # ??? yield ???
            self.__make_book__()
            db.session.add(self.book)
            db.session.commit()
        else:
            flash_errors(self.form)
        return render_template("library/loan_book.html", form=self.form)

2 个答案:

答案 0 :(得分:0)

尝试在服务器端的连续操作之间进行用户干预,您将不会取得多大成功。可以将这些冲突检测为初始页面的异步组件的API,以便用户在提交到此端点之前解析它们可能是最好的。

答案 1 :(得分:0)

这不能单独在Flask中完成,除非,正如你所说,你得到一点RESTless ......但是一种方法是预先保存数据并返回第一次碰撞的页面,其中包含你的记录的标识符在创造过程中。当输入作者的名字时,我会在一些AJAX或者一个websocket连接中加入一个加载了页面另一个区域(div)的碰撞 - 如果你对完全无状态感到害怕:)

我会使用websockets(实际上,socket.io是一个更实用的websockets包装器),当用户输入作者姓名时,会在请求中触发一个JavaScript事件。然后可以使用来自websocket的JSON响应来填充页面上的区域,并且可以在那里选择任何匹配的结果。在服务器端使用flask-socketio;文档中有一个JavaScript示例,可以让您在浏览器端启动。

Flask-SocketIO的文档可以在这里找到: http://flask-socketio.readthedocs.org/en/latest/

这是一个很棒的视频,展示了这个的基础知识,以及所用代码的回购: https://www.youtube.com/watch?v=L5YQbNrFfyw