Python Forum

Full Version: Displaying list of lists in template
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

I'm trying to create a list of url links in categories on a site at work, they use about 80 web based tools for content discovery and other things. I have built the site using django and currently the links are all hard coded into the side bar. This would usually be fine, but the links change on a daily basis as there are so many and tools migrate to different servers etc, so I wanted to serve the links dynamically, but I struggling to find out how this is done. In the python I have learned, I would just do:
for i in categories:
    print(i)
    for j in links:
        print(j)
But I can't seem to do that in django. So far I am only able to use one model per view and one view per template, so I haven't a clue as to how you would do this. Ultimately I will be using the nested loops in the template so that I can get the javascript that opens and closes the nested links correctly, but can't figure out how to take a category from the category model and the links from the links model. I tried using the foreign key only to have the category name printed as many times as there is links in the category. There are basically 10 categories and anything from 3 links to 20+ links in each category.

Any pointers would be really helpful as I have been through the django tutorial and I have nearly finished a full on course on Django that has taken me a good 3 months to go through and unfortunately, that does not cover this issue either. I'm assuming there is a way to work with multiple models, as I thought that was the the point to have two or more tables and take data from both, but django does not make this easy for newbies.

This is what I have so far:
model.py
from datetime import datetime
from django.db import models


class Category(models.Model):
    '''
    Category of links in the Sidebar
    '''
    name = models.CharField(max_length=30,unique=True)

    def __str__(self):
        return self.name


class Link(models.Model):
    
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    date = models.DateTimeField(auto_now_add=True)
    name = models.CharField(max_length=24,unique=True)
    url = models.URLField(unique=True)

    def __str__(self):
        return self.name
view.py
from django.shortcuts import render, redirect
from django.template import RequestContext
from django.views.generic import View,TemplateView,ListView,DetailView
from . import models


class TestpageView(ListView):
    context_object_name = 'link_tree'
    model = models.Link
I can work with the other areas of django, settings urls etc. but trying to work with the logic in django is really tricky. Any pointers would be really appreciated.
1) create ./templates/main.html with the following content:
Output:
<ul> {% for category in categories %} <li> {{category.name}} {%if category.link_set%} <ul> {%for link in category.link_set.all%} <li>{{link.name}}</li> {%endfor%} </ul> {%else%} :without children links {%endif%} </li> {%endfor%} </ul>
views.py:
....
# Use category model instead of link
class TestPageView(ListView):
    context_object_name = 'categories'
    model = models.Category
    template_name='main.html'
urls.py (or something like this):

from django.contrib import admin
from django.urls import path

from main.views import TestPageView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('testing/', TestPageView.as_view(), name='listing-links')
]
This works as expected in Django 2.1.4;


In general, if you need to render categories (nested categories) and related links,
it would be better to implement a custom tag. This custom tag could be recursively invoked in the template
to handle hierarchy of categories.
Hi thank you, that's perfect. I can see now what I was missing, which was the 'link_set', and having done a bit of research, I can see that the '_set' is a reverse lookup class variable, that in my interpretation, is the reference to the other model.

Django decided what my template was called as it was calling for a template called category_list.html, so renaming the template to that solved that one and I can see the connection, there. Where I am a little lost is, the line:
template_name='main.html
I was expecting that to over ride Django's default, but it still wanted category_list.html not main.html, I think I may have missed a setting somewhere that hasn't been highlighted in this thread.