如何在Play框架表单中定义可选字段的默认值?

6
我正在使用scala 2.0.2 play框架实现web api。我想提取和验证许多get参数。为此,我使用play "form"来定义可选字段。
问题: 对于那些可选字段,如果未传递参数,我需要定义一个默认值。 代码旨在正确解析以下三种用例:
/test?top=abc(错误,abc不是整数) /test?top=123(有效,top是123) /test(有效,top是42(默认值))
我想到了以下代码:
def test = Action {
  implicit request =>

  case class CData(top:Int)

  val p = Form(
    mapping(
      "top" -> optional(number)
    )((top) => CData($top.getOrElse(42))) ((cdata:CData) => Some(Some(cdata.top)))
  ).bindFromRequest()

  Ok("all done.")
}

这段代码可以运行,但是显然不够优雅。为了设置缺失请求参数的默认值,需要写很多样板代码。

有没有更简洁、更清晰的解决方案?

2个回答

12

在Play 2.1中

val p = Form(
    mapping(
      "top" -> default(number,42)
    )(CData.apply)(CData.unapply)
  ).bindFromRequest()

将会实现您的需求。


9
这是路由器验证查询字符串参数的工作。只需在routes文件中定义您的参数即可:
GET /test controllers.Application.test(top: Int ?= 42)

top作为参数添加到您的控制器方法中:

def test(top: Int) = Action {
  // Use top here
  val data = CData(top)
}

然后,Play会为你完成所有的验证工作。注意使用?=语法指定默认值。

您应该仅将表单用于POST请求。

更新:

如果您希望手动检查参数,则可以定义助手方法:

def getQueryParam(key: String, default: String)(implicit request: RequestHeader) =
  request.queryString.get(key).flatMap(_.headOption).getOrElse(default)

使用它在您的控制器方法中:

def test = Action { implicit request =>
  val top = getQueryParam("top", "42")
  ...

但是这样做会失去类型检查。当然,你可以为每种类型定义帮助函数,例如getIntParamgetStringParam等,但Play已经包含了安全路由实现,旨在解决此类问题。我建议您使用路由机制而不是手动检查。


这个提议的解决方案效果很好。不幸的是,这个解决方案在处理大量默认参数时无法很好地扩展。当您构建必须支持列表过滤的 Web 服务/ Web 应用程序时,在路由中公开所有默认参数可能会降低代码的可读性和健壮性。在所有其他情况下,这确实是首选解决方案。 - natbusa
1
答案已更新,附带了一个实用的辅助方法实现。 - lambdas
1
我已经提出了一个扩展Play框架的建议,以编写更多关于默认参数的代码驱动方法。请参见https://github.com/playframework/Play20/pull/381 - natbusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接