1

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'
Unknown123
  • 208
  • 2
  • 13
  • 1
    I have the same problem :( did you try to test databases separately? – strg Jun 23 '21 at 07:33
  • 1
    Yes, but this doesn't work either – Unknown123 Jun 23 '21 at 07:35
  • did you manage to solve it? – Mazhar Ali Aug 10 '21 at 09:49
  • 1
    @mazharAli yes, my database router was pointing to wrong database in allow_migrate method. Migrations from postgres was applying to mongodb and this caused a problem. – Unknown123 Aug 10 '21 at 13:13
  • @Unknown123 I have one database with 2 different engines (postgis and timescale). Even if i don't allow migrate for the default database for my Location model (which uses postgis only), i get this error. – Mazhar Ali Aug 11 '21 at 05:03
  • 1
    @MazharAli Yes, because the migrations were not performed. That's why you don't have access to some columns. Debug your routers and set as it should be set. – Unknown123 Aug 11 '21 at 09:50
  • @Unknown123 I know but how do i force a specific migration to run on a different DB? allow_migrate only allows me to tell whether migration will be performed or not, it doesn't give me ability to run that specific migration on the Location database and all ohters on the default database – Mazhar Ali Aug 11 '21 at 10:09
  • 1
    @MazharAli I added my router config in the original question, check this. MongoDB is not requiring migrations in default settings. – Unknown123 Aug 12 '21 at 12:17

1 Answers1

1

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'
Unknown123
  • 208
  • 2
  • 13