Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an inline argument to render a partial where it is defined #9

Merged
merged 1 commit into from Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -79,6 +79,16 @@ END
{% endblock main %}
```

You might want to wrap an existing part of your page, and continue rendering the content inside your partial, use the `inline` argument in that situation:

```html
{% block main %}
{% startpartial inline-partial inline=True %}
CONTENT
{% endpartial %}
{% endblock main %}
```

`django-template-partials` is also integrated with the template loader, so you can pass a template plus a partial name to the loader to have just that part rendered:

```python
Expand Down
31 changes: 24 additions & 7 deletions src/template_partials/templatetags/partials.py
Expand Up @@ -34,13 +34,17 @@ def render(self, context):


class DefinePartialNode(template.Node):
def __init__(self, partial_name, nodelist):
def __init__(self, partial_name, inline, nodelist):
self.partial_name = partial_name
self.inline = inline
self.nodelist = nodelist

def render(self, context):
"""Set content into context and return empty string"""
return ""
if self.inline:
return self.nodelist.render(context)
else:
return ""


class RenderPartialNode(template.Node):
Expand Down Expand Up @@ -72,15 +76,28 @@ def startpartial_func(parser, token):

Stores the nodelist in the context under the key "partial_contents" and can
be retrieved using the {% partial %} tag.

The optional inline=True argument will render the contents of the partial
where it is defined.
"""
# Parse the tag
try:
tag_name, partial_name = token.split_contents()
except ValueError:
tokens = token.split_contents()

# check we have the expected number of tokens before trying to assign them
# via indexes
if len(tokens) not in (2, 3):
raise template.TemplateSyntaxError(
"%r tag requires a single argument" % token.contents.split()[0]
"%r tag requires 2-3 arguments" % token.contents.split()[0]
)

partial_name = tokens[1]

try:
inline = tokens[2]
except IndexError:
# the inline argument is optional, so fallback to not using it
inline = False

# Parse the content until the {% endpartial %} tag
nodelist = parser.parse(("endpartial",))
parser.delete_first_token()
Expand All @@ -91,7 +108,7 @@ def startpartial_func(parser, token):
nodelist, parser.origin, partial_name
)

return DefinePartialNode(partial_name, nodelist)
return DefinePartialNode(partial_name, inline, nodelist)


# Define the partial tag to render the partial content.
Expand Down
4 changes: 4 additions & 0 deletions tests/templates/example.html
Expand Up @@ -12,3 +12,7 @@
{% partial test-partial %}
END
{% endblock main %}

{% startpartial inline-partial inline=True %}
INLINE-CONTENT
{% endpartial %}
23 changes: 22 additions & 1 deletion tests/tests.py
Expand Up @@ -18,21 +18,42 @@ def test_partial_tags(self):
# Check the rendered content
self.assertEqual("HERE IS THE TEST CONTENT", rendered.strip())

def test_startpartial_tag_with_inline(self):
template = """
{% load partials %}
{% startpartial "testing-partial" inline=True %}
HERE IS THE TEST CONTENT
{% endpartial %}
"""

# Compile and render the template
engine = engines["django"]
t = engine.from_string(template)
rendered = t.render()

# Check the rendered content
self.assertEqual("HERE IS THE TEST CONTENT", rendered.strip())

def test_full_template_from_loader(self):
engine = engines["django"]
template = engine.get_template("example.html")
rendered = template.render()

# Check the partial was rendered twice
self.assertEqual(2, rendered.count("TEST-PARTIAL-CONTENT"))
self.assertEqual(1, rendered.count("INLINE-CONTENT"))

def test_just_partial_from_loader(self):
engine = engines["django"]

template = engine.get_template("example.html#test-partial")
rendered = template.render()

self.assertEqual("TEST-PARTIAL-CONTENT", rendered.strip())

template = engine.get_template("example.html#inline-partial")
rendered = template.render()
self.assertEqual("INLINE-CONTENT", rendered.strip())

def test_debug_template(self):
class LazyExceptionObject:
def __str__(self):
Expand Down