Search code examples
pythondjangodjango-templatesdjango-viewsdjango-mptt

child node is treated as grand child node when trying to structure


I am using django-mptt library for the category. I could show the list of categories in template but I wanted to indent it properly so user can know which is a main category and which one is sub-category and etc. The way i tried to structure is

{% recursetree nodes %}
  <li class="node">
    <a href="/category/{{ node.get_absolute_url }}"
      class="{% if not node.is_leaf_node and not node.is_root_node and node.is_child_node %} child_parent {% elif node.is_leaf_node and not node.is_root_node %}leaf_node{% endif %}">
      {{ node.name }}
      {% if node.is_root_node %}
        <span class="badge">{{ node.get_count_children }}</span>
      {% endif %}
    </a>
      {% if not node.is_leaf_node %}
          <ul class="children">
            <li>{{ children }}</li>
          </ul>
      {% endif %}
  </li>
{% endrecursetree %}

This yields the following design of category

enter image description here

Here Dressing Table is a child of Bedroom Items like Bed and Almirah not a child of Bed. How could i fix this? I know the problem is here

<a href="/category/{{ node.get_absolute_url }}"
class="{% if not node.is_leaf_node and not node.is_root_node and node.is_child_node %} child_parent {% elif node.is_leaf_node and not node.is_root_node %}leaf_node{% endif %}">

but could not fix this issue

Not the dressing table in the screenshot

enter image description here


Solution

  • According to you updated answer.
    Dinning Set, Kitchen Rack, and Kitchen Setup(Modular Kitchen) are supposed to be cyan since they are second level. If my understanding is correct.
    Here is my hacked solution. If anybody found the better one please raise.

    1. Add extra method to the Model instance
    2. I have to add nodes to the context. (This would be an optional if you are using Django2.0 like mine)
    3. Use the instance method in the template

    models.py

    from django.db import models
    from mptt.models import MPTTModel, TreeForeignKey
    
    
    class Genre(MPTTModel):
        name = models.CharField(max_length=50, unique=True)
        parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True,
                                on_delete=models.CASCADE)
    
        class MPTTMeta:
            order_insertion_by = ['name']
    
        def __str__(self):
            return f'{self.name}'
    
        def is_second_node(self):
            return True if (self.get_ancestors().count() == 1) else False
    

    views.py

    from django.views.generic import ListView
    
    from genres.models import Genre
    
    
    class GenreListView(ListView):
        model = Genre
        template_name = 'genre_list.html'
    
        def get_context_data(self, *, object_list=None, **kwargs):
            """Get the context for this view."""
            queryset = object_list if object_list is not None else self.object_list
            page_size = self.get_paginate_by(queryset)
            context_object_name = self.get_context_object_name(queryset)
            if page_size:
                paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
                context = {
                    'paginator': paginator,
                    'page_obj': page,
                    'is_paginated': is_paginated,
                    'object_list': queryset
                }
            else:
                context = {
                    'paginator': None,
                    'page_obj': None,
                    'is_paginated': False,
                    'object_list': queryset
                }
            if context_object_name is not None:
                context[context_object_name] = queryset
            context.update(kwargs)
            context['nodes'] = context.get('object_list')
            return super().get_context_data(**context)
    

    genre_list.html

    <!DOCTYPE html>
    {% load mptt_tags %}
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Genre ListView</title>
    </head>
    <style>
        .root {color: purple}
        .child{color: cyan}
        .leaf {color: gray}
    </style>
    <body>
        {% recursetree nodes %}
        <div class="
            {% if node.is_root_node %}
            root
            {% elif node.is_child_node and not node.is_leaf_node or node.is_second_node%}
            child
            {% elif node.is_leaf_node and not node.is_root_node%}
            leaf
            {%endif%}">
            {{node.name}}
            {{node.is_second_node}}
        </div>
        {% if not node.is_leaf_node%}
        <ul>{{children}}</ul>
        {% endif %}
    
        {% endrecursetree %}
    </ul>
    </body>
    </html>
    

    enter image description here