Performance (+50%): Compile ComponentNode at creation, not render (#22)

Co-authored-by: rbeard0330 <@dul2k3BKW6m>
This commit is contained in:
rbeard0330 2021-02-06 04:09:57 -05:00 committed by GitHub
parent d61c0fa469
commit 87f9994c81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 17 deletions

View file

@ -28,6 +28,7 @@ class Component(with_metaclass(MediaDefiningClass)):
def __init__(self, component_name):
self.__component_name = component_name
self.instance_template = None
def context(self):
return {}
@ -54,14 +55,15 @@ class Component(with_metaclass(MediaDefiningClass)):
def slots_in_template(template):
return {node.name: node.nodelist for node in template.template.nodelist if is_slot_node(node)}
def render(self, context, slots_filled=None):
slots_filled = slots_filled or {}
def compile_instance_template(self, slots_for_instance):
"""Use component's base template and the slots used for this instance to compile
a unified template for this instance."""
template = get_template(self.template(context))
slots_in_template = self.slots_in_template(template)
component_template = get_template(self.template({}))
slots_in_template = self.slots_in_template(component_template)
defined_slot_names = set(slots_in_template.keys())
filled_slot_names = set(slots_filled.keys())
filled_slot_names = set(slots_for_instance.keys())
unexpected_slots = filled_slot_names - defined_slot_names
if unexpected_slots:
if settings.DEBUG:
@ -71,20 +73,21 @@ class Component(with_metaclass(MediaDefiningClass)):
)
)
for unexpected_slot in unexpected_slots:
del slots_filled[unexpected_slot]
del slots_for_instance[unexpected_slot]
combined_slots = dict(slots_in_template, **slots_filled)
combined_slots = dict(slots_in_template, **slots_for_instance)
if combined_slots:
# Replace slot nodes with their nodelists, then combine into a single, flat nodelist
node_iterator = ([node] if not is_slot_node(node) else combined_slots[node.name]
for node in template.template.nodelist)
for node in component_template.template.nodelist)
template = copy(template.template)
template.nodelist = NodeList(chain.from_iterable(node_iterator))
self.instance_template = copy(component_template.template)
self.instance_template.nodelist = NodeList(chain.from_iterable(node_iterator))
else:
template = template.template
self.instance_template = component_template.template
return template.render(context)
def render(self, context):
return self.instance_template.render(context)
class Media:
css = {}