3

I have a Django project with a default database set up for everything Django, but also need access to a legacy database. I have this working in settings and a database router. The models objects themselves from the Django app which hit the legacy database appear in the admin. However, the models from the legacy database Django app do not appear under the permissions section of the admin, and I was hoping to create a Django Group with permissions to these models / tables for staff members to execute CRUD functions on lookup tables. Here's my setup:

DATABASES:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'mysite_classroom_d',
        'USER': 'mysite_classroom_user',
        'PASSWORD': '',
        'HOST': 'mysite-pg1.institution.edu',
        'PORT': '5432',
    },
    'mssqlmysite': {
        'ENGINE': 'sql_server.pyodbc',
        'HOST': 'sql14-dev.institution.edu',
        'PORT': '1433',
        'NAME': 'mysite',
        'USER': 'mysite_user',
        'PASSWORD': '',
        'AUTOCOMMIT': True,
        'OPTIONS': {
            'driver': 'FreeTDS',
            'autocommit': True,
            'unicode_results': True,
            'host_is_server': True,
            'extra_params': 'tds_version=7.2',
        },
    },
}

And my routers; the legacy DB app is called 'formeditor':

class FormEditorRouter(object):
    """
    A router to control all database operations on models in the
    formeditor application.
    """

    def db_for_read(self, model, **hints):
        """
        Attempts to read formeditor models go to mssqlmysite.
        """

        if model._meta.app_label == 'formeditor':
            return 'mssqlmysite'
        return None


    def db_for_write(self, model, **hints):
        """
        Attempts to write formeditor models go to mssqlmysite.
        """

        if model._meta.app_label == 'formeditor':
            return 'mssqlmysite'
        return None


    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the formeditor app is involved.
        """

        if obj1._meta.app_label == 'formeditor' or \
           obj2._meta.app_label == 'formeditor':
           return True
        return None


    def allow_migrate(self, db, app_label, model=None, **hints):
        """
        Make sure the formeditor app only appears in the 'mssqlmysite'
        database.
        """

        if app_label == 'formeditor':
            return db == 'mssqlmysite'
        return None

And an example model:

class DataCompanyMap(models.Model):
    vendor_id = models.IntegerField(blank=True, null=True)
    product_id = models.IntegerField(blank=True, null=True)
    file_id = models.IntegerField(blank=True, null=True)
    var_name = models.TextField(blank=True)
    common_var_name = models.TextField()
    searchable = models.NullBooleanField()
    example = models.TextField(blank=True)
    description = models.TextField(blank=True)

    class Meta:
        managed = False
        db_table = 'data_company_map'

I thought the problem might be the managed = False, but even changing the legacy DB model to managed = True doesn't make it appear in the permissions section of the Django Admin. Any ideas here? Can the Django Admin only handle models in the default database, since formeditor and admin are in the default database? I have Google'd and checked through the Django docs but couldn't seem to find a definitive answer, and I'm hoping for a solution or something obvious I've missed. Thanks in advance for taking the time.

1 Answer 1

3

For me, i'ts missing the "in_db" Meta param but maybe you routers don't work like this. Also make sure you point your router in settings DATABASE_ROUTERS

The solution it worked for me:

My routers: (from: https://djangosnippets.org/snippets/2687/)

class ModelDatabaseRouter(object):
"""Allows each model to set its own destiny"""

def db_for_read(self, model, **hints):
    # Specify target database with field in_db in model's Meta class
    if hasattr(model._meta, 'in_db'):
        return model._meta.in_db
    return None

def db_for_write(self, model, **hints):
    # Specify target database with field in_db in model's Meta class
    if hasattr(model._meta, 'in_db'):
        return model._meta.in_db
    return None

def allow_syncdb(self, db, model):
    # Specify target database with field in_db in model's Meta class
    if hasattr(model._meta, 'in_db'):
        if model._meta.in_db == db:
            return True
        else:
            return False
    else:
        # Random models that don't specify a database can only go to 'default'
        if db == 'default':
            return True
        else:
            return False

in settings add:

DATABASE_ROUTERS = ['api.routers.ModelDatabaseRouter']

then the model:

class DataCompanyMap(models.Model):

    ..... The fields .... 

    class Meta:
        in_db = 'mssqlmysite'  
Sign up to request clarification or add additional context in comments.

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.