我在Play中有一个Web应用程序。 Web应用程序由几个页面组成。在每个页面中都有一个小标记,使用户可以将语言(语言环境)从德语更改为英语并返回。
我通过重定向到referer处理这个:
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请求。
我有一个特定的页面,用户必须在表单中输入数据。然后将此表单POST到服务器。如果发现错误,表单会像往常一样再次显示错误消息。现在,如果用户想要更改语言(通过单击标志),重定向到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!
对此有更优雅的解决方案吗?
答案 0 :(得分:0)
您可以将其更改为此类内容(未经测试):
def changeLang(lang:String, returnUri:String) = Action {
Redirect(returnUri)
.withCookies(Cookie(LANG, if (lang == "de" || lang == "en") lang else "de"))
}
在您的模板中,您将在链接中输出更改路线的路线,您可以通过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路由。用户可能会在结果页面上重新加载页面。