我又来了一个关于Play2.0的问题:-)。
我有一个模型叫Task
。此任务包含一个名为 createdBy
的字段。此字段必须填充已登录的用户。
我的字段声明如下所示:
@ManyToOne
@Constraints.Required
public User createdBy;
我呈现一个表单,登录用户可以在其中从下拉框中输入描述和优先级。提交表单后,我调用我的save()
方法。在保存方法中,我有以下代码:
Form<Task> taskForm = form(Task.class).bindFromRequest();
if (taskForm.hasErrors()) {
return badRequest(views.html.tasks.taskCreate.render(taskForm));
}
taskForm.get().save();
显然,Task
永远不会保存,因为字段createdBy
不包含任何(有效)用户。对用户的唯一引用是我在会话中保存他的唯一 CODE 而不是主键。
只有当我删除必需约束并将用户后填充到保存的任务时,我才能让它工作。一定有更好的方法将表单和用户绑定在一起,对吧?
Play2.0 想要你做的是区分你的"数据库模型"和你的"表单 bean"。我也认为应该有一个更好的解决方案。但另一方面,它很干净。所以你应该做的是:
- 例如,创建一个名为
TaskForm
的"表单豆"。此类仅包含表单中显示的字段,并具有正确的批注和验证。 - 在
TaskForm
中创建一个返回Task
的toTask(User user)
方法。 -
将控制器中的代码更改为:
Form<TaskForm> taskForm = form(TaskForm.class).bindFromRequest(); if (taskForm.hasErrors()) { return badRequest(views.html.tasks.taskCreate.render(taskForm)); } taskForm.get().toTask(user).save();
-
将注释/验证保留在"模型类"
Task
中,但将它们视为数据库验证,而不是表单验证。
编辑:
-
一些额外的解释:我在Play组上就这个验证/绑定问题进行了几次讨论:讨论1,讨论2。据我了解,Play 开发人员的想法是使用 Form 类进行绑定/验证。此 Form 类包装现有类。我认为他们的想法没有错,这个包装的类是表单的 1 对 1 表示。唯一的问题是,Scala语言使这比Java语言容易得多。在Java中,你必须创建大量的"表单表示类",而在Scala中,你可以使用"mapping"和"case classes"之类的东西(参见ScalaForms)。所以我完全同意你在评论中的观点,即为一个不同的属性编写一个新的"表单 bean"可能不值得,你宁愿在一个地方进行验证。但这就是它的设计方式。我希望他们要么自己更改 API,要么其他人仔细查看并提交拉取请求。但是现在,这就是框架希望你进行绑定/验证的方式。
-
例:
public class Task extends Model { @Constraints.Required public String description; @Constraints.Required public Integer priority; @ManyToOne @Constraints.Required public User createdBy; public Task() { } public Task(final TaskForm taskForm, final Long userCode) { description = taskForm.description; userCode = taskForm.userCode; createdBy = User.findByCode(userCode); } } public class TaskForm { @Constraints.Required public String description; @Constraints.Required public Integer priority; public toTask(final Long userCode) { return new Task(this, userCode); } } public class Tasks extends Controller { public static Result save() { Form<TaskForm> taskForm = form(TaskForm.class).bindFromRequest(); if (taskForm.hasErrors()) { return badRequest(views.html.tasks.taskCreate.render(taskForm)); } taskForm.get().toTask(session("userCode")).save(); } }
从模型中删除所需的注释,并通过两个步骤绑定新任务:
Form<Task> taskForm = form(Task.class).bindFromRequest();
if (taskForm.hasErrors()) {
return badRequest(views.html.tasks.taskCreate.render(taskForm));
}
Task newTask = taskForm.get();
newTask.createdBy = someObjectOfUserModel;
newTask.save();
return ok("New user added");