Rename pre_ and post_syncdb to *_migrate, with aliases from old names

This commit is contained in:
Andrew Godwin 2013-07-30 11:52:52 +01:00
parent 086389f5fc
commit 68e0a169c4
13 changed files with 113 additions and 74 deletions

View File

@ -187,7 +187,7 @@ def get_default_username(check_db=True):
return '' return ''
return default_username return default_username
signals.post_syncdb.connect(create_permissions, signals.post_migrate.connect(create_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions") dispatch_uid="django.contrib.auth.management.create_permissions")
signals.post_syncdb.connect(create_superuser, signals.post_migrate.connect(create_superuser,
sender=auth_app, dispatch_uid="django.contrib.auth.management.create_superuser") sender=auth_app, dispatch_uid="django.contrib.auth.management.create_superuser")

View File

@ -88,7 +88,7 @@ def update_all_contenttypes(verbosity=2, **kwargs):
for app in get_apps(): for app in get_apps():
update_contenttypes(app, None, verbosity, **kwargs) update_contenttypes(app, None, verbosity, **kwargs)
signals.post_syncdb.connect(update_contenttypes) signals.post_migrate.connect(update_contenttypes)
if __name__ == "__main__": if __name__ == "__main__":
update_all_contenttypes() update_all_contenttypes()

View File

@ -45,7 +45,7 @@ class SpatiaLiteCreation(DatabaseCreation):
# We need to then do a flush to ensure that any data installed by # We need to then do a flush to ensure that any data installed by
# custom SQL has been removed. The only test data should come from # custom SQL has been removed. The only test data should come from
# test fixtures, or autogenerated from post_syncdb triggers. # test fixtures, or autogenerated from post_migrate triggers.
# This has the side effect of loading initial data (which was # This has the side effect of loading initial data (which was
# intentionally skipped in the syncdb). # intentionally skipped in the syncdb).
call_command('flush', call_command('flush',

View File

@ -33,4 +33,4 @@ def create_default_site(app, created_models, verbosity, db, **kwargs):
Site.objects.clear_cache() Site.objects.clear_cache()
signals.post_syncdb.connect(create_default_site, sender=site_app) signals.post_migrate.connect(create_default_site, sender=site_app)

View File

@ -6,7 +6,7 @@ from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
from django.core.management import call_command from django.core.management import call_command
from django.core.management.base import NoArgsCommand, CommandError from django.core.management.base import NoArgsCommand, CommandError
from django.core.management.color import no_style from django.core.management.color import no_style
from django.core.management.sql import sql_flush, emit_post_sync_signal from django.core.management.sql import sql_flush, emit_post_migrate_signal
from django.utils.importlib import import_module from django.utils.importlib import import_module
from django.utils.six.moves import input from django.utils.six.moves import input
from django.utils import six from django.utils import six
@ -23,8 +23,8 @@ class Command(NoArgsCommand):
help='Tells Django not to load any initial data after database synchronization.'), help='Tells Django not to load any initial data after database synchronization.'),
) )
help = ('Returns the database to the state it was in immediately after ' help = ('Returns the database to the state it was in immediately after '
'syncdb was executed. This means that all data will be removed ' 'migrate was first executed. This means that all data will be removed '
'from the database, any post-synchronization handlers will be ' 'from the database, any post-migration handlers will be '
're-executed, and the initial_data fixture will be re-installed.') 're-executed, and the initial_data fixture will be re-installed.')
def handle_noargs(self, **options): def handle_noargs(self, **options):
@ -35,7 +35,7 @@ class Command(NoArgsCommand):
# The following are stealth options used by Django's internals. # The following are stealth options used by Django's internals.
reset_sequences = options.get('reset_sequences', True) reset_sequences = options.get('reset_sequences', True)
allow_cascade = options.get('allow_cascade', False) allow_cascade = options.get('allow_cascade', False)
inhibit_post_syncdb = options.get('inhibit_post_syncdb', False) inhibit_post_migrate = options.get('inhibit_post_migrate', False)
self.style = no_style() self.style = no_style()
@ -54,7 +54,7 @@ class Command(NoArgsCommand):
if interactive: if interactive:
confirm = input("""You have requested a flush of the database. confirm = input("""You have requested a flush of the database.
This will IRREVERSIBLY DESTROY all data currently in the %r database, This will IRREVERSIBLY DESTROY all data currently in the %r database,
and return each table to the state it was in after syncdb. and return each table to a fresh state.
Are you sure you want to do this? Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: """ % connection.settings_dict['NAME']) Type 'yes' to continue, or 'no' to cancel: """ % connection.settings_dict['NAME'])
@ -77,8 +77,8 @@ Are you sure you want to do this?
"The full error: %s") % (connection.settings_dict['NAME'], e) "The full error: %s") % (connection.settings_dict['NAME'], e)
six.reraise(CommandError, CommandError(new_msg), sys.exc_info()[2]) six.reraise(CommandError, CommandError(new_msg), sys.exc_info()[2])
if not inhibit_post_syncdb: if not inhibit_post_migrate:
self.emit_post_syncdb(verbosity, interactive, db) self.emit_post_migrate(verbosity, interactive, db)
# Reinstall the initial_data fixture. # Reinstall the initial_data fixture.
if options.get('load_initial_data'): if options.get('load_initial_data'):
@ -89,13 +89,13 @@ Are you sure you want to do this?
self.stdout.write("Flush cancelled.\n") self.stdout.write("Flush cancelled.\n")
@staticmethod @staticmethod
def emit_post_syncdb(verbosity, interactive, database): def emit_post_migrate(verbosity, interactive, database):
# Emit the post sync signal. This allows individual applications to # Emit the post migrate signal. This allows individual applications to
# respond as if the database had been sync'd from scratch. # respond as if the database had been migrated from scratch.
all_models = [] all_models = []
for app in models.get_apps(): for app in models.get_apps():
all_models.extend([ all_models.extend([
m for m in models.get_models(app, include_auto_created=True) m for m in models.get_models(app, include_auto_created=True)
if router.allow_syncdb(database, m) if router.allow_syncdb(database, m)
]) ])
emit_post_sync_signal(set(all_models), verbosity, interactive, database) emit_post_migrate_signal(set(all_models), verbosity, interactive, database)

