0

I am building a website where an instructor can create courses and students can enroll the courses. Is there any way to display top 3 most enrolled courses by students that an instructor has created?

I have tried using .values().annotate().order_by()[] but it seems that i cant display it on template.

models.py

class Enrollment(models.Model):
student = models.ForeignKey(User, on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
enrollment_date = models.DateField(auto_now_add=True, null = True)

class Course(models.Model):
user = models.ForeignKey(Users, on_delete = models.CASCADE)
media = models.ImageField(upload_to = 'media/course')
title = models.CharField(max_length=300, null = False)
subtitle = models.CharField(max_length=500, null = False)
description = models.TextField(max_length=5000, null = False)
language = models.CharField(max_length=20, null = False, choices=LANGUAGE)
level = models.CharField(max_length=20, null = False, choices=LEVEL)
category = models.CharField(max_length=30, null = False, choices=CATEGORY)
subcategory = models.CharField(max_length=20, null = False)
price = models.FloatField(null = True)
roles_responsibilities = models.TextField(max_length=2500, null = False)
timeline_budget = models.TextField(max_length=250, null = False)
req_prerequisite = models.TextField(max_length=2500, null = False)
certificate = models.CharField(max_length=5, null = False, choices=CERTIFICATE)
slug = AutoSlugField(populate_from='title', max_length=500, unique=True, null=True)

views.py

def instructorDashboard(request):
student = Enrollment.objects.filter(course__in=course)
popular_courses= student.values('course__title').annotate(count=Count('course__title')).order_by('-count')[:3]

print(popular_courses)

context = {
  'popular_courses': popular_courses,
  }
return render(request, 'instructor_dashboard/index.html', context)

index.html

<!-- Popular Courses -->
                <div class="col-xl-4 col-lg-5">
                    <div class="card shadow mb-4">
                        <!-- Card Header - Dropdown -->
                        <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
                            <h6 class="m-0 font-weight-bold text-primary">Popular Courses</h6>
                        </div>
                        {% for popular_course in popular_courses %}
                        <div class="card-body">
                            {{ course.title }}
                        </div>
                        {% endfor %}
                    </div>
                </div>
Suraya Zulkifli
  • 105
  • 2
  • 8
  • "My code does not work" isn't a descriptive enough statement of the problem - you need to say what specifically doesn't work - what is your output vs what you want. – solarissmoke Apr 03 '22 at 04:20
  • The code does not work when i tried to get the top 3 most enrolled courses by students by ordering it in desc order according to the number of students and only select [:3] top courses only. Hope this helps – Suraya Zulkifli Apr 03 '22 at 04:34
  • remove your forloop and try this – Thierno Amadou Sow Apr 03 '22 at 04:44
  • `student = Enrollment.objects.filter(course__in=course) student_count = student.annotate(count=Count('course')).order_by('-count')[:3] print(student_count)` – Thierno Amadou Sow Apr 03 '22 at 04:44
  • @ThiernoAmadouSow it only print the students that enrolled to the courses. I wanted it to be able to count how many students has enrolled a particular course and then get only the top 3 most enrolled courses – Suraya Zulkifli Apr 03 '22 at 06:10

1 Answers1

0

Expected: Get the list of courses having more enrollments.

In Django, if we are using ForeignKey, you can easily get all the rows(Enrollment) that are in a relationship with a single row(Course) using the 'realted_name' parameter.

models.py

class Enrollment(models.Model):
    student = models.ForeignKey(User, on_delete=models.CASCADE)
    course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='enrollment')
    enrollment_date = models.DateField(auto_now_add=True, null = True)

views.py

 # Get the user object and filter the course that are created by user.
 # Retrieve all the enrollments for every course created by user and sort in descending order.
 # courses_list will be having all the courses that are created by the user.
 courses_ranking = []
 for course in courses_list:
     courses_ranking.append({'course_id': course.id, 'count':course.enrollment.count()})
 # After this, courses_ranking will be having list of dict objects that contains courses_id and specific enrollment count. If you sort that dictionary based on the "count" key, you will get the required sorted list.
 result = sorted(courses_ranking, key=lambda x: x[1], reverse=True)
 # result will have list of courses with highest to lowest enrollments(descending order).
B.Anup
  • 585
  • 4
  • 6