使用psql模式进行Django测试

2024-09-26 18:18:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个这样的模型(没什么特别的)

class Building(SchemaModel):
    name = models.CharField(max_length=50, null=False)
    site = models.ForeignKey(Site, null=False, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

它们保存在一个PSQL数据库中,实现了前一篇文章here中所要求的模式

基本上,我的模型都扩展了一个基本的class{}

class SchemaModel(models.Model):
    """Base Model for dynamically implementing schema information"""

    class Meta:
        abstract = True
        managed = True

models.py的末尾,确保db_table属性中包含正确的模式

for model in SchemaModel.__subclasses__():
    db_table = '{}s'.format(model._meta.label_lower.replace('.', '\".\"'))
    model._meta.original_attrs['db_table'] = db_table
    model._meta.db_table = db_table

我还向settings.py中的数据库配置文件添加了选项(使用的模式是jdb)

'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
            'options': '-c search_path=jdb,public'
        },

在我实现单元测试之前,它一直工作得非常好

Django的单元测试引擎创建了自己的数据库,但是没有创建它需要的模式。尽管如此,它还是尝试访问与测试数据库上的真实数据库相同的模式,而测试数据库不存在。 在创建测试数据库之后,测试引擎尝试创建表“jdb”。“buildings”,显然失败了

堆栈跟踪:

(venv) C:\code\py\thommen>py manage.py test jdb
schema: jdb
 table: companys
new db_table=jdb_companys
schema: jdb
 table: locations
new db_table=jdb_locations
schema: jdb
 table: sites
new db_table=jdb_sites
schema: jdb
 table: buildings
new db_table=jdb_buildings
schema: jdb
 table: rooms
new db_table=jdb_rooms
schema: jdb
 table: employees
new db_table=jdb_employees
schema: jdb
 table: employeerooms
new db_table=jdb_employeerooms
schema: jdb
 table: categorys
new db_table=jdb_categorys
schema: jdb
 table: statuss
new db_table=jdb_statuss
schema: jdb
 table: manufacturers
new db_table=jdb_manufacturers
schema: jdb
 table: models
new db_table=jdb_models
schema: jdb
 table: items
new db_table=jdb_items
Creating test database for alias 'default'...
Got an error creating the test database: database "test_Thommen" already exists

Type 'yes' if you would like to try deleting the test database 'test_Thommen', or 'no' to cancel: yes
Destroying old test database for alias 'default'...
Traceback (most recent call last):
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.InvalidSchemaName: schema "jdb" does not exist
LINE 1: CREATE TABLE "jdb"."buildings" ("id" serial NOT NULL PRIMARY...
                     ^


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

Traceback (most recent call last):
  File "C:\code\py\thommen\manage.py", line 22, in <module>
    main()
  File "C:\code\py\thommen\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\commands\test.py", line 23, in run_from_argv
    super().run_from_argv(argv)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\commands\test.py", line 53, in handle
    failures = test_runner.run_tests(test_labels)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\test\runner.py", line 695, in run_tests
    old_config = self.setup_databases(aliases=databases)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\test\runner.py", line 614, in setup_databases
    return _setup_databases(
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\test\utils.py", line 170, in setup_databases
    connection.creation.create_test_db(
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\base\creation.py", line 72, in create_test_db
    call_command(
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\__init__.py", line 168, in call_command
    return command.execute(*args, **defaults)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\base.py", line 85, in wrapped
    res = handle_func(*args, **kwargs)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\management\commands\migrate.py", line 243, in handle
    post_migrate_state = executor.migrate(
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\migrations\executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\migrations\migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\migrations\operations\models.py", line 92, in database_forwards
    schema_editor.create_model(model)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\base\schema.py", line 324, in create_model
    self.execute(sql, params or None)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\base\schema.py", line 142, in execute
    cursor.execute(sql, params)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\chuanito\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: schema "jdb" does not exist
LINE 1: CREATE TABLE "jdb"."buildings" ("id" serial NOT NULL PRIMARY...

                 ^

即使我禁用了处理模式的部分,测试引擎仍然希望在不存在的模式中创建表。(我甚至不知道它从何处获得架构名称)

有两个职位如此类似的问题。不幸的是one其中一人没有得到答案(我无法对此发表评论,问他是否找到了解决方案^^) {a3}确实得到了一个答案,我按照这个答案创建了一个{}扩展了{}并覆盖了{}和{}

from django.test.runner import DiscoverRunner
from django.apps import apps


class SchemaModelTestRunner(DiscoverRunner):

    def setup_test_environment(self, **kwargs):
        self.original_db_tables = {}
        self.schema_models = [model for model in apps.get_models()
                                if '"."' in model._meta.db_table]

        for model in self.schema_models:
            schema, table = model._meta.db_table.split('"."')
            print("schema: {}\n table: {}".format(schema, table))
            db_table = "{}_{}".format(schema, table)
            print("new db_table=%s" % db_table)
            self.original_db_tables[model] = model._meta.db_table
            model._meta.db_table = db_table
            model._meta.original_attrs['db_table'] = db_table

        super(SchemaModelTestRunner, self).setup_test_environment(**kwargs)

    def teardown_test_environment(self, **kwargs):
        super(SchemaModelTestRunner, self).teardown_test_environment(**kwargs)

        for model in self.schema_models:
            model._meta.db_table = self.original_db_tables[model]
            model._meta.original_attrs['db_table'] = self.original_db_tables[model]

并在TEST_RUNNER设置中的settings.py中链接它

TEST_RUNNER = 'thommen.runner.SchemaModelTestRunner'

不幸的是,结果是一样的,尽管SchemaModelTestRunner似乎被激活了,并且按照我告诉它的做了。 我真的不知道现在该怎么办。正如我所说,我还禁用了代码中实现模式的所有跟踪,但它仍然知道我的模型使用模式,并尝试复制该模式

有人有主意吗


Tags: djangoinpyselfdbschemalocalline

热门问题