View File

@ -6,7 +6,7 @@ from django.conf import settings
from django.core.management import call_command from django.core.management import call_command
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.core.management.color import color_style, no_style from django.core.management.color import color_style, no_style
from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal, emit_pre_sync_signal from django.core.management.sql import custom_sql_for_model, emit_post_migrate_signal, emit_pre_migrate_signal
from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
from django.db.migrations.executor import MigrationExecutor from django.db.migrations.executor import MigrationExecutor
from django.db.migrations.loader import AmbiguityError from django.db.migrations.loader import AmbiguityError
@ -99,10 +99,14 @@ class Command(BaseCommand):
# Run the syncdb phase. # Run the syncdb phase.
# If you ever manage to get rid of this, I owe you many, many drinks. # If you ever manage to get rid of this, I owe you many, many drinks.
# Note that pre_migrate is called from inside here, as it needs
# the list of models about to be installed.
if run_syncdb: if run_syncdb:
if self.verbosity >= 1: if self.verbosity >= 1:
self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:")) self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:"))
self.sync_apps(connection, executor.loader.unmigrated_apps) created_models = self.sync_apps(connection, executor.loader.unmigrated_apps)
else:
created_models = []
# Migrate! # Migrate!
if self.verbosity >= 1: if self.verbosity >= 1:
@ -113,6 +117,10 @@ class Command(BaseCommand):
else: else:
executor.migrate(targets, plan, fake=options.get("fake", False)) executor.migrate(targets, plan, fake=options.get("fake", False))
# Send the post_migrate signal, so individual apps can do whatever they need
# to do at this point.
emit_post_migrate_signal(created_models, self.verbosity, self.interactive, connection.alias)
def migration_progress_callback(self, action, migration): def migration_progress_callback(self, action, migration):
if self.verbosity >= 1: if self.verbosity >= 1:
if action == "apply_start": if action == "apply_start":
@ -159,7 +167,7 @@ class Command(BaseCommand):
) )
create_models = set([x for x in itertools.chain(*manifest.values())]) create_models = set([x for x in itertools.chain(*manifest.values())])
emit_pre_sync_signal(create_models, self.verbosity, self.interactive, connection.alias) emit_pre_migrate_signal(create_models, self.verbosity, self.interactive, connection.alias)
# Create the tables for each model # Create the tables for each model
if self.verbosity >= 1: if self.verbosity >= 1:
@ -188,10 +196,6 @@ class Command(BaseCommand):
# If you can prove we don't need this, remove it. # If you can prove we don't need this, remove it.
transaction.set_dirty(using=connection.alias) transaction.set_dirty(using=connection.alias)
# Send the post_syncdb signal, so individual apps can do whatever they need
# to do at this point.
emit_post_sync_signal(created_models, self.verbosity, self.interactive, connection.alias)
# The connection may have been closed by a syncdb handler. # The connection may have been closed by a syncdb handler.
cursor = connection.cursor() cursor = connection.cursor()
@ -220,6 +224,7 @@ class Command(BaseCommand):
if self.verbosity >= 1: if self.verbosity >= 1:
self.stdout.write(" Installing indexes...\n") self.stdout.write(" Installing indexes...\n")
# Install SQL indices for all newly created models # Install SQL indices for all newly created models
for app_name, model_list in manifest.items(): for app_name, model_list in manifest.items():
for model in model_list: for model in model_list:
@ -238,3 +243,5 @@ class Command(BaseCommand):
# Load initial_data fixtures (unless that has been disabled) # Load initial_data fixtures (unless that has been disabled)
if self.load_initial_data: if self.load_initial_data:
call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=connection.alias, skip_validation=True) call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=connection.alias, skip_validation=True)
return created_models

