Django - accessing the RequestContext from within a custom filter

前端 未结 4 1946
花落未央
花落未央 2021-01-04 02:33

I\'ve got a filter currency, which takes a value in USD and converts it to a currency (either USD or GBP). The currency to convert to is stored in the session,

相关标签:
4条回答
  • 2021-01-04 02:41

    If you create a template tag instead of a filter, you are given the context to work with (which contains the request). http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

    0 讨论(0)
  • 2021-01-04 02:42

    This can be done using a filter. First make sure that you have "django.core.context_processors.request" in you TEMPLATE_CONTEXT_PROCESSORS. If you don't, you can add this to your settings.py file:

    TEMPLATE_CONTEXT_PROCESSORS += (
        "django.core.context_processors.request"
    )
    

    Then in your template, your filter will look like this (assuming your session variable is named 'currency_type'):

    {{value|currency:request.session.currency_type}}
    

    Or is something like this what you are considering fairly horrible?

    0 讨论(0)
  • 2021-01-04 02:56

    I would have to agree with Adam that migrating the code to a custom tag is the best way.

    However, a client needed to record the use of certain filters only when a page was published and had a HUGE inventory of templates that used the existing filter syntax. It would have been a costly undertaking to rewrite all the templates. So, I came up with this simple function that extracts the context from the call stack:

    https://gist.github.com/drhoden/e05292e52fd5fc92cc3b

    def get_context(max_depth=4):
        import inspect
        stack = inspect.stack()[2:max_depth]
        context = {}
        for frame_info in stack:
            frame = frame_info[0]
            arg_info = inspect.getargvalues(frame)
            if 'context' in arg_info.locals:
                context = arg_info.locals['context']
                break
        return context
    

    Be sure to read my warnings, but this DOES give standard filters access to the context (when it is available) WITHOUT having to turn your filter into a tag.

    0 讨论(0)
  • 2021-01-04 03:06

    A somehow less hacky solution to Daniel Rhoden's proposal is, to use threading.local(). Define a middleware class, which stores your request as a global object inside your local thread, and add that class to your MIDDLEWARE_CLASSES.

    Now a template filter can easily access that request object.

    0 讨论(0)
提交回复
热议问题