Skip to content

Instantly share code, notes, and snippets.

@drhoden
Last active December 7, 2023 16:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drhoden/e05292e52fd5fc92cc3b to your computer and use it in GitHub Desktop.
Save drhoden/e05292e52fd5fc92cc3b to your computer and use it in GitHub Desktop.
Obtain context from within Django custom template filter
"""
What if you suddenly need to have access to the context object from within
certain filters, and it would be costly to alter its syntax? Well, that
just happend to me. Here is my solution.
"""
def get_context(max_depth=4):
"""A simple (and perhaps dangerous) way of obtaining a context. Keep
in mind these shortcomings:
1. There is no guarantee this returns the right 'context'.
2. This only works during render execution. So, be sure your
filter continues to work in other cases.
This approach uses the 'inspect' standard Python Library to harvest
the context from the call stack.
"""
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
#Example of useage
@register.filter(name='distance')
def distance(locatable, locatable2=None):
"""
Output nice distance information
"""
log.debug('distance filter')
context = get_context()
if context:
value = context['my_important_context_value'] # <<< this could be 'request'
log.debug('This came from the context: %s', value)
from support.geotools import Point
if not locatable2:
locatable2 = getattr(locatable, 'nearest_major_city_or_town', None)
if not locatable2:
return ''
try:
p1 = Point(locatable)
p2 = Point(locatable2)
if p1 and p2:
return p1 - p2
except:
pass
return ''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment