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>