2016-02-23 161 views
1

我正在开发一个Flask应用来管理一个库。我遇到的其中一个问题与添加新书有关。在很多情况下,有“作者碰撞”;基本上是一本以“约翰·史密斯”为作者的书,然后另一本以“约翰·史密斯”为作者的书被添加到数据库中。第一本书的作者“约翰史密斯”是否与第二本书的作者一样是“约翰史密斯”?交互式Flask提示

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

我在想我应该做的是在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) 

回答

0

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

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

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

这是表示在本基础的优秀的视频,与用于代码回购: https://www.youtube.com/watch?v=L5YQbNrFfyw

+0

的问题是,碰撞AREN直到表单提交后才能检测到。我对AJAX不太熟悉,如果给出一个与作者匹配的书籍的JSON对象,它可以在输入时检测到冲突吗?你会怎么做呢? – BrotherJack

+0

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

+0

这听起来像个好主意。我会认为这是一个答案,如果你只是将以前的评论放入你的答案,我会选择它。如果这不被认为是“太宽泛”:| – BrotherJack

0

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