フィクスチャ (fixture)

フィクスチャ (fixture) とは、シリアライズされたデータベースのコンテンツを含むファイルのコレクションです。各フィクスチャにはユニークな名前があり、フィクスチャを構成するファイルは、複数のアプリケーションの複数のディレクトリに分散できます。

フィクスチャを生成する

フィクスチャは manage.py dumpdata によって生成できます。また、 シリアライゼーションツール を直接使って、あるいは手書きでカスタムフィクスチャを生成することもできます。

フィクスチャを使う

フィクスチャを使えば、 テスト のためのデータを事前に投入できます。

class MyTestCase(TestCase):
    fixtures = ["fixture-label"]

または 初期データloaddata コマンドを使って提供することもできます:

django-admin loaddata <fixture label>

Djangoにフィクスチャを認識させる

Django はこれらの場所でフィクスチャを探します:

  1. インストールされた各アプリケーションの fixtures ディレクトリ内

  2. FIXTURE_DIRS 設定にリストされている任意のディレクトリ内

  3. フィクスチャによって名前が付けられたリテラル パス内

Django は、指定されたフィクスチャ名と一致するフィクスチャをすべて読み込みます。指定されたフィクスチャに拡張子がある場合、そのタイプのフィクスチャだけが読み込まれます。たとえば

django-admin loaddata mydata.json

mydata と呼ばれる JSON フィクスチャのみを読み込みます。フィクスチャの拡張子は シリアライザ に登録された名前 (例: jsonxml) に対応していなければなりません。

拡張子を省略した場合、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 のドキュメントを参照してください)。

フィクスチャはどのようにデータベースに保存されるか

When fixture files are processed, the data is saved to the database as is. Model defined save() methods are not called, and any pre_save, post_save, or m2m_changed signals will be called with raw=True since the instance only contains attributes that are local to the model. You may, for example, want to disable handlers that access related fields that aren't present during fixture loading and would otherwise raise an exception:

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 の間だけでなく、フィクスチャがデシリアライズされるときは常にシグナルを無効にすることに注意してください。

Changed in Django 6.1:

The raw argument was added to m2m_changed signals.

圧縮されたフィクスチャ

フィクスチャは zipgzbz2lzmaxz フォーマットのいずれかに圧縮される場合があります。次に例を示します。

django-admin loaddata mydata.json

これは mydata.json, mydata.json.zip, mydata.json.gz, mydata.json.bz2, mydata.json.lzma, mydata.json.xz のいずれかを探します。圧縮アーカイブに含まれる最初のファイルが使用されます。

同じ名前で異なるフィクスチャタイプを持つ2つのフィクスチャが見つかった場合(例えば、 mydata.jsonmydata.xml.gz が同じフィクスチャディレクトリで見つかった場合)、フィクスチャのインストールは中断され、 loaddata の呼び出しでインストールされたデータはデータベースから削除されることに注意してください。

MyISAM を使用した MySQL とフィクスチャ

MySQL の MyISAM ストレージエンジンはトランザクションや制約をサポートしていないため、 MyISAM を使用する場合、フィクスチャデータの検証や、複数のトランザクションファイルが見つかった場合のロールバックはできません。

データベース別のフィクスチャ

複数のデータベースをセットアップしている場合、あるデータベースには読み込ませたいが、別のデータベースには読み込ませたくないフィクスチャ・データがあるかもしれません。このような状況では、フィクスチャの名前にデータベース識別子を追加できます。

例えば、 DATABASES 設定に users データベースが定義されている場合、フィクスチャの名前を mydata.users.json または mydata.users.json.gz とすると、 users データベースにデータを読み込むと指定したときだけフィクスチャが読み込まれます。