Last active
December 7, 2023 16:18
-
-
Save drhoden/e05292e52fd5fc92cc3b to your computer and use it in GitHub Desktop.
Obtain context from within Django custom template filter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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