玩!framework 2.0:使用其他字段验证表单中的字段

Ang*_*nco 18 validation scala playframework

在剧中!框架,使用scala,说我有一个如下形式:

import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints._

case class User(someStringField: String, someIntField: Int)

val userForm = Form(
  mapping(
    "someStringField" -> text,
    "someIntField" -> number verifying(x => SomeMethodThatReceivesAnIntAndReturnsABoolean(x))
  )(User.apply)(User.unapply)
Run Code Online (Sandbox Code Playgroud)

)

where SomeMethodThatReceivesAnIntAndReturnsABoolean是一个在int上执行某些逻辑以验证它的方法.

但是,我希望能够考虑someStringField验证时的价值someIntField,有没有办法在Play框架的形式中实现这一点?我知道我可以这样做:

val userForm = Form(
  mapping(
    "someStringField" -> text,
    "someIntField" -> number 
  )(User.apply)(User.unapply)
.verifying(x => SomeFunctionThatReceivesAnUserAndReturnsABoolean(x))
Run Code Online (Sandbox Code Playgroud)

然后我会将整个用户实例传递给验证函数.该方法的问题在于,产生的错误将与整个表单相关联,而不是与someIntField字段相关联.

有没有办法获得两件事,使用另一个字段验证字段并维护与我希望验证的特定字段相关的错误,而不是整个表单?

Tom*_*yer 8

我对字段添加验证具有相同的要求,具体取决于其他字段的值.我不确定在惯用的PLAY 2.2.1中如何做到这一点,但我提出了以下解决方案.在这种用法中,我将内置"映射"降级为简单类型转换器,并在"validateForm"方法中应用我的"高级域间"验证.映射:

val userForm = Form(
mapping(
  "id" -> optional(longNumber),
  "surename" -> text,
  "forename" -> text,
  "username" -> text,
  "age" -> number
)(User.apply)(User.unapply)
)

private def validateForm(form:Form[User]) = {
  if(form("username").value.get == "tom" || form("age").value.get == "38") {
    form
      .withError("forename", "tom - forename error")
      .withError("surename", "tom - surename error")
  }
  else
    form
}

def update = Action { implicit request =>
  userForm.bindFromRequest.fold({
    formWithErrors => BadRequest(users.edit(validateForm(formWithErrors)))
  }, { user => 
    val theForm = validateForm(userForm.fill(user))
    if(theForm.hasErrors) {
      BadRequest(users.edit(theForm))
    } else {
      Users.update(user)
      Redirect(routes.UsersController.index).flashing("notice" -> s"${user.forename} updated!")
    }
  }) 
} 
Run Code Online (Sandbox Code Playgroud)

即使它有效,我也迫切地寻找更具惯用性的版本......

编辑:在惯用游戏中使用自定义play.api.data.format.Formatter,更多信息,请访问http://workwithplay.com/blog/2013/07/10/advanced-forms-techniques/ - 这可让您以编程方式添加错误表单.我的Formatter看起来像这样:

val usernameFormatter = new Formatter[String] {

override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], String] = {
  // "data" lets you access all form data values
  val age = data.get("age").get
  val username = data.get("username").get
  if(age == "66") {
    Left(List(FormError("username", "invalid"), FormError("forename", "invalid")))
  } else {
    Right(username)
  }
}

override def unbind(key: String, value: String): Map[String, String] = {
  Map(key -> value)
}
}
}
Run Code Online (Sandbox Code Playgroud)

在表单映射中注册如下:

mapping(
[...]
  "username" -> of(usernameFormatter),
[....]
Run Code Online (Sandbox Code Playgroud)

  • 对我来说仍然觉得不够惯用......我做这个问题已经很长时间了,从那时起,我一直在为 scala https://github.com/NovaMage/SValidator 开发我自己的验证框架。实现几乎完成,但还没有很好的文档记录。不过,它有一套完整的单元测试。一旦我完成了有关如何使用它以及如何将其与游戏集成的文档,我会将其发布在这里作为答案:) (2认同)

nit*_*ar7 6

我相信你所寻找的是play.api.data.validation.Constraint.

假设你有一个RegisterForm预定义列表cities和一个otherCity字段,你需要提供cities或者otherCity提供,即otherCity如果cities没有提供应该验证:

case class RegisterForm(
  email: String,
  password: String,
  cities: Option[List[String]],
  otherCity: Option[String]
)
Run Code Online (Sandbox Code Playgroud)

您可以围绕此编写自定义约束:

val citiesCheckConstraint: Constraint[RegisterForm] = Constraint("constraints.citiescheck")({
  registerForm =>
    // you have access to all the fields in the form here and can
    // write complex logic here
    if (registerForm.cities.isDefined || registerForm.otherCity.isDefined) {
      Valid
    } else {
      Invalid(Seq(ValidationError("City must be selected")))
    }
})
Run Code Online (Sandbox Code Playgroud)

您的表单定义变为:

val registerForm = Form(
  mapping(
    "email" -> nonEmptyText.verifying(emailCheckConstraint),
    "password" -> nonEmptyText.verifying(passwordCheckConstraint),
    "cities" -> optional(list(text)),
    "other_city" -> optional(text)
  )(RegisterForm.apply)(RegisterForm.unapply).verifying(citiesCheckConstraint)
)
Run Code Online (Sandbox Code Playgroud)

在该示例中emailCheckConstraint并且passwordCheckConstraint是我所定义类似于其他自定义的约束citiesCheckConstraint.这适用于Play 2.2.x.

更新:也 适用于Play 2.3.8.


nie*_*els 0

我猜他们将 scala 代码映射到 JSR 验证。那里绝对不可能。这样做有一些论据。主要是验证应该简单,不要做出复杂的逻辑。但我还是很怀念这个。play1 的 OVal 对我来说更好。