在我的多租户站点中,我具有以下数据库结构:
Public (shared):
tenants
domains
users
Test:
users
clients
projects
projectusers
tasks
Test2:
users
clients
projects
projectusers
tasks
这是一个简化的列表-所有三个模式(包括其他)包括auth_permissions,auth_group和auth_group_permissions。
projectusers表(将用户与项目联系起来的交叉引用),具有User表的一对一字段和projects表的ForeignKey,如下所示:
class ProjectUser(DateFieldsModelMixin, models.Model):
user = models.OneToOneField(
User,
on_delete=models.PROTECT,
verbose_name=_('User'),
related_name='user_projects',
)
project = models.ForeignKey(
Project,
on_delete=models.PROTECT,
verbose_name=_('Project'),
related_name='project_users',
)
...other fields omitted...
重点是,在ProjectUser模型中定义了从projectusers到用户的引用。用户模型没有回溯到ProjectUser的参考。
我写了一个load_fixtures(management)命令来加载设备,以使用我们需要进行初步测试的数据(在编写/运行单元测试之前)来建立我们的开发站点。
该命令执行的操作之一是清空auth_permissions表,将自动增量值重置为1,然后导入其固定装置,以使所有ID在本地开发站点之间(最终在生产环境中)匹配。这是必要的,因为auth_group和auth_group_permissions的固定装置通过ID引用权限。
在“公共”模式下运行时,在该表的删除过程中发生了我遇到的错误。请注意,在Public中没有projectusers表。这是在auth_permissions上删除的行:
model.objects.all().delete()
在clear_table()方法中,就是load_fixtures命令中的第215行。您可以看到回溯引用的那一行:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.6/site-packages/django/core/management/base.py", line 316, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/python3.6/site-packages/django/core/management/base.py", line 353, in execute
output = self.handle(*args, **options)
File "/code/src/virticl_api/utilities/management/commands/load_fixtures.py", line 148, in handle
self.clear_table(file_path, self.clear_tables[file_name])
File "/code/src/virticl_api/utilities/management/commands/load_fixtures.py", line 215, in clear_table
model.objects.all().delete()
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 662, in delete
collector.collect(del_query)
File "/usr/local/lib/python3.6/site-packages/django/db/models/deletion.py", line 220, in collect
elif sub_objs:
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 272, in __bool__
self._fetch_all()
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 1186, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 54, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1065, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "projects_projectuser" does not exist
LINE 1: ...ourly_rate", "projects_projectuser"."status" FROM "projects_...
那为什么在公开模式下运行的delete方法会找到与projectuser表的关系?