This page is written with "normal" django templates, not the pure python hypergen templates.
{% load hypergen %}{% load static %}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{# Due to technical reasons both header and footer media are needed #}
{% hypergen_media_header %}
<link rel="stylesheet" type="text/css" href="https://unpkg.com/simpledotcss/simple.min.css"></link>
<link rel="stylesheet" type="text/css" href="{% static 'website/website.css' %}"></link>
</head>
<body>
<p><a href="{% url 'website:documentation' %}">Back to documentation</a></p>
<h1>Stack based calculator</h1>
<p>This page is written with "normal" django templates, not the pure python hypergen templates.</p>
{# This matches the target_id keyword argument to the @actions #}
<div id="content">
{% block content %}
{% endblock %}
</div>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/default.min.css"></link>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
<script src="{% static 'website/website.js' %}" defer></script>
{{sources|safe}}
{# Due to technical reasons both header and footer media are needed #}
{% hypergen_media_footer %}
</body>
</html>
templates/djangotemplates/content.html{% extends "djangotemplates/base.html"%}
{% load hypergen %}{% csrf_token %}
{% block content %}
<h2>Add number to stack</h2>
<input id="number" type="number" autofocus>
{# The {% callback %} template tag works exactly like it's python cousin, except it requires an id and event. #}
{# Also notice that you can reference other elements with "#id[.type]" magic strings. #}
<button {% callback "djangotemplates:push" "#number.float" id="push" event="onclick" %}>Push</button>
<h2>Perform operation</h2>
<button {% callback "djangotemplates:add" id="add" event="onclick" %}>+</button>
<button {% callback "djangotemplates:subtract" id="subtract" event="onclick" %}>-</button>
<button {% callback "djangotemplates:multiply" id="multiply" event="onclick" %}>*</button>
<button {% callback "djangotemplates:divide" id="divide" event="onclick" %}>/</button>
<button {% callback "djangotemplates:reset" id="reset" event="onclick" %}>C</button>
<h2>Stack</h2>
<ol>
{% for item in stack reversed %}
<li>{{item}}</li>
{% endfor %}
</ol>
{% endblock %}
urls.pyfrom djangotemplates import views
from hypergen.hypergen import autourls
try:
from django.conf.urls import url
except ImportError:
from django.urls import re_path as url
app_name = 'djangotemplates'
urlpatterns = [
url('^$', views.djangotemplates, name="djangotemplates"),] + autourls(views, app_name)
views.pyimport operator
from hypergen.imports import *
from hypergen.context import context as c
from hypergen.templatetags.hypergen import render_to_hypergen
from django.shortcuts import render
from website.templates2 import show_sources
# appstate lives in Django's session and are automatically saved at the end of each request.
def init_appstate():
return []
init_appstate.namespace = "djangotemplates"
# djangotemplates is a vanilla Django view, with it's route defined in urls.py and not by autourls.
# It's decorated with @liveview to enable liveview capabilities.
@liveview(perm=NO_PERM_REQUIRED, autourl=False, appstate=init_appstate)
def djangotemplates(request):
return render(request, "djangotemplates/content.html", context=dict(stack=context.hypergen.appstate,
sources=hypergen(show_sources, __file__)))
def render_content():
# render_to_hypergen() works exactly as Djangos render_to_string except for two things:
# 1. It writes the HTML directly to the page.
# 2. It supports a "block" keyword argument so that only the content of that block is rendered.
render_to_hypergen("djangotemplates/content.html", context=dict(stack=context.hypergen.appstate,
sources=hypergen(show_sources, __file__)), block="content")
### ACTIONS ###
# @actions works exactly like vanilla hypergen actions, so the hypergen template language is enabled.
# Here we choose to use render_context to partially render a Django html template.
@action(perm=NO_PERM_REQUIRED, target_id="content", appstate=init_appstate)
def push(request, number):
if number is not None:
assert type(number) is float
context.hypergen.appstate.append(number)
render_content()
@action(perm=NO_PERM_REQUIRED, target_id="content", appstate=init_appstate)
def reset(request):
context.hypergen.appstate = []
render_content()
@action(perm=NO_PERM_REQUIRED, target_id="content", appstate=init_appstate)
def add(request, *args):
apply_operation(operator.add)
@action(perm=NO_PERM_REQUIRED, target_id="content", appstate=init_appstate)
def subtract(request, *args):
apply_operation(operator.sub)
@action(perm=NO_PERM_REQUIRED, target_id="content", appstate=init_appstate)
def multiply(request, *args):
apply_operation(operator.mul)
@action(perm=NO_PERM_REQUIRED, target_id="content", appstate=init_appstate)
def divide(request, *args):
if len(context.hypergen.appstate) and context.hypergen.appstate[-1] == 0:
command("alert", "Can't divide by zero")
return
apply_operation(operator.truediv)
def apply_operation(op):
if len(context.hypergen.appstate) < 2:
command("alert", "Stack has too few elements")
return
b, a = context.hypergen.appstate.pop(), context.hypergen.appstate.pop()
context.hypergen.appstate.append(op(a, b))
render_content()