Django TestCase verwendet keine Transaktionen in der sekundären Datenbank

Ich benutze Django 1.3.1. Ich habe zwei Datenbanken, einige meiner Modelle befinden sich in der einen Datenbank, andere in der anderen. Beide Datenbanken sind contrib.gis.db.backends.postgis-Datenbanken.

Zu meiner Überraschung macht Djangos TestCase keine Änderungen rückgängig, die ich zwischen den Tests in der sekundären Datenbank vorgenommen habe.

Im folgenden Code ist myproject.models.WellOwner ein sehr einfaches Modell, das im Grunde nur ein Feld "name" enthält. Der Router gibt an, dass er sich in der sekundären Datenbank befinden soll. Die Bestätigung im ersten Test ist erfolgreich, der zweite Test schlägt fehl:

<code>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!
</code>

Ich gehe davon aus, dass Django dies in eine Transaktion für die Standarddatenbank einwickelt, nicht jedoch für die Sekundärdatenbank. Ist das ein bekanntes Problem? Gibt es eine Lösung? In 1.4 vielleicht? Mein Google-fu schlägt fehl.

(Wenn ich DATABASE_ROUTERS in den Einstellungen auf [] ändere, damit alles in dieselbe Datenbank verschoben wird, verschwindet das Problem.)

Ich werde den gesamten Code des Routers hinzufügen, falls es hilft:

<code>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
</code>

Antworten auf die Frage(1)

Ihre Antwort auf die Frage