简体   繁体   中英

Django with Multiple Databases, Models from non-default Database Permissions in Admin

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.

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'  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM