フィクスチャ (fixture)¶
フィクスチャとは何ですか?¶
フィクスチャ (fixture) とは、シリアライズされたデータベースのコンテンツを含むファイルのコレクションです。各フィクスチャにはユニークな名前があり、フィクスチャを構成するファイルは、複数のアプリケーションの複数のディレクトリに分散できます。
フィクスチャはどのように作成するべきですか?¶
フィクスチャは manage.py dumpdata
によって生成できます。また、 シリアライゼーションツール を直接使って、あるいは手書きでカスタムフィクスチャを生成することもできます。
フィクスチャはどう使えばよいのですか?¶
フィクスチャは テスト 用のデータをあらかじめデータベースに投入するために使えます:
class MyTestCase(TestCase):
fixtures = ["fixture-label"]
または 初期データ を loaddata
コマンドを使って提供することもできます:
django-admin loaddata <fixture label>
Django はどこでフィクスチャを探しますか?¶
Django はこれらの場所でフィクスチャを探します:
インストールされた各アプリケーションの
fixtures
ディレクトリ内FIXTURE_DIRS
設定にリストされている任意のディレクトリ内フィクスチャによって名前が付けられたリテラル パス内
Django は、指定されたフィクスチャ名と一致するフィクスチャをすべて読み込みます。指定されたフィクスチャに拡張子がある場合、そのタイプのフィクスチャだけが読み込まれます。たとえば
django-admin loaddata mydata.json
mydata
と呼ばれる JSON フィクスチャのみを読み込みます。フィクスチャの拡張子は シリアライザ に登録された名前 (例: json
や xml
) に対応していなければなりません。
拡張子を省略した場合、Django は利用可能なすべてのフィクスチャタイプから、マッチするフィクスチャを検索します。例えば
django-admin loaddata mydata
これは mydata
というフィクスチャタイプのフィクスチャを探します。フィクスチャディレクトリに mydata.json
が含まれていれば、そのフィクスチャは JSON フィクスチャとして読み込まれます。
命名されたフィクスチャはディレクトリ・コンポーネントを含むことができます。これらのディレクトリは検索パスに含まれます。たとえば:
django-admin loaddata foo/bar/mydata.json
これは、インストールされている各アプリケーションに対して <app_label>/fixtures/foo/bar/mydata.json
を、 FIXTURE_DIRS
内の各ディレクトリに対して <dirname>/foo/bar/mydata.json
を、そしてリテラルパス foo/bar/mydata.json
を検索します。
フィクスチャが読み込まれる順番¶
複数のフィクスチャを同じ呼び出しで指定できます。たとえば:
django-admin loaddata mammals birds insects
またはテストケースクラスで:
class AnimalTestCase(TestCase):
fixtures = ["mammals", "birds", "insects"]
フィクスチャが読み込まれる順番は、管理コマンドを使うときでも、上で示したようにテストケースクラスでリストアップするときでも、リストアップされた順番に従います。
これらの例では、すべてのアプリケーション( INSTALLED_APPS
で定義されたアプリケーションの順番)から mammals
という名前のすべてのフィクスチャが最初に読み込まれます。続いて、すべての birds
フィクスチャが読み込まれ、続いてすべての insects
フィクスチャが読み込まれます。
データベースのバックエンドが行レベルの制約をサポートしている場合、これらの制約はトランザクションの最後にチェックされることに注意してください。データベース構成が遅延制約チェックをサポートしていない場合、フィクスチャをまたぐリレーションシップは読み込みエラーになるかもしれません(例については MySQL のドキュメントを参照してください)。
フィクスチャはどのようにデータベースに保存されますか?¶
フィクスチャファイルが処理されると、データはそのままデータベースに保存されます。モデルで定義された save()
メソッドは呼び出されず、 pre_save
や post_save
シグナルは raw=True
で呼び出されます。インスタンスはモデルにローカルな属性しか持たないからです。例えば、フィクスチャの読み込み中に存在せず、例外を発生させるようなリレーション先フィールドにアクセスするハンドラを無効にしたい場合があるでしょう:
from django.db.models.signals import post_save
from .models import MyModel
def my_handler(**kwargs):
# disable the handler during fixture loading
if kwargs["raw"]:
return
...
post_save.connect(my_handler, sender=MyModel)
このロジックをカプセル化するデコレータを書くこともできます:
from functools import wraps
def disable_for_loaddata(signal_handler):
"""
Decorator that turns off signal handlers when loading fixture data.
"""
@wraps(signal_handler)
def wrapper(*args, **kwargs):
if kwargs["raw"]:
return
signal_handler(*args, **kwargs)
return wrapper
@disable_for_loaddata
def my_handler(**kwargs): ...
このロジックは、 loaddata
の間だけでなく、フィクスチャがデシリアライズされるときは常にシグナルを無効にすることに注意してください。
圧縮されたフィクスチャ¶
フィクスチャは zip
、gz
、bz2
、lzma
、xz
フォーマットのいずれかに圧縮される場合があります。次に例を示します。
django-admin loaddata mydata.json
これは mydata.json
, mydata.json.zip
, mydata.json.gz
, mydata.json.bz2
, mydata.json.lzma
, mydata.json.xz
のいずれかを探します。圧縮アーカイブに含まれる最初のファイルが使用されます。
同じ名前で異なるフィクスチャタイプを持つ2つのフィクスチャが見つかった場合(例えば、 mydata.json
と mydata.xml.gz
が同じフィクスチャディレクトリで見つかった場合)、フィクスチャのインストールは中断され、 loaddata
の呼び出しでインストールされたデータはデータベースから削除されることに注意してください。
MyISAM を使用した MySQL とフィクスチャ
MySQL の MyISAM ストレージエンジンはトランザクションや制約をサポートしていないため、 MyISAM を使用する場合、フィクスチャデータの検証や、複数のトランザクションファイルが見つかった場合のロールバックはできません。
データベース別のフィクスチャ¶
複数のデータベースをセットアップしている場合、あるデータベースには読み込ませたいが、別のデータベースには読み込ませたくないフィクスチャ・データがあるかもしれません。このような状況では、フィクスチャの名前にデータベース識別子を追加できます。
例えば、 DATABASES
設定に users
データベースが定義されている場合、フィクスチャの名前を mydata.users.json
または mydata.users.json.gz
とすると、 users
データベースにデータを読み込むと指定したときだけフィクスチャが読み込まれます。