The graphical user interface is where Pytigon meets its users. Unlike many frameworks that bet everything on a single rendering technology, Pytigon embraces diversity: the same application logic can present itself through a native desktop window, a web browser tab, or a mobile screen. The magic is in the abstraction.
[row]
Regardless of the client face, the rendering pipeline follows the same path:
.ihtml Template → Preprocessor → .html Django Template → Context Rendering → HTML Output
↓
┌─────────────────────────────────────┤
↓ ↓ ↓
wxPython Web Browser schhtml
(native) (browser) (PDF/print)
.ihtml)The .ihtml format is Pytigon's secret sauce. It uses indentation-based syntax that compiles to standard Django templates. Key rules:
% introduce Django template tags; ending with : auto-closes blocks%% define Django blocks. are plain text (leading dot stripped)This means a form template that would be 200 lines of noisy {% and %} in vanilla Django becomes a clean, readable 60-line .ihtml file.
For PDF generation and wxPython native rendering, Pytigon uses schhtml — a simplified HTML-like format optimized for page-based rendering. It supports:
The format is intentionally not HTML-compatible. It sacrifices web standards for rendering performance and simplicity. Think of it as HTML that went to minimalism school.
The desktop client embeds a WebKit browser. This means:
Communication between the native shell and the embedded browser happens through a custom bridge, allowing JavaScript to trigger native dialogs and native code to inject into the DOM.
Pytigon detects the client device and serves appropriately themed templates:
| Device Class | Template Theme | Characteristics |
|---|---|---|
| Desktop | desktop |
Full menus, sidebars, multi-column layouts |
| Tablet | tablet |
Simplified navigation, touch-friendly spacing |
| Smartphone | smartfon |
Single-column, hamburger menus, minimal chrome |
| Embedded | schweb |
Stripped-down, optimized for hybrid mode |
Template inheritance resolves automatically: if theme/smartfon doesn't define a block, it falls back to theme/tablet, then theme/desktop, then the base templates.
The web client includes a custom JavaScript library that handles:
The library is designed to work without heavy frameworks — jQuery is included for DOM manipulation convenience, but Pytigon's own components are vanilla JavaScript wrapped in Web Components.
The context processor injects client detection variables into every template:
standard_web_browser: 0=wxPython, 1=standard browser, 2=hybrid, 3=webkit frame
browser_type: 'desktop_standard', 'tablet_standard', 'smartfon_standard', 'schweb'
client_type: 'desktop', 'tablet', 'smartfon', 'schweb'
Use these in templates to conditionally render different UI elements for different clients.