term = m.ForeignKey(Term)
title = m.CharField(max_length=1024)
access = m.CharField(max_length=5,
- choices = [('ANON', _('World-accessible')),
- ('LOGIN', _('Accessible to all logged-in users')),
- ('STUDT', _('Accessible to course students')),
- ('CLOSE', _('Accessible only to course owners'))],
+ choices = [
+ ('ANON', _('World-accessible')),
+ ('LOGIN', _('Accessible to all logged-in users')),
+ ('STUDT', _('Accessible to course students (by section)')),
+ ('PASWD', _('Accessible to course students (by password)')),
+ ('CLOSE', _('Accessible only to course owners'))],
default='CLOSE')
- # For sites that use a passphrase as an invitation (STUDT access).
- passkey = m.CharField(db_index=True, unique=True, blank=True, null=True,
- max_length=255)
+ # For sites that use a passphrase as an invitation (PASWD access).
+ passkey = m.CharField(db_index=True, blank=True, null=True, max_length=255)
# For sites that have registration-lists from an external system
# (STUDT access).
enrol_codes = m.CharField(_('Registrar keys for class lists'),
max_length=4098,
blank=True, null=True)
+
+
+ def save(self, force_insert=False, force_update=False):
+ # We need to override save() to ensure unique passkey
+ # values. Django (and some backend databases) will not allow
+ # multiple NULL values in a unique column.
+ if self.passkey:
+ try:
+ already = Course.objects.get(passkey=self.passkey)
+ except Course.DoesNotExist:
+ super(Course, self).save(force_insert, force_update)
+ else:
+ super(Course, self).save(force_insert, force_update)
+
def __unicode__(self):
return self.code or self.title
def open_courses(request):
page_num = int(request.GET.get('page', 1))
count = int(request.GET.get('count', 5))
- paginator = Paginator(models.Course.objects.filter(moderated=False), count)
+ paginator = Paginator(models.Course.objects.all(), count) # fixme, what filter?
return g.render('open_courses.xhtml', paginator=paginator,
page_num=page_num,
count=count)
if action == 'join':
paginator = Paginator(models.UserProfile.active_instructors(), count)
elif action == 'drop':
- paginator = Paginator(models.Course.objects.filter(moderated=False), count)
+ paginator = Paginator(models.Course.objects.all(), count) # fixme, what filter?
else:
- paginator = Paginator(models.Course.objects.filter(moderated=False), count)
+ paginator = Paginator(models.Course.objects.all(), count) # fixme, what filter?
return g.render('instructors.xhtml', paginator=paginator,
page_num=page_num,
def my_courses(request):
return g.render('my_courses.xhtml')
+def course_detail(request, course_id):
+ course = get_object_or_404(models.Course, pk=course_id)
+ if course.access != 'ANON' and request.user.is_anonymous():
+ #fixme, don't stop access just if anonymous, but rather if not
+ #allowed to access. We need to set up a permissions model.
+ return login_required(lambda *args: None)(request)
+ return g.render('course_detail.xhtml', course=course)
+
+def course_search(request, course_id):
+ course = get_object_or_404(models.Course, pk=course_id)
+ return search(request, in_course=course)
+
+
+#------------------------------------------------------------
+# Creating a new course
+
class NewCourseForm(ModelForm):
class Meta:
model = models.Course
+
def clean_code(self):
v = (self.cleaned_data.get('code') or '').strip()
is_valid_func = models.course_codes.course_code_is_valid
else:
raise ValidationError, _('invalid course code')
+# I want different choice labels on the access screen than are given
+# in the model.
+NewCourseForm.base_fields['access'].widget.choices = [
+ ('CLOSE', _('For now, just myself and designated colleagues')),
+ ('STUDT', _('Students in my course (I will provide section numbers)')),
+ ('PASWD', _('Students in my course (I will share a password with them)')),
+ ('LOGIN', _('All Reserves patrons'))]
+
+
# hack the new-course form if we have course-code lookup
COURSE_CODE_LIST = bool(models.course_codes.course_code_list)
COURSE_CODE_LOOKUP_TITLE = bool(models.course_codes.course_code_lookup_title)
form = NewCourseForm(request.POST, instance=models.Course())
if not form.is_valid():
return g.render('add_new_course.xhtml', **locals())
+ else:
+ form.save()
+ course = form.instance
+ assert course.id
+ mbr = course.member_set.create(user=request.user, role='INSTR')
+ mbr.save()
+
+ # fixme, need to ask about PASWD and STUDT settings before redirect.
+ return HttpResponseRedirect('../') # back to My Courses
def add_new_course_ajax_title(request):
course_code = request.GET['course_code']
title = models.course_codes.course_code_lookup_title(course_code)
return HttpResponse(simplejson.dumps({'title':title}))
-def course_detail(request, course_id):
- course = get_object_or_404(models.Course, pk=course_id)
- if course.moderated and request.user.is_anonymous():
- #fixme, don't stop access just if anonymous, but rather if not
- #allowed to access. We need to set up a permissions model.
- return login_required(lambda *args: None)(request)
- return g.render('course_detail.xhtml', course=course)
-
-def course_search(request, course_id):
- course = get_object_or_404(models.Course, pk=course_id)
- return search(request, in_course=course)
+#------------------------------------------------------------
def instructor_detail(request, instructor_id):
page_num = int(request.GET.get('page', 1))
def item_edit(request, course_id, item_id):
course = get_object_or_404(models.Course, pk=course_id)
item = get_object_or_404(models.Item, pk=item_id, course__id=course_id)
- template = 'item_add_%s.xhtml' % item.item_type.lower()
+ item_type = item.item_type
+ template = 'item_add_%s.xhtml' % item_type.lower()
+ parent_item = item.parent_heading
if request.method == 'GET':
return g.render(template, **locals())
else:
</head>
<body>
<h1>${title}</h1>
+ <ul py:for="fld in form" py:if="fld.errors">
+ <li py:for="err in fld.errors">${fld.name}: ${err}</li>
+ </ul>
<form action="." method="POST">
- <tr py:def="field_row(field)">
- <th>${field.label}</th><td>${Markup(field)} !!!</td></tr>
+ <tr py:def="field_row(field, example=None)">
+ <th>${field.label}</th>
+ <td>
+ <ul py:if="field.errors" class="errorlist">
+ <li py:for="err in field.errors">${err}</li>
+ </ul>
+ ${Markup(field)}
+ </td>
+ <td class="example" py:if="example">e.g., ${example}</td>
+ </tr>
<fieldset>
<legend>General description</legend>
<table class="formtable">
- <tr><th>Course code</th><td>${Markup(form.code)}</td>
- <td py:if="example">e.g. ${example}</td></tr>
- <tr><th>Title</th><td>${Markup(form.title)} <span>${form.title.errors}</span></td></tr>
- <tr><th>Term</th><td>${Markup(form.term)}</td></tr>
- <tr><th>Access</th><td>${Markup(form.access)}</td></tr>
+ ${field_row(form.code, example)}
+ ${field_row(form.title)}
+ ${field_row(form.term)}
${field_row(form.department)}
<!-- <tr><th>Department</th><td>${Markup(form.department)} ${errorlist(form.department)}</td></tr> -->
</table>
<fieldset>
<legend>Access controls</legend>
<p>This site will be available to:</p>
- <select>
- <option>For now, just myself and designated colleagues</option>
- <option>Students in my course (I will provide section numbers)</option>
- <option>Students in my course (I will share a password with them)</option>
- <option>All Reserves patrons</option>
- </select>
+ ${Markup(form.access)}
</fieldset>
<p><input type="submit" value="Continue"/></p>
</form>