我正在使用 supabase postgresql 和 django。默认情况下它使用公共模式,但现在我想将模型中的 user_id 字段链接到 auth.users.id ,其中 auth 是模式,users 是表名称,id 是 UUID 字段
模型定义在这里
# auth/models.py
class SupabaseUser(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
verbose_name="User ID",
help_text="Supabase managed user id",
editable=False,
)
class Meta:
managed = False
db_table = "users"
# myapp/models.py
class MyModel(models.Model):
user = models.ForeignKey(
SupabaseUser,
on_delete=models.CASCADE,
verbose_name="Supabase User",
help_text="Supabase user associated with the account",
null=False,
)
在设置中我有两个数据库连接
DATABASES = {
"default": dj_database_url.config(),
"supabase_auth": dj_database_url.config(),
}
DATABASES["supabase_auth"]["OPTIONS"] = {
"options": "-c search_path=auth",
}
当然型号路由器配置为
from django.db.models import Model
from django.db.models.options import Options
class ModelRouter:
@staticmethod
def db_for_read(model: Model, **kwargs):
return ModelRouter._get_db_schema(model._meta)
@staticmethod
def db_for_write(model: Model, **kwargs):
return ModelRouter._get_db_schema(model._meta)
@staticmethod
def allow_migrate(db, app_label, model: Model, model_name=None, **kwargs):
return True
@staticmethod
def _get_db_schema(options: Options) -> str:
if options.app_label == "auth":
return "supabase_auth"
return "default"
当我使用
./manage.py shell
并运行以下脚本时,它可以工作
from auth.models import SupabaseUser
assert SupabaseUser.objects.count() == 1
但是当我为
myapp
申请迁移时,我收到以下错误
$ ./manage.py makemigration myapp && ./manage.py migrate myapp
Operations to perform:
Apply all migrations: myapp
Running migrations:
Applying myapp.0013_mymodel_user...Traceback (most recent call last):
File "/mnt/Projects/myapp/backend/.venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 103, in _execute
return self.cursor.execute(sql)
^^^^^^^^^^^^^^^^^^^^^^^^
psycopg2.errors.UndefinedTable: relation "users" does not exist
....
snip
....
django.db.utils.ProgrammingError: relation "users" does not exist
migrations.RunSQL
解决这个问题
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("auth", "0001_initial"),
("myapp", "0012_alter_mymodel_some_field"),
]
operations = [
migrations.RunSQL(
sql=(
"ALTER TABLE myapp_mymodel ADD COLUMN user_id UUID;",
"ALTER TABLE myapp_mymodel ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES auth.users (id) ON DELETE CASCADE;",
),
reverse_sql=(
"ALTER TABLE myapp_mymodel DROP CONSTRAINT fk_user_id;",
"ALTER TABLE myapp_mymodel DROP COLUMN user_id;",
),
),
]
在此,每当应用迁移时都会执行
sql
字段,而每当恢复迁移时都会执行 reverse_sql
。反向 SQL 是可选的,但通常添加它是为了清理迁移中的混乱。