Reputation: 51844
In my GeoDjango project I want to connect to a legacy PostgreSQL/PostGIS database. It contains the following schemas:
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.
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?
Upvotes: 14
Views: 23388
Reputation: 59
For me this article helped a lot: https://erthalion.info/2014/03/08/django-with-schemas/
Basically it suggest setting search_path
not via DATABASES...OPTIONS
, but using connection_created
signal.
In my case, I created signal.py
in my core
app an put this code inside. This work both for migrations and basic usage.
from django.conf import settings
from django.db.backends.signals import connection_created
from django.dispatch import receiver
@receiver(connection_created)
def setup_connection(sender, connection, **kwargs):
# Чтобы грузить данные приложения в конкретную схему.
if connection.alias == "default":
cursor = connection.cursor()
cursor.execute(f'SET search_path="{settings.SEARCH_PATH}"')
Upvotes: 0
Reputation: 251
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"'
Upvotes: 7
Reputation: 51844
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',
},
}
Upvotes: 10
Reputation: 1991
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.
Upvotes: 2