The aim of my website is to have a page, let's call it "Random Question!"
Each time the user enters the page, a set of numbers are randomly generated, and they have to correctly answer the question: numbera + number b .
IF they are correct, they go to a page that says "Correct" and then they are redirected back to the same page, again, with a different set of numbers.
Now, the issue is, on the first page "Random Question!", I want to add another question to it.
Views.py:
def form_handle(request):
if request.method == 'POST':
form = MyForm(request.POST) # if post method then form will be validated
if form.is_valid():
cd = form.cleaned_data
num1 = cd.get('num1')
a = request.session.get('a', 0)
b = request.session.get('b', 0)
if float(num1) == float(a + b):
# give HttpResponse only or render page you need to load on success
return render(request, 'sectipn1part1success', {})
else:
# if sum not equal... then redirect to custom url/page
return HttpResponseRedirect('rr/') # mention redirect url in argument
else:
a = random.randrange(5,10);
b = random.randrange(10,20);
request.session['a'] = a
request.session['b'] = b
question1 = ('What is ' + str(a) + ' + ' + str(b) + ' ?')
form = MyForm() # blank form object just to pass context if not post method
context = {
'form': form,
'a': a,
'b': b,
'question1': question1
}
return render(request, "section1part1.html", context)
As you can see, right now it only does one simple style of question, addition only (question 1).
I would like to add another question, such as question 2, which could be something like "What is a / 2".
Something like the above would be achieved using something like a Java SWITCH statement ( I am not sure if Django has it, though it should be possible to do it without it). A random number would be generated corresponding to another question. Then I'd have to use another IF statement after if request.method == 'POST' to calculate the correct answer as each new question would be calculated differently.
Now, the above would be a good strategy in the short term.
In the long term, I am not sure if it is ideal. Is there a better way of doing this sort of thing or is my way ok?
I was thinking of other ways including:
** Are there any performance considerations I should be aware of ? **
Update #1
Ok, I've gone ahead and implemented what I suggested above. This is what happens:
Django view gets called --> Another view function is randomly called and does the processing and returns a context object
else: #add another 'if' randomiser to selection question function randomly
context = question1(request)
context = question2(request)
return render(request, "section1part1.html", context)
Is this good practice / style? Should I just continue doing it this way?
form_handle
should only be responsible for handling forms. All the work of creating questions and answers should be done by something else. Once you do that, it's easy to to switch out question types, or generate endless loops of questions, or create a list of questions to loop through, or ...
Here's an example with a Question
class. You could just as easily create functions that return a tuple of (question, answer)
or any other variety of question/answer generators.
class Question(object):
def answer(self):
raise NotImplementedError
def question(self):
raise NotImplementedError
class AdditionQuestion(Question):
def __init__(self):
a_range = (5, 10)
b_range = (10, 20)
self.a = random.randrange(*a_range)
self.b = random.randrange(*b_range)
def answer(self):
return self.a + self.b
def question(self):
return 'What is {} + {}?'.format(self.a, self.b)
class MultiplicationQuestion(Question):
def __init__(self):
a_range = (100, 200)
b_range = (10, 20)
self.a = random.randrange(*a_range)
self.b = random.randrange(*b_range)
def answer(self):
return self.a * self.b
def question(self):
return 'What is {} * {}?'.format(self.a, self.b)
then, your code only relies on an object that has object.question()
and object.answer()
. If you want non-numeric answers, or answers that are close enough (ex: 3.3333 is close enough to 3.333333) you can change if float(num1) == float(answer):
to if compare_answers(num1, answer):
and then write a compare_answers
function.
def form_handle(request):
if request.method == 'POST':
form = MyForm(request.POST) # if post method then form will be validated
if form.is_valid():
cd = form.cleaned_data
num1 = cd.get('num1')
answer = request.session.get('answer', 0)
if float(num1) == float(answer):
# give HttpResponse only or render page you need to load on success
return render(request, 'sectipn1part1success', {})
else:
# if sum not equal... then redirect to custom url/page
return HttpResponseRedirect('rr/') # mention redirect url in argument
else:
question = AdditionQuestion()
answer = question.answer()
request.session['answer'] = answer
form = MyForm() # blank form object just to pass context if not post method
context = {
'form': form,
'answer': answer,
'question': question.question()
}
return render(request, "section1part1.html", context)
If you want a random question-type generator, also make that its own function/object. Keep it separated from the form_handle
so that it's easy to change:
def random_question():
class_ = random.choice([MultiplicationQuestion, AdditionQuestion])
return class_()
then change the line here from:
else:
question = AdditionQuestion()
to:
else:
question = random_question()