Configure Template Engine
To configure your Django application to use PH7 templates, update settings.py
to use PH7's Django template engine.
TEMPLATES = [
{
"NAME": "PH7",
"BACKEND": "ph7.django.PH7Templates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {},
}
]
Templates
|_ home
|_ templates
|_ __init__.py # default view
Define your view in __init__.py
, when defining the view you need to name the default view template
, for example
from ph7.html import body, div, html, title
template = html(
title("Hello World"),
body(
div(
"Hello, World!",
)
),
)
When rendering the view, refer to this template using relative path
from django.shortcuts import render
def home(request):
return render(
request=request,
template_name="home", # or "home:template"
)
If you name your view anything other than template
, you can specify the view name using module:view
format. For example if you name your view home
, you can specify the template as app:home
.
Forms
Forms can be included directly using form
tag.
from django import forms
from ph7.django import csrf_token
from ph7.html import body, button, div, form, html, title
class UserForm(forms.Form):
"""User form class."""
name = forms.CharField(label="username")
email = forms.EmailField(label="email")
password = forms.CharField(label="password", widget=forms.PasswordInput())
template = html(
title("Forms Example"),
body(
div(
form(
UserForm(),
csrf_token,
button("submit", type="submit"),
),
)
),
)
<html>
<head>
<title>Forms Example</title>
</head>
<body>
<div>
<form>
<label for="id_name">username:</label>
<input type="text" name="name" required="" id="id_name" />
<label for="id_email">email:</label>
<input type="email" name="email" maxlength="320" required="" id="id_email"/>
<label for="id_password">password:</label>
<input type="password" name="password" required="" id="id_password" />
<input
name="csrfmiddlewaretoken"
value="aaAAAaAAaAAAaaAAAAAAAaAaaAaAAAaaAAAaaaaaaAAaAAaaAAaaaAAaAAAAaaaa"
id="csrfmiddlewaretoken"
hidden="True"
/><button type="submit">submit</button>
</form>
</div>
</body>
</html>
Stylesheets
Define your stylesheet using CSSObject
and use Static Context
to include the stylesheets in your views. First let's define templates/styles.py
from ph7.css import CSSObject
class container(CSSObject):
display = "flex"
align_items = "center"
justify_content = "center"
height = "100vh"
width = "100vw"
box_sizing = "border-box"
margin = "0px"
padding = "0px"
Next include the stylesheet by importing it and using one of the style classes.
from static_files.templates import styles as stylesheet
from ph7.context import ctx
from ph7.html import body, div, head, html, title
ctx.static.view(__name__)
template = html(
title("Static Files Example"),
head(
ctx.static.include,
),
body(
div(
"Hello, World!",
class_name=stylesheet.container,
)
),
)
This is what the rendered view looks like
<html>
<head>
<title>Static Files Example</title>
<link
href="/static/css/static_files_templates_styles.css"
rel="stylesheet"
id="css.static_files.templates.styles"
/>
</head>
<body>
<div class="main">Hello, World!</div>
</body>
</html>
And this is what the rendered stylesheet looks like
.main {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
box-sizing: border-box;
margin: 0px;
padding: 0px;
}
Note: In the final render of the stylesheet generated by static context, only the classes which have been used in a template will be included.
Scripts
Write your scripts using the ph7.js
APIs.
from ph7.js import alert, console, document, fetch, js_callable
@js_callable
async def fetchDog():
console.log("Fetching dog")
response = await fetch(
"https://dog.ceo/api/breeds/image/random",
{
"method": "GET",
},
)
data = await response.json()
console.log("Dog fetched")
document.getElementById("image").src = data.message
Use the function in the view
from javascript.templates.script import fetchDog
from javascript.templates.styles import container, image
from ph7.context import ctx
from ph7.html import body, button, div, head, html, img
ctx.static.view(__name__)
template = html(
head(
ctx.static.include,
),
body(
div(
img(
src="#",
id="image",
alt="Click to fetch dog",
class_name=image,
),
button(
"Click to fetch a dog",
on={
"click": fetchDog(),
},
),
class_name=container,
)
),
)
if __name__ == "__main__":
print(template.render({"_view": __name__}))
This is what the rendered view looks like
<html>
<head>
<link
href="/static/css/javascript_templates_styles.css"
rel="stylesheet"
id="css.javascript.templates.styles"
/>
<script
src="/static/js/javascript_templates_script.js"
id="js.javascript.templates.script"
></script>
</head>
<body>
<div class="main">
<img src="#" alt="Click to fetch dog" id="image" class="image" /><button
onclick="fetchDog()"
>
Click to fetch a dog
</button>
</div>
</body>
</html>
And this is what the rendered script looks like
async function fetchDog() {
console.log("Fetching dog");
let response = await fetch("https://dog.ceo/api/breeds/image/random", {
method: "GET",
});
let data = await response.json();
console.log("Dog fetched");
document.getElementById("image").src = data.message;
}