|
// retoor <retoor@molodetz.nl>
|
|
|
|
import "jinja" for Environment, DictLoader
|
|
|
|
System.print("=" * 60)
|
|
System.print("JINJA TEMPLATE INHERITANCE - Extends, Blocks, and Includes")
|
|
System.print("=" * 60)
|
|
|
|
var templates = {
|
|
"base.html": "<!DOCTYPE html>
|
|
<html lang=\"en\">
|
|
<head>
|
|
<meta charset=\"UTF-8\">
|
|
<title>{\% block title \%}Default Title{\% endblock \%}</title>
|
|
<style>
|
|
{\% block styles \%}
|
|
body { font-family: sans-serif; margin: 20px; }
|
|
{\% endblock \%}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
{\% block header \%}
|
|
<h1>My Website</h1>
|
|
<nav>{\% block nav \%}<a href=\"/\">Home</a>{\% endblock \%}</nav>
|
|
{\% endblock \%}
|
|
</header>
|
|
|
|
<main>
|
|
{\% block content \%}
|
|
<p>Default content goes here.</p>
|
|
{\% endblock \%}
|
|
</main>
|
|
|
|
<footer>
|
|
{\% block footer \%}
|
|
<p>Copyright 2024</p>
|
|
{\% endblock \%}
|
|
</footer>
|
|
</body>
|
|
</html>",
|
|
|
|
"page.html": "{\% extends \"base.html\" \%}
|
|
|
|
{\% block title \%}{{ page_title }} - My Website{\% endblock \%}
|
|
|
|
{\% block content \%}
|
|
<article>
|
|
<h2>{{ heading }}</h2>
|
|
<p>{{ content }}</p>
|
|
</article>
|
|
{\% endblock \%}",
|
|
|
|
"blog_base.html": "{\% extends \"base.html\" \%}
|
|
|
|
{\% block nav \%}
|
|
{{ super() }}
|
|
| <a href=\"/blog\">Blog</a>
|
|
| <a href=\"/about\">About</a>
|
|
{\% endblock \%}
|
|
|
|
{\% block styles \%}
|
|
{{ super() }}
|
|
.blog-post { border: 1px solid #ccc; padding: 10px; margin: 10px 0; }
|
|
.blog-meta { color: #666; font-size: 0.9em; }
|
|
{\% endblock \%}
|
|
|
|
{\% block content \%}
|
|
<section class=\"blog\">
|
|
{\% block blog_content \%}
|
|
<p>Blog posts will appear here.</p>
|
|
{\% endblock \%}
|
|
</section>
|
|
{\% endblock \%}",
|
|
|
|
"blog_post.html": "{\% extends \"blog_base.html\" \%}
|
|
|
|
{\% block title \%}{{ post.title }} - Blog{\% endblock \%}
|
|
|
|
{\% block blog_content \%}
|
|
<article class=\"blog-post\">
|
|
<h2>{{ post.title }}</h2>
|
|
<p class=\"blog-meta\">By {{ post.author }} on {{ post.date }}</p>
|
|
<div class=\"blog-body\">
|
|
{{ post.body }}
|
|
</div>
|
|
{\% if post.tags \%}
|
|
<p class=\"blog-tags\">Tags: {{ post.tags|join(\", \") }}</p>
|
|
{\% endif \%}
|
|
</article>
|
|
{\% endblock \%}",
|
|
|
|
"blog_list.html": "{\% extends \"blog_base.html\" \%}
|
|
|
|
{\% block title \%}All Posts - Blog{\% endblock \%}
|
|
|
|
{\% block blog_content \%}
|
|
<h2>Recent Posts</h2>
|
|
{\% for post in posts \%}
|
|
<article class=\"blog-post\">
|
|
<h3>{{ post.title }}</h3>
|
|
<p class=\"blog-meta\">{{ post.date }} by {{ post.author }}</p>
|
|
<p>{{ post.excerpt }}</p>
|
|
<a href=\"/blog/{{ post.slug }}\">Read more...</a>
|
|
</article>
|
|
{\% else \%}
|
|
<p>No posts yet.</p>
|
|
{\% endfor \%}
|
|
{\% endblock \%}",
|
|
|
|
"admin_base.html": "{\% extends \"base.html\" \%}
|
|
|
|
{\% block header \%}
|
|
<h1>Admin Panel</h1>
|
|
<nav>
|
|
<a href=\"/admin\">Dashboard</a> |
|
|
<a href=\"/admin/users\">Users</a> |
|
|
<a href=\"/admin/posts\">Posts</a> |
|
|
<a href=\"/admin/settings\">Settings</a>
|
|
</nav>
|
|
{\% endblock \%}
|
|
|
|
{\% block styles \%}
|
|
{{ super() }}
|
|
.admin-panel { background: #f5f5f5; padding: 20px; }
|
|
.admin-table { width: 100\%; border-collapse: collapse; }
|
|
.admin-table th, .admin-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
|
{\% endblock \%}
|
|
|
|
{\% block content \%}
|
|
<div class=\"admin-panel\">
|
|
{\% block admin_content \%}
|
|
<p>Welcome to the admin panel.</p>
|
|
{\% endblock \%}
|
|
</div>
|
|
{\% endblock \%}
|
|
|
|
{\% block footer \%}
|
|
<p>Admin Panel v1.0 | <a href=\"/\">Back to site</a></p>
|
|
{\% endblock \%}",
|
|
|
|
"admin_users.html": "{\% extends \"admin_base.html\" \%}
|
|
|
|
{\% block title \%}User Management - Admin{\% endblock \%}
|
|
|
|
{\% block admin_content \%}
|
|
<h2>User Management</h2>
|
|
<table class=\"admin-table\">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Name</th>
|
|
<th>Email</th>
|
|
<th>Role</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{\% for user in users \%}
|
|
<tr>
|
|
<td>{{ user.id }}</td>
|
|
<td>{{ user.name }}</td>
|
|
<td>{{ user.email }}</td>
|
|
<td>{{ user.role|title }}</td>
|
|
<td>{{ \"Active\" if user.active else \"Inactive\" }}</td>
|
|
</tr>
|
|
{\% endfor \%}
|
|
</tbody>
|
|
</table>
|
|
<p>Total users: {{ users|length }}</p>
|
|
{\% endblock \%}",
|
|
|
|
"sidebar.html": "<aside class=\"sidebar\">
|
|
<h3>{{ title|default(\"Sidebar\") }}</h3>
|
|
{\% if items \%}
|
|
<ul>
|
|
{\% for item in items \%}
|
|
<li><a href=\"{{ item.url }}\">{{ item.label }}</a></li>
|
|
{\% endfor \%}
|
|
</ul>
|
|
{\% endif \%}
|
|
</aside>",
|
|
|
|
"alert.html": "<div class=\"alert alert-{{ type|default(\"info\") }}\">
|
|
{\% if dismissible \%}<button class=\"close\">×</button>{\% endif \%}
|
|
<strong>{{ title }}:</strong> {{ message }}
|
|
</div>",
|
|
|
|
"page_with_includes.html": "{\% extends \"base.html\" \%}
|
|
|
|
{\% block title \%}Page with Includes{\% endblock \%}
|
|
|
|
{\% block content \%}
|
|
<div class=\"container\">
|
|
<div class=\"main-content\">
|
|
{\% include \"alert.html\" \%}
|
|
<h2>Main Content</h2>
|
|
<p>{{ content }}</p>
|
|
</div>
|
|
{\% include \"sidebar.html\" \%}
|
|
</div>
|
|
{\% endblock \%}",
|
|
|
|
"email_base.html": "From: {{ from_email }}
|
|
To: {{ to_email }}
|
|
Subject: {\% block subject \%}No Subject{\% endblock \%}
|
|
|
|
{\% block greeting \%}Hello,{\% endblock \%}
|
|
|
|
{\% block body \%}
|
|
This is the email body.
|
|
{\% endblock \%}
|
|
|
|
{\% block signature \%}
|
|
Best regards,
|
|
{{ sender_name }}
|
|
{\% endblock \%}",
|
|
|
|
"welcome_email.html": "{\% extends \"email_base.html\" \%}
|
|
|
|
{\% block subject \%}Welcome to Our Service, {{ user.name }}!{\% endblock \%}
|
|
|
|
{\% block greeting \%}Dear {{ user.name }},{\% endblock \%}
|
|
|
|
{\% block body \%}
|
|
Thank you for signing up for our service!
|
|
|
|
Your account details:
|
|
- Username: {{ user.username }}
|
|
- Email: {{ user.email }}
|
|
- Plan: {{ user.plan|title }}
|
|
|
|
To get started, please verify your email by clicking the link below:
|
|
{{ verification_url }}
|
|
|
|
If you have any questions, feel free to contact our support team.
|
|
{\% endblock \%}"
|
|
}
|
|
|
|
var env = Environment.new(DictLoader.new(templates))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("1. BASIC PAGE (extends base.html)")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("page.html").render({
|
|
"page_title": "Welcome",
|
|
"heading": "Welcome to Our Website",
|
|
"content": "This is a simple page that extends the base template."
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("2. BLOG POST (three-level inheritance: blog_post -> blog_base -> base)")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("blog_post.html").render({
|
|
"post": {
|
|
"title": "Getting Started with Jinja Templates",
|
|
"author": "Alice Smith",
|
|
"date": "2024-01-15",
|
|
"body": "Template inheritance is a powerful feature that allows you to build a base skeleton template containing common elements of your site and defines blocks that child templates can override.",
|
|
"tags": ["jinja", "templates", "tutorial"]
|
|
}
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("3. BLOG LIST (loops within inherited template)")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("blog_list.html").render({
|
|
"posts": [
|
|
{"title": "First Post", "date": "2024-01-15", "author": "Alice", "excerpt": "This is my first post...", "slug": "first-post"},
|
|
{"title": "Second Post", "date": "2024-01-14", "author": "Bob", "excerpt": "Another great article...", "slug": "second-post"},
|
|
{"title": "Third Post", "date": "2024-01-13", "author": "Charlie", "excerpt": "More content here...", "slug": "third-post"}
|
|
]
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("4. ADMIN USERS PAGE (admin template hierarchy)")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("admin_users.html").render({
|
|
"users": [
|
|
{"id": 1, "name": "Alice Smith", "email": "alice@example.com", "role": "admin", "active": true},
|
|
{"id": 2, "name": "Bob Jones", "email": "bob@example.com", "role": "editor", "active": true},
|
|
{"id": 3, "name": "Charlie Brown", "email": "charlie@example.com", "role": "user", "active": false},
|
|
{"id": 4, "name": "Diana Ross", "email": "diana@example.com", "role": "user", "active": true}
|
|
]
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("5. PAGE WITH INCLUDES")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("page_with_includes.html").render({
|
|
"type": "warning",
|
|
"title": "Notice",
|
|
"message": "This page demonstrates the include feature.",
|
|
"dismissible": true,
|
|
"content": "This is the main content of the page.",
|
|
"title": "Quick Links",
|
|
"items": [
|
|
{"label": "Home", "url": "/"},
|
|
{"label": "About", "url": "/about"},
|
|
{"label": "Contact", "url": "/contact"}
|
|
]
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("6. STANDALONE INCLUDE (sidebar)")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("sidebar.html").render({
|
|
"title": "Navigation",
|
|
"items": [
|
|
{"label": "Dashboard", "url": "/dashboard"},
|
|
{"label": "Profile", "url": "/profile"},
|
|
{"label": "Settings", "url": "/settings"},
|
|
{"label": "Logout", "url": "/logout"}
|
|
]
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("7. EMAIL TEMPLATE (text-based inheritance)")
|
|
System.print("-" * 60)
|
|
System.print(env.getTemplate("welcome_email.html").render({
|
|
"from_email": "noreply@example.com",
|
|
"to_email": "newuser@example.com",
|
|
"sender_name": "The Example Team",
|
|
"user": {
|
|
"name": "John Doe",
|
|
"username": "johndoe",
|
|
"email": "newuser@example.com",
|
|
"plan": "premium"
|
|
},
|
|
"verification_url": "https://example.com/verify?token=abc123"
|
|
}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("8. SUPER() DEMONSTRATION")
|
|
System.print("-" * 60)
|
|
|
|
var superDemo = {
|
|
"level1": "[L1-START]{\% block content \%}Level1-Content{\% endblock \%}[L1-END]",
|
|
"level2": "{\% extends \"level1\" \%}{\% block content \%}{{ super() }}+Level2{\% endblock \%}",
|
|
"level3": "{\% extends \"level2\" \%}{\% block content \%}{{ super() }}+Level3{\% endblock \%}"
|
|
}
|
|
|
|
var superEnv = Environment.new(DictLoader.new(superDemo))
|
|
System.print("Level 1: " + superEnv.getTemplate("level1").render({}))
|
|
System.print("Level 2: " + superEnv.getTemplate("level2").render({}))
|
|
System.print("Level 3: " + superEnv.getTemplate("level3").render({}))
|
|
|
|
System.print("\n" + "-" * 60)
|
|
System.print("9. MULTIPLE BLOCKS INHERITANCE")
|
|
System.print("-" * 60)
|
|
|
|
var multiBlock = {
|
|
"base": "A:{\% block a \%}base-a{\% endblock \%} B:{\% block b \%}base-b{\% endblock \%} C:{\% block c \%}base-c{\% endblock \%}",
|
|
"override_a": "{\% extends \"base\" \%}{\% block a \%}OVERRIDE-A{\% endblock \%}",
|
|
"override_bc": "{\% extends \"base\" \%}{\% block b \%}OVERRIDE-B{\% endblock \%}{\% block c \%}OVERRIDE-C{\% endblock \%}",
|
|
"override_all": "{\% extends \"base\" \%}{\% block a \%}NEW-A{\% endblock \%}{\% block b \%}NEW-B{\% endblock \%}{\% block c \%}NEW-C{\% endblock \%}"
|
|
}
|
|
|
|
var multiEnv = Environment.new(DictLoader.new(multiBlock))
|
|
System.print("Base: " + multiEnv.getTemplate("base").render({}))
|
|
System.print("Override A: " + multiEnv.getTemplate("override_a").render({}))
|
|
System.print("Override BC:" + multiEnv.getTemplate("override_bc").render({}))
|
|
System.print("Override All:" + multiEnv.getTemplate("override_all").render({}))
|
|
|
|
System.print("\n" + "=" * 60)
|
|
System.print("End of Inheritance Demo")
|
|
System.print("=" * 60)
|