3

Djangoプロジェクトで未使用のテンプレートを検出する方法はありますか?

Django 1.3より前は、このような単純な文字列照合関数でそれが可能でした。template_nameただし、1.3以降、オーバーライドしない場合に自動的にを生成する汎用クラスベースのビューがあります(たとえば、DetailView)。

また、サードパーティのモジュールテンプレートをオーバーライドすると、それらのテンプレートはビューのどこにも直接使用されません。

たぶん、すべてのURL定義をクロールし、対応するビューをロードして、template_nameそれらから取得することで実行できますか?

4

2 に答える 2

2

代わりに、モンキーパッチ/get_templateを装飾することでこれを実行できるかどうか興味がありました。すべてのテンプレート読み込み関数を見つける必要がありますが、できると思います(以下の例では2つあります)。

loader.get_templateだけにとどまらないことに気付いたときに、wraptを使用しましたが、うまくいくようです。もちろん、これを製品から50000 km離してください、しかし...

さて、私もこれをユニットテストとノーズテストで駆動しているので、テンプレートの完全なブランチカバレッジがある場合は、Pythonコードを使用して、ほとんどのテンプレートを取得できるはずです(私が見逃していないと仮定して) get_template-type関数)。

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)

wraptの詳細については、safely-applying-monkey-patches-in-pythonを参照してくださいドキュメントを理解するよりも実際に使いやすいので、デコレータは私の脳を傷つけます。

また、どの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)

上記の2つの関数をラップすると、extends、%includes、straight get_templates、およびクラスベースのビューで使用されていたリストタイプのテンプレートが検出されたようです。それは、ファイルシステム上にさえないがカスタムローダーでロードされる私の動的に生成されたテンプレートさえも捕らえました。

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
于 2015-07-18T01:53:44.640 に答える
1

一般的なビューがない場合でも、次のようなコードをいつでも記述できるため、未使用のテンプレートを確実に検出することはできません。

get_template(any_code_you_like()).render(context)

したがって、Django 1.3より前でも、リンクしたdjango-unused-templatesアプリケーションは、テンプレートの使用に関するある種の規律を尊重するプロジェクトでしか機能しませんでした。(たとえば、get_templateandなどの関数のテンプレート引数として常に文字列リテラルを使用しrender_to_responseます。)

すべてのビューをロードするだけでは不十分です。ビューは、さまざまな状況でさまざまなテンプレートを使用する場合があります。

def my_view(request):
    if request.user.is_authenticated():
        return render(request, 'template1.html')
    else:
        return render(request, 'template2.html')

そしてもちろん、テンプレートはビューではまったく使用されないかもしれませんが、システムの他の部分(たとえば、電子メールメッセージ)によって使用される可能性があります。

于 2012-02-12T20:29:12.753 に答える