UI components for Python using Pydantic and Jinja2 templates
Project description
PyJinHx
Build reusable, type-safe UI components for template-based web apps in Python. PyJinHx combines Pydantic models with Jinja2 templates to give you template discovery, component composition, and JavaScript bundling.
Installation
pip install pyjinhx
Core ideas
You can use PyJinHx in two ways, and mix them:
- Python-side: render a typed Python component instance (
BaseComponent.render()). - Template-side: render HTML-like source with PascalCase custom tags (
Renderer(...).render(source)).
Python-to-HTML Example
Start here if you want a typed component library.
Step 1: Define Component Classes
# components/ui/button.py
from pyjinhx import BaseComponent
class Button(BaseComponent):
id: str
text: str
variant: str = "default"
# components/ui/card.py
from pyjinhx import BaseComponent
from components.ui.button import Button
class Card(BaseComponent):
id: str
title: str
action_button: Button
menu_items: list[Button]
Step 2: Create Templates
<!-- components/ui/button.html (auto-discovered) -->
<button id="{{ id }}" class="btn btn-{{ variant }}">{{ text }}</button>
<!-- components/ui/card.html (auto-discovered) -->
<div id="{{ id }}" class="card">
<h2>{{ title }}</h2>
<div class="action">
<p>Button: {{ action_button.props.text }}</p>
{{ action_button }}
</div>
<ul class="menu">
{% for item in menu_items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</div>
Step 3: Use in Python
from components.ui.card import Card
from components.ui.button import Button
card = Card(
id="form-card",
title="User Form",
action_button=Button(id="submit", text="Submit", variant="primary"),
menu_items=[
Button(id="home", text="Home"),
Button(id="about", text="About")
]
)
html = card.render()
HTML-like syntax (custom tags)
Start here if you prefer composing pages with an HTML-like string.
<!-- templates/card.html -->
<div id="{{ id }}" class="card">
<h2>{{ title }}</h2>
{{ content }}
</div>
<!-- templates/button.html -->
<button id="{{ id }}" class="btn btn-{{ variant }}">{{ text }}</button>
from jinja2 import Environment, FileSystemLoader
from pyjinhx import Renderer
renderer = Renderer(Environment(loader=FileSystemLoader("./templates")), auto_id=True)
html = renderer.render('''
<Card title="Welcome">
<Button text="Get Started" variant="primary"/>
<Button text="Learn More" variant="secondary"/>
</Card>
''')
This mode supports:
- Registered classes: if
Button(BaseComponent)exists, its Pydantic fields are enforced when<Button .../>is instantiated. - Generic tags: if there is no registered class, a generic
BaseComponentis used as long as the template file can be found.
Use custom tags inside component templates
BaseComponent.render() expands <PascalCase /> tags found inside a component template, so component templates can compose other components directly:
<!-- components/ui/page.html -->
<div id="{{ id }}">
<Button id="save" text="Save"/>
</div>
JavaScript & extra assets
- Component-local JS: if a component class
MyWidgethas a sibling filemy-widget.js, it is auto-collected and injected once at the root render. - Extra JS: pass
js=[...]with file paths; missing files are ignored. - Extra HTML files: pass
html=[...]with file paths; they are rendered and exposed in the template context by filename stem (e.g.extra_content.html→extra_content.htmlwrapper). Missing files raiseFileNotFoundError.
Configuration
- Default environment:
Renderer.get_default_renderer()auto-detects a project root and usesFileSystemLoader(root). - Override: call
Renderer.set_default_environment(Environment(loader=FileSystemLoader(...)))for explicit control (tests do this).
Key Benefits
- Type Safety: Pydantic models provide validation and IDE support
- Composability: Nest components easily—works with single components, lists, and dictionaries
- Automatic Template Discovery: Place templates next to component files—no manual paths
- JavaScript Bundling: Automatically collects and bundles
.jsfiles from component directories - Flexible: Use Python classes for reusable components, HTML syntax for quick page composition
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyjinhx-0.2.0.tar.gz.
File metadata
- Download URL: pyjinhx-0.2.0.tar.gz
- Upload date:
- Size: 31.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32308a79dc49b7d82f990ac3488b19c7eac354167559f5b1d985c804e596ab02
|
|
| MD5 |
d95799974030e1833cde7cc31533be5e
|
|
| BLAKE2b-256 |
709a14478006388721fa19f53e7faf23d1d3de7ed8d91987a42706875b6fba8b
|
File details
Details for the file pyjinhx-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pyjinhx-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c04532a154c9fc03d446768305e978daebe49c9033ed14519c2d2dfc663975cd
|
|
| MD5 |
372ade0279e967ce78292c12c1d3c2ff
|
|
| BLAKE2b-256 |
1c9f170072ce3b549a709aabac76ff0ad6478702e0ab4db735ce036d5342a40b
|