1

ホームプロジェクト用に書いたミドルウェアを適応させようとしています。ミドルウェアの目的は、HTML または XML (または他のユーザー定義のテンプレート タイプ) の先頭にコメント ブロックを追加して、そのテンプレートに関する情報 (それを呼び出したビュー、テンプレートの場所など) を表示することでした。テンプレートとその場所をすばやく特定できるため、特に慣れていないプロジェクトで作業する場合は特に、デバッグに非常に役立ちました.

問題は、テンプレート名を取得するためにビューでの SimpleTemplateResponse の使用に依存していることです。それはテンプレート名を保持しているため、process_template_response() のミドルウェアで取得できます。

通常は render_to_response() が使用され、それをレンダリングするために使用されたテンプレートをより長く知っている HttpResponse オブジェクトを返すため、これは明らかにミドルウェアを既存のプロジェクトに移植するのに非常に実用的ではありません。

私が以前取り組んでいたプロジェクトで遭遇したテンプレート識別子の最初のインスタンス (そこから私が自分のバージョンを適応させたもの) を書いた人は、threading.currentThread() などを使用し、その方法でテンプレート名を見つけて渡しました。ミドルウェアにアクセスしましたが、そのコードにアクセスできなくなったため、それがどのように行われたかを確認できません。

SimpleTemplateResponse の使用や、理想的には render_to_response へのパッチ適用を伴わないテンプレート名にアクセスする方法を知っている人はいますか (ただし、それが唯一の方法であると思われる場合は受け入れます)。

ミドルウェア:

# Base template for the html/url locator comment block
COMMENT_BLOCK = """
<!--
[ url      ] >> http://%(host)s%(path)s
[ referer  ] >> %(referer)s
[ module   ] >> %(module)s
[ function ] >> %(function)s, line %(line)s
[ args     ] >> args=%(args)s, kwargs=%(kwargs)s, defaults=%(defaults)s
[ template ] >> %(template)s
-->

"""

# Add any additional template types you wish to add the comment block to.
MIMETYPES = (
    "text/html",
    "text/xml",
)


class HtmlTemplateFinder:
    """
    Middleware class that adds a comment block to an html response object.
    Currently adds url, referer, the python module and its function/line,
    the function arguments, and the template passed in. Only triggers if
    a SimpleTemplateResponse object was used to render the template and
    the template is .html.
    """

    def __init__(self):
        self.host = None
        self.referer = None
        self.path = None
        self.module = None
        self.function = None
        self.line = None
        self.args = None
        self.kwargs = None
        self.defaults = None
        self.template = None
        self.valid_template = False

    def _populate_comment_block(self):
        return COMMENT_BLOCK % {
                                'host': self.host,
                                'referer': self.referer,
                                'path': self.path,
                                'module': self.module,
                                'function': self.function,
                                'line': self.line,
                                'args': self.args,
                                'kwargs': self.kwargs,
                                'defaults': self.defaults,
                                'template': self.template,
                               }

    def process_view(self, request, view_func, view_args, view_kwargs):
        self.host = request.META.get('HTTP_HOST', None)
        self.referer = request.META.get('HTTP_REFERER', None)
        self.path = request.path
        self.module = view_func.func_code.co_filename
        self.function = ('.').join((view_func.__module__, view_func.func_name))
        self.line = view_func.func_code.co_firstlineno
        self.args = view_args
        self.kwargs = view_kwargs
        self.defaults = view_func.func_defaults
        return None

    def process_template_response(self, request, response):
        from mimetypes import guess_type
        # Use this rather than response.template_name, this always returns str
        self.template = response.resolve_template(response.template_name).name
        self.valid_template = guess_type(self.template)[0] in MIMETYPES
        return response

    def process_response(self, request, response):
        import threading
        print threading.current_thread.request
        if settings.DEBUG:
            if self.valid_template:
                block = self._populate_comment_block()
                response.content = "%s%s" % (block, response.content)
        return response
4

2 に答える 2

0

ビューがクラスベースの場合、次のことができます。

from contextlib import suppress

class MyMiddleware(SessionMiddleware):
    def process_response(self, request, response):
        html = response.content
        dostuff()
        return super().process_response(request, response)

    def process_view(self, request, view_func, view_args, view_kwargs):
        with suppress(AttributeError):
            template_name = view_func.view_class.template_name
        with suppress(AttributeError):
            # Do something else for function based views, e.g. add it as an attribute to the function
            return view_func.template_name
        print(template_name)
        return None
于 2021-11-10T14:03:44.377 に答える