Django:固定对象不可检索
Django : fixtures object not retrievable
我在任何地方都没有看到 LiveServerTestCase 没有加载固定装置,但是当我执行以下命令时:
class FrontTest(LiveServerTestCase):
fixtures = ['event.json']
@classmethod
def setUpClass(cls):
super().setUpClass()
print(Event.objects.all())
输出为:
Using existing test database for alias 'default'...
[]
而当我使用 TestCase
class FrontTest(TestCase):
fixtures = ['event.json']
@classmethod
def setUpClass(cls):
super().setUpClass()
print(Event.objects.all())
输出是:
[<Event: event search>]
你知道为什么我的夹具只在 TestCase 中加载吗?我真的很想让它能够使用 Selenium。谢谢!
PS : event.json :
{
"model": "mezzanine_agenda.event",
"pk": 1,
"fields": {
"comments_count": 0,
"keywords_string": "",
"rating_count": 0,
"rating_sum": 0,
"rating_average": 0.0,
"site": 1,
"title": "event search",
"slug": "event-search",
"_meta_title": "",
"description": "event search",
"gen_description": true,
"created": "2018-05-25T15:49:55.223Z",
"updated": "2018-05-25T15:49:55.257Z",
"status": 2,
"publish_date": "2018-05-25T15:49:32Z",
"expiry_date": null,
}
},
首先,令人遗憾的是,Django 会忽略它找不到的固定装置。您看到的错误意味着 Django 无法找到夹具文件并失败并显示警告:https://code.djangoproject.com/ticket/18990
以下是 Django 查找固定装置的方式:
- 使用夹具文件的绝对路径,不是一个好主意,因为夹具可能作为代码的一部分放置 -> 这将覆盖第二种技术
- 它在
settings.FIXTURE_DIRS
下定义的所有目录下查找
- 它会在所有 app 目录 下查找一个按照惯例名为
fixtures
的文件夹。
据此,查看你的文件所在位置,就可以解决这个问题
这是 fixture_dirs
的 Django 代码:
@cached_property
def fixture_dirs(self):
"""
Return a list of fixture directories.
The list contains the 'fixtures' subdirectory of each installed
application, if it exists, the directories in FIXTURE_DIRS, and the
current directory.
"""
dirs = []
fixture_dirs = settings.FIXTURE_DIRS
if len(fixture_dirs) != len(set(fixture_dirs)):
raise ImproperlyConfigured("settings.FIXTURE_DIRS contains duplicates.")
for app_config in apps.get_app_configs():
app_label = app_config.label
app_dir = os.path.join(app_config.path, 'fixtures')
if app_dir in fixture_dirs:
raise ImproperlyConfigured(
"'%s' is a default fixture directory for the '%s' app "
"and cannot be listed in settings.FIXTURE_DIRS." % (app_dir, app_label)
)
if self.app_label and app_label != self.app_label:
continue
if os.path.isdir(app_dir):
dirs.append(app_dir)
dirs.extend(list(fixture_dirs))
dirs.append('')
dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs]
return dirs
那是因为 TransactionTestCase
在实例的 setUp
方法中加载固定装置,所以它的子 classes 包括 LiveServerTestCase
做同样的事情 - 除了 TestCase
,它使用每个 class 的单个原子事务并加载 setUpClass
中的固定装置以加速测试执行。 #20392.
中添加了此行为
这对您来说意味着您应该将所有与数据库相关的代码从 setupClass
移动到 LiveServerTestCase
子 classes:[=27= 中的 setUp
]
class FrontendLiveTest(LiveServerTestCase):
def setUp(self):
# the transaction is opened, fixtures are loaded
assert Event.objects.exists()
备注
以防您尝试将 TestCase
的原子事务与 LiveServerTestCase
的后台线程混淆:如 LiveServerTestCase
文档所述,
It inherits from TransactionTestCase
instead of TestCase
because the threads don't share the same transactions (unless if using in-memory sqlite
) and each thread needs to commit all their transactions so that the other thread can see the changes.
我在任何地方都没有看到 LiveServerTestCase 没有加载固定装置,但是当我执行以下命令时:
class FrontTest(LiveServerTestCase):
fixtures = ['event.json']
@classmethod
def setUpClass(cls):
super().setUpClass()
print(Event.objects.all())
输出为:
Using existing test database for alias 'default'...
[]
而当我使用 TestCase
class FrontTest(TestCase):
fixtures = ['event.json']
@classmethod
def setUpClass(cls):
super().setUpClass()
print(Event.objects.all())
输出是:
[<Event: event search>]
你知道为什么我的夹具只在 TestCase 中加载吗?我真的很想让它能够使用 Selenium。谢谢!
PS : event.json :
{
"model": "mezzanine_agenda.event",
"pk": 1,
"fields": {
"comments_count": 0,
"keywords_string": "",
"rating_count": 0,
"rating_sum": 0,
"rating_average": 0.0,
"site": 1,
"title": "event search",
"slug": "event-search",
"_meta_title": "",
"description": "event search",
"gen_description": true,
"created": "2018-05-25T15:49:55.223Z",
"updated": "2018-05-25T15:49:55.257Z",
"status": 2,
"publish_date": "2018-05-25T15:49:32Z",
"expiry_date": null,
}
},
首先,令人遗憾的是,Django 会忽略它找不到的固定装置。您看到的错误意味着 Django 无法找到夹具文件并失败并显示警告:https://code.djangoproject.com/ticket/18990
以下是 Django 查找固定装置的方式:- 使用夹具文件的绝对路径,不是一个好主意,因为夹具可能作为代码的一部分放置 -> 这将覆盖第二种技术
- 它在
settings.FIXTURE_DIRS
下定义的所有目录下查找
- 它会在所有 app 目录 下查找一个按照惯例名为
fixtures
的文件夹。
据此,查看你的文件所在位置,就可以解决这个问题
这是 fixture_dirs
的 Django 代码:
@cached_property
def fixture_dirs(self):
"""
Return a list of fixture directories.
The list contains the 'fixtures' subdirectory of each installed
application, if it exists, the directories in FIXTURE_DIRS, and the
current directory.
"""
dirs = []
fixture_dirs = settings.FIXTURE_DIRS
if len(fixture_dirs) != len(set(fixture_dirs)):
raise ImproperlyConfigured("settings.FIXTURE_DIRS contains duplicates.")
for app_config in apps.get_app_configs():
app_label = app_config.label
app_dir = os.path.join(app_config.path, 'fixtures')
if app_dir in fixture_dirs:
raise ImproperlyConfigured(
"'%s' is a default fixture directory for the '%s' app "
"and cannot be listed in settings.FIXTURE_DIRS." % (app_dir, app_label)
)
if self.app_label and app_label != self.app_label:
continue
if os.path.isdir(app_dir):
dirs.append(app_dir)
dirs.extend(list(fixture_dirs))
dirs.append('')
dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs]
return dirs
那是因为 TransactionTestCase
在实例的 setUp
方法中加载固定装置,所以它的子 classes 包括 LiveServerTestCase
做同样的事情 - 除了 TestCase
,它使用每个 class 的单个原子事务并加载 setUpClass
中的固定装置以加速测试执行。 #20392.
这对您来说意味着您应该将所有与数据库相关的代码从 setupClass
移动到 LiveServerTestCase
子 classes:[=27= 中的 setUp
]
class FrontendLiveTest(LiveServerTestCase):
def setUp(self):
# the transaction is opened, fixtures are loaded
assert Event.objects.exists()
备注
以防您尝试将 TestCase
的原子事务与 LiveServerTestCase
的后台线程混淆:如 LiveServerTestCase
文档所述,
It inherits from
TransactionTestCase
instead ofTestCase
because the threads don't share the same transactions (unless if using in-memorysqlite
) and each thread needs to commit all their transactions so that the other thread can see the changes.