我正在尝试将大型Django项目迁移到1.7版本。
我已经解决了所有问题,网站运行顺畅,但我再也无法运行测试套件了。
在populate
方法期间,问题来自Django的app注册表。有一些应用程序的url模式在相当早的阶段使用ORM。
例如:
url(r'^(?:(?P<platform_slug>%s)/)?(?:(?P<genre_slug>%s)/)?(?:(?P<year>%s)/)?$' % (
r'|'.join([i['slug'] for i in Platform.active_objects.values("slug")]),
r'|'.join([i['slug'] for i in Genre.objects.values("slug")]),
r'|'.join([str(i) for i in YEAR_FILTER_RANGE])),
views.archive, name="gamecard_archive")
这是一个复杂的模式,允许可选但可区分的参数,但它与问题无关。
当我运行测试时,我得到了臭名昭着的django.db.utils.OperationalError: no such table: contrib_platform
,因为显然,测试运行者仍然无法在该阶段创建数据库。执行整个测试设置的顺序明显不同于1.6。
虽然一个解决方案可能是避免在测试期间访问url配置中的应用程序模型,方法是使用更简单的版本替换这些规则{/ 1}},如
sys.argv
我想知道是否有人想出更优雅和便携的解决方案。
更新 我想添加回溯堆栈的头部 它表明它确实不是与测试严格相关,而是与应用程序配置有关 我不能说这是一个回归,因为Django 1.7已经存在了一段时间,我怀疑之前没有人发现它。只是我项目的一个角落。然而,在Django 1.6中它的功能就像一个魅力,显然数据库可以在早期阶段访问。
if 'test' in sys.argv:
[simple url pattern here]
else:
[uber url pattern here]
答案 0 :(得分:0)
通常我不会考虑从模型实例构建您的网址是一种很好的做法。所以可能试图找到另一个解决方案,例如。像Genre.objects.filter(platform__slug=platform_slug)
那样做某事(不知道你的确切模型结构)。
您遇到的问题很可能是由于Django 1.7引入的App-loading refactoring并且在您的模型等方面发生了很大的变化等等。所以您应该尝试将更改网址的代码放入在Django完成加载所有必要的东西后运行的AppConfig.ready()
方法。但是,我通常会避免根据数据库中的数据构建您的网址。
答案 1 :(得分:0)
你的解决方案(由数据库表指定的url配置)在一个简单的应用程序中与Django 1.7很好用。您可能有一个复杂的依赖项或循环导入,某些模型在导入时需要配置URL。相互依赖可以解决,例如当真正使用时,通过导入函数内部。使用'test' in sys.argv
的解决方案也很好,但更好的方法是在不排除测试的情况下解决它,以便您可以编写集成测试,也可以编写复杂的URL代码。
奇怪的是你有测试问题,而不是其他命令(例如python manage.py runserver),因为你的问题很快就会出现问题,之后命令之间和testrunner之前会有任何区别。
标准解决方案是在TesCase中定义属性urls
。例如,一行urls = 'myapp.test_urls'
。请参阅文档test urlconf configuration。在您修复错误之后,这可能会很有用,或者您应该为包含测试数据的网站配置一个看似矫枉过正的工具。