Skip to content

API/ENH: Styler template arguments #15649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chris-b1 opened this issue Mar 10, 2017 · 9 comments
Closed

API/ENH: Styler template arguments #15649

chris-b1 opened this issue Mar 10, 2017 · 9 comments
Labels
IO HTML read_html, to_html, Styler.apply, Styler.applymap

Comments

@chris-b1
Copy link
Contributor

Usecase - I have a Styler subclass with a new template that I want to pass some arbitrary stuff into - which currently there isn't a great way to do (right now I'm overriding and re-implementing .render()).

Open to suggestions on the api, but I was thinking of adding template_args argument that would be passed to the template.

from pandas.formats.style import Styler
from jinja2 import Template

class MyStyler(Styler):
    template = Template("""
        .... omitted
        {{ my_value_1 }}
        """)

MyStyler(df, template_args={'my_value_1': '...'}).render()

xref #11610 (master tracker)

pandas 0.19.2

@chris-b1 chris-b1 added the IO HTML read_html, to_html, Styler.apply, Styler.applymap label Mar 10, 2017
@TomAugspurger
Copy link
Contributor

Are you familiar with Jinja's template inheritence? I wonder if we inserted some {% block ... %} in good places, it'd be easier for people to extend it and insert their own?

@TomAugspurger
Copy link
Contributor

Oh, are these template_args known when instantiating the data, or at render-time?

I think django gets around that problem by providing a get_context_data() method that subclasses can override. It returns a dict that gets sent to the template engine.

@chris-b1
Copy link
Contributor Author

chris-b1 commented Mar 10, 2017

In my case the template_args are known at render time.

I was actually just looking at how jinja does inheritance, - some {% bock ... %} extension points would also be good, right now I'm copy-pasting the whole template and adding what I need, which of course isn't great.

@TomAugspurger
Copy link
Contributor

@chris-b1 can you take a look at TomAugspurger@aafba92 and let me know if that would be sufficient? I moved it into it's own template file to make things easier to work on.

I also added **kwargs to render. I think that'll be a bit nicer than passing template_args to your Style subclass.

I'll add some tests and submit a PR, but it could be a bit.

@chris-b1
Copy link
Contributor Author

@TomAugspurger thanks! Made one inline comment on the blocks.

My only question / thing needing docs would be how to actually extend that template. I understand the template syntax ({% extends 'html.tpl' %} ...), but it's not clear to me how I would create a jinja2 Environment containing both my template and the base?

@TomAugspurger
Copy link
Contributor

My only question / thing needing docs would be how to actually extend that template.

I'll look into this. I think the idea is to use a PrefixLoader or ChoiceLoader.

class MyStyler(Styler):
    my_loader = FileSystemLoader("templates/")
    loader = ChoiceLoader([my_loader, Styler.loader])
    template_name = 'mytemplate.tpl'

then if you make a file templates/mytemplate.tpl, you should be able to {% extends "html.tpl" %}. I'll have a couple fixes to push first, but I think that'll work...

@TomAugspurger
Copy link
Contributor

@chris-b1 http://nbviewer.jupyter.org/gist/anonymous/c84f30b41609fef7fd1c06b9fd748729 has an example (using my branch)

I'll get things cleaned up and submitted as a PR this week.

@chris-b1
Copy link
Contributor Author

chris-b1 commented Apr 3, 2017

Very nice! Might be nice to wrap the subclassing into some kind of factory function to lessen the jinja2 knowledge required? Roughly

def make_styler_subclass(template_folder, visible_template_name):
    loader = ChoiceLoader([
        FileSystemLoader(template_folder),
        PackageLoader("pandas.formats")
    ])
    class MyStyler(pd.formats.style.Styler):
        env = Environment(loader=loader)
        template = env.get_template(visible_template_name)
    return MyStyler

@TomAugspurger
Copy link
Contributor

Closed by #15649 (I think solved everything, just forget to close it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
IO HTML read_html, to_html, Styler.apply, Styler.applymap
Projects
None yet
Development

No branches or pull requests

2 participants