[new feature request] Navigation filter #176

Closed
jpfarias opened this Issue Feb 11, 2013 · 7 comments

Projects

None yet

3 participants

@jpfarias

Hi! I use mongodb as my backend and as result I often have dictionaries with subdictionaries and I have this filter that is useful to get data down the tree of dictionaries.

def navigate(obj, path):
    parts = path.split('.')
    d = obj
    for p in parts:
        d = d.get(p, {})
    if not d:
        return ''
    return d

Then I can use my_obj|navigate(path) where path = "x.y.z" and my_obj = {'x': {'y': {'z': 1}}}.

This is a simple enough filter that I image being useful for other people, specially if they use documents with subdocuments from mongodb.

If I get some free time I will try send a pull request for this filter with docs and tests later, unless someone does that before me. :-)

@mitsuhiko
The Pallets Projects member

I think this is a bit too specific. You can already do my_obj.x.y.z anyways.

@mitsuhiko mitsuhiko closed this May 20, 2013
@jpfarias

Maybe I wasn't clear enough on my description. That filter would be applied when you have an object and a string with dotted notation on how to get to an element of that object.

I use that on my projects specially when writing macros where I can pass the macro the root object and a string on how to get the attribute.

So if you have a root object my_obj and a string path with 'x.y.z' you can't really do my_obj.path.

@mitsuhiko
The Pallets Projects member

That can be easily implemented yourself in your project. It's too specific for Jinja itself.

@Naddiseo

@jpfarias

@environmentfilter
def jinja_getattr(env, obj, attr_string):
    if attr_string == '':
        return obj
    for attr in attr_string.split('.'):
        obj = env.getattr(obj, attr)
    return obj

jinja_env.filters.update({ 'navigate' : jinja_getattr })
@jpfarias

Yes, I've written that in a different way on my first post. I just thought it would be useful enough to other people that it could be included with the standard filters, seems that is not the case though.

@Naddiseo

The one you gave in your first post doesn't work when mixing objects and dictionaries, what I meant to point out was that jinja already has this functionality. If you know you're just going to be using one or the other you can use the jinja functions directly (in a loop), or even use operator.{attrgetter, itemgetter} in which case the filters become simpler:

import operator


jinja_env.globals.update({ 'getattr' : lambda obj, attr: operator.attrgetter(attr)(obj) })
# your implementation is equivalent to the following: 
jinja_env.globals.update({ 'getitem' : lambda obj, attr: operator.itemgetter(attr)(obj) })
@jpfarias

Thanks for the input, I didn't know that could be done already. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment