181 lines
6.1 KiB
Python
181 lines
6.1 KiB
Python
from __future__ import print_function
|
|
|
|
from django.shortcuts import render
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
from django.urls import reverse
|
|
|
|
from django.http import HttpResponse
|
|
from django.http import HttpResponseRedirect
|
|
|
|
from django import template
|
|
from django.template.defaultfilters import stringfilter
|
|
|
|
# Class Based Views (CBV)
|
|
from django.views.generic import View
|
|
from django.views.generic import ListView
|
|
|
|
|
|
from .models import Course
|
|
from .models import Section
|
|
from .models import Slide
|
|
from .models import UserCourse
|
|
from .models import UserSolution
|
|
|
|
import sys
|
|
import json
|
|
|
|
class ListCourseView(ListView):
|
|
model = Course
|
|
|
|
|
|
###############################################################################
|
|
def index(request):
|
|
data = {}
|
|
return render(request, 'courses/index.html')
|
|
|
|
###############################################################################
|
|
def course(request, cid):
|
|
course = get_object_or_404(Course, pk=cid)
|
|
first_section = course.sections.first()
|
|
first_slide = first_section.slides.first()
|
|
|
|
if request.user.is_authenticated():
|
|
try:
|
|
# when the user is merely opening the course, jump the last active section (better: last incomplete?)
|
|
user_course = UserCourse.objects.get(course=course, user=request.user)
|
|
return HttpResponseRedirect(reverse('courses:slide', args=(course.id, user_course.progress_section.id, user_course.progress_slide.id)))
|
|
except UserCourse.DoesNotExist:
|
|
# usfrom django import template
|
|
# also redirect to course beginning
|
|
user_course = UserCourse.objects.create(course=course, user=request.user, progress_section=first_section, progress_slide=first_slide)
|
|
return HttpResponseRedirect(reverse('courses:slide', args=(course.id, first_section.id, first_slide.id)))
|
|
else:
|
|
return HttpResponseRedirect(reverse('courses:slide', args=(course.id, first_section.id, first_slide.id)))
|
|
|
|
|
|
data = {'course': course}
|
|
return render(request, 'courses/course.html', data)
|
|
|
|
|
|
###############################################################################
|
|
def section(request, cid, seid):
|
|
course = get_object_or_404(Course, pk=cid)
|
|
section = get_object_or_404(Section, pk=seid)
|
|
first_slide = section.slides.first()
|
|
|
|
if request.user.is_authenticated():
|
|
try:
|
|
user_course = UserCourse.objects.get(course=course, user=request.user)
|
|
|
|
if section.id == user_course.progress_section.id:
|
|
# only redirect if progress was made in this sections
|
|
return HttpResponseRedirect(reverse('courses:slide', args=(course.id, user_course.progress_section.id, user_course.progress_slide.id)))
|
|
else:
|
|
# otherwise switch to first slide in section
|
|
first_slide = section.slides.first()
|
|
return HttpResponseRedirect(reverse('courses:slide', args=(course.id, section.id, first_slide.id)))
|
|
|
|
except UserCourse.DoesNotExist:
|
|
# TODO how are direct visitors handled?
|
|
pass
|
|
else:
|
|
return HttpResponseRedirect(reverse('courses:slide', args=(course.id, section.id, first_slide.id)))
|
|
|
|
data = {'course': course}
|
|
return render(request, 'courses/course.html', data)
|
|
|
|
|
|
###############################################################################
|
|
def slide(request, cid, seid, slid):
|
|
""" The slide view serves the smallest servable unit of material to the
|
|
user. In principle a single slide is meant to provide
|
|
"""
|
|
course = get_object_or_404(Course, pk=cid)
|
|
section = get_object_or_404(Section, pk=seid)
|
|
slide = get_object_or_404(Slide, pk=slid)
|
|
|
|
|
|
|
|
if request.user.is_authenticated():
|
|
try:
|
|
user_course = UserCourse.objects.get(course=course, user=request.user)
|
|
# simply update last user_course action
|
|
user_course.progress_section = section
|
|
user_course.progress_slide = slide
|
|
user_course.save()
|
|
|
|
except UserCourse.DoesNotExist:
|
|
# TODO Should direct visitors get a special treatment?
|
|
pass
|
|
|
|
|
|
|
|
user_solution = None
|
|
if request.user.is_authenticated():
|
|
try:
|
|
user_solution = UserSolution.objects.get(slide=slide, user=request.user)
|
|
|
|
except UserSolution.DoesNotExist:
|
|
# TODO Should direct visitors get a special treatment?
|
|
pass
|
|
|
|
|
|
print(user_solution, file=sys.stderr)
|
|
|
|
|
|
result = request
|
|
print(result, file=sys.stderr)
|
|
print(dir(result), file=sys.stderr)
|
|
|
|
# determine next slide, as necessary for the navigation
|
|
next_slide = {'course': course, 'section': None, 'slide': None}
|
|
matched_slide = False
|
|
slides = section.slides.all()
|
|
for s in slides:
|
|
if matched_slide:
|
|
next_slide['slide'] = s
|
|
next_slide['section'] = section
|
|
break;
|
|
|
|
if slide.id == s.id:
|
|
matched_slide = True
|
|
|
|
# looks like the slide was the last for this section find next section
|
|
if next_slide['slide'] == None:
|
|
matched_section = False
|
|
sections = course.sections.all()
|
|
for sec in sections:
|
|
if matched_section:
|
|
next_slide['slide'] = sec.slides.first()
|
|
next_slide['section'] = sec
|
|
break;
|
|
|
|
if section.id == sec.id:
|
|
matched_section = True
|
|
|
|
try:
|
|
slide_data = json.loads(slide.data)
|
|
except:
|
|
slide_data = "Exception!"
|
|
|
|
|
|
try:
|
|
user_solution_data = json.loads(user_solution.data)
|
|
except:
|
|
user_solution_data = "Exception!"
|
|
|
|
|
|
|
|
|
|
data = {'course': course, 'section': section, 'slide': slide, 'next_slide': next_slide, 'slide_data': slide_data, 'user_solution_data': user_solution_data}
|
|
# return render(request, 'courses/course.html', data)
|
|
|
|
try:
|
|
template_path = 'generated_exercises/%s/template.html' % (slide.slide_type)
|
|
print(template_path, file=sys.stderr)
|
|
template.loader.get_template(template_path)
|
|
return render(request, template_path, data)
|
|
except template.TemplateDoesNotExist:
|
|
return render(request, 'courses/course.html', data)
|