2017-03-16 59 views
1

我正在使用Flask制作一个小型的网络应用程序。我需要在这个应用程序中执行CRUD操作。我的主要问题是如何以适当和“性感”的方式实施“删除”操作。我原本可以用“GET”方法实现“删除”操作。但是在阅读了一堆文件后,我发现这并不是一个好的方法。用Flask和JQuery,如何用“性感”方式通过“POST”方法删除记录?

所以我尝试了一些解决方案,以实现 “删除” 操作与 “POST” 方法,最后我用下面的代码:

HTML

{% block mainbody %} 
<div class="container"> 
    <div class="page-header"> 
     <h3>{{ _('User Setting') }}</h3> 
    </div> 

    <fieldset> 
     <legend><label>{{ _('Article Category') }}</label></legend> 
     <table class="col-md-offset-2 col-md-8"> 
      <tbody> 
       {% for article_category in article_categories %} 
       <tr> 
        <td>{{ article_category.name }}</td> 
        <td width="30px"><a href="{{ url_for('user.edit_article_category', id=article_category.id) }}"><span class="glyphicon glyphicon-pencil"></span></a></td> 
        <td width="30px"><a href="#" data-record-url="{{ url_for('user.delete_article_category', id=article_category.id) }}" data-record-title="{{ article_category.name }}" data-toggle="modal" data-target="#confirm-delete-modal"><span class="glyphicon glyphicon-trash"></span></a></td> 
       </tr> 
       {% endfor %} 
       <tr> 
        <td><a href="{{ url_for('user.add_article_category') }}" class="btn" style="margin-top:10px"><span class="glyphicon glyphicon-plus"></span> {{ _('Create New Article Category') }}</a></td> 
       </tr> 
      </tbody> 
     </table> 
    </fieldset> 
</div> 

<div class="modal fade" id="confirm-delete-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> 
    <div class="modal-dialog"> 
     <div class="modal-content"> 
      <div class="modal-header"> 
       <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> 
       <h4 class="modal-title">{{ _('Confirm Delete') }}</h4> 
      </div> 
      <div class="modal-body"> 
       <p>{{ _('You are about to delete this record:') }} <strong><span id="deleted-content"></span></strong>, {{ _('the procedure is irreversible') }}.</p> 
       <p>{{ _('Do you want to proceed?') }}</p> 
      </div> 
      <div class="modal-footer"> 
       <button type="button" class="btn btn-default" data-dismiss="modal">{{ _('Cancel') }}</button> 
       <button type="button" class="btn btn-danger btn-ok">{{ _('Delete') }}</button> 
      </div> 
     </div> 
    </div> 
</div> 

<script type=text/javascript src="{{ url_for('static', filename='js/jquery-3.1.1.min.js') }}"></script> 
<script> 
    $(document).ready(function() { 
     var csrf_token = "{{ csrf_token() }}"; 
     $.ajaxSetup({ 
      beforeSend: function(xhr, settings) { 
       if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) { 
        xhr.setRequestHeader("X-CSRFToken", csrf_token); 
       } 
      } 
     }); 
     $('#confirm-delete-modal').on('click', '.btn-ok', function(e) { 
      var recordUrl = $(this).data('recordUrl'); 
      $.post(recordUrl, function(data) { 
       console.log(data); 
      }); 
      $('#confirm-delete-modal').modal('hide'); 
     }); 
     $('#confirm-delete-modal').on('show.bs.modal', function(e) { 
      var recordTitle = $(e.relatedTarget).data('recordTitle'); 
      var recordUrl = $(e.relatedTarget).data('recordUrl'); 
      $(e.currentTarget).find('#deleted-content').text(recordTitle); 
      $(e.currentTarget).find('.btn-ok').data('recordUrl', recordUrl); 
     }); 
     $('#confirm-delete-modal').on('hidden.bs.modal', function() { 
      location.reload(false); 
     }); 
    }); 
</script> 
{% endblock %} 

