Displaying courses

For our course catalog, we have to build the following functionality:

  • List all available courses, optionally filtered by subject
  • Display a single course overview

Edit the views.py file of the courses application and add the following code:

from django.db.models import Count
from .models import Subject

class CourseListView(TemplateResponseMixin, View):
model = Course
template_name = 'courses/course/list.html'

def get(self, request, subject=None):
subjects = Subject.objects.annotate(
total_courses=Count('courses'))
courses = Course.objects.annotate(
total_modules=Count('modules'))
if subject:
subject = get_object_or_404(Subject, slug=subject)
courses = courses.filter(subject=subject)
return self.render_to_response({'subjects': subjects,
'subject': subject,
'courses': courses})

This is the CourseListView view. It inherits from TemplateResponseMixin and View. In this view, we perform the following tasks:

  1. We retrieve all subjects, including the total number of courses for each of them. We use the ORM's annotate() method with the Count() aggregation function to include the total number of courses for each subject.
  2. We retrieve all available courses, including the total number of modules contained in each course.
  3. If a subject slug URL parameter is given, we retrieve the corresponding subject object and we limit the query to the courses that belong to the given subject.
  4. We use the render_to_response() method provided by TemplateResponseMixin to render the objects to a template and return an HTTP response.

Let's create a detail view for displaying a single course overview. Add the following code to the views.py file:

from django.views.generic.detail import DetailView

class CourseDetailView(DetailView):
model = Course
template_name = 'courses/course/detail.html'

This view inherits from the generic DetailView provided by Django. We specify the model and template_name attributes. Django's DetailView expects a primary key (pk) or slug URL parameter to retrieve a single object for the given model. Then, it renders the template specified in template_name, including the object in the context as object.

Edit the main urls.py file of the educa project and add the following URL pattern to it:

from courses.views import CourseListView

urlpatterns = [
# ...
path('', CourseListView.as_view(), name='course_list'),
]

We add the course_list URL pattern to the main urls.py file of the project because we want to display the list of courses in the URL http://127.0.0.1:8000/ and all other URLs for the courses application have the /course/ prefix.

Edit the urls.py file of the courses application and add the following URL patterns:

path('subject/<slug:subject>)/',
views.CourseListView.as_view(),
name='course_list_subject'),

path('<slug:slug>/',
views.CourseDetailView.as_view(),
name='course_detail'),

We define the following URL patterns:

  • course_list_subject: For displaying all courses for a subject
  • course_detail: For displaying a single course overview

Let's build templates for the CourseListView and CourseDetailView views.
Create the following file structure inside the templates/courses/ directory of the courses application:

course/
list.html
detail.html

Edit the courses/course/list.html template and write the following code:

{% extends "base.html" %}

{% block title %}
{% if subject %}
{{ subject.title }} courses
{% else %}
All courses
{% endif %}
{% endblock %}

{% block content %}
<h1>
{% if subject %}
{{ subject.title }} courses
{% else %}
All courses
{% endif %}
</h1>
<div class="contents">
<h3>Subjects</h3>
<ul id="modules">
<li {% if not subject %}class="selected"{% endif %}>
<a href="{% url "course_list" %}">All</a>
</li>
{% for s in subjects %}
<li {% if subject == s %}class="selected"{% endif %}>
<a href="{% url "course_list_subject" s.slug %}">
{{ s.title }}
<br><span>{{ s.total_courses }} courses</span>
</a>
</li>
{% endfor %}
</ul>
</div>
<div class="module">
{% for course in courses %}
{% with subject=course.subject %}
<h3><a href="{% url "course_detail" course.slug %}">
{{ course.title }}</a></h3>
<p>
<a href="{% url "course_list_subject" subject.slug %}">
{{ subject }}</a>.
{{ course.total_modules }} modules.
Instructor: {{ course.owner.get_full_name }}
</p>
{% endwith %}
{% endfor %}
</div>
{% endblock %}

This is the template for listing the available courses. We create an HTML list to display all Subject objects and build a link to the course_list_subject URL for each of them. We add a selected HTML class to highlight the current subject, if any. We iterate over every Course object, displaying the total number of modules and the instructor name.

Run the development server and open http://127.0.0.1:8000/ in your browser. You should see a page similar to the following one:

The left sidebar contains all subjects, including the total number of courses for each of them. You can click any subject to filter the courses displayed.

Edit the courses/course/detail.html template and add the following code to it:

{% extends "base.html" %}

{% block title %}
{{ object.title }}
{% endblock %}

{% block content %}
{% with subject=course.subject %}
<h1>
{{ object.title }}
</h1>
<div class="module">
<h2>Overview</h2>
<p>
<a href="{% url "course_list_subject" subject.slug %}">
{{ subject.title }}</a>.
{{ course.modules.count }} modules.
Instructor: {{ course.owner.get_full_name }}
</p>
{{ object.overview|linebreaks }}
</div>
{% endwith %}
{% endblock %}

In this template, we display the overview and details for a single course. Open http://127.0.0.1:8000/ in your browser and click one of the courses. You should see a page with the following structure:

We have created a public area for displaying courses. Next, we need to allow users to register as students and enroll in courses.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset