CRUD

□未翻訳

□翻訳中

■翻訳完了(細田謙二)

■レビュー(Omi Chiba)

CRUD

web2pyに最近追加されたものの1つは、SQLFORMの上にあるCreate/Read/Update/Delete (CRUD) APIです。CRUDはSQLFORMを作成しますが、フォームの作成、フォームの処理、通知、リダイレクトを、すべて1つの関数において補完することによって、コーディングを単純化します。

One of the recent additions to web2py is the Create/Read/Update/Delete (CRUD) API on top of SQLFORM. CRUD creates an SQLFORM, but it simplifies the coding because it incorporates the creation of the form, the processing of the form, the notification, and the redirection, all in one single function.

初めに注意する点は、CRUDが他のこれまで使用してきたweb2pyのAPIと異なり、APIがすでに公開されていないことです。これはインポートしなければなりません。また、特定のデータベースにリンクする必要があります。例:

The first thing to notice is that CRUD differs from the other web2py APIs we have used so far because it is not already exposed. It must be imported. It also must be linked to a specific database. For example:

1.

2.

from gluon.tools import Crud

crud = Crud(globals(), db)

コンストラクタの最初の引数は現在のコンテキストglobals()です。これにより、CRUDがローカルのrequest、response、sessionにアクセスできるようになります。二番目の引数は、データベース接続オブジェクトdbです。

The first argument of the constructor is the current context globals() so that CRUD can access the local request, response, and session. The second argument is a database connection object, db.

上で定義したcrudオブジェクトは次のようなAPIを提供します:

The crud object defined above provides the following API:

.

  • crud.tables() は、データベースに定義されているテーブルのリストを返します。

    • returns a list of tables defined in the database.

  • crud.create(db.tablename) は、テーブルのtablenameに対する作成フォームを返します。

    • returns a create form for table tablename.

  • crud.read(db.tablename, id) は、tablenameとレコードidに対する読み取り専用のフォームを返します。

    • returns a readonly form for tablename and record id.

  • crud.update(db.tablename, id) は、tablenameとレコードidに対する更新フォームを返します。

    • returns an update form for tablename and record id.

  • crud.delete(db.tablename, id) は、レコードを削除します。

    • deletes the record.

  • crud.select(db.tablename, query) は、テーブルから選択されたレコードのリストを返します。

    • returns a list of records selected from the table.

  • crud.search(db.tablename) は、(form, records)のタプルを返します。formは検索フォームで、recordsはサブミットされた検索フォームに基づくレコードのリストです。

    • returns a tuple (form, records) where form is a search form and records is a list of records based on the submitted search form.

  • crud() は、request.args()に基づいて、上記のうちの1つを返します。

    • returns one of the above based on the request.args().

たとえば、次のアクションは:

For example, the following action:

1.

def data(): return dict(form=crud())

1.

2.

def create_tablename():

return dict(form=crud.create(db.tablename))

以下の作成メソッドしか公開しません

would only expose the create method

http://.../[app]/[controller]/create_tablename

また、次のアクションは:

While the following action:

1.

2.

def update_tablename():

return dict(form=crud.update(db.tablename, request.args(0)))

以下の更新メソッドしか公開しません

would only expose the update method

http://.../[app]/[controller]/update_tablename/[id]

他も同様です。

CRUDの挙動は二通りの方法でカスタマイズできます。1つは、crudオブジェクトにいくつかの属性を設定することです。もう1つは、各メソッドにさらなるパラメータを渡すことです。

The behavior of CRUD can be customized in two ways: by setting some attributes of the crudobject or by passing extra parameters to each of its methods.

設定

Settings

ここに、現在のCRUD属性と、そのデフォルトの値と、意味のリスト一式を示します:

Here is a complete list of current CRUD attributes, their default values, and meaning:

すべてのcrudのフォームに認証をかけます:

To enforce authentication on all crud forms:

1.

crud.settings.auth = auth

利用方法は第8章で説明します。

The use is explained in chapter 8.

crudオブジェクトを返すdata関数を定義しているコントローラを指定します

To specify the controller that defines the data function which returns the crud object

1.

crud.settings.controller = 'default'

レコードの"create"が成功した後のりダイレクト先のURLを指定します:

To specify the URL to redirect to after a successful "create" record:

1.

crud.settings.create_next = URL('index')

レコードの"update"が成功した後のりダイレクト先のURLを指定します:

