Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions onlinecourse/admin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
from django.contrib import admin
# <HINT> Import any new Models here
from .models import Course, Lesson, Instructor, Learner
from .models import Course, Lesson, Instructor, Learner, Question, Choice, Submission

# <HINT> Register QuestionInline and ChoiceInline classes here

class ChoiceInline(admin.StackedInline):
model = Choice
extra = 2

class QuestionInline(admin.StackedInline):
model = Question
extra = 2

class LessonInline(admin.StackedInline):
model = Lesson
Expand All @@ -21,10 +27,16 @@ class CourseAdmin(admin.ModelAdmin):
class LessonAdmin(admin.ModelAdmin):
list_display = ['title']

class QuestionAdmin(admin.ModelAdmin):
inlines = [ChoiceInline]
list_display = ['content']

# <HINT> Register Question and Choice models here

admin.site.register(Course, CourseAdmin)
admin.site.register(Lesson, LessonAdmin)
admin.site.register(Instructor)
admin.site.register(Learner)
admin.site.register(Question, QuestionAdmin)
admin.site.register(Choice)
admin.site.register(Submission)
78 changes: 78 additions & 0 deletions onlinecourse/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Generated by Django 5.1 on 2024-08-21 09:26

import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Course',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='online course', max_length=30)),
('image', models.ImageField(upload_to='course_images/')),
('description', models.CharField(max_length=1000)),
('pub_date', models.DateField(null=True)),
('total_enrollment', models.IntegerField(default=0)),
],
),
migrations.CreateModel(
name='Enrollment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_enrolled', models.DateField(default=django.utils.timezone.now)),
('mode', models.CharField(choices=[('audit', 'Audit'), ('honor', 'Honor'), ('BETA', 'BETA')], default='audit', max_length=5)),
('rating', models.FloatField(default=5.0)),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='onlinecourse.course')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='course',
name='users',
field=models.ManyToManyField(through='onlinecourse.Enrollment', to=settings.AUTH_USER_MODEL),
),
migrations.CreateModel(
name='Instructor',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('full_time', models.BooleanField(default=True)),
('total_learners', models.IntegerField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='course',
name='instructors',
field=models.ManyToManyField(to='onlinecourse.instructor'),
),
migrations.CreateModel(
name='Learner',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('occupation', models.CharField(choices=[('student', 'Student'), ('developer', 'Developer'), ('data_scientist', 'Data Scientist'), ('dba', 'Database Admin')], default='student', max_length=20)),
('social_link', models.URLField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Lesson',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(default='title', max_length=200)),
('order', models.IntegerField(default=0)),
('content', models.TextField()),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='onlinecourse.course')),
],
),
]
40 changes: 40 additions & 0 deletions onlinecourse/migrations/0002_question_choice_submission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 5.1 on 2024-08-21 09:36

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('onlinecourse', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='Question',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content', models.CharField(max_length=200)),
('grade', models.IntegerField(default=50)),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='onlinecourse.course')),
],
),
migrations.CreateModel(
name='Choice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content', models.CharField(max_length=200)),
('is_correct', models.BooleanField(default=False)),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='onlinecourse.question')),
],
),
migrations.CreateModel(
name='Submission',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choices', models.ManyToManyField(to='onlinecourse.choice')),
('enrollment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='onlinecourse.enrollment')),
],
),
]
30 changes: 24 additions & 6 deletions onlinecourse/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,27 @@ class Enrollment(models.Model):
rating = models.FloatField(default=5.0)


