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
Empty file added existing_file.html
Empty file.
24 changes: 13 additions & 11 deletions onlinecourse/admin.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
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 LessonInline(admin.StackedInline):
model = Lesson
extra = 5


class ChoiceInline(admin.StackedInline):
model = Choice
extra = 2
class QuestionInline(admin.StackedInline):
model = Question
extra = 2
# Register your models here.
class CourseAdmin(admin.ModelAdmin):
inlines = [LessonInline]
list_display = ('name', 'pub_date')
list_filter = ['pub_date']
search_fields = ['name', 'description']


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


# <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 4.2.3 on 2024-08-07 17:40

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


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='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')),
],
),
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='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.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='instructors',
field=models.ManyToManyField(to='onlinecourse.instructor'),
),
migrations.AddField(
model_name='course',
name='users',
field=models.ManyToManyField(through='onlinecourse.Enrollment', to=settings.AUTH_USER_MODEL),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Generated by Django 4.2.3 on 2024-08-07 17:59

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


class Migration(migrations.Migration):

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

operations = [
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)),
],
),
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')),
],
),
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.AddField(
model_name='choice',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='onlinecourse.question'),
),
]
42 changes: 20 additions & 22 deletions onlinecourse/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
except Exception:
print("There was an error loading django modules. Do you have django installed?")
sys.exit()

from django.conf import settings
import uuid


# Instructor model
class Instructor(models.Model):
user = models.ForeignKey(
Expand All @@ -18,11 +15,8 @@ class Instructor(models.Model):
)
full_time = models.BooleanField(default=True)
total_learners = models.IntegerField()

def __str__(self):
return self.user.username


# Learner model
class Learner(models.Model):
user = models.ForeignKey(
Expand All @@ -46,12 +40,9 @@ class Learner(models.Model):
default=STUDENT
)
social_link = models.URLField(max_length=200)

def __str__(self):
return self.user.username + "," + \
self.occupation


# Course model
class Course(models.Model):
name = models.CharField(null=False, max_length=30, default='online course')
Expand All @@ -62,20 +53,15 @@ class Course(models.Model):
users = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Enrollment')
total_enrollment = models.IntegerField(default=0)
is_enrolled = False

def __str__(self):
return "Name: " + self.name + "," + \
"Description: " + self.description


# Lesson model
class Lesson(models.Model):
title = models.CharField(max_length=200, default="title")
order = models.IntegerField(default=0)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
content = models.TextField()


# Enrollment model
# <HINT> Once a user enrolled a class, an enrollment entry should be created between the user and course
# And we could use the enrollment to track information such as exam submissions
Expand All @@ -93,11 +79,23 @@ class Enrollment(models.Model):
date_enrolled = models.DateField(default=now)
mode = models.CharField(max_length=5, choices=COURSE_MODES, default=AUDIT)
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)
27 changes: 27 additions & 0 deletions onlinecourse/templates/onlinecourse/course_detail_bootstrap.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,33 @@ <h2>{{ course.name }}</h2>
{% 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>
26 changes: 23 additions & 3 deletions onlinecourse/templates/onlinecourse/exam_result_bootstrap.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'onlinecourse:index' %}">Home</a>
</div>

<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li>
Expand All @@ -38,17 +39,36 @@
<div class="container-fluid">
{% if grade > 80 %}
<div class="alert alert-success">
<!--HINT Display passed info -->
<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">
<!--HINT Display failed info -->
<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>
{% else %}{% if choice.is_correct and not choice in choices %}
<div class="text-warning">Not selected: {{ choice.content }}</div>
{% else %}{% if not choice.is_correct and choice in choices %}
<div class="text-danger">Wrong answer: {{ choice.content }}</div>
{% else %}
<div>{{ choice.content }}</div>
{% endif %}{% endif %}{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</body>
Expand Down
1 change: 1 addition & 0 deletions onlinecourse/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
path('<int:pk>/', views.CourseDetailView.as_view(), name='course_details'),
# ex: /enroll/5/
path('<int:course_id>/enroll/', views.enroll, name='enroll'),
path('<int:course_id>/submit/', views.submit, name="submit"),

# <HINT> Create a route for submit view

Expand Down
Loading