To specify the URL to redirect to after a successful "update" record:

1.

crud.settings.update_next = URL('index')

レコードの"delete"が成功した後のりダイレクト先のURLを指定します:

To specify the URL to redirect to after a successful "delete" record:

1.

crud.settings.delete_next = URL('index')

アップロードされたファイルへリンクするために使用するURLを指定します:

To specify the URL to be used for linking uploaded files:

1.

crud.settings.download_url = URL('download')

crud.createフォームに対する標準の検証処理の後に実行される追加の関数を指定します:

To specify extra functions to be executed after standard validation procedures forcrud.create forms:

1.

crud.settings.create_onvalidation = StorageList()

StorageListはStorageオブジェクトと同様で、両者"gluon/storage.py"ファイルに定義されていますが、そのデフォルトはNoneではなく[]になります。これにより、次の構文が使用できます:

StorageList is the same as a Storage object, they are both defined in the file "gluon/storage.py", but it defaults to [] as opposed to None. It allows the following syntax:

1.

crud.settings.create_onvalidation.mytablename.append(lambda form:....)

crud.updateフォームに対する標準の検証処理の後に実行される追加の関数を指定します:

To specify extra functions to be executed after standard validation procedures forcrud.update forms:

1.

crud.settings.update_onvalidation = StorageList()

crud.createフォームの完了後に実行される追加の関数を指定します:

To specify extra functions to be executed after completion of crud.create forms:

1.

crud.settings.create_onaccept = StorageList()

crud.updateフォームの完了後に実行される追加の関数を指定します:

To specify extra functions to be executed after completion of crud.update forms:

1.

crud.settings.update_onaccept = StorageList()

レコードが削除される場合において、crud.updateの完了後に実行される追加の関数を指定します:

To specify extra functions to be executed after completion of crud.update if record is deleted:

1.

crud.settings.update_ondelete = StorageList()

crud.deleteの完了後に実行される追加の関数を指定します:

To specify extra functions to be executed after completion of crud.delete:

1.

crud.settings.delete_onaccept = StorageList()

"update"フォームが"delete"ボタンを持つかどうかを決めます:

To determine whether the "update" forms should have a "delete" button:

1.

crud.settings.update_deletable = True

"update"フォームが編集レコードの"id"を表示するかどうかを決めます:

To determine whether the "update" forms should show the id of the edited record:

1.

crud.settings.showid = False

フォームが前回挿入された値を維持するか、サブミット成功後デフォルトにリセットするかどうかを決めます:

To determine whether forms should keep the previously inserted values or reset to default after successful submission:

1.

crud.settings.keepvalues = False

フォームのスタイルは次のようにして変更することができます

You can change the form style by

1.

crud.settings.formstyle = 'table3cols' or 'table2cols' or 'divs' or 'ul'

authで説明されるのと同じやり方で、フォームにキャプチャを加えることができます:

You can add captcha to forms, using the same convention explained for auth, with:

1.

2.

3.

crud.settings.create_captcha = None

crud.settings.update_captcha = None

crud.settings.captcha = None

メッセージ

Messages

カスタマイズ可能なメッセージのリストを以下に示します:

Here is a list of customizable messages:

1.

crud.messages.submit_button = 'Submit'

これは、create、updateフォーム両方に対して"submit"ボタンのテキストを設定します。

sets the text of the "submit" button for both create and update forms.

1.

crud.messages.delete_label = 'Check to delete:'

これは、"update"フォームにおいて"delete"ボタンのラベルを設定します。

sets the label of the "delete" button in "update" forms.

1.

crud.messages.record_created = 'Record Created'

これは、レコードの作成が成功した際のflashメッセージを設定します。

sets the flash message on successful record creation.

1.

crud.messages.record_updated = 'Record Updated'

これは、レコードの更新が成功した際のflashメッセージを設定します。

sets the flash message on successful record update.

1.

crud.messages.record_deleted = 'Record Deleted'

これは、レコードの削除が成功した際のflashメッセージを設定します。

sets the flash message on successful record deletion.

1.

crud.messages.update_log = 'Record %(id)s updated'

これは、レコードの更新が成功したときのログメッセージを設定します。

sets the log message on successful record update.

1.

crud.messages.create_log = 'Record %(id)s created'

これは、レコードの作成が成功したときのログメッセージを設定します。

sets the log message on successful record creation.

1.

