Add command to generate sample physics questions with customizable options

This commit is contained in:
Ross
2025-11-10 20:56:18 +00:00
parent eebbe8b759
commit 10739f517f
@@ -0,0 +1,129 @@
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from django.db import transaction
import random
from physics.models import Question, Category, Exam
User = get_user_model()
class Command(BaseCommand):
help = "Generate a number of sample physics questions for development/testing."
def add_arguments(self, parser):
parser.add_argument(
"--count",
type=int,
default=10,
help="Number of sample questions to create (default: 10)",
)
parser.add_argument(
"--category",
type=str,
default=None,
help="Category name to assign to created questions (created if missing)",
)
parser.add_argument(
"--author",
type=str,
default=None,
help="Username of an existing user to add as author for created questions",
)
parser.add_argument(
"--seed",
type=int,
default=None,
help="Optional random seed for reproducible generation",
)
parser.add_argument(
"--create-exam",
dest="create_exam",
type=str,
default=None,
help="If provided, create an exam with this name and add generated questions to it",
)
parser.add_argument(
"--activate",
action="store_true",
dest="activate",
help="If set when creating an exam, mark the exam active",
)
def handle(self, *args, **options):
count = options.get("count") or 10
category_name = options.get("category")
author_username = options.get("author")
seed = options.get("seed")
if seed is not None:
random.seed(seed)
category = None
if category_name:
category, _ = Category.objects.get_or_create(category=category_name)
created_exam = None
create_exam_name = options.get("create_exam")
activate = options.get("activate")
if create_exam_name:
created_exam = Exam.objects.create(name=create_exam_name, active=bool(activate))
author_user = None
if author_username:
try:
author_user = User.objects.get(username=author_username)
except User.DoesNotExist:
self.stdout.write(self.style.WARNING(f"Author username '{author_username}' not found; continuing without author"))
author_user = None
created = 0
with transaction.atomic():
for i in range(count):
qnum = Question.objects.count() + 1
stem = f"Sample physics question #{qnum}: Identify which of the following statements are true."
# simple option texts
opts = [
f"Statement A for question {qnum}",
f"Statement B for question {qnum}",
f"Statement C for question {qnum}",
f"Statement D for question {qnum}",
f"Statement E for question {qnum}",
]
# randomly decide true/false for each option but ensure at least one True
answers = [random.choice([True, False]) for _ in range(5)]
if not any(answers):
answers[random.randrange(5)] = True
q = Question.objects.create(
stem=stem,
a=opts[0],
a_answer=answers[0],
a_feedback="",
b=opts[1],
b_answer=answers[1],
b_feedback="",
c=opts[2],
c_answer=answers[2],
c_feedback="",
d=opts[3],
d_answer=answers[3],
d_feedback="",
e=opts[4],
e_answer=answers[4],
e_feedback="",
category=category,
)
# If we created an exam, add this question to it
if created_exam:
created_exam.exam_questions.add(q)
if author_user:
q.author.add(author_user)
created += 1
self.stdout.write(self.style.SUCCESS(f"Created {created} sample physics question(s)."))