1

My code:

  • Django 4.1
  • I am using multiple postgresql schemas for my models, postgresql12 with out-of-box ubuntu 20.04 setup.
  • I am performing unit tests of some code which uses transactions.
  • migrations are created
  • When running other non-transaction tests with django TestCase, everything works normal.
  • When running transaction test with TransactionTestCase (even with empty test function), this happens:
django.db.utils.NotSupportedError: cannot truncate a table referenced in a foreign key constraint
DETAIL:  Table "users_user_permissions" references "auth_permission".
HINT:  Truncate table "users_user_permissions" at the same time, or use TRUNCATE ... CASCADE.
...
django.core.management.base.CommandError: Database test_mike3 couldn't be flushed. Possible reasons:
  * The database isn't running or isn't configured correctly.
  * At least one of the expected database tables doesn't exist.
  * The SQL was invalid.
Hint: Look at the output of 'django-admin sqlflush'. That's the SQL this command wasn't able to run.

django-admin sqlflush:

BEGIN;
TRUNCATE "django_content_type", "auth_group_permissions", "django_session", "auth_group", "auth_permission", "django_admin_log" RESTART IDENTITY;                                                                                                                           
COMMIT;

My solution

I have gone into code and added _fixture_teardown(self) override to my ExampleTestCase(TransactionTestCase): basically changed allow_cascade=True in flush command.

Since by this documentation: https://docs.djangoproject.com/en/4.1/topics/testing/advanced/ not setting available_apps might cause memory leaks, I will probably set all my apps to it so allow_cascade is set to True automatically. Original django code:

    def _fixture_teardown(self):
        # Allow TRUNCATE ... CASCADE and don't emit the post_migrate signal
        # when flushing only a subset of the apps
        for db_name in self._databases_names(include_mirrors=False):
            # Flush the database
            inhibit_post_migrate = (
                self.available_apps is not None or
                (   # Inhibit the post_migrate signal when using serialized
                    # rollback to avoid trying to recreate the serialized data.
                    self.serialized_rollback and
                    hasattr(connections[db_name], '_test_serialized_contents')
                )
            )
            call_command('flush', verbosity=0, interactive=False,
                         database=db_name, reset_sequences=False,
                         allow_cascade=self.available_apps is not None,
                         inhibit_post_migrate=inhibit_post_migrate)

Do you have any idea why is it unable to flush db with TransactionTestCase in the first place?

wtdmn
  • 73
  • 1
  • 7

0 Answers0