123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- .. _fixtures-explanation:
- ========
- Fixtures
- ========
- .. seealso::
- * :doc:`/howto/initial-data`
- What is a fixture?
- ==================
- A *fixture* is a collection of files that contain the serialized contents of
- the database. Each fixture has a unique name, and the files that comprise the
- fixture can be distributed over multiple directories, in multiple applications.
- How to produce a fixture?
- =========================
- Fixtures can be generated by :djadmin:`manage.py dumpdata <dumpdata>`. It's
- also possible to generate custom fixtures by directly using
- :doc:`serialization documentation </topics/serialization>` tools or even by
- handwriting them.
- What to use a fixture for?
- ==========================
- Fixtures can be used to pre-populate database with data for
- :ref:`tests <topics-testing-fixtures>` or to provide some :ref:`initial data
- <initial-data-via-fixtures>`.
- Were Django looks for fixtures?
- ===============================
- Django will search in three locations for fixtures:
- 1. In the ``fixtures`` directory of every installed application
- 2. In any directory named in the :setting:`FIXTURE_DIRS` setting
- 3. In the literal path named by the fixture
- Django will load any and all fixtures it finds in these locations that match
- the provided fixture names.
- If the named fixture has a file extension, only fixtures of that type
- will be loaded. For example:
- .. code-block:: shell
- django-admin loaddata mydata.json
- would only load JSON fixtures called ``mydata``. The fixture extension
- must correspond to the registered name of a
- :ref:`serializer <serialization-formats>` (e.g., ``json`` or ``xml``).
- If you omit the extensions, Django will search all available fixture types
- for a matching fixture. For example:
- .. code-block:: shell
- django-admin loaddata mydata
- would look for any fixture of any fixture type called ``mydata``. If a fixture
- directory contained ``mydata.json``, that fixture would be loaded
- as a JSON fixture.
- The fixtures that are named can include directory components. These
- directories will be included in the search path. For example:
- .. code-block:: shell
- django-admin loaddata foo/bar/mydata.json
- would search ``<app_label>/fixtures/foo/bar/mydata.json`` for each installed
- application, ``<dirname>/foo/bar/mydata.json`` for each directory in
- :setting:`FIXTURE_DIRS`, and the literal path ``foo/bar/mydata.json``.
- How fixtures are saved to the database?
- =======================================
- When fixture files are processed, the data is saved to the database as is.
- Model defined :meth:`~django.db.models.Model.save` methods are not called, and
- any :data:`~django.db.models.signals.pre_save` or
- :data:`~django.db.models.signals.post_save` 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)
- You could also write a decorator to encapsulate this logic::
- 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):
- ...
- Just be aware that this logic will disable the signals whenever fixtures are
- deserialized, not just during ``loaddata``.
- Note that the order in which fixture files are processed is undefined. However,
- all fixture data is installed as a single transaction, so data in
- one fixture can reference data in another fixture. If the database backend
- supports row-level constraints, these constraints will be checked at the
- end of the transaction.
- Compressed fixtures
- ===================
- Fixtures may be compressed in ``zip``, ``gz``, ``bz2``, ``lzma``, or ``xz``
- format. For example:
- .. code-block:: shell
- django-admin loaddata mydata.json
- would look for any of ``mydata.json``, ``mydata.json.zip``, ``mydata.json.gz``,
- ``mydata.json.bz2``, ``mydata.json.lzma``, or ``mydata.json.xz``. The first
- file contained within a compressed archive is used.
- Note that if two fixtures with the same name but different
- fixture type are discovered (for example, if ``mydata.json`` and
- ``mydata.xml.gz`` were found in the same fixture directory), fixture
- installation will be aborted, and any data installed in the call to
- ``loaddata`` will be removed from the database.
- .. admonition:: MySQL with MyISAM and fixtures
- The MyISAM storage engine of MySQL doesn't support transactions or
- constraints, so if you use MyISAM, you won't get validation of fixture
- data, or a rollback if multiple transaction files are found.
- Database-specific fixtures
- ==========================
- If you're in a multi-database setup, you might have fixture data that
- you want to load onto one database, but not onto another. In this
- situation, you can add a database identifier into the names of your fixtures.
- For example, if your :setting:`DATABASES` setting has a ``users`` database
- defined, name the fixture ``mydata.users.json`` or
- ``mydata.users.json.gz`` and the fixture will only be loaded when you
- specify you want to load data into the ``users`` database.
|