Error on migrate using postgresql schema

Hi all

I’m working on a django project in which i set 3 environment : DEV,VIP,PROD.

So i add a variable in my settings that detect in which environment i am and then i use it in models to change dynamically the schema name to use.

To do that i write this in the models.py:

from django.db import models
# from django.contrib.auth.models import AbstractUser 
from django.contrib.auth.models import AbstractUser
#Pour plus d'information sur le fonctionnement des models : https://docs.djangoproject.com/fr/5.1/topics/db/models/
from django.conf import settings

if settings.ENV == "DEV":
    schema="applications_db"
elif settings.ENV == "VIP":
    schema="applications_vip_db"
elif settings.ENV == "PROD":
    schema="applications_prod_db"

and then in my class models i write this :

class ApplicationDjango(models.Model):
    a_name = models.CharField(max_length=100,verbose_name="Nom")
    a_portail_name = models.CharField(max_length=100,verbose_name="Nom portail")
    a_views_name = models.CharField(max_length=100,verbose_name="Views name")
    a_url_home = models.CharField(max_length=100,verbose_name="Url home")

    def __str__(self):
        return self.a_name+"_"+self.a_portail_name
    #class pour ajouter une contrainte d'unicité
    class Meta:
        managed= True
        db_table = f"{schema}.'ApplicationDjango'"

I havent got any problems when running the makemigrations that give me this in my migration file:

# Generated by Django 4.2.15 on 2025-05-26 13:16

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('Applications', '0003_alter_applicationdjango_table_alter_user_table'),
    ]

    operations = [
        migrations.AlterModelTable(
            name='applicationdjango',
            table="applications_db.'ApplicationDjango'",
        ),
        migrations.AlterModelTable(
            name='user',
            table='"applications_db"."User" ',
        ),
    ]

But i have this error when i try to migrate :

Applying Applications.0004_alter_applicationdjango_table_alter_user_table...Traceback (most recent call last):
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.UndefinedTable: relation "Applications_applicationdjango" does not exist


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/livraison/toto/DJANGOPROJET/./manage.py", line 22, in <module>
    main()
  File "/opt/livraison/toto/DJANGOPROJET/./manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/toto/.local/lib/python3.9/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/home/toto/.local/lib/python3.9/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/toto/.local/lib/python3.9/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/toto/.local/lib/python3.9/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
  File "/home/toto/.local/lib/python3.9/site-packages/django/core/management/base.py", line 106, in wrapper
    res = handle_func(*args, **kwargs)
  File "/home/toto/.local/lib/python3.9/site-packages/django/core/management/commands/migrate.py", line 356, in handle
    post_migrate_state = executor.migrate(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 135, in migrate
    state = self._migrate_all_forwards(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 167, in _migrate_all_forwards
    state = self.apply_migration(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 252, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/migrations/migration.py", line 132, in apply
    operation.database_forwards(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/migrations/operations/models.py", line 559, in database_forwards
    schema_editor.alter_db_table(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/base/schema.py", line 627, in alter_db_table
    self.execute(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/postgresql/schema.py", line 48, in execute
    return super().execute(sql, None)
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/base/schema.py", line 201, in execute
    cursor.execute(sql, params)
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 102, in execute
    return super().execute(sql, params)
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/toto/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "Applications_applicationdjango" does not exist

it seem that it sear a the table but in lowercase instead of ApplicationDjango, how can i solve it ?

If you want to use a case-sensitive table name, it must be enclosed by double-quotes. Using single-quotes does not work.

See PostgreSQL: Documentation: 17: 4.1. Lexical Structure

Ok so i change db_table to this :

db_table = f'{schema}."ApplicationDjango"'

so now in my migration file i have this :

migrations.AlterModelTable(
     name='applicationdjango',
     table='applications_db."ApplicationDjango"',

and now when i try to apply the migration :

Applying Applications.0004_alter_applicationdjango_table_alter_user_table...Traceback (most recent call last):
  File "/home/webadmin/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.SyntaxError: syntax error at or near "ApplicationDjango"
LINE 1: ...ns_applicationdjango" RENAME TO "applications_db."Applicatio...

 File "/home/webadmin/.local/lib/python3.9/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/webadmin/.local/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: syntax error at or near "ApplicationDjango"
LINE 1: ...ns_applicationdjango" RENAME TO "applications_db."Applicatio...

:frowning:

A part of the problem is that your models.py changes with the environment and thus the migration engine detects it and tries to “fix it”.

I would recommend to read this other topic which covers a similar use-case:

i havent have problem with my schema before i variabilise. all my schema are in the search path.
the problème i have its with the variable “schema”.

The goal of it is to avoid manual modification from “applications_db” to “applications_vip_db” on the models.py

did i need to override something ?

Whenever Meta.db_table changes the migration framework will detect it as a change in your model and will attempt to write a migration to address to it.

The simpliest way to handle it is to just change the DB connection configuration according to your environment. In this way the models are not altered and thus no migration is issued when you change environment. In other words: the logic to change schema should be in your settings file and not in your models.

see also https://stackoverflow.com/a/74056139/30169297

My recommendation would be to not do this. It’s a bad idea and not supported by Django.

Setting the NAME parameter in DATABASES/default works fine though, that’s probably what you want to do.

1 Like