from django.shortcuts import render, get_object_or_404, redirect from django.db.models import Q from django.contrib.auth.decorators import login_required, user_passes_test from django.utils.html import strip_tags from .models import Assignment, Submission, Answer import json from .forms import AnswersForm, StudentRegistrationForm from django.contrib.auth import login def register(request): if request.user.is_authenticated: return redirect('lms:dashboard') if request.method == 'POST': form = StudentRegistrationForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.role = 'STUDENT' user.save() login(request, user) return redirect('lms:dashboard') else: form = StudentRegistrationForm() return render(request, 'lms/register.html', {'form': form}) def is_student(user): return user.is_authenticated and user.role == 'STUDENT' def home(request): if request.user.is_authenticated: if getattr(request.user, 'role', None) == 'STUDENT': return redirect('lms:dashboard') else: return redirect('/admin/') return render(request, 'lms/home.html') @login_required @user_passes_test(is_student, login_url='/login/') def dashboard(request): assignments = Assignment.objects.filter( Q(assign_to_all=True) | Q(assigned_students=request.user), is_published=True ).distinct().order_by('-created_at') # Check which ones the student has submitted submissions = Submission.objects.filter(student=request.user) submitted_assignment_ids = submissions.values_list('assignment_id', flat=True) from django.utils import timezone return render(request, 'lms/dashboard.html', { 'assignments': assignments, 'submitted_assignment_ids': submitted_assignment_ids, 'submissions': {sub.assignment_id: sub for sub in submissions}, 'now': timezone.now() }) @login_required @user_passes_test(is_student, login_url='/login/') def assignment_detail(request, pk): assignment = get_object_or_404(Assignment, pk=pk, is_published=True) questions = assignment.questions.all() # Try to get existing submission submission = Submission.objects.filter(assignment=assignment, student=request.user).first() from django.utils import timezone can_submit = True if assignment.is_closed: can_submit = False if assignment.deadline and timezone.now() > assignment.deadline: can_submit = False if submission: if request.method == 'POST': # Do not allow updating return redirect('lms:dashboard') form = None else: if not can_submit: form = None elif request.method == 'POST': form = AnswersForm(request.POST, request.FILES, questions=questions) if form.is_valid(): submission = Submission.objects.create(assignment=assignment, student=request.user) all_auto = True total_points = 0 max_points = 0 for q in questions: answer_obj = Answer(submission=submission, question=q) if q.question_type == 'TEXT_AUTO': val = form.cleaned_data.get(f'answer_{q.id}', '') answer_obj.text_answer = val if q.correct_answer: correct = strip_tags(q.correct_answer).strip().lower() answer_obj.is_correct = (val.strip().lower() == correct) answer_obj.points = 1 if answer_obj.is_correct else 0 total_points += answer_obj.points else: all_auto = False max_points += 1 elif q.question_type == 'TABLE_AUTO': rows = getattr(q, 'table_rows', 2) or 2 table_data = [] for i in range(1, rows + 1): val1 = form.cleaned_data.get(f'answer_{q.id}_r{i}_c1', '') val2 = form.cleaned_data.get(f'answer_{q.id}_r{i}_c2', '') table_data.append([val1, val2]) answer_obj.text_answer = json.dumps(table_data) if q.correct_answer: correct_rows = q.correct_answer.split(';') is_correct = True if len(correct_rows) != rows: is_correct = False else: for i, row in enumerate(correct_rows): cols = row.split('|') if len(cols) == 2: if cols[0].strip().lower() != table_data[i][0].strip().lower() or cols[1].strip().lower() != table_data[i][1].strip().lower(): is_correct = False break else: is_correct = False break answer_obj.is_correct = is_correct answer_obj.points = 1 if is_correct else 0 total_points += answer_obj.points else: all_auto = False max_points += 1 else: all_auto = False val = form.cleaned_data.get(f'file_{q.id}') if val: answer_obj.file_answer = val answer_obj.save() if all_auto and max_points > 0: submission.status = 'GRADED' submission.grade = f"{total_points}/{max_points}" else: submission.status = 'PENDING' submission.save() return redirect('lms:dashboard') else: form = AnswersForm(questions=questions) question_fields = [] if form: for q in questions: if q.question_type == 'TEXT_AUTO': question_fields.append((q, 'text', form[f'answer_{q.id}'])) elif q.question_type == 'TABLE_AUTO': rows = getattr(q, 'table_rows', 2) or 2 table_fields = [] for i in range(1, rows + 1): table_fields.append([form[f'answer_{q.id}_r{i}_c1'], form[f'answer_{q.id}_r{i}_c2']]) question_fields.append((q, 'table', table_fields)) else: question_fields.append((q, 'file', form[f'file_{q.id}'])) return render(request, 'lms/assignment_detail.html', { 'assignment': assignment, 'form': form, 'submission': submission, 'questions': questions, 'question_fields': question_fields, 'can_submit': can_submit, })