python - Django:检测未使用的模板

标签 python django refactoring code-cleanup

有没有办法检测 Django 项目中未使用的模板?

在 Django 1.3 之前,这可以通过简单的字符串匹配函数(如 this one)来实现。 。但从 1.3 开始,有一些基于通用类的 View ,如果您不覆盖它(例如 DetailView),它们会自动生成 template_name

此外,如果您覆盖第 3 方模块模板,这些模板不会直接在您的 View 中的任何位置使用。

也许可以通过抓取所有 URL 定义、加载相应的 View 并从中获取 template_name 来完成?

最佳答案

我很好奇你是否可以通过猴子修补/装饰 get_template 来做到这一点。我想你可以,尽管你必须找到所有模板加载 函数(在下面的示例中我有两个)。

我用了wrapt当我注意到它不仅仅是 loader.get_template 时,但它似乎很好。当然,要与产品保持 50000 公里的距离,但是...

现在,还要遵循的是,我正在使用单元测试和 Nose 测试来驱动它,因此,如果您使用 Python 代码对模板进行了完整的分支覆盖,那么您应该能够获得大多数模板(假设我没有)不要错过任何 get_template 类型的函数)。

settings.py

这是修补 get_template & co 的“大脑”。

import wrapt
import django.template.loader
import django.template.engine

def wrapper(wrapped, instance, args, kwargs):

    #concatenate the args vector into a string.
    # print "\n\n\n\n%s\nI am a wrapper \nusage:%s\n%s\n\n\n\n\n" % ("*"*80, usage, "*"*80)
    try:
        return wrapped(*args, **kwargs)
    finally:
        usage = ",".join([unicode(arg) for arg in args if arg])
        track_usage(usage)

#you have to wrap whatever is loading templates...
#imported django module + class/method/function path of what needs to be
#wrapped within that module.  comment those 2 lines out and you are back to
#normal


wrapt.wrap_function_wrapper(django.template.loader, 'get_template', wrapper)
wrapt.wrap_function_wrapper(django.template.engine, 'Engine.find_template', wrapper)

参见safely-applying-monkey-patches-in-python有关wrapt 的更多详细信息。实际上使用起来比理解文档更容易,装饰器让我伤脑筋。

此外,为了跟踪哪些 django 函数正在执行实际加载,我在代码和模板中故意拼错了一些模板名称,对其运行单元测试并查看堆栈跟踪以查找丢失的模板异常。

这是我写得相当糟糕的函数,它将添加到一个集合中并将其放入 json 输出....

def track_usage(usage):
    fnp_usage = "./usage.json"

    try:
        with open(fnp_usage, "r") as fi:
            data = fi.read()
            #read the set of used templates from the json file
            j_data = json.loads(data)
            s_used_file = set(j_data.get("li_used"))

    except (IOError,),e:
            s_used_file = set()
            j_data = dict()

    s_used_file.add(usage)
    #convert the set back to a list for json compatibility
    j_data["li_used"] = list(s_used_file)

    with open(fnp_usage, "w") as fo:
        json.dump(j_data, fo)

和输出(使用脚本对其进行格式化):

import sys
import json
fnp_usage = sys.argv[1]


with open(fnp_usage, "r") as fi:
    data = fi.read()
    #read the set of used templates from the json file
    j_data = json.loads(data)
    li_used_file = j_data.get("li_used")
    li_used_file.sort()

    print "\n\nused templates:"
    for t in li_used_file:
        print(t)

通过包装上面的两个函数,它似乎捕获了扩展、%includes 和直接 get_templates,以及基于类的 View 使用的列表类型模板。它甚至捕获了我动态生成的模板,这些模板甚至不在文件系统上,但使用自定义加载器加载。

used templates:
bootstrap/display_form.html
bootstrap/errors.html
bootstrap/field.html
bootstrap/layout/baseinput.html
bootstrap/layout/checkboxselectmultiple.html
bootstrap/layout/field_errors.html
bootstrap/layout/field_errors_block.html
bootstrap/layout/help_text.html
bootstrap/layout/help_text_and_errors.html
bootstrap/layout/radioselect.html
bootstrap/whole_uni_form.html
django_tables2/table.html
dynamic_template:db:testdb:name:pssecurity/directive.PrimaryDetails.json
uni_form/layout/div.html
uni_form/layout/fieldset.html
websec/__base.html
websec/__full12.html
websec/__l_right_sidebar.html
websec/bootstrapped_home.html
websec/changedb.html
websec/login.html
websec/requirejs_config.html
websec/topnav.html
websec/user_msg.html

关于python - Django:检测未使用的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9227489/

相关文章:

spring - 如何在 Spring Boot 服务应用程序中的 REST 服务调用之间按原样传递请求参数?

python - 为什么Python3.5有generator based co-routines?

python - 如何在Django中用 "SlugField()"增加 "unique=True"的大小?

python - Json 字段搜索与 django 意外行为

django - 如何对 Django-CMS 扩展进行单元测试?

java - 如何使用重构工具安全地重构代码?

python - 如何打开多个pygame?

python - 查找列表中列的总和获取 "TypeError: cannot perform reduce with flexible type"

python - 在 python 2.4 中,如何使用 csh 而不是 bash 执行外部命令?

c - 如何在 Clion 中自动生成 .h 文件的函数头?