13

In my GeoDjango project I want to connect to a legacy PostgreSQL/PostGIS database. It contains the following schemas:

  • data // contains all the geospatial data
  • django // empty, created by me
  • public // system tables such as spatial_ref_sys

I want the Django tables shown in the screenshot to go into the django schema. I do not want to pollute the public schema.

Django tables

I want the "data" models to connect to the data schema. I already tried to generate models from the legacy tables but python manage.py inspectdb connects to the public schema.


In order to provide access to the different schemas I adapted the approach 2 of this article which preassigns individual search_path values to specific database users:

-- user accessing django schema...
CREATE ROLE django_user LOGIN PASSWORD 'secret';
ALTER ROLE django_user SET search_path TO django, public;

-- user accessing data schema...
CREATE ROLE data_user LOGIN PASSWORD 'secret';
ALTER ROLE data_user SET search_path TO data, public;

Then I configured the database connections as follows:

DATABASES = {

    'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'multi_schema_db',
            'USER': 'django_user',
            'PASSWORD': 'secret',
    },

    'data': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'multi_schema_db',
            'USER': 'data_user',
            'PASSWORD': 'secret',
    },
}

How can I actually configure that Django uses the django schema while "data" models connect to the data schema?


Readings

Community
  • 1
  • 1
JJD
  • 50,076
  • 60
  • 203
  • 339
  • See [Automatic database router](https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#automatic-database-routing) – falsetru Jul 30 '15 at 14:13
  • @falsetru The documentation for automatic database router does not mention how to deal with multiple schemas in the one database. – JJD Aug 05 '15 at 17:07
  • @JJD Did you found the answer on this problem? Thank you! – Abz Rockers Jan 19 '17 at 01:29
  • @AbzRockers Only what you can read [here](http://stackoverflow.com/a/39322184/356895). – JJD Jan 20 '17 at 11:06
  • 1
    @JJD Thank you for the response! I think you should mark it the right answer if it solved your problem, I neglected the answers on this question because it has no marked right answer and no up votes as well. – Abz Rockers Jan 21 '17 at 07:04

3 Answers3

11

You have to leverage the search_path:

DATABASES = {

    'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'OPTIONS' : {
                'options': '-c search_path=django,public'
            },
            'NAME': 'multi_schema_db',
            'USER': 'django_user',
            'PASSWORD': 'secret',
    },

    'data': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'OPTIONS' : {
                'options': '-c search_path=data,public'
            },
            'NAME': 'multi_schema_db',
            'USER': 'data_user',
            'PASSWORD': 'secret',
    },
}
JJD
  • 50,076
  • 60
  • 203
  • 339
7

If you don't need to manage the tables through migrations, you could use escaped quotes for the db_table attribute of your model:

class SomeModel(models.Model):
    field1 = models.AutoField(primary_key=True)  
    class Meta():
        managed=False
        db_table=u'"schema\".\"table"'
JJD
  • 50,076
  • 60
  • 203
  • 339
wbloos
  • 231
  • 3
  • 3
2

We use Django Tenant Schemas with great success. It allows you to access different schemas by delineating different tenants as the owners of the schemas.

This will allow you to set the schema on a per call basis. If the schema needs to be set on a per url basis, you can do that in middleware.

Sina Khelil
  • 2,001
  • 1
  • 18
  • 27