View File

@ -192,25 +192,25 @@ def custom_sql_for_model(model, style, connection):
return output return output
def emit_pre_sync_signal(create_models, verbosity, interactive, db): def emit_pre_migrate_signal(create_models, verbosity, interactive, db):
# Emit the pre_sync signal for every application. # Emit the pre_migrate signal for every application.
for app in models.get_apps(): for app in models.get_apps():
app_name = app.__name__.split('.')[-2] app_name = app.__name__.split('.')[-2]
if verbosity >= 2: if verbosity >= 2:
print("Running pre-sync handlers for application %s" % app_name) print("Running pre-migrate handlers for application %s" % app_name)
models.signals.pre_syncdb.send(sender=app, app=app, models.signals.pre_migrate.send(sender=app, app=app,
create_models=create_models, create_models=create_models,
verbosity=verbosity, verbosity=verbosity,
interactive=interactive, interactive=interactive,
db=db) db=db)
def emit_post_sync_signal(created_models, verbosity, interactive, db): def emit_post_migrate_signal(created_models, verbosity, interactive, db):
# Emit the post_sync signal for every application. # Emit the post_migrate signal for every application.
for app in models.get_apps(): for app in models.get_apps():
app_name = app.__name__.split('.')[-2] app_name = app.__name__.split('.')[-2]
if verbosity >= 2: if verbosity >= 2:
print("Running post-sync handlers for application %s" % app_name) print("Running post-migrate handlers for application %s" % app_name)
models.signals.post_syncdb.send(sender=app, app=app, models.signals.post_migrate.send(sender=app, app=app,
created_models=created_models, verbosity=verbosity, created_models=created_models, verbosity=verbosity,
interactive=interactive, db=db) interactive=interactive, db=db)

View File

@ -344,7 +344,7 @@ class BaseDatabaseCreation(object):
# We need to then do a flush to ensure that any data installed by # We need to then do a flush to ensure that any data installed by
# custom SQL has been removed. The only test data should come from # custom SQL has been removed. The only test data should come from
# test fixtures, or autogenerated from post_syncdb triggers. # test fixtures, or autogenerated from post_migrate triggers.
# This has the side effect of loading initial data (which was # This has the side effect of loading initial data (which was
# intentionally skipped in the syncdb). # intentionally skipped in the syncdb).
call_command('flush', call_command('flush',

View File

@ -12,7 +12,9 @@ post_save = Signal(providing_args=["instance", "raw", "created", "using", "updat
pre_delete = Signal(providing_args=["instance", "using"], use_caching=True) pre_delete = Signal(providing_args=["instance", "using"], use_caching=True)
post_delete = Signal(providing_args=["instance", "using"], use_caching=True) post_delete = Signal(providing_args=["instance", "using"], use_caching=True)
pre_syncdb = Signal(providing_args=["app", "create_models", "verbosity", "interactive", "db"]) pre_migrate = Signal(providing_args=["app", "create_models", "verbosity", "interactive", "db"])
post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive", "db"], use_caching=True) pre_syncdb = pre_migrate
post_migrate = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive", "db"], use_caching=True)
post_syncdb = post_migrate
m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set", "using"], use_caching=True) m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set", "using"], use_caching=True)

View File

@ -718,7 +718,7 @@ class TransactionTestCase(SimpleTestCase):
"""Performs any pre-test setup. This includes: """Performs any pre-test setup. This includes:
* If the class has an 'available_apps' attribute, restricting the app * If the class has an 'available_apps' attribute, restricting the app
cache to these applications, then firing post_syncdb -- it must run cache to these applications, then firing post_migrate -- it must run
with the correct set of applications for the test case. with the correct set of applications for the test case.
* If the class has a 'fixtures' attribute, installing these fixtures. * If the class has a 'fixtures' attribute, installing these fixtures.
""" """
@ -726,8 +726,7 @@ class TransactionTestCase(SimpleTestCase):
if self.available_apps is not None: if self.available_apps is not None:
cache.set_available_apps(self.available_apps) cache.set_available_apps(self.available_apps)
for db_name in self._databases_names(include_mirrors=False): for db_name in self._databases_names(include_mirrors=False):
flush.Command.emit_post_syncdb( flush.Command.emit_post_migrate(verbosity=0, interactive=False, database=db_name)
verbosity=0, interactive=False, database=db_name)
try: try:
self._fixture_setup() self._fixture_setup()
except Exception: except Exception:
@ -772,7 +771,7 @@ class TransactionTestCase(SimpleTestCase):
"""Performs any post-test things. This includes: """Performs any post-test things. This includes:
* Flushing the contents of the database, to leave a clean slate. If * Flushing the contents of the database, to leave a clean slate. If
the class has an 'available_apps' attribute, post_syncdb isn't fired. the class has an 'available_apps' attribute, post_migrate isn't fired.
* Force-closing the connection, so the next test gets a clean cursor. * Force-closing the connection, so the next test gets a clean cursor.
""" """
try: try:
@ -790,14 +789,14 @@ class TransactionTestCase(SimpleTestCase):
cache.unset_available_apps() cache.unset_available_apps()
def _fixture_teardown(self): def _fixture_teardown(self):
# Allow TRUNCATE ... CASCADE and don't emit the post_syncdb signal # Allow TRUNCATE ... CASCADE and don't emit the post_migrate signal
# when flushing only a subset of the apps # when flushing only a subset of the apps
for db_name in self._databases_names(include_mirrors=False): for db_name in self._databases_names(include_mirrors=False):
call_command('flush', verbosity=0, interactive=False, call_command('flush', verbosity=0, interactive=False,
database=db_name, skip_validation=True, database=db_name, skip_validation=True,
reset_sequences=False, reset_sequences=False,
allow_cascade=self.available_apps is not None, allow_cascade=self.available_apps is not None,
inhibit_post_syncdb=self.available_apps is not None) inhibit_post_migrate=self.available_apps is not None)
def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True): def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True):
items = six.moves.map(transform, qs) items = six.moves.map(transform, qs)

View File

@ -267,7 +267,7 @@ To enable the sites framework, follow these steps:
3. Run :djadmin:`migrate`. 3. Run :djadmin:`migrate`.
``django.contrib.sites`` registers a ``django.contrib.sites`` registers a
:data:`~django.db.models.signals.post_syncdb` signal handler which creates a :data:`~django.db.models.signals.post_migrate` signal handler which creates a
default site named ``example.com`` with the domain ``example.com``. This site default site named ``example.com`` with the domain ``example.com``. This site
will also be created after Django creates the test database. To set the will also be created after Django creates the test database. To set the
correct name and domain for your project, you can use an :doc:`initial data correct name and domain for your project, you can use an :doc:`initial data

View File