@user.route("/setting/article-category/<int:id>/delete", methods=["POST"]) 
@login_required 
def delete_article_category(id): 
    deleting_article_category = ArticleCategory.get(ArticleCategory.id == id) 
    deleting_article_category.delete_instance() 
    return redirect(url_for("user.setting")) 

上面的代码确实有效,但至少有两个缺点。

  1. /user/setting (url_for("user.setting"))页面内容被传送两次。第一次是Flask代码return redirect(url_for("user.setting"))。第二次是JQuery代码location.reload(false)。看起来这两个代码段是重复的。但我无法删除其中的任何一个。如果我删除了JQuery代码,/user/setting (url_for("user.setting"))页面在我确认了模式并且真的从数据库中删除了记录后,无法自动刷新,这意味着删除的项目看起来仍然停留在那里,直到我手动刷新页面。这当然是我应该避免的不一致的结果。如果我删除了Flask代码return redirect(url_for("user.setting"))或将其更改为return Null,我将从服务器收到500错误。尽管实际上记录仍然可以被删除,但我可以从Chrome的Javascript控制台捕获此错误。我不能忍受这一点。
  2. JQuery代码location.reload(false)将下载很多支持的东西,比如bootstrap.css,bootstrap.js,logo.png,而不是纯html文件。即使我已经使用false参数来要求它试图从浏览器的缓存中找到这些东西。

由于上述两个缺点,我认为我的代码效率太低。谁可以帮助我改进我的代码?

通过使用console.log(data),我注意到Flask代码return redirect(url_for("user.setting"))已经导致JQuery的$.post()操作获取反馈数据中的新页面内容。新的页面内容非常正确,这意味着已删除的记录不再在那里列出。但是没有页面刷新机制可以使用这个正确的数据。我认为这是导致低效率的关键。

我在想,Flask应该提供一些简单的方法来安全删除数据库记录。只是一个删除操作,比编辑或添加复杂得多。是否因为我不知道如何使用Form来实现它,或者有其他理由让删除操作过于困难?我是初学者,所以也许我的想法是错误的。

有没有一些建议给我?谢谢!

更新数据包捕获工具 - Charles屏幕截图: enter image description here

+1

Ahaha打死我 – DanielPanic

+0

我的“性感”是指全的功能,但没有任何额外的代码和数据流。 (苗条的身材没有任何额外的脂肪:)) – urbainy

+0

为什么不使用HTTP DELETE方法? – leovp

回答

2

其实你并不需要发送完整的网页中返回删除请求。空HTTP 204响应这种请求的标准返回值:

def delete_article_category(id): 
    deleting_article_category = ArticleCategory.get(ArticleCategory.id == id) 
    deleting_article_category.delete_instance() 
    return Response(status=204) 

您不必担心清爽页面所有静态文件是通过其浏览器的缓存了。当然,除非你使用location.reload(true)。检查你的应用程序的日志:最有可能是静态文件与HTTP 304码(未修改)是这样的:

127.0.0.1 - - [16/Mar/2017 10:10:10] "GET /static/admin/bootstrap/bootstrap3/css/bootstrap.min.css?v=3.3.5 HTTP/1.1" 304 - 
+0

我验证了你的答案。你的解决方案'返回Response(status = 204)'确实解决了我的重新传输数据问题。非常感谢!虽然我仍然不清楚静态文件重新传输的事实。尽管HTTP 304代码指示请求数据没有修改,但似乎服务器仍然将数据作为数据包捕获工具传输 - “Charles”进行监控。它只是“看起来像”,但没有真正的转移,或者我无法避免,所以我需要忽略它? – urbainy

+0

@urbainy我纠正你的服务器发送304响应静态和内容?这很奇怪:304响应不能包含消息体。也许你的捕捉工具显示它以前收到的内容。我在Firefox开发工具中有相同的行为:带有静态的数据包显示为“缓存”,但我仍然可以查看其内容。 –

+0

正如您所说,服务器确实会显示大量304消息。虽然'查尔斯'显示数据包真正发送和接收时间戳,持续时间和数据包大小的统计数据。我会尝试在我的原始文章中粘贴屏幕截图以供您检查。 – urbainy