2012年10月18日木曜日

web2py SQLFORM あれこれ ⑤ SQLFORM.grid とカスタマイズ2

SQLFORM あれこれ ④ の続きです。今回も SQLFORM.grid を使ったカスタマイズを説明します。

SQLFORM.grid のカスタマイズ(一覧表示)

前回記事で、SQLFORM.grid の一覧表示画面を紹介した。

一覧画面のカスタマイズ用に使用可能なパラメータが、いくつか存在する。

表示項目を指定したり、項目の並び順を変えるカスタマイズでは、fields パラメータを使用する。項目のフィールド名を変更する場合は headers パラメータを指定する。サンプルコードは次のようになる。

1
2
3
4
5
6
7
8
@auth.requires_login()
def manage():
    fields = [db.image.name, db.image.category]
    headers = {'image.name':T('Name'), 'image.category':T('Category')}
    grid = SQLFORM.grid(db.image, upload=URL(c='default', f='download'),
                        fields=fields, headers=headers, csv=False)

    return dict(grid=grid)

コードを実行すると、次の画面イメージが表示される。

少し説明すると、fields には、表示する Fieldオブジェクトを指定する。これはリスト値で、指定順に表示される。
headers は、辞書値でフィールドと名前を指定する。ここでは翻訳オブジェクトである T を使って、名前を指定している。 この他、csv パラメータも指定しているが、これは CSVエクスポートを無効にしている。

ここまでは普通の設定だ。もう少し難しいことを試してみよう。画像データがあるため、画像を表示するカスタマイズを試してみる。

テーブルに存在しないフィールドを表示するには、links パラメータを使用する。もともと links はレコードと関連するリンクを表示するためにあるようだが、無名関数(lambda)も使用可能なため、画像表示にも利用可能だ。links は、次のようにリスト値で指定する。

links =[lambda row: IMG(_src=row.url, _width=50, _height=40, _id='image')  
        if row.url else IMG(_src=URL(c='default', f='download', args=row.file), 
                            _width=50, _height=40, _id='image')]

links で無名関数を指定した場合、パラメータとしてレコード一覧の Row オブジェクトをが渡される。このためサンプルコードでは、url に値がある場合は src 属性に urlを指定したIMGタグを、urlに値がない場合は src 属性に file を指定する。links はリスト値のため、複数の定義フィールドを指定することも可能だ。

また links でフィールドを追加する時に、タイトルを付加することも可能だ。その場合、辞書値で headerbody を指定し、header にはタイトル、body にはフィールド定義を指定する。

links=[{'header':T('Image'), 
        'body':lambda row: IMG(_src=row.url, _width=50, _height=40, _id='image') 
         if row.url else IMG(_src=URL(c='default', f='download', args=row.file), 
                             _width=50, _height=40, _id='image')}]

links パラメータを指定したコードを実行すると、次の画面イメージになる。

ここで注意して欲しいのは画面で、url と file フィールドも表示していることである。これは links に指定する無名関数のパラメータには、レコード一覧の Rowオブジェクトが使われるためである。つまり、無名関数で url と file フィールドを利用するために、レコード一覧に url と file が含まれている必要がある。

しかし無名関数に使用するといっても、一覧表示に url と file フィールドは不要だ。このため SQLFORM.grid の定義の前に、Fieldオブジェクトの readable 属性を False に指定する。

db.image.url.readable = db.image.file.readable = False

これによって一覧から、url と file フィールドを隠すことが可能になる。しかし、この設定で詳細表示(View)画面を表示させると、一覧と同様に url と file フィールドも表示されない。このため、ignore_rw パラメータを True に設定し、詳細画面では表示するように変更する。

以上まとめると、次のサンプルコードになる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@auth.requires_login()
def manage():
    db.image.url.readable = db.image.file.readable = False

    fields = [db.image.name, db.image.category, db.image.url, db.image.file]
    headers = {'image.name':T('Name'), 'image.category':T('Category')}

    links=[{'header':T('Image'), 
            'body':lambda row: IMG(_src=row.url, _width=50, _height=40, 
                                   _id='image') 
             if row.url else IMG(_src=URL(c='default', f='download', 
                                          args=row.file), 
                                 _width=50, _height=40, _id='image')}]
    
    grid = SQLFORM.grid(db.image, upload=URL(c='default', f='download'),
                        fields=fields, headers=headers, csv=False,
                        links=links, ignore_rw=True)

    return dict(grid=grid)

