Skip to content

Commit

Permalink
Invalid kwargs used to be parsed as a string, but now they will be `N…
Browse files Browse the repository at this point in the history
…one` as expected.
  • Loading branch information
adamghill committed Feb 25, 2024
1 parent 9d2a5ea commit cc28ac3
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 10 deletions.
18 changes: 11 additions & 7 deletions django_unicorn/templatetags/unicorn.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,21 @@ def unicorn(parser, token):

args = []
kwargs = {}
unparseable_kwargs = {}

for arg in contents[2:]:
try:
parsed_kwarg = parse_kwarg(arg)
parsed_kwarg = parse_kwarg(arg, raise_if_unparseable=True)
kwargs.update(parsed_kwarg)
except InvalidKwargError:
# Assume it's an arg if invalid kwarg and kwargs is empty
if not kwargs:
args.append(arg)
except ValueError:
parsed_kwarg = parse_kwarg(arg, raise_if_unparseable=False)
unparseable_kwargs.update(parsed_kwarg)

return UnicornNode(component_name, args, kwargs)
return UnicornNode(component_name, args, kwargs, unparseable_kwargs)


class UnicornNode(template.Node):
Expand All @@ -71,10 +75,12 @@ def __init__(
component_name: FilterExpression,
args: Optional[List] = None,
kwargs: Optional[Dict] = None,
unparseable_kwargs: Optional[Dict] = None,
):
self.component_name = component_name
self.args = args if args is not None else []
self.kwargs = kwargs if kwargs is not None else {}
self.unparseable_kwargs = unparseable_kwargs if unparseable_kwargs is not None else {}
self.component_key = ""
self.parent = None

Expand All @@ -92,9 +98,9 @@ def render(self, context):
resolved_arg = template.Variable(value).resolve(context)
resolved_args.append(resolved_arg)

resolved_kwargs = {}
resolved_kwargs = self.kwargs.copy()

for key, value in self.kwargs.items():
for key, value in self.unparseable_kwargs.items():
try:
resolved_value = template.Variable(value).resolve(context)

Expand All @@ -113,8 +119,6 @@ def render(self, context):
except TypeError:
resolved_kwargs.update({key: value})
except template.VariableDoesNotExist:
resolved_kwargs.update({key: value})

if value.endswith(".id"):
pk_val = value.replace(".id", ".pk")

Expand All @@ -123,7 +127,7 @@ def render(self, context):
except TypeError:
resolved_kwargs.update({key: value})
except template.VariableDoesNotExist:
resolved_kwargs.update({key: value})
pass

if "key" in resolved_kwargs:
self.component_key = resolved_kwargs.pop("key")
Expand Down
1 change: 1 addition & 0 deletions django_unicorn/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ def _process_component_request(request: HttpRequest, component_request: Componen
partial_found = True
break

# Sort data so it's stable
component_request.data = {key: component_request.data[key] for key in sorted(component_request.data)}

result = {
Expand Down
11 changes: 8 additions & 3 deletions example/www/templates/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@

<h2>Index</h2>

<button onclick="Unicorn.call('unicorn.components.hello_world.HelloWorldView', 'set_name');">Method call from outside of the component</button>
<button onclick="Unicorn.call('unicorn.components.hello_world.HelloWorldView', 'set_name');">
Method call from outside of the component
</button>

<button onclick="alert(Unicorn.getReturnValue('unicorn.components.hello_world.HelloWorldView'));">Last return value from component</button>
<button onclick="alert(Unicorn.getReturnValue('unicorn.components.hello_world.HelloWorldView'));">
Last return value from component
</button>

{% unicorn 'unicorn.components.hello_world.HelloWorldView' %}
<!-- abcdf should be ignored and name will be None -->
{% unicorn 'unicorn.components.hello_world.HelloWorldView' name=abcdf %}

{% endblock content %}
12 changes: 12 additions & 0 deletions tests/templatetags/test_unicorn_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ def test_unicorn_render_kwarg():
assert "<b>tested!</b>" in actual


def test_unicorn_render_invalid_kwarg():
token = Token(
TokenType.TEXT,
"unicorn 'tests.templatetags.test_unicorn_render.FakeComponentKwargs' test_kwarg=tested",
)
unicorn_node = unicorn(Parser([]), token)
context = {}
actual = unicorn_node.render(Context(context))

assert "<b>None</b>" in actual


def test_unicorn_render_context_variable():
token = Token(
TokenType.TEXT,
Expand Down

0 comments on commit cc28ac3

Please sign in to comment.