Skip to content
This repository was archived by the owner on Jun 22, 2025. It is now read-only.
This repository was archived by the owner on Jun 22, 2025. It is now read-only.

Implementation of Jinja2 Variables #217

Open

Description

@Nootaku

First of all : Eel is amazing ! This is a project I'd love to participate with.

One of the features I find lacking is the implementation of Jinja Variables. While the documentation and the options allow for inserting and using templates (with the jinja_templates argument in the start() function), I did not see any possibility to transfer variables within the templates.

It would be nice if this could be included either as a decorator or in a more "flask-like" fashion in the return of a function.

One solution that I tried to fiddle with but to no avail, was to create a decorator for the _static function (in the __init__.py) that seems to handle Jinja's template.render() function.

Here's what I got so far:

def jinjaVariables(_static):
    def innerFunction(path, jinja_variable=None):
        # the decorator recieved a Jinja Variable
        if "jinja_variables" is not None:
            response = None
            if 'jinja_env' in _start_args and 'jinja_templates' in _start_args:
                template_prefix = _start_args['jinja_templates'] + '/'
                if path.startswith(template_prefix):
                    n = len(template_prefix)
                    template = _start_args['jinja_env'].get_template(path[n:])
                    response = btl.HTTPResponse(template.render(jinja_variable))

            if response is None:
                response = btl.static_file(path, root=root_path)

            _set_response_headers(response)
            return response

        _static(path)

    return innerFunction

The idea was to create a global dictionary variable called jinja_variable and to update that variable depending on the page you want to visit.

If you were to include the jinja_variable in the kwargs of the start() function, wouldn't it be possible to dynamically change the output of the html page by accessing the required keys ?

Activity

  1. samuelhwilliams commented on Dec 6, 2019

    @samuelhwilliams
    Collaborator

    Hey @Nootaku - thanks for your interest in Eel!

    You're definitely right that the implementation of jinja templating is a little lacking here, and being able to pass variables into the render calls does limit its utility.

    I'd love to understand your use-case a little better so we can start to work out the best way forward. At the moment I'm not sure I understand your proposed solution or that it works for a general case. I'll start to have a think about it, but any details you can provide will help me understand where you're coming from.

    Thanks!

  2. Nootaku commented on Dec 9, 2019

    @Nootaku
    Author

    Hey @samuelhwilliams - thank you for your swift answer.

    I'm am a relatively inexperienced programmer, so the code above was simply something that I thought could be possible to integrate in the framework.

    I'll try to be as short as possible, but here is my thought process:

    • Based on what Flask does, it is possible to nest Jinja's template.render() function inside flask's render_template() function (see templating.py line 116 to 141). This means the arguments of Flask's render_template() function are being passed on to Jinja's template.render() function.
    • Currently Eel does something similar in its _static() function.
    • This means that it should be possible to modify the _static() function as follows (or something similar)
    def _static(path, **context):
        """Arguments:
        		- path: path to the jinja template
        		- context: dictionary with
        			key = jinja variable name
        			value = jinja variable value
        """
        response = None
        if (
            'jinja_env' in _start_args and
            'jinja_templates' in _start_args
        ):
            template_prefix = _start_args['jinja_templates'] + '/'
            if path.startswith(template_prefix):
                n = len(template_prefix)
                template = _start_args['jinja_env'].get_template(path[n:])
                if context is not None:
                    response = btl.HTTPRespons(
                        template.render(context)
                    )
                else:
                    response = btl.HTTPRespons(
                        template.render()
                    )
         
        if response is None:
            response = btl.static_file(path, root=root_path)
    
        _set_response_headers(response)
        return response
    • By doing this, the last problem we are facing is to provide the **context argument to _static() in a way that is possible for the user to send variable for each html-page he/she wants to load. To do so, I have two options that come to mind:
      1. the use of a decorator
      2. create an independant function

    In both cases, taking Eel's structure in consideration, we should pass 2 arguments:

    • a path_to_template
    • the context_dictionary

    I believe it might end up looking something like this (and it is what I tried to make last week):

    @eel.jinja_variables(some_context_dictionary)
    def load_template(path_to_template):
        html_page = eel.render_page(path_to_template, some_context_dictionary)
        return html_page

    Cheers

  3. Nama commented on Sep 30, 2020

    @Nama

    It's making building html in for-loops waaaay cleaner.

    I would just pass an object to the template and get the values in a for-loop. But for Eel, I have to get the values in a for-loop, run the python command from javascript and do another for-loop for building the html.

    And putting in values in html is in jinja itself muuch fancier.

  4. forno96 commented on Jul 6, 2021

    @forno96

    There's some update on this topic?
    I'm falling in love with this project and having the possibility to pass context to jinja would be super helpfull

  5. eddyizm commented on Jan 28, 2022

    @eddyizm

    So am I correct in understanding that you can't pass a python variable to jinja or for example a data table?

  6. Khharua commented on Jul 24, 2023

    @Khharua

    I also hope this will be implemented, before or (probably) later! 👯

  7. TadeasFrycak commented on Aug 16, 2023

    @TadeasFrycak

    Hello, would it be possible to implement that, please? Just change of 1-2 lines of code in init.py is required:

    Line 245 before:
    response = btl.HTTPResponse(template.render())

    Line 245 after:
    response = btl.HTTPResponse(template.render(_start_args['jinja_context']))

    And then optionally add 'jinja_context': None to _start_args on line 53

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions