Search code examples
pythondjangomongodbpostgresqldjongo

Django - Unable to test with two databases (postgres with gis extension and mongoDB (Djongo)


I'm not able to test two databases using Django's unittests.

My databases configuration:

DATABASES = {
'default': {},
'postgres': {
    'ENGINE': 'django.contrib.gis.db.backends.postgis',
    'NAME': "<name>",
    'USER': "<user>",
    'PASSWORD': "<pass>",
    'HOST': "localhost",
    'PORT': 5432,
},
'mongodb': {
    'ENGINE': 'djongo',
    'NAME': '<name>',
    'ENFORCE_SCHEMA': True,
}

}

my simple test:

from django.test import TestCase



class TestFormModel(TestCase):
    databases = {'postgres', 'mongodb'}


    def test_generate_persistent_data_indexes(self):
        assert True

Error that I'm getting:

AttributeError: 'DatabaseOperations' object has no attribute 'geo_db_type'

I migrated both databases

When I set postgres database as a default I'm getting:

self = <django.db.backends.utils.CursorWrapper object at 0x1132de580>
sql = 'SELECT "user_userdata"."id", "user_userdata"."user_profile", 
"user_userdata"."data", "user_userdata"."is_persistent" FROM "user_userdata" ORDER BY 
"user_userdata"."id" ASC', params = () 
ignored_wrapper_args = (False, {'connection': 
<django.contrib.gis.db.backends.postgis.base.DatabaseWrapper object at 0x112d96f70>, 
'cursor': <django.db.backends.utils.CursorWrapper object at 0x1132de580>})

    def _execute(self, sql, params, *ignored_wrapper_args):
        self.db.validate_no_broken_transaction()
        with self.db.wrap_database_errors:
            if params is None:
            return self.cursor.execute(sql)
            else:
>               return self.cursor.execute(sql, params)
E               django.db.utils.ProgrammingError: column user_userdata.data does not 
exist
E               LINE 1: ...r_userdata"."id", "user_userdata"."user_profile", 
"user_user...
E                                                                            ^

venv/lib/python3.8/site-packages/django/db/backends/utils.py:84: ProgrammingError

My MongoDB model:

class UserData(djongo_models.Model):
    id = djongo_models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user_profile = djongo_models.UUIDField()
    data = djongo_models.JSONField(default={})
    is_persistent = djongo_models.BooleanField(default=False)
    objects = djongo_models.DjongoManager()

Update: My database router was pointing to the wrong database in the allow_migrate method. Migrations from Postgres was applying to MongoDB and this caused a problem.

(Not) Fun fact: model._meta.app_label returns lowercase models names, I spent about 2 hours getting it right.

allow migrate method from my router:

only UserData model from User app is using mongodb

    ROUTE_APP_LABEL = 'user'
    ROUTE_MODEL_LABELS = {'userdata'}

    def allow_migrate(self, db, app_label, model_name=None, **hints):
    """
    Migrate specified models in specified apps to mongodb
    OR
    Migrate rest of the models if database is default (postgres)
    """
    if app_label == self.ROUTE_APP_LABEL and model_name in self.ROUTE_MODEL_LABELS:
        return db == 'mongodb'

    return db != 'mongodb'

Solution

  • I managed to resolve this issue.

    My database router was pointing to the wrong database in the allow_migrate method. Migrations from Postgres was applying to MongoDB and this caused a problem.

    (Not) Fun fact: model._meta.app_label returns lowercase models names, I spent about 2 hours getting it right.

    allow migrate method from my router:

    only UserData model from User app is using mongodb

        ROUTE_APP_LABEL = 'user'
        ROUTE_MODEL_LABELS = {'userdata'}
    
        def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Migrate specified models in specified apps to mongodb
        OR
        Migrate rest of the models if database is default (postgres)
        """
        if app_label == self.ROUTE_APP_LABEL and model_name in self.ROUTE_MODEL_LABELS:
            return db == 'mongodb'
    
        return db != 'mongodb'