How to render many to many field data in Django template

Viewed 42

I am able to render list of all courses and list of topics corresponding to the courses in different templates.

I need help to view list of all courses and when each course is clicked,a new page should show the list of associated topics


models.py

class Topic(models.Model):

  topic_name = models.CharField(max_length=200, null=True)
  topic_file = models.FileField(upload_to = "topic_file", blank=True, null=True)

  def __str__(self):
        return self.topic_name

class Course(models.Model):
  course_name = models.CharField(max_length=200, null=True)
  course_image = models.ImageField(upload_to="images", blank=True, null=True)
  related_topic = models.ManyToManyField(Topic)
 
  def __str__(self):
        return self.course_name

Views.py

def view_course(request):
  course_list = Course.objects.all()
  context = {'course_list':course_list}
  return render(request, 'upskill/view_course.html',context)

def course_topic(request,pk):
  course_topic_list = Course.objects.get(id=pk)
  var = course_topic_list.related_topic.all 
  context = {'var':var}
  return render(request, 'upskill/course_topic.html',context)
1 Answers

Here is how you could get the related topics inside of a template.

{% for course in course_list %}
    ... data
    {% for topic in course.related_topic.all %}
        ...data
    {% endfor %}
{% endfor %}

If you don't want to do a query every single iteration of the {{course}} loop, I recommend you this in your views:

course_list = Course.objects.all().prefetch_related('related_topic')

And for a single object:

def course_topic(request,pk):
  course = Course.objects.prefetch_related('related_topic').get(id=pk)
  context = {'course ':course }
  return render(request, 'upskill/course_topic.html',context)

And then in the template:

{{course.data...}}
{% for topic in course.related_topic.all %}
    ...data
{% endfor %}

To only have topics:

def topic_view(request, pk)
    topics = Topic.objects.filter(course__pk=pk) #The reverse name of Course model.
    # You can set a related name the "related_topic" field. 
    # Then access the above filter with that related name.
    .... data
    context = {
        "topics":topics 
    }
    return render(request, 'template.html', context)
Related