带有附加约束的 PlayFramework 表单验证
PlayFramework form validation with additional constraints
免责声明:此处使用 PlayFramework 2.6.0-M4!
我显示一个表单并想添加额外的限制条件,以禁止给定字段使用某些字符串。
现在我有两个问题:
def create() = Action(parse.form(createUserForm))
{
implicit request =>
val formData: CreateUserData = request.body
if(validate(formData).isDefined)
{
userRepository.create(formData.name, formData.dummy)
Ok(s"Here should go success, if user was created: $formData")
} else {
BadRequest("No means no!")
}
}
case class CreateUserData(name: String, dummy: Boolean)
private val createUserForm = Form(
mapping(
"name" -> text,
"dummy" -> boolean
)(CreateUserData.apply)(CreateUserData.unapply)
verifying("Failed form constraints!", fields => fields match
{
case data => validate(data).isDefined
})
)
private def validate(formData: CreatUserData): Option[CreatUserData] =
{
ReservedWords.filter(
_.equalsIgnoreCase(formData.name)
).isEmpty match
{
case true => Some(formData)
case false => None
}
}
1) Ok(s"Here should go success, if user was created: $formData").as("text/html")
在提供的数据有效的情况下工作,但在用户输入禁止名称的情况下:
a) 没有创建用户(良好)
b) BadRequest("No means no!")
永远不会返回! (虽然我得到了一个 http 400 响应,只是空的)
我不明白为什么 b) 会发生。
另外我想关注https://www.playframework.com/documentation/2.6.x/ScalaForms
改为编写如下代码:
def create() = Action(parse.form(createUserForm))
{
implicit request =>
createUserForm.bindFromRequest.fold(
formWithErrors =>
{
BadRequest("Errors: " + formWithErrors.errors).as("text/html")
},
formData =>
{
userRepository.create(formData.name, formData.dummy)
Redirect(s"/")
}
)
}
但遗憾的是,这会导致每个 post 请求出错,即使是完全有效的请求也是如此:
Errors: List(FormError(name,List(error.required),List()))
我做错了什么?
编辑:为了阐明我所说的 "total valid request" 的意思,我举了一个例子来说明 returns 上面的错误。
name=Teolha&dummy=true
作为 post 请求发送。
实际上我输入什么并不重要,但是(呈现的)表单的 HTML5 部分确保我必须输入一些东西。我期望的是 Ok
,以防 ReservedWords
列表中的 NOT,否则 BadRequest
edit2:这可能是因为默认过滤器吗?
那些是 运行 在玩 2.6:
play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter
我问,因为我没有在这里使用 Twirl(但 ScalaTags)来呈现表单!所以也许我遗漏了一些 twirl 实现将涵盖的隐含内容(令牌或其他东西)?
这是正确的行为:
https://playframework.com/documentation/2.6.0-M4/ScalaForms
val userPost = Action(parse.form(userForm)) { implicit request =>
In the failure case, the default behavior is to return an empty BadRequest response.
下一个:
You can override this behavior with your own logic. For instance, the following code is completely equivalent to the preceding one using bindFromRequest and fold.
val userPostWithErrors = Action(parse.form(userForm, onErrors = (formWithErrors: Form[UserData]) => {
implicit val messages = messagesApi.preferred(Seq(Lang.defaultLang))
BadRequest(views.html.user(formWithErrors))
})) { implicit request =>
val userData = request.body
val newUser = models.User(userData.name, userData.age)
val id = models.User.create(newUser)
Redirect(routes.Application.home(id))
}
你的情况
Action(parse.form(createUserForm))
在代码中调用它之前调用验证(if(validate(formData).isDefined)
是多余的)。所以它调用验证,验证不成功并播放 returns 一个空的错误请求。
修复:parse.form
函数的 onError
处理程序中的 处理错误。即 Action(parse.form(createUserForm, onErrors = ...
第二题
你调用 Action(parse.form(createUserForm))
- 它处理表单,然后你调用 createUserForm.bindFromRequest
但表单已经处理,所以你得到一个空表单。这也是正确的。
修复: 删除 parse.form(createUserForm)
所以你必须只有 Action()
免责声明:此处使用 PlayFramework 2.6.0-M4!
我显示一个表单并想添加额外的限制条件,以禁止给定字段使用某些字符串。
现在我有两个问题:
def create() = Action(parse.form(createUserForm))
{
implicit request =>
val formData: CreateUserData = request.body
if(validate(formData).isDefined)
{
userRepository.create(formData.name, formData.dummy)
Ok(s"Here should go success, if user was created: $formData")
} else {
BadRequest("No means no!")
}
}
case class CreateUserData(name: String, dummy: Boolean)
private val createUserForm = Form(
mapping(
"name" -> text,
"dummy" -> boolean
)(CreateUserData.apply)(CreateUserData.unapply)
verifying("Failed form constraints!", fields => fields match
{
case data => validate(data).isDefined
})
)
private def validate(formData: CreatUserData): Option[CreatUserData] =
{
ReservedWords.filter(
_.equalsIgnoreCase(formData.name)
).isEmpty match
{
case true => Some(formData)
case false => None
}
}
1) Ok(s"Here should go success, if user was created: $formData").as("text/html")
在提供的数据有效的情况下工作,但在用户输入禁止名称的情况下:
a) 没有创建用户(良好)
b) BadRequest("No means no!")
永远不会返回! (虽然我得到了一个 http 400 响应,只是空的)
我不明白为什么 b) 会发生。
另外我想关注https://www.playframework.com/documentation/2.6.x/ScalaForms
改为编写如下代码:
def create() = Action(parse.form(createUserForm))
{
implicit request =>
createUserForm.bindFromRequest.fold(
formWithErrors =>
{
BadRequest("Errors: " + formWithErrors.errors).as("text/html")
},
formData =>
{
userRepository.create(formData.name, formData.dummy)
Redirect(s"/")
}
)
}
但遗憾的是,这会导致每个 post 请求出错,即使是完全有效的请求也是如此:
Errors: List(FormError(name,List(error.required),List()))
我做错了什么?
编辑:为了阐明我所说的 "total valid request" 的意思,我举了一个例子来说明 returns 上面的错误。
name=Teolha&dummy=true
作为 post 请求发送。
实际上我输入什么并不重要,但是(呈现的)表单的 HTML5 部分确保我必须输入一些东西。我期望的是 Ok
,以防 ReservedWords
列表中的 NOT,否则 BadRequest
edit2:这可能是因为默认过滤器吗?
那些是 运行 在玩 2.6:
play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter
我问,因为我没有在这里使用 Twirl(但 ScalaTags)来呈现表单!所以也许我遗漏了一些 twirl 实现将涵盖的隐含内容(令牌或其他东西)?
这是正确的行为:
https://playframework.com/documentation/2.6.0-M4/ScalaForms
val userPost = Action(parse.form(userForm)) { implicit request =>
In the failure case, the default behavior is to return an empty BadRequest response.
下一个:
You can override this behavior with your own logic. For instance, the following code is completely equivalent to the preceding one using bindFromRequest and fold.
val userPostWithErrors = Action(parse.form(userForm, onErrors = (formWithErrors: Form[UserData]) => {
implicit val messages = messagesApi.preferred(Seq(Lang.defaultLang))
BadRequest(views.html.user(formWithErrors))
})) { implicit request =>
val userData = request.body
val newUser = models.User(userData.name, userData.age)
val id = models.User.create(newUser)
Redirect(routes.Application.home(id))
}
你的情况
Action(parse.form(createUserForm))
在代码中调用它之前调用验证(if(validate(formData).isDefined)
是多余的)。所以它调用验证,验证不成功并播放 returns 一个空的错误请求。
修复:parse.form
函数的 onError
处理程序中的 处理错误。即 Action(parse.form(createUserForm, onErrors = ...
第二题
你调用 Action(parse.form(createUserForm))
- 它处理表单,然后你调用 createUserForm.bindFromRequest
但表单已经处理,所以你得到一个空表单。这也是正确的。
修复: 删除 parse.form(createUserForm)
所以你必须只有 Action()