1
Fork 0

Use jinja2 for rendering

It does multi-line tags, which are really useful
This commit is contained in:
Jake Howard 2024-10-17 14:13:17 +01:00
parent caed8daeda
commit b882bc44dd
Signed by: jake
GPG key ID: 57AFB45680EDD477
8 changed files with 35 additions and 105 deletions

View file

@ -2,7 +2,7 @@
title: Test title: Test
tags: tags:
- tag-1 - tag-1
runtime_render: false runtime_render: true
media: ./media.txt media: ./media.txt
--- ---

View file

@ -4,3 +4,5 @@ gunicorn
markdown markdown
chrono chrono
django-debug-toolbar django-debug-toolbar
django-jinja
jinja2-simple-tags

View file

@ -1,4 +1,3 @@
{% load core_tags %}
<head> <head>
<title>{{ page.title }}</title> <title>{{ page.title }}</title>
</head> </head>

View file

@ -1,12 +1,12 @@
from django.db import models from django.db import models
import markdown import markdown
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.template import Template, Context
from django.core.files.storage import storages from django.core.files.storage import storages
from django.core.files import File from django.core.files import File
from pathlib import Path from pathlib import Path
import os.path import os.path
from django.template import engines
from django_jinja.backend import Origin
class Tag(models.Model): class Tag(models.Model):
__yamdl__ = True __yamdl__ = True
@ -72,12 +72,17 @@ class Page(models.Model):
@cached_property @cached_property
def content_template(self): def content_template(self):
if self.runtime_render: if cached_template := self._template_cache.get(self.slug):
return Template(self.content, name=self.slug) return cached_template
if (cached_template := self._template_cache.get(self.slug)) is None: template = engines["jinja2"].from_string(self.content)
cached_template = self._template_cache[self.slug] = Template(self.content, name=self.slug) template.origin = Origin(name=self.slug, template_name=self.slug)
return cached_template template.name = self.slug
if not self.runtime_render:
self._template_cache[self.slug] = template
return template
def get_context(self): def get_context(self):
return { return {
@ -88,4 +93,4 @@ class Page(models.Model):
if extra_context is None: if extra_context is None:
extra_context = {} extra_context = {}
return self.content_template.render(Context({**self.get_context(), **extra_context})) return self.content_template.render({**self.get_context(), **extra_context})

View file

@ -1,86 +0,0 @@
from inspect import getfullargspec, unwrap
from django.template.library import parse_bits, SimpleNode
from django.template.exceptions import TemplateSyntaxError
from functools import wraps
class SimpleBlockNode(SimpleNode):
def __init__(self, nodelist, *args, **kwargs):
super().__init__(*args, **kwargs)
self.nodelist = nodelist
def get_resolved_arguments(self, context):
resolved_args, resolved_kwargs = super().get_resolved_arguments(context)
# Restore the "content" argument.
# It will move depending on whether takes_context was passed.
resolved_args.insert(
1 if self.takes_context else 0, self.nodelist.render(context)
)
return resolved_args, resolved_kwargs
def simple_block_tag(register, takes_context=None, name=None):
def dec(func):
(
params,
varargs,
varkw,
defaults,
kwonly,
kwonly_defaults,
_,
) = getfullargspec(unwrap(func))
function_name = name or func.__name__
@wraps(func)
def compile_func(parser, token):
tag_params = params.copy()
if takes_context:
if len(tag_params) >= 2 and tag_params[1] == "content":
del tag_params[1]
else:
raise TemplateSyntaxError(
f"'{function_name}' is decorated with takes_context=True so"
" it must have a first argument of 'context' and a second "
"argument of 'content'"
)
else:
if tag_params and tag_params[0] == "content":
del tag_params[0]
else:
raise TemplateSyntaxError(
f"'{function_name}' must have a first argument of 'content'"
)
bits = token.split_contents()[1:]
target_var = None
if len(bits) >= 2 and bits[-2] == "as":
target_var = bits[-1]
bits = bits[:-2]
nodelist = parser.parse((f"end{function_name}",))
parser.delete_first_token()
args, kwargs = parse_bits(
parser,
bits,
tag_params,
varargs,
varkw,
defaults,
kwonly,
kwonly_defaults,
takes_context,
function_name,
)
return SimpleBlockNode(
nodelist, func, takes_context, args, kwargs, target_var
)
register.tag(function_name, compile_func)
return func
return dec

View file

@ -0,0 +1,10 @@
from django_jinja import library
from jinja2_simple_tags import ContainerTag
@library.extension
class MyTag(ContainerTag):
tags = {"mytag"}
def render(self, caller=None):
return "foo{}bar".format(caller())

View file

@ -1,9 +0,0 @@
from yamdl_playground.core.simple_tags import simple_block_tag
from django import template
register = template.Library()
@simple_block_tag(register, takes_context=True)
def mytag(context, content):
return "foo{}bar".format(content)

View file

@ -58,6 +58,15 @@ TEMPLATES = [
], ],
}, },
}, },
{
'BACKEND': 'django_jinja.jinja2.Jinja2',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'app_dirname': "jinja2",
"match_extension": ".html"
}
},
] ]
WSGI_APPLICATION = 'yamdl_playground.wsgi.application' WSGI_APPLICATION = 'yamdl_playground.wsgi.application'