@ -360,40 +360,36 @@ Management signals
Signals sent by :doc:`django-admin </ref/django-admin>`. Signals sent by :doc:`django-admin </ref/django-admin>`.
pre_syncdb pre_migrate
---------- -----------
.. data:: django.db.models.signals.pre_syncdb .. data:: django.db.models.signals.pre_migrate
:module: :module:
Sent by the :djadmin:`syncdb` command before it starts to install an Sent by the :djadmin:`migrate` command before it starts to install an
application. application.
Any handlers that listen to this signal need to be written in a particular Any handlers that listen to this signal need to be written in a particular
place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If
handlers are registered anywhere else they may not be loaded by handlers are registered anywhere else they may not be loaded by
:djadmin:`syncdb`. :djadmin:`migrate`.
Arguments sent with this signal: Arguments sent with this signal:
``sender`` ``sender``
The ``models`` module that was just installed. That is, if The ``models`` module of the app about to be migrated/synced.
:djadmin:`syncdb` just installed an app called ``"foo.bar.myapp"``, For example, if :djadmin:`migrate` is about to install
``sender`` will be the ``foo.bar.myapp.models`` module. an app called ``"foo.bar.myapp"``, ``sender`` will be the
``foo.bar.myapp.models`` module.
``app`` ``app``
Same as ``sender``. Same as ``sender``.
``create_models``
A list of the model classes from any app which :djadmin:`syncdb` plans to
create.
``verbosity`` ``verbosity``
Indicates how much information manage.py is printing on screen. See Indicates how much information manage.py is printing on screen. See
the :djadminopt:`--verbosity` flag for details. the :djadminopt:`--verbosity` flag for details.
Functions which listen for :data:`pre_syncdb` should adjust what they Functions which listen for :data:`pre_migrate` should adjust what they
output to the screen based on the value of this argument. output to the screen based on the value of this argument.
``interactive`` ``interactive``
@ -407,42 +403,57 @@ Arguments sent with this signal:
``db`` ``db``
The alias of database on which a command will operate. The alias of database on which a command will operate.
post_syncdb
-----------
.. data:: django.db.models.signals.post_syncdb pre_syncdb
----------
.. data:: django.db.models.signals.pre_syncdb
:module: :module:
Sent by the :djadmin:`syncdb` command after it installs an application, and the .. deprecated:: 1.7
This signal has been renamed to :data:`~django.db.models.signals.pre_migrate`.
Alias of :data:`django.db.models.signals.pre_migrate`. As long as this alias
is present, for backwards-compatability this signal has an extra argument it sends:
``create_models``
A list of the model classes from any app which :djadmin:`migrate` is
going to create, **only if the app has no migrations**.
post_migrate
------------
.. data:: django.db.models.signals.post_migrate
:module:
Sent by the :djadmin:`migrate` command after it installs an application, and the
:djadmin:`flush` command. :djadmin:`flush` command.
Any handlers that listen to this signal need to be written in a particular Any handlers that listen to this signal need to be written in a particular
place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If
handlers are registered anywhere else they may not be loaded by handlers are registered anywhere else they may not be loaded by
:djadmin:`syncdb`. It is important that handlers of this signal perform :djadmin:`migrate`. It is important that handlers of this signal perform
idempotent changes (e.g. no database alterations) as this may cause the idempotent changes (e.g. no database alterations) as this may cause the
:djadmin:`flush` management command to fail if it also ran during the :djadmin:`flush` management command to fail if it also ran during the
:djadmin:`syncdb` command. :djadmin:`migrate` command.
Arguments sent with this signal: Arguments sent with this signal:
``sender`` ``sender``
The ``models`` module that was just installed. That is, if The ``models`` module that was just installed. That is, if
:djadmin:`syncdb` just installed an app called ``"foo.bar.myapp"``, :djadmin:`migrate` just installed an app called ``"foo.bar.myapp"``,
``sender`` will be the ``foo.bar.myapp.models`` module. ``sender`` will be the ``foo.bar.myapp.models`` module.
``app`` ``app``
Same as ``sender``. Same as ``sender``.
``created_models``
A list of the model classes from any app which :djadmin:`syncdb` has
created so far.
``verbosity`` ``verbosity``
Indicates how much information manage.py is printing on screen. See Indicates how much information manage.py is printing on screen. See
the :djadminopt:`--verbosity` flag for details. the :djadminopt:`--verbosity` flag for details.
Functions which listen for :data:`post_syncdb` should adjust what they Functions which listen for :data:`post_migrate` should adjust what they
output to the screen based on the value of this argument. output to the screen based on the value of this argument.
``interactive`` ``interactive``
@ -459,14 +470,34 @@ Arguments sent with this signal:
For example, ``yourapp/management/__init__.py`` could be written like:: For example, ``yourapp/management/__init__.py`` could be written like::
from django.db.models.signals import post_syncdb from django.db.models.signals import post_migrate
import yourapp.models import yourapp.models
def my_callback(sender, **kwargs): def my_callback(sender, **kwargs):
# Your specific logic here # Your specific logic here
pass pass
post_syncdb.connect(my_callback, sender=yourapp.models) post_migrate.connect(my_callback, sender=yourapp.models)
post_syncdb
-----------
.. data:: django.db.models.signals.post_syncdb
:module:
.. deprecated:: 1.7
This signal has been renamed to :data:`~django.db.models.signals.post_migrate`.
Alias of :data:`django.db.models.signals.post_migrate`. As long as this alias
is present, for backwards-compatability this signal has an extra argument it sends:
``created_models``
A list of the model classes from any app which :djadmin:`migrate` has
created, **only if the app has no migrations**.
Request/response signals Request/response signals
======================== ========================

