Search code examples
django

How to show multiple objects in Django detailview


I have two models created, one Topic and another Entries. Listview showing all the Topics link. Clicking on each topic link will show all the entries related to that particular topic. I have created multiple entries for each Topic. DetailView only showing single entries for each topic link. How to show multiple entries for each topic link using DetailView?

Models.py

class Topic(models.Model):
    '''A topic that user will add the content about.'''
    title = models.CharField(max_length=200)

class Entries(models.Model):
    '''Entries and Topic will have many to one relationship'''
    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
    text = models.TextField()
    image = models.ImageField(upload_to='images', blank=True)
    date_added = models.DateTimeField(auto_now_add=True)

views.py

class TopicListView(ListView):
    model = Topic
    template_name = 'cms_app/topic_list.html'
    context_object_name = 'topic'

class ContentDetailView(DetailView):
    model = Entries

urls.py

urlpatterns = [
    path('', TopicListView.as_view(), name = 'all-topic'),
    path('content/<int:pk>', ContentDetailView.as_view(), name = 'all-content'),
]

Topic.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>All Topics</title>
</head>
<body>
    <h1>Topic List</h1>
    <h3>
    {% for data in topic %}
        <p><a href="{% url 'all-content' data.id %}">{{ data.title }}</a></p>
    {% endfor %}
    </h3>
</body>
</html>

Entries.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>All Contents</title>
</head>
<body>
        <p>{{object.text }}</p>
        <p>{{object.image }}</p>
        <p>{{object.date_added }}</p>
</body>
</html>

Solution

  • You have configured ContentDetailView with model = Entries. A DetailView only looks up a single object from the database and makes that available in the context, so it is only giving you one Entries object. Further, you are passing a Topic ID value in the URL to ContentDetailView. That means you are passing something like Topic ID 1 to the URL, but it is then looking up the Entries object with an ID of 1 and displaying that Entries object, even though that Entries object may not even be related to the Topic that was clicked.

    You need to change ContentDetailView to look up the Topic that was clicked:

    class ContentDetailView(DetailView):
        model = Topic
        context_object_name = 'topic'
    

    And then change Entries.html to iterate over the Entries in the selected Topic:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>All Contents</title>
    </head>
    <body>
        <div>Topic: {{ topic.title }}<div>
    
        {% for entry in topic.entries_set.all %}
            <p>{{object.text }}</p>
            <p>{{object.image }}</p>
            <p>{{object.date_added }}</p>
        {% endfor %}
    </body>
    </html>