crud.messages.read_log = 'Record %(id)s read'

これは、レコードの読み取りアクセスが成功したときのログメッセージを設定します。

sets the log message on successful record read access.

1.

crud.messages.delete_log = 'Record %(id)s deleted'

これは、レコードの削除が成功したときのログメッセージを設定します。

sets the log message on successful record deletion.

なお、crud.messagesはgluon.storage.Messageクラスに所属しています。これは、gluon.storage.Storageに似ていますが、T演算子の必要なしに、自動的にその値を翻訳します。

Notice that crud.messages belongs to the class gluon.storage.Message which is similar togluon.storage.Storage but it automatically translates its values, without need for the Toperator.

ログメッセージは、CRUDが第8章で説明するAuthに接続された場合のみ使用されます。イベントは、Authテーブルの"auth_events"にログとして記録されます。

Log messages are used if and only if CRUD is connected to Auth as discussed in Chapter 8. The events are logged in the Auth table "auth_events".

メソッド

Methods

CRUDのメソッドの挙動は、呼び出し毎の原則でカスタマイズすることができます。ここにその用法を示します:

The behavior of CRUD methods can also be customized on a per call basis. Here are their signatures:

1.

2.

3.

4.

5.

6.

7.

crud.tables()

crud.create(table, next, onvalidation, onaccept, log, message)

crud.read(table, record)

crud.update(table, record, next, onvalidation, onaccept, ondelete, log, message, deletable)

crud.delete(table, record_id, next, message)

crud.select(table, query, fields, orderby, limitby, headers, **attr)

crud.search(table, query, queries, query_labels, fields, field_labels, zero)

  • table は、DALのテーブル、または、テーブル名です。メソッドはその上で動作します。

    • is a DAL table or a tablename the method should act on.

  • record and record_id は、レコードのidです。メソッドはその上で動作します。

    • are the id of the record the method should act on.

  • next は、成功後にリダイレクトする先のURLです。URLが部分文字列"[id]"を含む場合、これは、ちょうど作成/更新されたレコードのidによって置換されます。

  • is the URL to redirect to after success. If the URL contains the substring "[id]" this will be replaced by the id of the record currently created/updated.

  • onvalidation は、SQLFORM(..., onvalidation)と同じ機能を持ちます。

    • has the same function as SQLFORM(..., onvalidation)

  • onaccept は、フォームのサブミットが受理された後に呼ばれ、そこで、リダイレクトする前に、動作する関数です。

    • is a function to be called after the form submission is accepted and acted upon, but before redirection.

  • log はログのメッセージです。CRUDにおけるログのメッセージは、form.varsの辞書変数を"%(id)s"のように参照します。

  • is the log message. Log messages in CRUD see variables in the form.vars dictionary such as "%(id)s".

  • message はフォームが受理されたときのflashメッセージです。

    • is the flash message upon form acceptance.

  • ondelete は、"update"フォームを介してレコードが削除されるときに、onacceptの場所で呼ばれます。

    • is called in place of onaccept when a record is deleted via an "update" form.

  • deletable は、"update"フォームがdeleteオプションを持つかどうかを決めます。

    • determines whether the "update" form should have a delete option.

  • query は、レコードを選択するために使用するクエリです。

    • is the query to be used to select records.

  • fields は、レコードを選択するために使用するクエリです。

    • is a list of fields to be selected.

  • orderby は、選択したレコードの順序を決めます(第6章を参照してください)。

    • determines the order in which records should be selected (see Chapter 6).

  • limitby は、表示される選択レコードの範囲を決めます(第6章を参照してください)。

    • determines the range of selected records that should be displayed (see Chapter 6).

  • headers は、テーブルのヘッダの名前からなる辞書です。

    • is a dictionary with the table header names.

  • queries は、['equals', 'not equal', 'contains'] のようなリストです。検索フォームにおける使用可能なメソッドを保持します。

    • a list like ['equals', 'not equal', 'contains'] containing the allowed methods in the search form.

  • query_labels は、query_labels=dict(equals='Equals')のような辞書です。検索メソッドに対する名前を与えます。

    • a dictionary like query_labels=dict(equals='Equals') giving names to search methods.

  • fields は、検索ウィジェットにおいて列挙されるフィールドのリストです。

    • a list of fields to be listed in the search widget.

  • field_labels は、フィールド名をラベルにマッピングする辞書です。

    • a dictionary mapping field names into labels.

  • zero は、デフォルトでは"choose one"で、検索ウィジェットのドロップダウンのためのデフォルトのオプションとして使用されます。

    • defaults to "choose one" is used as default option for the drop-down in the search widget.