# One enrollment could have multiple submission
# One submission could have multiple choices
# One choice could belong to multiple submissions
#class Submission(models.Model):
# enrollment = models.ForeignKey(Enrollment, on_delete=models.CASCADE)
# choices = models.ManyToManyField(Choice)
class Question(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
content = models.CharField(max_length=200)
grade = models.IntegerField(default=50)

def __str__(self):
return "Question: " + self.content

def is_get_score(self, selected_ids):
all_answers = self.choice_set.filter(is_correct=True).count()
selected_correct = self.choice_set.filter(is_correct=True, id__in=selected_ids).count()
if all_answers == selected_correct:
return True
else:
return False

class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
content = models.CharField(max_length=200)
is_correct = models.BooleanField(default=False)

class Submission(models.Model):
enrollment = models.ForeignKey(Enrollment, on_delete=models.CASCADE)
choices = models.ManyToManyField(Choice)
28 changes: 27 additions & 1 deletion onlinecourse/templates/onlinecourse/course_detail_bootstrap.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,33 @@ <h2>{{ course.name }}</h2>
</div>
{% endfor %}
</div>
<!-- Course detail template changes go here -->
{% if user.is_authenticated %}
</br>
<button class="btn btn-primary btn-block" data-toggle="collapse" data-target="#exam">Start Exam</button>
<div id="exam" class="collapse">
<form id="questionform" action="{% url 'onlinecourse:submit' course.id %}" method="POST">
{% for question in course.question_set.all %}
<div class="card mt-1">
<div class="card-header">
<h5>{{ question.content }}</h5>
</div>
{% csrf_token %}
<div class="form-group">
{% for choice in question.choice_set.all %}
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" name="choice_{{choice.id}}" class="form-check-input"
id="{{choice.id}}" value="{{choice.id}}">{{ choice.content }}
</label>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
<input class="btn btn-success btn-block" type="submit" value="Submit">
</form>
</div>
{% endif %}
</div>
</body>
</html>
140 changes: 96 additions & 44 deletions onlinecourse/templates/onlinecourse/exam_result_bootstrap.html
Original file line number Diff line number Diff line change
@@ -1,55 +1,107 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<head>
<meta charset="UTF-8" />
{% load static %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>

<nav class="navbar navbar-light bg-light">
<div class="container-fluid">
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
/>
</head>
<body>
<nav class="navbar navbar-light bg-light">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'onlinecourse:index' %}">Home</a>
<a class="navbar-brand" href="{% url 'onlinecourse:index' %}">Home</a>
</div>
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li>
<a class="btn btn-link" href="#">{{ user.first_name }}({{ user.username }})</a>
<a class="btn btn-link" href="{% url 'onlinecourse:logout' %}">Logout</a>
</li>
{% else %}
<li>
<form class="form-inline" action="{% url 'onlinecourse:login' %}" method="post">
{% csrf_token %}
<div class="input-group">
<input type="text" class="form-control" placeholder="Username" name="username" >
<input type="password" class="form-control" placeholder="Username" name="psw" >
<button class="btn btn-primary" type="submit">Login</button>
<a class="btn btn-link" href="{% url 'onlinecourse:registration' %}">Sign Up</a>
</div>
</form>
</li>
{% endif %}
{% if user.is_authenticated %}
<li>
<a class="btn btn-link" href="#"
>{{ user.first_name }}({{ user.username }})</a
>
<a class="btn btn-link" href="{% url 'onlinecourse:logout' %}"
>Logout</a
>
</li>
{% else %}
<li>
<form
class="form-inline"
action="{% url 'onlinecourse:login' %}"
method="post"
>
{% csrf_token %}
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Username"
name="username"
/>
<input
type="password"
class="form-control"
placeholder="Username"
name="psw"
/>
<button class="btn btn-primary" type="submit">Login</button>
<a
class="btn btn-link"
href="{% url 'onlinecourse:registration' %}"
>Sign Up</a
>
</div>
</form>
</li>
{% endif %}
</ul>
</div>
</nav>
</div>
</nav>

<div class="container-fluid">
{% if grade > 80 %}
<div class="alert alert-success">
<!--HINT Display passed info -->
</div>
{% else %}
<div class="alert alert-danger">
<!--HINT Display failed info -->
</div>
<a class="btn btn-link text-danger" href="{% url 'onlinecourse:course_details' course.id %}">Re-test</a>
{% endif %}
<div class="card-columns-vertical mt-1">
<div class="container-fluid">
{% if grade > 80 %}
<div class="alert alert-success">
<b>Congratulations, {{ user.first_name }}!</b> You have passed the exam
and completed the course with score {{ grade }}/100
</div>
{% else %}
<div class="alert alert-danger">
<b>Failed</b> Sorry, {{ user.first_name }}! You have failed the exam
with score {{ grade }}/100
</div>
<a
class="btn btn-link text-danger"
href="{% url 'onlinecourse:course_details' course.id %}"
>Re-test</a
>
{% endif %}

<div class="card-columns-vertical mt-1">
<h5 class="">Exam results</h5>
<!--HINT Display exam results-->
{% for question in course.question_set.all %}
<div class="card mt-1">
<div class="card-header"><h5>{{ question.content }}</h5></div>
<div class="form-group">
{% for choice in question.choice_set.all %}
<div class="form-check">
{% if choice.is_correct and choice in choices %}
<div class="text-success">
Correct answer: {{ choice.content }}
</div>
{% elif choice.is_correct and not choice in choices %}
<div class="text-warning">Not selected: {{ choice.content }}</div>
{% elif not choice.is_correct and choice in choices %}
<div class="text-danger">Wrong answer: {{ choice.content }}</div>
{% else %}
<div>{{ choice.content }}</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</body>
</html>
</body>
</html>
4 changes: 3 additions & 1 deletion onlinecourse/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
path('<int:pk>/', views.CourseDetailView.as_view(), name='course_details'),
# ex: /enroll/5/
path('<int:course_id>/enroll/', views.enroll, name='enroll'),


# <HINT> Create a route for submit view

path('<int:course_id>/submit/', views.submit, name="submit"),
# <HINT> Create a route for show_exam_result view
path('course/<int:course_id>/submission/<int:submission_id>/result/', views.show_exam_result, name="show_exam_result"),

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Loading