I am using django-tenant-schemas for multi-tenancy on my app (see: https://github.com/bernardopires/django-tenant-schemas)
It works fine locally, but on Heroku I face a problem when I try to run migrations for a non-public schema:
My backend engine is django.contrib.gis.db.backends.postgis
; when django creates a non-public schema and sets the search path to the newly created schema for migration, it tries to run CREATE EXTENSION IF NOT EXISTS postgis
, which throws the following error:
NOTICE: extension "postgis" already exists, skipping
ERROR: relation "spatial_ref_sys" does not exist
If I run the same command on my public schema, psql handles it gracefully and just gives me the notice, and of course it only happens on heroku.
Not sure if it is relevant, but the following is included in my buildpacks:
https://github.com/cyberdelia/heroku-geo-buildpack
I searched a lot, but so far have not found a solution. Any help on how to fix this error is much appreciated! 🙂
I managed to resolve this issue, see: PosGis and Django-Tenants
Solution here:
The issue seems to be cause by the default PostGis backend, specifically the call to prepare the database for migration, by explicitly setting the search path prior to calling CREATE EXTENSION IF NOT EXISTS postgis
I was able to migrate/create a schema by creating a custom DB backend that overrides this behaviour:
from django.contrib.gis.db.backends.postgis.base import (
DatabaseWrapper as OriginalPostGisDatabaseWrapper,
)
from django_tenants.utils import get_public_schema_name
class DatabaseWrapper(OriginalPostGisDatabaseWrapper):
"""
This database wrapper explicitly sets the search path when preparing the database, as
multi-schema environments (like with Django-tenants) can cause issues with the PostGis
backend.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.PUBLIC_SCHEMA_NAME = get_public_schema_name()
def prepare_database(self):
# Check that postgis extension is installed.
with self.cursor() as cursor:
cursor.execute('SET search_path = %s', params=[self.PUBLIC_SCHEMA_NAME])
cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
Then, set your ORIGINAL_BACKEND
setting to the location of the above DB backend instead of the standard PostGis backend.