Play Framework Processing部分表单

lin*_*ips 5 playframework playframework-2.0

我正在使用Play框架,我有一个常见的用例,用控制器动作中的表单更新模型.但是我有一些问题需要理解它背后的概念,因为如果你有一个包含模型所有属性的表单,那么这个问题就可以了.如果您只有一个部分表单,例如只编辑用户模型的密码,则此方法会破坏模型,因为它会将模型的其他属性设置为null.这个问题有"官方"解决方案吗?任何方式Play只更新现有属性?

public static Result update(Long id) {
    Model model = Model.findById(id);
    Form<Model> filledForm = modelForm.bindFromRequest();
    if (filledForm.hasErrors()) {
        return badRequest(edit.render(filledForm));
    } else {
        model.update();
        flash("message", "Created new Model!");
        return ok(index.render());
    }
}
Run Code Online (Sandbox Code Playgroud)

可能该解决方案在某种程度上可以使用其他参数调用bindFormRequest()方法,如字符串或字符串映射?但我无法找到目的.对此的一些见解也会很棒.非常感谢!

mgu*_*min 7

在最近的一个项目中,我需要这种功能,我不得不重新实现Form类(基于原始的Play表单)以允许该bindFromRequest()方法的附加参数.

以您的代码为例,它会变成这样:

Model model = Model.findById(id);
Form<Model> filledForm = CustomForm.form(Model.class).bindFromRequest(model);
Run Code Online (Sandbox Code Playgroud)

我们的想法是只修改表单中定义的字段,并保持模型的其他字段不被修改.

要允许此特定绑定,您必须使用以下内容重新定义bind(Map<String,String> data, String... allowedFields)方法(以及bindFromRequest):

public Form<T> bind(T instance, Map<String,String> data, String... allowedFields) {

    DataBinder dataBinder = null;
    Map<String, String> objectData = data;
    if(rootName == null) {
        dataBinder = new DataBinder(instance);
    } else {
        dataBinder = new DataBinder(instance, rootName);
        objectData = new HashMap<String,String>();
        for(String key: data.keySet()) {
            if(key.startsWith(rootName + ".")) {
                objectData.put(key.substring(rootName.length() + 1), data.get(key));
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

而不是创建的DataBinderblankInstance()作为标准的播放Form类呢,你跟你创建模型实例作为构造函数的参数.