Skip to main content

A component preprocessor for Flask/Jinja that mimics React/Vue-style components

Project description

jinpro

jinpro is a module that makes it easy to render custom Jinja components in HTML templates for Flask applications. It enables the use of custom component tags, which can simplify your templates and make your code more readable, and closely mimics the same functionality of Vue or React (without the reactivity, of course).

This guide will walk you through each part of the JinjaProcessor class and provide an example of how to use it in your Flask project.

Overview

The main purpose of JinjaProcessor is to:

  1. Parse custom component tags in your HTML.
  2. Ensure all required attributes are passed in.
  3. Render the components into full HTML using Jinja templates.

Getting Started

To start, create an instance of JinjaProcessor and initialize it with your Flask app:

from flask import Flask
app = Flask(__name__)

# Initialize JinjaProcessor like this
jinja_processor = JinjaProcessor(app)

# or this
jinja_processor = JinjaProcessor()
jinja_processor.init(app)

You can then use jinja_processor.render() (directly replacing Flask's render_template) to render templates that contain custom tags.

Example Usage

Let's say you have a custom component for a button that you want to use throughout your templates. Here's what the process might look like:

Create the Component Template

In any of your templates folders, create a file called Button.jinja for your custom button component:

{# attributes content, color="blue", size="medium", non_clickable = False #}
<button class="btn btn-{{ color }} btn-{{ size }}" {% if non_clickable %} disabled {% endif %}>
    {{ content }}
</button>

This component expects the automatic content attribute (more on that in the exceptions section), and color and size attributes (optional, with defaults), as indicated by the commented line on the top.

This commented line is always required. At present, if you include an attribute in this list and the component is called without one of these attributes, it will throw an error. However, the component will still render attributes passed to it if they're not in the list. Components are also rendered "in context", meaning that variables and data passed to the parent .html template are also passed to the components.

Use the Custom Tag in a Template

In another template, use the Button tag with your custom attributes:

<h1>Welcome to My Site</h1>
<Button color="green" size="large" non-clickable>Click Me</Button>

As you can see, the content attribute is missing. This is because it refers to the stuff in between the tags, and for that reason, it is "reserved".

Additionally, arguments with a hyphen, like non-clickable, get converted to an underscore, like non_clickable. HTML syntax highlighting usually doesn't like underscores in HTML, and Python doesn't allow for hyphens in variable names.

And, lastly, in typical HTML style, passing an argument without a value defaults it to True.

Render the Template with JinjaProcessor

Now, render the parent template using JinjaProcessor, and it will replace the <Button> tag with the actual HTML from Button.jinja:

@app.route('/')
def home():
    html = jinja_processor.render("welcometomysite.html")
    return html

The rendered HTML will look like this:

<h1>Welcome to My Site</h1>
<button class="btn btn-green btn-large">Click Me</button>

JinjaProcessor scans your code to look for components first, and then scans those to look for components, and so on, until it's all out of components to find. After that, the entire page is rendered "regularly" by render_template_string.

The idea is that you replace all your render calls with this .render() function. Since it looks in the same folders and can take the same arguments, it will enable you to use components wherever you want.

For instance, instead of typing this...

{% extends 'base.html' %}

{% block content %}
    <p>Hi!</p>
{% endblock %}

You can now just type this...

<PageLayout>
    <p>Hi!</p>
</PageLayout>

Exceptions and other notes

MissingComponent: Raised when the specified component file isn't found.

MissingAttributeList: Raised if the component template lacks a required attribute list.

MissingAttributeInCall: Raised if a required attribute is missing in the component call.

Additionally, it will throw a KeyError if the content attribute is used in a component. The content attribute is considered "reserved", and refers to the text in between the opening and closing tags.

Since the components are passed the template context and are rendered recursively, you can access page-specific variables in templates without defining them as part of your commented attributes list -- in example, if you pass a name variable to your page, you can access the name variable inside of your components without declaring it as part of the required attributes or passed components. They have a shared context.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jinpro-1.0.5.tar.gz (18.1 kB view hashes)

Uploaded Source

Built Distribution

jinpro-1.0.5-py3-none-any.whl (21.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page