【问题标题】:How to lazily evaluate ORM call after fixtures are loaded into db in Django?如何在 Django 中将固定装置加载到数据库后懒惰地评估 ORM 调用?
【发布时间】:2010-06-25 16:11:13
【问题描述】:

我有一个模块pagetypes.py,它从数据库中提取了几个常量(我不应该在这里真正使用常量一词)以供以后重用:

def _get_page_type_(type):
    return PageType.objects.get(type=type)

PAGE_TYPE_MAIN = _get_page_type_('Main')
PAGE_TYPE_OTHER = _get_page_type_('Other')

然后在我做的视图中的某个地方:

import pagetypes
...
print pagetypes.PAGE_TYPE_MAIN #simplified

当 db 有这些记录时一切正常,我确保它确实如此......除非这段代码正在测试中。在这种情况下,我想通过固定装置将这些记录加载到数据库中。这样做的问题是,在导入 pagetypes 模块时未加载固定装置(即使 syncdb 未运行),导致 _get_page_type_ 调用失败:

psycopg2.ProgrammingError: relation "pagetype" does not exist

测试运行器总是尝试导入pagetypes 模块,因为它是由正在测试的视图导入的。

我该如何解决这个问题?

我正在考虑延迟加载页面类型常量PAGE_TYPE_MAINPAGE_TYPE_OTHER,但是如果这些记录不在数据库中(或者在测试中的固定装置中),我希望它尽早失败,所以我真的不知道如何实现。

我也在考虑对象级缓存,只要使用/调用常量就调用PageType.objects.get(type=type),但这不是矫枉过正吗?在没有缓存的情况下调用 orm 会导致过多的 db 调用,我想防止这种情况发生。

这一定是很简单的事情,但我无法解决。 ;-)

【问题讨论】:

    标签: python django unit-testing lazy-loading fixtures


    【解决方案1】:

    我会使用函数而不是常量,但要记住它们:

    _cache = {}
    
    def get_page_type(type_name):
        if type_name not in _cache:
            _cache[type_name] = PageType.objects.get(type=type_name)
        return _cache[type_name]
    

    所以现在您可以在必要时直接致电get_page_type('Main')

    【讨论】:

    • 这很聪明也很简单。
    • 我稍微修改了您的代码,以减少每次我想使用页面类型常量时的输入:PAGE_TYPE_MAIN = property(lambda: get_page_type('Main')) 我使用了来自stackoverflow.com/questions/880530/… 的一些代码来使property 在模块级别上工作。工作正常,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 2021-08-12
    • 2014-10-10
    • 2017-01-13
    • 2014-01-04
    • 2021-07-10
    • 2019-01-07
    相关资源
    最近更新 更多