From a6d64778adfe2ba020abe606b14fb3225a5dfe86 Mon Sep 17 00:00:00 2001
From: Teemu Lehtinen
Date: Mon, 25 Jan 2016 09:06:39 +0200
Subject: [PATCH] Add enrollment to courses
---
a-plus/settings.py | 2 +
course/long_urls.py | 3 +
course/migrations/0016_auto_20160124_2214.py | 34 ++++++
course/models.py | 53 ++++----
course/templates/course/index.html | 7 ++
course/templates/course/toc.html | 24 ++++
course/tree.py | 2 +-
course/viewbase.py | 35 ++++--
course/views.py | 29 ++++-
edit_course/course_forms.py | 4 +-
exercise/exercise_models.py | 114 +++++++++++-------
.../migrations/0015_auto_20160124_2139.py | 33 +++++
exercise/views.py | 17 +++
templates/403.html | 2 +
userprofile/viewbase.py | 3 +-
15 files changed, 281 insertions(+), 81 deletions(-)
create mode 100644 course/migrations/0016_auto_20160124_2214.py
create mode 100644 exercise/migrations/0015_auto_20160124_2139.py
diff --git a/a-plus/settings.py b/a-plus/settings.py
index 5e84a0585..36071bafc 100644
--- a/a-plus/settings.py
+++ b/a-plus/settings.py
@@ -37,6 +37,8 @@
LOGIN_TITLE_TEXT = ''
LOGIN_BODY_TEXT = ''
LOGIN_BUTTON_TEXT = 'Maintenance login'
+INTERNAL_USER_LABEL = 'Aalto'
+EXTERNAL_USER_LABEL = 'MOOC'
WELCOME_TEXT_FI = 'A+ verkkopohjainen oppimisympäristö'
SHIBBOLETH_TITLE_TEXT_FI = 'Aalto-yliopiston käyttäjät'
diff --git a/course/long_urls.py b/course/long_urls.py
index 571dd334e..80cb4c0e6 100644
--- a/course/long_urls.py
+++ b/course/long_urls.py
@@ -5,6 +5,9 @@
# These need to be listed before the exercise URL routings.
urlpatterns = [
+ url(USER_URL_PREFIX + r'enroll/$',
+ views.Enroll.as_view(),
+ name='enroll'),
url(USER_URL_PREFIX + r'export-calendar/$',
views.CalendarExport.as_view(),
name='export-calendar'),
diff --git a/course/migrations/0016_auto_20160124_2214.py b/course/migrations/0016_auto_20160124_2214.py
new file mode 100644
index 000000000..8e265b718
--- /dev/null
+++ b/course/migrations/0016_auto_20160124_2214.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('course', '0015_auto_20160121_1544'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='courseinstance',
+ name='submission_access',
+ ),
+ migrations.RemoveField(
+ model_name='courseinstance',
+ name='view_access',
+ ),
+ migrations.AddField(
+ model_name='courseinstance',
+ name='enrollment_audience',
+ field=models.IntegerField(choices=[(1, 'Internal users'), (2, 'External users'), (3, 'Internal and external users')], default=1),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='courseinstance',
+ name='view_content_to',
+ field=models.IntegerField(choices=[(1, 'Enrolled students'), (2, 'Enrollment audience'), (3, 'All registered users'), (4, 'Public to internet')], default=2),
+ preserve_default=True,
+ ),
+ ]
diff --git a/course/models.py b/course/models.py
index 46b004186..4eaa301b1 100644
--- a/course/models.py
+++ b/course/models.py
@@ -102,17 +102,17 @@ class CourseInstance(models.Model):
validators=[RegexValidator(regex="^[\w\-\.]*$")],
help_text=_("Input an URL identifier for this course instance."))
visible_to_students = models.BooleanField(default=True)
- view_access = models.IntegerField(choices=(
- (0, _('Public to internet')),
- (1, _('Internal and external users')),
- (2, _('Only external users')),
- (3, _('Only internal users')),
- ), default=3)
- submission_access = models.IntegerField(choices=(
- (1, _('Internal and external users')),
- (2, _('Only external users')),
- (3, _('Only internal users')),
- ), default=3)
+ enrollment_audience = models.IntegerField(choices=(
+ (1, _('Internal users')),
+ (2, _('External users')),
+ (3, _('Internal and external users')),
+ ), default=1)
+ view_content_to = models.IntegerField(choices=(
+ (1, _('Enrolled students')),
+ (2, _('Enrollment audience')),
+ (3, _('All registered users')),
+ (4, _('Public to internet')),
+ ), default=2)
starting_time = models.DateTimeField()
ending_time = models.DateTimeField()
image = models.ImageField(blank=True, null=True, upload_to=build_upload_dir)
@@ -170,16 +170,6 @@ def save(self, *args, **kwargs):
if self.image:
resize_image(self.image.path, (800,600))
- def has_submission_access(self, user):
- if not user or not user.is_authenticated():
- return False, _("You need to login to submit exercises to this course.")
- if self.submission_access == 2:
- return user.userprofile.is_external, \
- _("You need to login as external student to submit exercises to this course.")
- if self.submission_access > 2:
- return not user.userprofile.is_external, \
- _("You need to login as internal student to submit exercises to this course.")
-
def is_assistant(self, user):
return user and user.is_authenticated() \
and self.assistants.filter(id=user.userprofile.id).exists()
@@ -190,12 +180,31 @@ def is_teacher(self, user):
def is_course_staff(self, user):
return self.is_teacher(user) or self.is_assistant(user)
+ def is_student(self, user):
+ return user and user.is_authenticated() \
+ and self.students.filter(id=user.userprofile.id).exists()
+
+ def is_enrollable(self, user):
+ if user and user.is_authenticated():
+ if self.enrollment_audience == 1:
+ return not user.userprofile.is_external
+ if self.enrollment_audience == 2:
+ return user.userprofile.is_external
+ return True
+ return False
+
+ def enroll_student(self, user):
+ if user and user.is_authenticated() and not self.is_course_staff(user):
+ self.students.add(user.userprofile)
+
def get_course_staff_profiles(self):
return UserProfile.objects.filter(Q(teaching_courses=self.course) | Q(assisting_courses=self))\
.distinct()
def get_student_profiles(self):
- # TODO: enrollment should be designed
+ return self.students.all()
+
+ def get_submitted_profiles(self):
return UserProfile.objects.filter(submissions__exercise__course_module__course_instance=self)\
.distinct()\
.exclude(assisting_courses=self)\
diff --git a/course/templates/course/index.html b/course/templates/course/index.html
index fc1be7c9a..4d70d710b 100644
--- a/course/templates/course/index.html
+++ b/course/templates/course/index.html
@@ -38,6 +38,13 @@
{{ instance.starting_time|date:"N j, Y" }} –
{{ instance.ending_time|date:"N j, Y" }}
+
+ {% if instance.enrollment_audience == 1 or instance.enrollment_audience == 3 %}
+ {{ internal_user_label|safe }}
+ {% endif %}
+ {% if instance.enrollment_audience == 2 or instance.enrollment_audience == 3 %}
+ {{ external_user_label|safe }}
+ {% endif %}