Use jinja2 for rendering
It does multi-line tags, which are really useful
This commit is contained in:
parent
caed8daeda
commit
b882bc44dd
8 changed files with 35 additions and 105 deletions
|
@ -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
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,5 @@ gunicorn
|
||||||
markdown
|
markdown
|
||||||
chrono
|
chrono
|
||||||
django-debug-toolbar
|
django-debug-toolbar
|
||||||
|
django-jinja
|
||||||
|
jinja2-simple-tags
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
{% load core_tags %}
|
|
||||||
<head>
|
<head>
|
||||||
<title>{{ page.title }}</title>
|
<title>{{ page.title }}</title>
|
||||||
</head>
|
</head>
|
|
@ -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})
|
||||||
|
|
|
@ -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
|
|
10
yamdl_playground/core/templatetags/__init__.py
Normal file
10
yamdl_playground/core/templatetags/__init__.py
Normal 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())
|
|
@ -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)
|
|
|
@ -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'
|
||||||
|
|
Loading…
Reference in a new issue