2.17. レコードバージョン管理¶
web2pyにはレコード操作に伴ってバージョンを管理する仕組みが、次のように幾つか用意されています。
- table クラスの _enable_record_versioning メソッドを使用したバージョン管理機能
- Auth クラスの enable_record_versioning メソッドを使用したバージョン管理機能
- Auth クラスの archive メソッドを、SQLFORMやCRUDのコールバック関数に指定するバージョン管理機能
Auth
クラスは アクセス制御 -Access control で使用されます。つまり Authクラスのメソッドで提供しているバージョン管理機能は、
Authの付加機能という位置付けと考えて良いと思います。
これらの機能の詳細を、以下説明して行きます。説明には次のテーブルを使用します。
db.define_table('person',
Field('name'),
format='%(name)s')
2.17.1. Table._enable_record_versioning メソッドのバージョン管理¶
このメソッドでバージョン管理を行うためには、テーブルのモデルを次のように変更する必要があります。
db.define_table('person',
Field('name'),
auth.signature,
format='%(name)s')
ここで、 auth.signature のフィールドを継承させています。これによって、次のフィールドが追加されます。
フィールド タイプ 説明 is_active boolean Trueの場合レコードが有効です。レコードが削除されるとFalseになります。デフォルトはTrueです。 created_on datetime レコード作成日時です。 created_by reference auth_user レコード作成者です。auth_userを参照します。 modified_on datetime レコード更新日時です。 modified_by reference auth_user レコード更新者です。auth_userを参照します。
バージョン管理するには、次のようにモデル定義でTableオブジェクトのメソッドを呼び出します。
db.person._enable_record_versioning()
この設定によって、次のことが自動で行われます。
- 「 テーブル名_archive 」(サンプル例では person_archive)というバージョン管理用のテーブルが作成されます。
- メソッドを呼び出したテーブルのレコード更新・削除を行うと、「テーブル名_archive」に元のレコードが保存されます。
- 設定したテーブルに コモンフィルタ がセットされ、is_active フィールドが True でない場合、フィルタによってデータから外されます。
テーブル名_archive テーブルは次のフィールドと共に、元のテーブルのフィールドを継承します。
フィールド タイプ 説明 current_record reference テーブル名 元のテーブルを参照します。 id id アーカイブテーブルのidフィールドです。
メソッドのパラメータについては、 _enable_record_versioning()
を参照ください。
2.17.2. Auth.enable_record_versioning メソッドのバージョン管理¶
このメソッドは内部で、 _enable_record_versioning()
を呼び出しています。
このため同様に動作しますが、バージョン管理を実施するテーブルの指定方法が異なります。
Warning
このメソッドはバグのため web2py バージョン 2.6.0 以前では、設定しても実際には 動作しません 。
例えばモデル定義で、テーブルに auth.signature を継承させると共に、
db.define_table('person',
Field('name'),
auth.signature,
format='%(name)s')
次のように指定します。
auth.enable_record_versioning(db)
この場合 db データベースに含まれる全てのテーブルをチェックし、次の条件に合致するテーブルでバージョン管理が行われます。
id
フィールドが存在します(特殊なレガシデータベースには存在しません、 レガシデータベースの利用 を参照)。modified_on
フィールドが存在します(対象テーブルは、auth.signature を継承しています)。current_record
という名前のフィールドが含まれません(対象テーブルには、アーカイブテーブルは含まれません)。
次のようにテーブルを指定することもできます。
auth.enable_record_versioning(tables=[db.person, db.dog])
この場合も前記の条件に合致しなければ、指定されたテーブルはバージョン管理されません。
メソッドのパラメータは以下に説明します。
Auth.
enable_record_versioning
(tables[, archive_db, archive_name, current_record, is_active])¶
- tables
- バージョン管理するテーブルをイテレータオブジェクトで指定します。 前記の条件に合致する場合に、実際にバージョン管理されます。 DAL インスタンスを指定した場合、そのデータベースに含まれる全てのテーブルが対象になります。
- archive_db, archive_name, current_record, is_active
- これらのパラメータは、
_enable_record_versioning()
メソッドのパラメータ説明を参照ください。
2.17.3. Auth.archive メソッドのバージョン管理¶
このメソッドを使用したバージョン管理では、 SQLFORM や CRUD を利用しアーカイブデータを保管します。
Note
特殊な理由がない限り、このメソッドを使用するより Table._enable_record_versioning もしくは Auth.enable_record_versioning メソッドを利用した方が容易です。
メソッドの設定によって、次のことが自動で行われます。
- 「 テーブル名_archive 」(サンプル例では person_archive)というバージョン管理用のテーブルが作成されます。
- メソッドを呼び出したテーブルのレコード更新・削除を行うと、「テーブル名_archive」に元のレコードが保存されます。
_enable_record_versioning()
メソッドの動作とよく似ていますが、次の点が異なります。
- 自動で作成されるバージョン管理用テーブル(テーブル名_archive)は、モデル定義として公開されません。
- 対象テーブルは、auth.signature を継承する必要はなく、 (削除は is_active フィールドをFalseに変更するのではなく)実際にレコードがテーブルから 削除 されます。
- あくまでも SQLFORM や CRUD で設定した場合にバージョン管理が行われます。 独自にDALコマンドでレコード操作した場合は、バージョン管理は行われません。
それでは利用方法について解説します。
事前準備
テーブルは、auth.signature を継承する必要はありませんが、更新日時・ユーザの情報がテーブルにないのは不都合です。 このため次のように、対象テーブルに保存日時と保存ユーザのフィールドを追加します。
db.define_table('person', Field('name'), Field('saved_on', 'datetime', default=request.now, update=request.now, readable=False, writable=False), Field('saved_by', auth.settings.table_user, default=auth.user_id, update=auth.user_id, readable=False, writable=False), format='%(name)s')
このメソッドが作成するアーカイブテーブルは、標準では非公開です。 もしアプリなどで使用する予定がある場合は、次のようにモデルでテーブルを定義します。
db.define_table('person_archive', Field('current_record', db.person, ondelete='NO ACTION'), db.person)
- このテーブル定義では次のことが必要です。
- テーブル名が、「 テーブル名_archive 」という名前です。
- 「 current_record 」という名前の、元テーブルを参照するフィールドが存在します。
- 元のテーブルを継承します。
これらのルールは後で説明するメソッドのパラメータで変更可能です。
他に参照フィールド(current_record)の ondelete パラメータに、’NO ACTION’ を指定していることに注意してください。 このパラメータのデフォルト値は ‘CASCADE’ です。デフォルト値のままだと、元のテーブルのレコードを削除した場合、 アーカイブテーブルのレコードまで削除されてしまうことになります。
SQLFORMでの利用
SQLFORMでのサンプルを示します。
def person(): form = SQLFORM(db.person, request.args(0), True).process(onsuccess=auth.archive) return dict(form=form)
personテーブルのレコードを挿入・更新・削除するコントローラ関数です。 フォーム入力完了時のコールバック関数(onsuccess)を auth.archive と指定しています。 コールバック関数を指定するのではなく、次のように記述することも可能です。
def person(): form = SQLFORM(db.person, request.args(0), True) if form.process().accepted: auth.archive(form) return dict(form=form)
CRUDでの利用
CRUDでのサンプルを示します。
def data(): crud.settings.create_onaccept = crud.archive crud.settings.update_onaccept = crud.archive return dict(form=crud())
crud.achive は内部で auth.archive を呼び出しています。
削除時にコールバックされる crud.settigns.delete_onaccept 属性もありますが、パラメータがRowsオブジェクトになるため、 crud.archive は設定できません。crud.settings.update_deletable が True の場合(デフォルト値は True)、 更新画面で削除用チェックボックスが表示されます。このため更新画面で削除時すれば、 crud.settings.update_onaccept に設定されたコールバック関数が呼び出されます。
属性値に記述するのではなく、パラメータにコールバック関数を指定することもできます。
def data_create(): return dict(form=crud.create(db.person, onaccept=crud.archive)) def data_update(): return dict(form=crud.update(db.person, request.args(0), onaccept=crud.archive))
Auth.archive メソッドの詳細説明
メソッドに渡すことが可能なパラメータについて、以下に説明します。
-
Auth.
archive
(form[, archive_table, current_record, archive_current, fields])¶
- form
FORMオブジェクトを渡します。
- archive_table
アーカイブテーブル・オブジェクトを指定します。デフォルト値は None です。 None の場合は、「
テーブル名_archive
」となります。 指定する場合は、アーカイブテーブルをモデル定義しておく必要があります。- current_record
アーカイブテーブルの元のレコードを参照するフィールド名を指定します。 デフォルトは、
'current_record'
です。 指定した名前のフィールドがアーカイブテーブルに追加され、 元のテーブルのレコードを参照するフィールドとして使用されます。- archive_current
アーカイブ方法を指定します。デフォルトは False です。 True を指定した場合、現在のレコードの値をアーカイブテーブルに格納します。 False では、更新前のレコードの値をアーカイブテーブルに格納します。
- fields
アーカイブテーブルにレコード以外の例外フィールドを書きこむオプションです。 辞書型でフィールドと値を指定します。 指定するフィールドは事前にテーブルに定義しておく必要があります。フィールドと値は複数指定可能です。 デフォルトは None です。
パラメータを指定したサンプルです。
def person(): form = SQLFORM(db.person, request.args(0), True).process( onsuccess=lambda form: auth.archive(form, db.bk_person)) return dict(form=form)
アーカイブテーブルとして、bk_person を指定します。
-