mirror of
https://github.com/django-components/django-components.git
synced 2025-09-26 23:49:07 +00:00
Fix #143: ability to preload components (thanks @David-Guillot)
This commit is contained in:
commit
9632c4540f
2 changed files with 115 additions and 14 deletions
|
@ -15,6 +15,9 @@ from django_components.middleware import (
|
|||
register = template.Library()
|
||||
|
||||
|
||||
RENDERED_COMMENT_TEMPLATE = "<!-- _RENDERED {name} -->"
|
||||
|
||||
|
||||
def get_components_from_registry(registry):
|
||||
"""Returns a list unique components from the registry."""
|
||||
|
||||
|
@ -27,13 +30,36 @@ def get_components_from_registry(registry):
|
|||
return components
|
||||
|
||||
|
||||
def get_components_from_preload_str(preload_str):
|
||||
"""Returns a list of unique components from a comma-separated str"""
|
||||
|
||||
components = []
|
||||
for component_name in preload_str.split(","):
|
||||
component_name = component_name.strip()
|
||||
if not component_name:
|
||||
continue
|
||||
component_class = registry.get(component_name)
|
||||
components.append(component_class(component_name))
|
||||
|
||||
return components
|
||||
|
||||
|
||||
@register.simple_tag(name="component_dependencies")
|
||||
def component_dependencies_tag():
|
||||
def component_dependencies_tag(preload=""):
|
||||
"""Marks location where CSS link and JS script tags should be rendered."""
|
||||
|
||||
if is_dependency_middleware_active():
|
||||
preloaded_dependencies = []
|
||||
for component in get_components_from_preload_str(preload):
|
||||
preloaded_dependencies.append(
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=component._component_name
|
||||
)
|
||||
)
|
||||
return mark_safe(
|
||||
CSS_DEPENDENCY_PLACEHOLDER + JS_DEPENDENCY_PLACEHOLDER
|
||||
"\n".join(preloaded_dependencies)
|
||||
+ CSS_DEPENDENCY_PLACEHOLDER
|
||||
+ JS_DEPENDENCY_PLACEHOLDER
|
||||
)
|
||||
else:
|
||||
rendered_dependencies = []
|
||||
|
@ -44,11 +70,20 @@ def component_dependencies_tag():
|
|||
|
||||
|
||||
@register.simple_tag(name="component_css_dependencies")
|
||||
def component_css_dependencies_tag():
|
||||
def component_css_dependencies_tag(preload=""):
|
||||
"""Marks location where CSS link tags should be rendered."""
|
||||
|
||||
if is_dependency_middleware_active():
|
||||
return mark_safe(CSS_DEPENDENCY_PLACEHOLDER)
|
||||
preloaded_dependencies = []
|
||||
for component in get_components_from_preload_str(preload):
|
||||
preloaded_dependencies.append(
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=component._component_name
|
||||
)
|
||||
)
|
||||
return mark_safe(
|
||||
"\n".join(preloaded_dependencies) + CSS_DEPENDENCY_PLACEHOLDER
|
||||
)
|
||||
else:
|
||||
rendered_dependencies = []
|
||||
for component in get_components_from_registry(registry):
|
||||
|
@ -58,11 +93,20 @@ def component_css_dependencies_tag():
|
|||
|
||||
|
||||
@register.simple_tag(name="component_js_dependencies")
|
||||
def component_js_dependencies_tag():
|
||||
def component_js_dependencies_tag(preload=""):
|
||||
"""Marks location where JS script tags should be rendered."""
|
||||
|
||||
if is_dependency_middleware_active():
|
||||
return mark_safe(JS_DEPENDENCY_PLACEHOLDER)
|
||||
preloaded_dependencies = []
|
||||
for component in get_components_from_preload_str(preload):
|
||||
preloaded_dependencies.append(
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=component._component_name
|
||||
)
|
||||
)
|
||||
return mark_safe(
|
||||
"\n".join(preloaded_dependencies) + JS_DEPENDENCY_PLACEHOLDER
|
||||
)
|
||||
else:
|
||||
rendered_dependencies = []
|
||||
for component in get_components_from_registry(registry):
|
||||
|
@ -197,7 +241,9 @@ class ComponentNode(Node):
|
|||
rendered_component = self.component.render(context)
|
||||
if self.should_render_dependencies:
|
||||
return (
|
||||
f"<!-- _RENDERED {self.component._component_name} -->"
|
||||
RENDERED_COMMENT_TEMPLATE.format(
|
||||
name=self.component._component_name
|
||||
)
|
||||
+ rendered_component
|
||||
)
|
||||
else:
|
||||
|
|
|
@ -52,12 +52,7 @@ class ComponentMediaRenderingTests(SimpleTestCase):
|
|||
"{% load component_tags %}{% component_dependencies %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertInHTML('<script src="script.js>"', rendered, count=0)
|
||||
self.assertInHTML(
|
||||
'<link href="style.css" type="text/css" media="all" rel="stylesheet"/>',
|
||||
rendered,
|
||||
count=0,
|
||||
)
|
||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||
self.assertInHTML(
|
||||
'<link href="style.css" type="text/css" media="all" rel="stylesheet"/>',
|
||||
rendered,
|
||||
|
@ -71,7 +66,7 @@ class ComponentMediaRenderingTests(SimpleTestCase):
|
|||
"{% load component_tags %}{% component_js_dependencies %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertInHTML('<script src="script.js>"', rendered, count=0)
|
||||
self.assertInHTML('<script src="script.js">', rendered, count=0)
|
||||
|
||||
def test_no_css_dependencies_when_no_components_used(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
@ -86,6 +81,42 @@ class ComponentMediaRenderingTests(SimpleTestCase):
|
|||
count=0,
|
||||
)
|
||||
|
||||
def test_preload_dependencies_render_when_no_components_used(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
template = Template(
|
||||
"{% load component_tags %}{% component_dependencies preload='test' %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||
self.assertInHTML(
|
||||
'<link href="style.css" type="text/css" media="all" rel="stylesheet"/>',
|
||||
rendered,
|
||||
count=1,
|
||||
)
|
||||
|
||||
def test_preload_js_dependencies_render_when_no_components_used(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
template = Template(
|
||||
"{% load component_tags %}{% component_js_dependencies preload='test' %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||
|
||||
def test_preload_css_dependencies_render_when_no_components_used(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
template = Template(
|
||||
"{% load component_tags %}{% component_css_dependencies preload='test' %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertInHTML(
|
||||
'<link href="style.css" type="text/css" media="all" rel="stylesheet"/>',
|
||||
rendered,
|
||||
count=1,
|
||||
)
|
||||
|
||||
def test_single_component_dependencies_render_when_used(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
|
@ -101,6 +132,21 @@ class ComponentMediaRenderingTests(SimpleTestCase):
|
|||
)
|
||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||
|
||||
def test_preload_dependencies_render_once_when_used(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
template = Template(
|
||||
"{% load component_tags %}{% component_dependencies preload='test' %}"
|
||||
"{% component 'test' variable='foo' %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertInHTML(
|
||||
'<link href="style.css" type="text/css" media="all" rel="stylesheet"/>',
|
||||
rendered,
|
||||
count=1,
|
||||
)
|
||||
self.assertInHTML('<script src="script.js">', rendered, count=1)
|
||||
|
||||
def test_placeholder_removed_when_single_component_rendered(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
|
@ -111,6 +157,15 @@ class ComponentMediaRenderingTests(SimpleTestCase):
|
|||
rendered = create_and_process_template_response(template)
|
||||
self.assertNotIn("_RENDERED", rendered)
|
||||
|
||||
def test_placeholder_removed_when_preload_rendered(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
template = Template(
|
||||
"{% load component_tags %}{% component_dependencies preload='test' %}"
|
||||
)
|
||||
rendered = create_and_process_template_response(template)
|
||||
self.assertNotIn("_RENDERED", rendered)
|
||||
|
||||
def test_single_component_css_dependencies(self):
|
||||
component.registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue