8

I am using Django 1.3.1. I have two databases, some of my models live in one database, some in the other. Both databases are contrib.gis.db.backends.postgis databases.

To my surprise, Django's TestCase isn't rolling back changes I made in the secondary database between tests.

In the following code, myproject.models.WellOwner is a very simple model that basically only has a field "name". The router says that it should be in the secondary database. The assertion in the first test succeeds, the second test fails:

from django.test import TestCase
from myproject.models import WellOwner

class SimpleTest(TestCase):
    def test1(self):
        WellOwner.objects.create(name="Remco")
        self.assertEquals(1, WellOwner.objects.count())  # Succeeds

class SimpleTest2(TestCase):
    def test2(self):
        # I would expect to have an empty database at this point
        self.assertEquals(0, WellOwner.objects.count())  # Fails!

I assume that Django wraps this in a transaction on the default database, but not on the secondary database. Is this a known problem? Is there a fix? In 1.4 perhaps? My Google-fu is failing.

(if I change DATABASE_ROUTERS to [] in settings so that everything goes into the same database, the problem disappears)

I'll add the whole code of the router, in case it helps:

SECONDARY_MODELS = ('WellOwner', ...)

import logging
logger = logging.getLogger(__name__)


class GmdbRouter(object):
    """Keep some models in a secondary database."""

    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'gmdb':
            if model._meta.object_name in SECONDARY_MODELS:
                return 'secondary'

        return None

    def db_for_write(self, model, **hints):
        # Same criteria as for reading
        return self.db_for_read(model, **hints)

    def allow_syncdb(self, db, model):
        if db == 'secondary':
            if model._meta.app_label in ('sites', 'south'):
                # Hack for bug https://code.djangoproject.com/ticket/16353
                # When testing, create django_site and south in both databases
                return True

            return self.db_for_read(model) == 'secondary'
        else:
            # Some other db
            if model._meta.app_label == 'gmdb':
                # Our models go in the other db if they don't go into secondary
                return self.db_for_read(model) != 'secondary'

            # Some other model in some other db, no opinion
            return None
3
  • you should include your routers in the question. That is where the problem could be. Commented Apr 12, 2012 at 11:31
  • I have a similar case where the connection._rollback() fix for integrityerror does not work anymore as soon as I move the model to a seperate database. Also postgis models, so maybe there is something wrong in django.contrib.gis.db.models Commented Aug 9, 2012 at 8:26
  • hey RemcoGerlich, did you ever find a resolution? I'm struggling with the same issue stackoverflow.com/questions/12205855/… Commented Sep 4, 2012 at 23:48

2 Answers 2

6

Try this:

class MyTestCase(TestCase):
    multi_db = True

https://docs.djangoproject.com/en/1.2/topics/testing/#django.test.TestCase.multi_db

Sign up to request clarification or add additional context in comments.

Comments

1

Note that multi_db is deprecated since Django 2.2.
The new option to use is databases.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.