Opened 9 years ago

Closed 9 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 9 years ago.

Download all attachments as: .zip

Change History (4)

Changed 9 years ago by kilian

Attachment: django.nodelist.patch added

comment:1 Changed 9 years ago by Malcolm Tredinnick

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 9 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 9 years ago by kilian

Resolution: invalid
Status: newclosed

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