ここでは、単一のコントローラ関数における使用例を示します:

Here is an example of usage in a single controller function:

1.

2.

3.

4.

5.

6.

7.

# assuming db.define_table('person', Field('name'))

def people():

form = crud.create(db.person, next=URL('index'),

message=T("record created"))

persons = crud.select(db.person, fields=['name'],

headers={'person.name': 'Name'})

return dict(form=form, persons=persons)

もう1つのとても汎用的なコントローラ関数を示します。これにより、任意のテーブルから任意のレコードを検索、作成、編集することができます。このとき、テーブル名はrequest.args(0)によって渡されます:

Here is another very generic controller function that lets you search, create and edit any records from any table where the tablename is passed request.args(0):

1.

2.

3.

4.

5.

6.

7.

def manage():

table=db[request.args(0)]

form = crud.update(table,request.args(1))

table.id.represent = lambda id: \

A('edit:',id,_href=URL(args=(request.args(0),id)))

search, rows = crud.search(table)

return dict(form=form,search=search,rows=rows)

なお、table.id.represent=...の行は、web2pyに対して、idフィールドの表現を変更し、代わりに、自分自身のページへのリンクを表示し、作成ページを更新ページに切り替えるためにidをrequest.args(1)として渡すように指示します。

Notice the line table.id.represent=... that tells web2py to change the representation of the id field and display a link instead to the page itself and passes the id as request.args(1) which turns the create page into an update page.

レコードのバージョニング

Record Versioning

CRUDはデータベースのレコードのバージョニングを行うユーティリティを提供しています:

CRUD provides a utility to version database records:

すべての改訂履歴を必要とするテーブル(db.mytable)を持ちたいなら、次のようにするだけです:

If you have a table (db.mytable) that needs full revision history you can just do:

1.

form=crud.update(db.mytable, myrecord, onaccept=crud.archive)

crud.archiveはdb.mytable_archiveという新規のテーブルを定義します(この名前は参照するテーブルの名前に由来します)。そして、更新時に、(更新前の)レコードのコピーを、作成した記録用のテーブルに保存します。そのレコードへの参照も含まれます。

crud.archive defines a new table called db.mytable_archive (the name is derived from the name of the table to which it refers) and on updating, it stores a copy of the record (as it was before the update) in the created archive table, including a reference to the current record.

レコードは実際に更新されるので(その前回の状態のみが記録されます)、参照が壊れることはありません。

Because the record is actually updated (only its previous state is archived), references are never broken.

これはすべて内部で行われます。記録テーブルにアクセスしたいならば、モデルにおいてそれを定義しておく必要があります:

This is all done under the hood. Should you wish to access the archive table you should define it in a model:

1.

2.

3.

db.define_table('mytable_archive',

Field('current_record',db.mytable),

db.mytable)

なお、テーブルはdb.mytableを拡張し(そのすべてのフィールドを含み)、current_recordへ参照を追加しています。

Notice the table extends db.mytable (including all its fields), and adds a reference to thecurrent_record.

crud.archiveは、次のように元のテーブルがtimestampフィールドを持たない限り、保存したレコードのタイムスタンプを取りません。

crud.archive does not timestamp the stored record unless your original table has timestamp fields, for example:

1.

2.

3.

4.

5.

db.define_table('mytable',

Field('created_on','datetime',

default=request.now,update=request.now,writable=False),

Field('created_by',auth.user,

default=auth.user_id,update=auth.user_id,writable=False),

これらのフィールドに関して何ら特別なことはなく、好きな名前を付けることが可能です。これらはレコードが記録される前に入力され、各レコードのコピーと共に記録されます。記録テーブルの名前、または/かつ、フィールドの名前は次のように変更することができます:

There is nothing special about these fields and you may give them any name you like. They are filled before the record is archived and are archived with each copy of the record. The archive table name and/or reference field name can be changed like this:

1.

2.

3.

4.

5.

6.

7.

8.

db.define_table('myhistory',

Field('parent_record',db.mytable),

db.mytable)

# ...

form = crud.update(db.mytable,myrecord,

onaccept=lambda form:crud.archive(form,

archive_table=db.myhistory,

current_record='parent_record'))