为什么我得到KeyError:" Django设置没有定义RESOLVER"?

时间:2015-01-12 04:06:27

标签: python django unit-testing webassets django-assets

我收到以下错误:

  

(testassets)➜testassetsgit :( master)✗django-admin.pytest       为别名创建测试数据库'默认' ...       Ë       ================================================== ====================       错误:test_get_site_root_with_settings_overrides(app.tests.AssetsTestCase)       -------------------------------------------------- --------------------       Traceback(最近一次调用最后一次):         文件" /Volumes/fifteen5cs/testassets/app/tests.py",第27行,在test_get_site_root_with_settings_overrides中           http_client.get(' /')         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/test/client.py" ;,第473行,获取           response = super(客户端,自我).get(路径,数据=数据,**额外)         File" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/test/client.py" ;,第280行,获取           返回self.request(** r)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/test/client.py",第444行,请求中           six.reraise(* exc_info)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/core/handlers/base.py" ;,第114行,在get_response中           response = wrapped_callback(request,* callback_args,** callback_kwargs)         文件" /Volumes/fifteen5cs/testassets/app/views.py",第9行,索引           context_instance = RequestContext的(请求))         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/shortcuts/ init .py",第29行,在render_to_response中           返回HttpResponse(loader.render_to_string(* args,** kwargs),** httpresponse_kwargs)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/template/loader.py" ;,第169行,在render_to_string中           return t.render(context_instance)         File" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/template/base.py" ;,第140行,渲染           return self._render(context)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/test/utils.py",第85行,在instrumented_test_render中           return self.nodelist.render(context)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/template/base.py" ;,第840行,在渲染中           bit = self.render_node(node,context)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django/template/debug.py",第78行,在render_node中           return node.render(context)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django_assets/templatetags/assets.py" ;,第72行,渲染           for bundle.urls()中的url:         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/webassets/bundle.py" ;,第783行,在网址中           for bundle,extra_filters,self.iterbuild中的new_ctx(ctx):         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/webassets/bundle.py" ;,第679行,在iterbuild中           for bundle,_ in self.resolve_contents(ctx):         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/webassets/bundle.py" ;,第233行,在resolve_contents中           result = ctx.resolver.resolve_source(ctx,item)         File" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/webassets/bundle.py" ;,第50行, getattr           return self.getattr(self._parent,item)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/webassets/bundle.py",第58行,在getattr中           return getattr(object,item)         文件" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/webassets/env.py",第675行,在_get_resolver中           return self._storage [' resolver']         File" /Users/paul/.pyenv/versions/testassets/lib/python2.7/site-packages/django_assets/env.py" ;,第62行, getitem           self._transform_key(键))       KeyError:" Django设置没有定义RESOLVER"

----------------------------------------------------------------------
Ran 1 test in 0.325s

FAILED (errors=1)
Destroying test database for alias 'default'...

我已将此错误半连接到我的一个单元测试中使用Django utils函数django.test.utils.override_settings(如下所示)

  1 from django.test.utils import override_settings
  2 from django.utils.unittest.case import TestCase
  3 from django.test.client import Client
  4
  5
  6 OVERRIDE_SETTINGS = {
  7     'DEBUG': True,
  8     'ASSETS_DEBUG': True,
  9     'ASSETS_AUTO_BUILD': True,
 10     'ASSETS_URL_EXPIRE': False,
 11     'ASSETS_CACHE': False,
 12     'ASSETS_MANIFEST': False,
 13     'ASSETS_VERSIONS': False,
 14 }
 15
 16
 17 class AssetsTestCase(TestCase):
 18     def test_get_site_root_with_settings_overrides(self):
 19         http_client = Client()
 20         # import pdb;pdb.set_trace()
 21         settings_override = override_settings(**OVERRIDE_SETTINGS)
 22         settings_override.enable()
 23         http_client.get('/')
 24         settings_override.disable()
 25
 26         settings_override.enable()
 27         http_client.get('/')
 28         settings_override.disable()

(注意:在第二次请求期间引发异常!)

我正在处理的代码库首先提出这个问题太大而且私密,所以我已经将项目剥离到仍然会产生问题的少量代码。这个迷你项目可以在https://github.com/logston/testassets找到。

我花了两天多时间试图确定这个错误的确切来源以及为什么它在第二个请求期间发生而不是第一个请求。我尝试了一些单元测试的排列。有趣的是,如果我创建第二个单元测试,一个不启用设置覆盖的测试(例如,如下所示)并命名该测试,使其在测试期间首先运行,测试套件通过。如果我在test_get_site_root_with_settings_overrides单元测试后进行相同的单元测试,则两者都将失败。

      def test_get_site_root(self):
          http_client = Client()
          http_client.get('/')

          http_client.get('/')

对此问题的任何帮助都会非常感激。

最后,我能找到的唯一可以解决相同或类似问题的问题是:https://github.com/miracle2k/django-assets/issues/44

更新2015/01/12

这个问题似乎与信号的使用有关。我已将上述失败的测试删除至以下内容:

from django.test.utils import override_settings
from django.utils.unittest.case import TestCase
from django_assets.env import get_env


class AssetsTestCase(TestCase):
    def test(self):
        settings_override = override_settings()
        settings_override.enable()
        get_env().resolver
        settings_override.disable()

        settings_override.enable()
        get_env().resolver
        settings_override.disable()

1 个答案:

答案 0 :(得分:3)

原来这个问题是由于在禁用任何django_assets.env.envoverride_settings单例未重置的事实。事实上,这个单例对象没有在'设置之间重建。对象表示如果在覆盖设置的上下文中构建django_assets.env.env对象,则为非覆盖设置换出这些被覆盖的设置时,通过创建{{1}将任何常量添加到临时设置模块对象将丢失。 django_assets.env.envRESOLVER是将丢失的常量的绝佳示例。为了避免这种损失,我们必须确保在更改设置模块后通过调用ASSETS_CACHE来重置django_assets.env.env对象。调用django_assets.env.reset将强制django-assets在下次调用reset时将这些常量重新插入当前设置模块。

不幸的是,调用django_assets.env.get_env会导致django_assets.env.reset字典被清空(nb。实际上它已被破坏并且构建了一个新字典)。丢失此字典会导致以下错误:

django_assets.env.env._bundle_names

要解决此问题,我们必须将BundleError: %s not found (using staticfiles finders) 更新为django_assets.env._ASSETS_LOADED并从False中删除每个应用的assets.py文件。我们必须更新sys.modules,以便django-assets在下次调用_ASSETS_LOADED时尝试重新导入每个应用的资源文件。对django_assets.env.get_env的调用也将重建django_assets.env.get_env字典。最后,我们必须从sys.modules中删除每个应用程序的资产模块。否则,env._bundle_names将无法导入(读取'执行')资产模块,因为资产模块已导入!

因此,这个问题的完整解决方案如下:

__import__('app.assets')
顺便说一下,我很想知道解决这个问题的其他方法。