目前,咱们还无法使用博客的UI来写新的文章,或修改评论。Play提供了一个即开即用的CRUD模块,能够快速生成一个基本的管理面板。javascript
一个Play应用能够由几个模块组装起来。这使得你能够在不一样应用间重用组件或分割一个大应用到几个小的。css
CRUD模块是一个通用的应用,能够对模型类进行内省生成简单的列表和表单。html
要启动CRUD模块,在/conf/dependencies.yml
的require
后面添加一行:(注意play后面的箭头两边须要留空格!)java
require: - play - play -> crud
如今运行play dependencies
命令,来解决新的模块依赖关系。若是正用着IDE,你应该更新项目配置,来包括新的模块依赖:好比,运行play eclipsify
,在Eclipse里从新导入项目,而后按F5刷新项目。segmentfault
而后这个模块提供一系列如今就能用上的路由。要导入这些路由,在/yabe/conf/routes
加入:mvc
# Import CRUD routes * /admin module:crud
这将导入全部的CRUD路由,并以/admin
做为URL前缀。app
你须要重启应用来使得新模块的导入生效。post
对于每一个想集成到管理面板的模型,咱们得声明一个继承自controllers.CRUD
的控制器。这很简单。ui
给每一个模型建立各建立一个控制器。好比,对于Post
类,在/yabe/app/controllers/Posts.java
建立一个Posts
控制器。this
package controllers; import play.*; import play.mvc.*; public class Posts extends CRUD { }
默认控制器的命名,是其对应的模型的复数。这样,Play就能自动搭配每一个控制器和对应的模型。若是你须要指定特别的名字,你可使用
@CRUD.For
注解。阅读CRUD文档。
一样建立其余的控制器:
package controllers; import play.*; import play.mvc.*; public class Users extends CRUD { } package controllers; import play.*; import play.mvc.*; public class Comments extends CRUD { } package controllers; import play.*; import play.mvc.*; public class Tags extends CRUD { }
如今打开http://localhost:9000/admin/,你应该看到管理面板。
若是仔细看,你将注意到列表中对象的名字有点奇怪。这是由于默认是以toString()
的输出来获得一个模型对象的表示。
因此,经过提供定制的toString()
,咱们就能解决这个问题。举个例子,对于User类:
… public String toString() { return email; } …
一般使用管理面板的问题是,提交的表单没有通过恰当的验证。但由于CRUD模块能够从验证注解提取出验证规则,因此若是模型类获得正确注解,就不会有问题。
让咱们给User
类添加一些注解。
package models; import java.util.*; import javax.persistence.*; import play.db.jpa.*; import play.data.validation.*; @Entity public class User extends Model { @Email @Required public String email; @Required public String password; public String fullname; public boolean isAdmin; …
如今若是你来到User
模型的编辑或建立表单,你将看到验证规则已经魔法般添加进去了。
接下来是Post
类:
package models; import java.util.*; import javax.persistence.*; import play.db.jpa.*; import play.data.validation.*; @Entity public class Post extends Model { @Required public String title; @Required public Date postedAt; @Lob @Required @MaxSize(10000) public String content; @Required @ManyToOne public User author; @OneToMany(mappedBy="post", cascade=CascadeType.ALL) public List<Comment> comments; @ManyToMany(cascade=CascadeType.PERSIST) public Set<Tag> tags; …
而后检查结果:
这里你会看到一个有趣的反作用:@MaxSize
验证规则改变了Play显示Post表单的方式。如今它给内容域准备的是textarea。
最后是给Comment
和Tag
类添加验证规则。
package models; import java.util.*; import javax.persistence.*; import play.db.jpa.*; import play.data.validation.*; @Entity public class Tag extends Model implements Comparable<Tag> { @Required public String name; … package models; import java.util.*; import javax.persistence.*; import play.db.jpa.*; import play.data.validation.*; @Entity public class Comment extends Model { @Required public String author; @Required public Date postedAt; @Lob @Required @MaxSize(10000) public String content; @ManyToOne @Required public Post post; …
如你所见,表单标签有点奇怪。Play使用Java成员变量做为表单标签。要想自定义它,咱们仅需在/yabe/conf/messages
中提供一组标签名。
事实上,你能够用一个单独的
messages
文件对应应用支持的每种语言。好比,你能够把中文信息放入/yabe/conf/messages.zh
。你将会在最后一章读到如何进行本地化。
添加这些标签到messages
文件:
title=Title content=Content postedAt=Posted at author=Author post=Related post tags=Tags set name=Common name email=Email password=Password fullname=Full name isAdmin=User is admin
而后刷新表单,你将看到新的表单标签:
你能够为所欲为地自定义CRUD模块。举个例子,你不大可能以为评论列表长得符合你的指望。咱们还须要添加更多列,特别是“相关文章”列来帮助咱们过滤评论。
事实上,因为你的应用才是老大,你能够覆盖掉CRUD模块提供的任意action和模板。举个例子,若是咱们想自定义评论列表,咱们仅需提供/yabe/app/views/Comments/list.html
模板。
在CRUD模块启动后,你就能使用更多的play命令。crud:ov
命令帮助你覆盖掉任意模板。在命令行里。输入:
$ play crud:ov --template Comments/list
如今你有一个新的模板/yabe/app/views/Comments/list.html
:
#{extends 'CRUD/layout.html' /} <div id="crudList" class="${type.name}"> <h2 id="crudListTitle">&{'crud.list.title', type.name}</h2> <div id="crudListSearch"> #{crud.search /} </div> <div id="crudListTable"> #{crud.table /} </div> <div id="crudListPagination"> #{crud.pagination /} </div> <p id="crudListAdd"> <a href="@{blank()}">&{'crud.add', type.modelName}</a> </p> </div>
首先看看&{'crud.list.title', type.name}
,这里输出了键名为crud.list.title
的本地化信息,使用type.name
做为信息参数。CRUD模块的conf/messages
包括条目crud.list.title=&{%s}
,其中的参数做为另外一个参数查找时的键,好比这里的&{'Comments'}
,由于type
是一个models.Comments
对应的CRUD.ObjectType
。既然咱们没有定义对应的信息文件条目,默认会输出信息键 - Comments
。在本教程的最后一章,你会学到关于本地化信息的更多东西。
#{crud.table /}
是生成表格的标签。咱们可使用fields
参数添加更多列。试一下这个:
#{crud.table fields:['content', 'post', 'author'] /}
如今咱们有三列信息了:
有个问题,content
域可能容不下有些过长的评论。咱们须要指定#{crud.table /}
可以在须要的时候截短它。
使用#{crud.custom /}
标签,咱们能够自定义每一个域的展现方式:
#{crud.table fields:['content', 'post', 'author']} #{crud.custom 'content'} <a href="@{Comments.show(object.id)}"> ${object.content.length() > 50 ? object.content[0..50] + '…' : object.content} </a> #{/crud.custom} #{/crud.table}
是的,这里撒了些Groovy的语法糖。
咱们也能够自定义生成的表单。举个例子,本来咱们在Post表单中输入标签并不容易。咱们须要改善体验。让咱们来重载掉Posts/show
模板:
$ play crud:ov --template Posts/show
如今你有了/yabe/app/views/Posts/show.html
:
#{extends 'CRUD/layout.html' /} <div id="crudShow" class="${type.name}"> <h2 id="crudShowTitle">&{'crud.show.title', type.modelName}</h2> <div class="objectForm"> #{form action:@save(object.id), enctype:'multipart/form-data'} #{crud.form /} <p class="crudButtons"> <input type="submit" name="_save" value="&{'crud.save', type.modelName}" /> <input type="submit" name="_saveAndContinue" value="&{'crud.saveAndContinue', type.modelName}" /> </p> #{/form} </div> #{form @delete(object.id)} <p class="crudDelete"> <input type="submit" value="&{'crud.delete', type.modelName}" /> </p> #{/form} </div>
你能够经过给#{crud.form /}
标签添加一个crud.custom
标签来自定义tags
域:
#{crud.form} #{crud.custom 'tags'} <label for="tags"> &{'tags'} </label> <script type="text/javascript"> var toggle = function(tagEl) { var input = document.getElementById('h'+tagEl.id); if(tagEl.className.indexOf('selected') > -1) { tagEl.className = 'tag'; input.value = ''; } else { tagEl.className = 'tag selected'; input.value = tagEl.id; } } </script> <div class="tags-list"> #{list items:models.Tag.findAll(), as:'tag'} <span id="${tag.id}" onclick="toggle(this)" class="tag ${object.tags.contains(tag) ? 'selected' : ''}"> ${tag} </span> <input id="h${tag.id}" type="hidden" name="${fieldName}" value="${object.tags.contains(tag) ? tag.id : ''}" /> #{/list} </div> #{/crud.custom} #{/crud.form}
经过使用Javascript,咱们实现了一个简单的标签选择器:
要想自定义标签列表的外观,如下面的内容建立public/stylesheets/tags.css
:
.tags-list .tag { cursor: pointer; padding: 1px 4px; } .crudField .tags-list .selected { background: #222; color: #fff; }
而后,在views/CRUD/layout.html
,改变#{set 'moreStyles'}
块成这样:
#{set 'moreStyles'} <link rel="stylesheet" type="text/css" media="screen" href="@{'/public/stylesheets/crud.css'}" /> <link rel="stylesheet" type="text/css" media="screen" href="@{'/public/stylesheets/tags.css'}" /> #{/set}
管理面板的工做暂告一段落。