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>
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>
I have got the resolution for my code and sharing the same here. Below code allowing me to add multiple instances of each model through DetailView in Django.
So for my Entries model if I have 10 instances created. Below code allowing me to show all those 10 instances on the detail View page which I wanted to do when user will click on the Topic link.
class ContentDetailView(DetailView):
model = Entries
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
c_id = get_object_or_404(Topic, pk = self.kwargs['pk'])
context['content'] = Entries.objects.filter(topic_id = c_id)
return context
Now we have to loop through this content key in the template to get all the instance data we have created for single model.
entries_detail.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>
{% for obj in content %}
<p>{{ obj.text }}</p>
<p>{{ obj.image }}</p>
<p>{{ obj.date_added }}</p>
{% endfor %}
</body>
</html>