网址和副作用(Django)

时间:2010-06-27 09:36:22

标签: python django url post django-views

我想知道它是否被认为是好的(特别是在Django中)有一个仅用于具有副作用的动作的URL,这仅用于通过POST访问,并且对用户来说基本上是不可见的。让我们说,为了使这个具体化,我在我的网站上有一个小消息系统,从他们的收件箱,用户应该可以做一些事情,如:

  • 删除信息
  • 将邮件标记为已读
  • 将邮件报告为垃圾邮件

所有这些都会导致页面刷新,但会导致返回同一页面。我想知道如何围绕这个设计我的URL和视图。我看到(至少)两个选项,我不知道哪个更惯用。

选项1)

为每个操作设置单独的网址和视图。所以,/ inbox / delete-message /映射到views.delete_message,依此类推。在每个视图结束时,它会重定向回/ inbox /.

我喜欢用这个选项清楚分开的方式。如果用户以某种方式发现自己向/ inbox / delete-message /发送GET请求,则会出现一种奇怪的情况(我是否会抛出错误页面?默默地重定向它们?)。

选项2)

对每个操作使用相同的URL和视图,并具有标识操作的POST参数。所以我会有一个相当长的收件箱视图,它会有一堆if语句测试request.POST ['action'] =='delete',或者request.POST ['delete'] =='true'或者其他什么

这个选项对我来说不太干净,但我觉得它更常见。

Djangonauts会选择哪个?或者是否有另一种选择比上述任何一种都好?

4 个答案:

答案 0 :(得分:2)

修改后的选项#1是最好的方法。考虑一下:假设我们不是在谈论一个Web应用程序,而只是设计一个收件箱类。您更喜欢哪种方法,多种方法(delete_message()mark_as_spam()等)或一种大方法(do_stuff(action))?当然你会使用不同的方法。

每个操作的单独URL(每个操作都有一个单独的视图)是更可取的。如果您不喜欢最后的重定向,请不要使用它。相反,使用render_inbox(request)方法返回HttpResponse,并在每个视图的末尾调用该方法。当然,在POST之后重定向是防止双重操作的好方法,并且始终为用户留下一致的URL。

更好的方法可能是使用Ajax隐藏操作,但这更为复杂。

答案 1 :(得分:1)

我认为这两种方案都没有任何问题,但从性能的角度来看,#2可能更好。发布操作后,您可以在没有重定向的情况下呈现收件箱,因此可以减少HTTP流量。

答案 2 :(得分:1)

如果您正在编写Web 2.0消息传递应用程序,那么您将使用AJAX调用,并且根本不会加载新页面。这个过程将如下进行:

  1. 用户点击[删除]查看邮件。此按钮具有绑定到它的javascript操作。此操作执行以下操作:

    我。更改UI以指示正在发生的事情(灰色消息或竖起沙漏)。

    II。发送请求到/ messages / inbox / 1234 /删除。 (其中1234是指示哪条消息的标识符)

    III。当服务器的响应返回时,它应指示成功或失败。在当前UI中反映此状态。例如,成功时,刷新收件箱视图(或只删除已删除的项目)。

  2. 在服务器端,现在您可以为每个所需的操作创建一个URL处理程序(即/ delete,/ flag等)。

    如果想要使用更加RESTful的方法,您可以使用HTTP操作本身来指示要执行的操作。因此,不是在您的网址中包含delete,而是在操作中。因此,请使用DELETE /messages/inbox/1234而不是GET或POST。要设置已读取的标记,请使用SET /messages/inbox/1234?read=true

    我不知道Django实现后一个建议有多么简单,但总的来说,利用协议(在本例中为HTTP)是一个好主意,而不是通过将您的操作编码为URL来解决它或参数。

答案 3 :(得分:0)

我同意#2是更好的方法。

但请注意使用不同的方法重载提交<input /> - 如果用户使用键盘输入并点击输入,则不一定会提交您期望的<input />。要么禁用自动提交输入,要么对代码进行编码,这样如果提交的内容不止一件,那么还有另一个字段可以设置操作应该是什么(例如,“删除”复选框,在此期间进行测试request.POST)

如果你选择了#1,我会说应该使用405(不支持的方法)来满足仅限POST的视图的GET - 或者,如果没有,则为404。