add Template support with mako and jinja2 examples

pull/39/head
Ciro 2022-11-16 09:02:41 -03:00
rodzic 0b2908446c
commit 84d849172d
10 zmienionych plików z 121 dodań i 4 usunięć

Wyświetl plik

@ -30,6 +30,7 @@
- Automatic Ping / Pong Support
- Per Socket Data
- Middlewares
- Templates Support (examples with [Mako](https://github.com/cirospaciari/socketify.py/tree/main/examples/template_mako.py) and [Jinja2)](https://github.com/cirospaciari/socketify.py/tree/main/examples/template_jinja2.py))
## :mag_right: Upcoming Features
- Fetch like API powered by libuv
- Async file IO powered by libuv

Wyświetl plik

@ -0,0 +1,31 @@
#Simple example of mako and jinja2 template plugin for socketify.py
from mako.template import Template
from mako.lookup import TemplateLookup
from mako import exceptions
from jinja2 import Environment, FileSystemLoader
class Jinja2Template:
def __init__(self, searchpath, encoding='utf-8', followlinks=False):
self.env = Environment(loader=FileSystemLoader(searchpath, encoding, followlinks))
#You can also add caching and logging strategy here if you want ;)
def render(self, templatename, **kwargs):
try:
template = self.env.get_template(templatename)
return template.render(**kwargs)
except Exception as err:
return str(err)
class MakoTemplate:
def __init__(self, **options):
self.lookup = TemplateLookup(**options)
#You can also add caching and logging strategy here if you want ;)
def render(self, templatename, **kwargs):
try:
template = self.lookup.get_template(templatename)
return template.render(**kwargs)
except Exception as err:
return exceptions.html_error_template().render()

Wyświetl plik

@ -3,4 +3,5 @@ aiofiles
aiofile
redis
strawberry-graphql
mako
git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"

Wyświetl plik

@ -0,0 +1,14 @@
from socketify import App
#see helper/templates.py for plugin implementation
from helpers.templates import Jinja2Template
app = App()
app.template(Jinja2Template("./templates", encoding='utf-8', followlinks=False))
async def home(res, req):
res.render("jinja2_home.html", title="Hello", message="Hello, World")
app.get("/", home)
app.listen(3000, lambda config: print("Listening on port http://localhost:%s now\n" % str(config.port)))
app.run()

Wyświetl plik

@ -0,0 +1,14 @@
from socketify import App
#see helper/templates.py for plugin implementation
from helpers.templates import MakoTemplate
app = App()
app.template(MakoTemplate(directories=['./templates'], output_encoding='utf-8', encoding_errors='replace'))
async def home(res, req):
res.render("mako_home.html", message="Hello, World")
app.get("/", home)
app.listen(3000, lambda config: print("Listening on port http://localhost:%s now\n" % str(config.port)))
app.run()

Wyświetl plik

@ -0,0 +1,20 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>{{ title }}</title>
</head>
<body>
<div id="header">
<h1>{{ title }}</h1>
</div>
{%- block body %}{%- endblock %}
<div id="footer">
</div>
</body>
</html>

Wyświetl plik

@ -0,0 +1,4 @@
{% extends "jinja2_base.html" %}
{% block body %}
<p>this is the body content. {{ message }}</p>
{% endblock body %}

Wyświetl plik

@ -0,0 +1,15 @@
<html>
<body>
<div class="header">
<%block name="header"/>
</div>
${self.body()}
<div class="footer">
<%block name="footer">
this is the footer
</%block>
</div>
</body>
</html>

Wyświetl plik

@ -0,0 +1,7 @@
<%inherit file="mako_base.html"/>
<%block name="header">
this is some header content
</%block>
this is the body content. ${ message }

Wyświetl plik

@ -422,7 +422,7 @@ def uws_websocket_upgrade_handler(res, req, context, user_data):
if not user_data == ffi.NULL:
try:
(handlers, app) = ffi.from_handle(user_data)
response = AppResponse(res, app.loop, app.SSL)
response = AppResponse(res, app.loop, app.SSL, app._template)
request = AppRequest(req)
handler = handlers.upgrade
if inspect.iscoroutinefunction(handler):
@ -463,7 +463,7 @@ def uws_generic_method_handler(res, req, user_data):
if not user_data == ffi.NULL:
try:
(handler, app) = ffi.from_handle(user_data)
response = AppResponse(res, app.loop, app.SSL)
response = AppResponse(res, app.loop, app.SSL, app._template)
request = AppRequest(req)
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
@ -1044,7 +1044,7 @@ class AppRequest:
self._ptr = ffi.NULL
class AppResponse:
def __init__(self, response, loop, ssl):
def __init__(self, response, loop, ssl, render=None):
self.res = response
self.SSL = ssl
self.aborted = False
@ -1060,6 +1060,7 @@ class AppResponse:
self._chunkFuture = None
self._dataFuture = None
self._data = None
self._render = render
def cork(self, callback):
if not self.aborted:
@ -1253,6 +1254,12 @@ class AppResponse:
self.cork(lambda res: res.end(message, end_connection))
return self
def render(self, *args, **kwargs):
if self._render:
self.cork_end(self._render.render(*args, **kwargs))
return self
raise RuntimeError("No registered templated engine")
def get_remote_address_bytes(self):
buffer = ffi.new("char**")
length = lib.uws_res_get_remote_address(self.SSL, self.res, buffer)
@ -1467,6 +1474,7 @@ class App:
socket_options_ptr = ffi.new("struct us_socket_context_options_t *")
socket_options = socket_options_ptr[0]
self.options = options
self._template = None
if options != None:
self.is_ssl = True
self.SSL = ffi.cast("int", 1)
@ -1498,7 +1506,9 @@ class App:
self._missing_server_handler = None
def template(self, template_engine):
self._template = template_engine
def static(self, route, directory):
static_route(self, route, directory)
return self