Opened 7 years ago

Closed 7 years ago

#7034 closed (invalid)

get_nodes_by_type() fails if nodelist = None

Reported by: kilian Owned by: nobody
Component: Template system Version: master
Severity: Keywords: inheritance nodelist
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Using Jacob's Google Charts templatetags, I've encountered a strange bug in the template systems. The {% axis "bottom" hide %} directive works fine in a stand-alone template, but fails if the template extends an other template.

For instance, the following template (straight from the examples):

{% extends "base.html" %}
{% load charts %}
{% chart %}
  {% chart-size "300x200" %}
  {% chart-type "line" %}
  {% chart-data "1,5,2,10" %}
  {% axis "left" %}
    {% axis-range "0" "10" %}
  {% endaxis %}
  {% axis "left" hide %}
{% endchart %}

raises the following exception:

File "/home/kilian/django/django/template/__init__.py" in get_nodes_by_type
  762.             nodes.extend(node.get_nodes_by_type(nodetype))
File "/home/kilian/django/django/template/__init__.py" in get_nodes_by_type
  741.             nodes.extend(self.nodelist.get_nodes_by_type(nodetype))

Exception Type: AttributeError at /test/
Exception Value: 'NoneType' object has no attribute 'get_nodes_by_type'

If the {% extends "base.html" %} is removed from the template, then it works fine, and no exception is raised. It looks like, for some reason, the parsing of the {% axis "left" hide %} tag generates a Node whose nodelist attribute is not a NodeList object. neither a list, but rather None.

The attached patch proposes a solution to take care of this case.

Attachments (1)

django.nodelist.patch (472 bytes) - added by kilian 7 years ago.

Download all attachments as: .zip

Change History (4)

Changed 7 years ago by kilian

comment:1 follow-up: Changed 7 years ago by mtredinnick

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I'm not sure your patch is really fixing the right problem. It's probably quite reasonable for us to assume nodelist is an actual list of nodes -- something we can iterate over. So if this is a real bug, it lies in the template tag causing it.

However, I suspect the problem actually lies elsewhere: the example you give in the description is not a valid template. If you extend another template you can only override the blocks from the parent template. Anything outside a block in the child template is invalid and so unexpected things will happen (as exhibited here, I suspect).

If you can repeat this problem with a proper template (all code outside the extends tag must lie inside {% block %}...{% endblock %} sections), then this is a bug (although in that case we can probably bounce it to google-charts project for fixing). If you can't repeat it in that case, it's not a bug since your template is invalid.

comment:2 in reply to: ↑ 1 Changed 7 years ago by kilian

Replying to mtredinnick:

I'm not sure your patch is really fixing the right problem. It's probably quite reasonable for us to assume nodelist is an actual list of nodes -- something we can iterate over. So if this is a real bug, it lies in the template tag causing it.

I was not sure either. I've looked in the template tag definition, but couldn't find any problem with it. If you want to take a look, maybe you'll find something I missed.


If you can repeat this problem with a proper template (all code outside the extends tag must lie inside {% block %}...{% endblock %} sections),

I omitted the {% block %}...{% endblock %} tags to keep things short (which I shouldn't have), but I can confirm the same behavior with the following template (where {% block content %} is defined in the "base.html" template):

{% extends "base.html" %}
{% block content %}
{% load charts %}
{% chart %}
  {% chart-size "300x200" %}
  {% chart-type "line" %}
  {% chart-data "1,5,2,10" %}
  {% axis "left" %}
    {% axis-range "0" "10" %}
  {% endaxis %}
  {% axis "left" hide %}
{% endchart %}
{% endblock %}

However, if the {% chart %}...{% end chart %} block is the only content of the template, it works fine.


then this is a bug (although in that case we can probably bounce it to google-charts project for fixing).

I'm afraid there's no official way to report bugs to that project, except sending a direct email to Jacob, probably.

comment:3 Changed 7 years ago by kilian

  • Resolution set to invalid
  • Status changed from new to closed

Actually, after further inspection, it indeed seems that the bug lies in the charts templatetag definition:

class AxisNode(template.Node):
    def __init__(self, side, nodelist=None):
        self.nodelist = nodelist
...

When the {% axis "..." hide %} tag is found, an AxisNode instance is created, with no nodelist argument. Hence self.nodelist gets the default None value, and the "'NoneType' object has no attribute 'get_nodes_by_type'" exception is raised while parsing it.

So that's not a Django bug after all. I'll send a patch to the google-charts project. Sorry for the noise. :)

Note: See TracTickets for help on using tickets.
Back to Top