コードを実行すると画面イメージは、次のようになる。

SQLFORM.grid のカスタマイズ(新規作成・編集・詳細表示画面)

新規作成や編集、詳細表示画面などもカスタマイズ可能だ。このために次のパラメータが用意されている。

パラメータ制御する機能
formargs新規作成・編集・詳細表示画面、共通パラメータ
createargs新規作成画面のみ
editargs編集画面のみ
viewargs詳細表示画面のみ

これらのパラメータには、通常の SQLFORM に指定できるパラメータを辞書値で設定する。サンプルコードを示してみる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@auth.requires_login()
def manage():
    db.image.url.readable = db.image.file.readable = False

    fields = [db.image.name, db.image.category, db.image.url, db.image.file]
    headers = {'image.name':T('Name'), 'image.category':T('Category')}

    links=[{'header':T('Image'), 
            'body':lambda row: IMG(_src=row.url, _width=50, _height=40, 
                                   _id='image') 
             if row.url else IMG(_src=URL(c='default', f='download', 
                                          args=row.file), 
                                 _width=50, _height=40, _id='image')}]

    submit = BUTTON(I(_class='icon-ok icon-white', _style='margin-right: 5px;'),
                    T('OK'), _class='btn btn-primary')
    cancel = BUTTON(I(_class='icon-remove', _style='margin-right: 5px;'),
                    T('Cancel'), _class='btn', _style='margin-left:10px', 
                    _type='reset', _onclick="history.back();")
    formargs = {'showid':False, 'buttons':[submit,cancel]}

    
    grid = SQLFORM.grid(db.image, upload=URL(c='default', f='download'),
                        fields=fields, headers=headers, csv=False,
                        links=links, ignore_rw=True,
                        formargs=formargs, onvalidation=check_image)
    
    return dict(grid=grid)

サンプルコードでは、id の画面表示を制御する showid の設定を行うと共に、SQLFORM あれこれ③ で紹介した Twitter Bootstrap を使ったフォームボタンのカスタマイズ(buttons)を行なっている。15-20行目でオプションの定義を行い、26行目で formargs に定義したパラメータを渡している。

また、19行目で Cancel ボタンを押した場合、前ページに戻る JavaScript を設定している。これは、一覧ではページネーション(ページ割り)があるためだ。

2012/10/23
Cancelボタンでは、location.href で page パラメータを指定していました。しかしキチンと動作しなかったため、JavaScript の history.back(); にコードを変更しました。

この他、入力値チェックのために、onvalidation パラメータも指定している。これは SQLFORM あれこれ② で最初に紹介した 次の check_image 関数を指定している。

1
2
3
4
5
6
7
8
def check_image(form):
    file_delete = '%s__delete' % 'file'

    if form.vars.url is None and \
    form.vars.file is None and (form.vars.has_key(file_delete) is False or \
    form.vars.get(file_delete, False)):
        form.errors.url = T('must enter a url')
        form.errors.file = T('must select a file')

このコードを実行すると、画面のイメージは次のようになる。

新規登録編集詳細表示

編集と詳細表示の画面の左上には、links パラメータで設定した画像が表示されている。これは SQLFORM.grid の仕様により、この位置に表示されるようだ。表示・非表示を指定できるパラメータもない。もしこのイメージを非表示にしたい場合は、CSS ファイルに次の記述を追加する(links オプションで、IMGタグの id を image と指定しているため)。

.form_header>#image {
    display:None;
}

このCSSを設定すると、画面表示は次のようになる。

編集詳細表示


以上で、SQLFORM.grid のカスタマイズの説明は終わりです。SQLFORM.grid はとても便利なのですが、カスタマイズには限界があります。例えば、SQLFORM あれこれ② で設定したような、DBテーブルにないフィールドを追加するとか、フィールドの属性追加や設定ができません。また一覧表示でも、編集・削除ボタンの位置変更や、links で設定したフィールドとDBフィールドの位置を入れ替えるなどの設定ができません。

このため 次回 はもう少し柔軟な設定が可能な、SQLTALBLE を使ったカスタマイズを紹介したいと思います。

SQLFORM.grid の他のパラメータについては、web2py Book に説明があります。

参考: web2py Book - SQLFORM.gridとSQLFORM.smartgrid