我正在构建一些类似CMS的粗略功能(以获得Play Framework的功能)。对于这个测试用例,我构建了2个页面,1个用于列出标签,1个用于创建/编辑/保存标签。
流程如下(routes-file):
#list tags
GET /tags Application.listTags
#view/edit existing tag
GET /tag/{<(?!new$)(.+)>name} Application.showTag
#new tag
GET /tag/new Application.showTag
创建/查看/编辑页面显示一个表单,该表单从tagDTO获取它的值。 正常流程没有问题,但是当表单给出验证错误(例如:标签名称必须存在)时,我想再次显示页面,使用编辑的值重新填充表单。
为此(遵循Play框架约定)我可以使用包含这些最后值的'flash'对象,但是表单已经绑定到tagDTO(重定向时为null)而不是'flash'-宾语。
首先是代码: Application.java
.....
public static void showTag(String name) {
TagDTO tagDTO = TagDTO.buildDTOFromModelOrNew(name);
render(tagDTO);
}
/**
* Save tag and redirect to Show
*
* @param name
* @param displayname
* @param isnew
*/
public static void saveTag(
@Required(message="Name is required") String name,
String displayname,
boolean isnew)
{
checkAuthenticity();
if(validation.hasErrors()) {
params.flash();
validation.keep();
showTag(null);
}
//fetch tagDTO based on backend or create new if not exist
TagDTO tag = TagDTO.buildDTOFromModelOrNew(name);
// Append / Overwrite values
tag.displayname = displayname;
tag.name = name;
//save result to model
TagDTO.buildAndSaveModelFromDTO(tag);
flash.success("Thanks for " + (isnew?"creating":"updating") + " tag " + tag.name);
//redirect to show
showTag(tag.name);
}
和ShowTag.html
#{extends 'main.html' /}
#{if flash.success}
<p class="success">${flash.success}</p>
#{/if}
#{ifErrors}
<p class="errors">Oops...</p>
#{/ifErrors}
#{form @Application.saveTag()}
#{authenticityToken /}
<p>
<label for="name">Name: </label>
<input type="text" name="name" id="name" value="${tagDTO.name}" />
<span class="error">#{error 'name' /}</span>
</p>
<p>
<label for="displayname">Displayname: </label>
<input type="text" name="displayname" id="displayname" value="${tagDTO.displayname}" />
<span class="error">#{error 'displayname' /}</span>
</p>
<p>
<input type="hidden" name="isnew" value="${tagDTO.isnew}" />
<input type="submit" value="Submit your comment" />
</p>
#{/form}
现在我可以想办法让它发挥作用,但没有一个真正优雅:
将表单绑定到flash对象(或params-object)并从tagDTO填充flas / params对象
,重新获取tagDTO(不再需要DB调用),并使用flash-object中可用的值覆盖tagDTO中的值,将表单绑定到tagDTO。
喜欢2,但使用某种缓存来快速获取tagDTO(因此不需要db-call)
(/)将tagDTO序列化到会话中的一些通用机制。
总之,我真的不喜欢他们中的任何一个。 在这种情况下,您认为什么是最佳做法?或者Play Framework中是否有任何我缺少的功能?
答案 0 :(得分:2)
这是显式渲染调用的便利之处。保留先前提交的表单值并将其返回(如果验证失败),如下所示,
checkAuthenticity();
if(validation.hasErrors()) {
render("@showTag", name, displayname, isnew);
}
如果您调用了“来自其他操作的操作”,这将避免额外的重定向(如果是播放,则为307!)。
答案 1 :(得分:0)
再次渲染表单并避免重定向是一种解决方案。我认为如果用户按F5就可以了,他会再次收到错误。但我认为您应该创建一个重新加载/取消按钮,这样用户就可以忽略所有信息。
要始终使用正确的URL,您可以在routes.conf中执行以下操作:
GET /tag/create TagController.create
POST /tag/create TagController.insert
闪存解决方案的缺点是您的cookie可能会变得非常大。