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 リクエストについては。

ユーザーがフォームにデータを入力する必要がある特定のページがあります。このフォームはサーバーに POST されます。エラーが見つかった場合は、通常どおり、エラー メッセージとともにフォームが再度表示されます。ここで、ユーザーが (フラグをクリックして) 言語を変更したい場合、リファラーへのリダイレクトは機能しません。これは、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 ルートにこのハックを追加する必要があります!

これに対するよりエレガントな解決策はありますか?

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 へのルートを出力しますurirequest

@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 に答える