我再次回答有关Play2.0的问题: - )。
我有一个名为Task
的模型。此任务包含一个名为createdBy
的字段。必须使用登录用户
我的字段声明如下:
@ManyToOne
@Constraints.Required
public User createdBy;
我呈现一个表单,其中登录用户可以从下拉框中输入描述和优先级。当表单被提交时,我调用我的save()
方法。在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 ,而不是会话中的主键。
当我删除必需约束并将用户后填充到已保存的任务时,我才能使其正常工作。必须有更好的方法将表单和用户绑定在一起,对吗?
答案 0 :(得分:2)
Play2.0要求您做的是区分“数据库模型”和“表单bean”。我也认为应该有更好的解决方案。但另一方面,它很干净。所以你应该做的是:
TaskForm
的'表单bean'。此类仅包含表单中显示的字段,并带有正确的注释和验证。toTask(User user)
中创建TaskForm
方法,返回Task
。将控制器中的代码更改为:
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小组上有几个关于此验证/绑定问题的讨论:discussion1,discussion2。据我所知,Play Developers的想法是使用Form类进行绑定/验证。此Form类包装现有类。我认为他们认为这个包装类是表单的一对一表示没有错。只有问题是,Scala语言比Java语言更容易。在Java中你必须创建许多'表单表示类',在Scala中你可以使用'mapping'和'case classes'(see 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();
}
}
答案 1 :(得分:0)
从模型中删除所需的注释,并分两步绑定新任务:
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");