vault backup: 2025-12-26 02:09:22
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
This commit is contained in:
2
stroma/quiz/management/__init__.py
Normal file
2
stroma/quiz/management/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# Management commands directory
|
||||
|
||||
2
stroma/quiz/management/commands/__init__.py
Normal file
2
stroma/quiz/management/commands/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# Management commands
|
||||
|
||||
46
stroma/quiz/management/commands/import_questions.py
Normal file
46
stroma/quiz/management/commands/import_questions.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from quiz.utils.importer import import_questions
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Import questions from Markdown files'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--folder',
|
||||
type=str,
|
||||
default='content/Anatomi & Histologi 2/Gamla tentor',
|
||||
help='Folder to import questions from (relative to project root)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--force',
|
||||
action='store_true',
|
||||
help='Force import even if files have not changed'
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
import_folder = options['folder']
|
||||
folder = settings.BASE_DIR.parent / import_folder
|
||||
|
||||
if not folder.exists():
|
||||
self.stdout.write(self.style.ERROR(f'Import folder {folder} does not exist'))
|
||||
return
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f'Importing questions from {folder}...'))
|
||||
|
||||
stats = import_questions(folder, folder, force=options['force'])
|
||||
|
||||
# Only show full statistics if there were changes
|
||||
output = stats.format_output(show_if_no_changes=False)
|
||||
if output:
|
||||
self.stdout.write(output)
|
||||
if stats.errors > 0:
|
||||
self.stdout.write(self.style.WARNING(f'Completed with {stats.errors} errors'))
|
||||
else:
|
||||
self.stdout.write(self.style.SUCCESS('Import completed successfully!'))
|
||||
else:
|
||||
# No changes, show brief message
|
||||
self.stdout.write(self.style.SUCCESS(f'✓ All {stats.total_files} files up to date, no changes needed'))
|
||||
|
||||
|
||||
87
stroma/quiz/management/commands/populate_exams.py
Normal file
87
stroma/quiz/management/commands/populate_exams.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
Management command to populate Course and Exam models from existing questions.
|
||||
"""
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from quiz.models import Course, Exam, Question
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Populate Course and Exam models from existing question file paths'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# Create default course
|
||||
course, created = Course.objects.get_or_create(
|
||||
name="Anatomi & Histologi 2",
|
||||
defaults={'code': 'AH2', 'description': 'Anatomy and Histology course'}
|
||||
)
|
||||
|
||||
if created:
|
||||
self.stdout.write(self.style.SUCCESS(f'Created course: {course.name}'))
|
||||
else:
|
||||
self.stdout.write(f'Course exists: {course.name}')
|
||||
|
||||
# Analyze existing questions and create exams
|
||||
questions = Question.objects.all()
|
||||
exam_folders = {}
|
||||
|
||||
for question in questions:
|
||||
# Extract exam date from file path
|
||||
# Expected: content/Anatomi & Histologi 2/Gamla tentor/2022-01-15/1.md
|
||||
path_parts = Path(question.file_path).parts
|
||||
|
||||
if len(path_parts) >= 2:
|
||||
# Try to find a date-like folder
|
||||
for part in path_parts:
|
||||
if '-' in part and len(part) == 10: # Looks like YYYY-MM-DD
|
||||
try:
|
||||
exam_date = datetime.strptime(part, '%Y-%m-%d').date()
|
||||
folder_path = '/'.join(path_parts[:-1])
|
||||
|
||||
if part not in exam_folders:
|
||||
exam_folders[part] = {
|
||||
'date': exam_date,
|
||||
'folder': folder_path,
|
||||
'questions': []
|
||||
}
|
||||
exam_folders[part]['questions'].append(question)
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# Create exams and assign questions
|
||||
exams_created = 0
|
||||
questions_assigned = 0
|
||||
|
||||
for folder_name, data in sorted(exam_folders.items()):
|
||||
exam, created = Exam.objects.get_or_create(
|
||||
course=course,
|
||||
date=data['date'],
|
||||
defaults={
|
||||
'name': folder_name,
|
||||
'folder_path': data['folder']
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
exams_created += 1
|
||||
self.stdout.write(self.style.SUCCESS(f' Created exam: {exam.date}'))
|
||||
|
||||
# Assign questions to this exam
|
||||
for question in data['questions']:
|
||||
if question.exam != exam:
|
||||
question.exam = exam
|
||||
question.save(update_fields=['exam'])
|
||||
questions_assigned += 1
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
f'\nSummary:\n'
|
||||
f' Exams created: {exams_created}\n'
|
||||
f' Questions assigned: {questions_assigned}\n'
|
||||
f' Total exams: {Exam.objects.count()}\n'
|
||||
f' Questions with exams: {Question.objects.filter(exam__isnull=False).count()}\n'
|
||||
f' Questions without exams: {Question.objects.filter(exam__isnull=True).count()}'
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user