从请求绑定表单并登录用户

时间:2012-04-19 19:27:44

标签: playframework-2.0

我再次回答有关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 ,而不是会话中的主键。

当我删除必需约束并将用户后填充到已保存的任务时,我才能使其正常工作。必须有更好的方法将表单和用户绑定在一起,对吗?

2 个答案:

答案 0 :(得分:2)

Play2.0要求您做的是区分“数据库模型”和“表单bean”。我也认为应该有更好的解决方案。但另一方面,它很干净。所以你应该做的是:

  1. 例如,创建一个名为TaskForm的'表单bean'。此类仅包含表单中显示的字段,并带有正确的注释和验证。
  2. toTask(User user)中创建TaskForm方法,返回Task
  3. 将控制器中的代码更改为:

    Form<TaskForm> taskForm = form(TaskForm.class).bindFromRequest();
    
    if (taskForm.hasErrors()) {
      return badRequest(views.html.tasks.taskCreate.render(taskForm));
    }
    taskForm.get().toTask(user).save();
    
  4. 在“模型类”Task中保留注释/验证,但将其视为数据库验证,而不是表单验证。

  5. 编辑:

    • 一些额外的解释:我在Play小组上有几个关于此验证/绑定问题的讨论:discussion1discussion2。据我所知,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");