[翻譯]Play框架1.2.7版本教程(7) - 經過CRUD來實現一個基本的管理面板

經過CRUD來實現一個基本的管理面板

目前,咱們還無法使用博客的UI來寫新的文章,或修改評論。Play提供了一個即開即用的CRUD模塊,能夠快速生成一個基本的管理面板。javascript

啓動CRUD模塊

一個Play應用能夠由幾個模塊組裝起來。這使得你能夠在不一樣應用間重用組件或分割一個大應用到幾個小的。css

CRUD模塊是一個通用的應用,能夠對模型類進行內省生成簡單的列表和表單。html

要啓動CRUD模塊,在/conf/dependencies.ymlrequire後面添加一行:(注意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

聲明CRUD控制器

對於每一個想集成到管理面板的模型,咱們得聲明一個繼承自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/,你應該看到管理面板。

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模型的編輯或建立表單,你將看到驗證規則已經魔法般添加進去了。

validation

接下來是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;
…

而後檢查結果:

post result

這裏你會看到一個有趣的反作用:@MaxSize驗證規則改變了Play顯示Post表單的方式。如今它給內容域準備的是textarea。

最後是給CommentTag類添加驗證規則。

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

而後刷新表單,你將看到新的表單標籤:

form label

自定義Comments列表

你能夠爲所欲爲地自定義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'] /}

如今咱們有三列信息了:

columns

有個問題,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的語法糖。

自定義Posts表單

咱們也能夠自定義生成的表單。舉個例子,本來咱們在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,咱們實現了一個簡單的標籤選擇器:

tags selector

要想自定義標籤列表的外觀,如下面的內容建立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}

管理面板的工做暫告一段落。

相關文章
相關標籤/搜索