1

我在 Play 中有一个 Web 应用程序。Web 应用程序由几个页面组成。在每个页面中都有一个小标志,使用户能够将语言(区域设置)从德语更改为英语并返回。

我通过重定向到引用者来处理这个问题:

  def referer(implicit request: Request[AnyContent]) =
    request.headers.get(REFERER).getOrElse(mainUrl)
  def locale(l: String) = Authenticated { user =>
     implicit request =>
     Redirect(referer).withCookies(Cookie(LANG, if (l == "de" || l == "en") l else "de"))
  }

它工作正常。好吧,至少对于 GET 请求。

我有一个特定的页面,用户必须在其中输入表单中的数据。然后将此表单发布到服务器。如果发现错误,与往常一样,表单会再次显示错误消息。现在,如果用户想要更改语言(通过单击标志),重定向到 referer 不起作用,因为它尝试使用 GET 请求,并且 Play 抱怨此方法不存在 GET 路由(其中是真的)。

我通过缓存表单并定义另一种从缓存中获取表单的方法来解决这个问题:

# User data is POSTed to the server
POST    /create/insert              controllers.MyCreate.insert()
# After a redirect the cached form is displayed again
GET     /create/insert              controllers.MyCreate.insertGet()

它有效,但我不喜欢这个解决方案。必须在路由中创建另一个条目和另一种方法来解决这个问题似乎并不正常。我需要为我的应用程序中的每个 POST 路由添加这个 hack!

有没有更优雅的解决方案?

4

1 回答 1

0

你可以把它改成这样(未经测试):

def changeLang(lang:String, returnUri:String) = Action {
  Redirect(returnUri)
    .withCookies(Cookie(LANG, if (lang == "de" || lang == "en") lang else "de"))
}

在您的模板中,您将在链接中输出到 changeLang 的路线,您可以uri通过request

@routes.Application.changeLang("en", request.uri).url

我建议您request在您的操作中隐含并将其定义为模板中的隐含,这样您就不需要将其传递给每个模板。

// in the controller
def myUrl = Action { implicit request =>
  Ok(views.html.myTemplate("something"))
}

// in the template
@(title:String)(implicit request:play.api.mvc.RequestHeader)

编辑

至于 POST 请求,通常(对于这些类型的框架)让 POST 请求简单地处理内容,然后重定向到另一个页面。通常的流程是这样的:

  • 表单提交给处理程序
  • 处理程序对表单信息做一些事情
  • 处理程序重定向到页面

一个例子:

// Hooked up to a GET route
def edit(id:Long) = Action {
   // render the view with a form that displays the element with given id
   // if the flash scope contains validation information, use that in display
}

// Hooked up to a POST route
def editHandler = Action {
   // validate the form
   // if validation succeeds
     // persist the object
     // redirect to edit
   // else
     // put the form information into the flash scope
     // put any validation messages into the flash scope
     // redirect to edit
}

如果您不想使用此流程,则无论如何都需要同时拥有 GET 和 POST 路由。用户可能会在结果页面上重新加载页面。

于 2013-02-16T11:55:03.973 回答