View File

@ -182,7 +182,7 @@ Advanced features of ``TransactionTestCase``
By default, ``available_apps`` is set to ``None``. After each test, Django By default, ``available_apps`` is set to ``None``. After each test, Django
calls :djadmin:`flush` to reset the database state. This empties all tables calls :djadmin:`flush` to reset the database state. This empties all tables
and emits the :data:`~django.db.models.signals.post_syncdb` signal, which and emits the :data:`~django.db.models.signals.post_migrate` signal, which
re-creates one content type and three permissions for each model. This re-creates one content type and three permissions for each model. This
operation gets expensive proportionally to the number of models. operation gets expensive proportionally to the number of models.
@ -190,13 +190,13 @@ Advanced features of ``TransactionTestCase``
behave as if only the models from these applications were available. The behave as if only the models from these applications were available. The
behavior of ``TransactionTestCase`` changes as follows: behavior of ``TransactionTestCase`` changes as follows:
- :data:`~django.db.models.signals.post_syncdb` is fired before each - :data:`~django.db.models.signals.post_migrate` is fired before each
test to create the content types and permissions for each model in test to create the content types and permissions for each model in
available apps, in case they're missing. available apps, in case they're missing.
- After each test, Django empties only tables corresponding to models in - After each test, Django empties only tables corresponding to models in
available apps. However, at the database level, truncation may cascade to available apps. However, at the database level, truncation may cascade to
related models in unavailable apps. Furthermore related models in unavailable apps. Furthermore
:data:`~django.db.models.signals.post_syncdb` isn't fired; it will be :data:`~django.db.models.signals.post_migrate` isn't fired; it will be
fired by the next ``TransactionTestCase``, after the correct set of fired by the next ``TransactionTestCase``, after the correct set of
applications is selected. applications is selected.
@ -205,10 +205,10 @@ Advanced features of ``TransactionTestCase``
cause unrelated tests to fail. Be careful with tests that use sessions; cause unrelated tests to fail. Be careful with tests that use sessions;
the default session engine stores them in the database. the default session engine stores them in the database.
Since :data:`~django.db.models.signals.post_syncdb` isn't emitted after Since :data:`~django.db.models.signals.post_migrate` isn't emitted after
flushing the database, its state after a ``TransactionTestCase`` isn't the flushing the database, its state after a ``TransactionTestCase`` isn't the
same as after a ``TestCase``: it's missing the rows created by listeners same as after a ``TestCase``: it's missing the rows created by listeners
to :data:`~django.db.models.signals.post_syncdb`. Considering the to :data:`~django.db.models.signals.post_migrate`. Considering the
:ref:`order in which tests are executed <order-of-tests>`, this isn't an :ref:`order in which tests are executed <order-of-tests>`, this isn't an
issue, provided either all ``TransactionTestCase`` in a given test suite issue, provided either all ``TransactionTestCase`` in a given test suite
declare ``available_apps``, or none of them. declare ``available_apps``, or none of them.