Edit:When you are creating a web app with html templates, then you will have to save the html file in templates folder in the Current Working Directory(CWD). If you save the file in the CWD directly you will get a TemplateNotFound error. Thank you Udhay for pointing it out.
In this post we will create a quiz website using python. I will be using the flask framework. After reading this tutorial you will learn form submission, flask templates, python code in flask templates, shuffling the questions and options with the random module and few others.
Please note that this tutorial is not big as it seems to be. Some of the code has been rewritten to maintain consistency and also font size is somewhat big so that your eyes won't get stressed reading this tutorial. Also the content has not occupied the full width of the page.
In this tutorial I am assuming that you are having a very basic understanding of the flask framework. Please refer the documentation if you don't. You can also create a similar kind of application using Bottle framework, a little bit of code might change.
Okay folks, the briefing is completed, fasten your seat belts and get ready for takeoff ;)
We will create a quiz related to the seven wonders of the world published by New7wonders. It is a multiple choice question type quiz, but we can modify it for fill-in-the-blanks type(After reading the tutorial you can do it for yourself) also.
In this post we will create a quiz website using python. I will be using the flask framework. After reading this tutorial you will learn form submission, flask templates, python code in flask templates, shuffling the questions and options with the random module and few others.
Please note that this tutorial is not big as it seems to be. Some of the code has been rewritten to maintain consistency and also font size is somewhat big so that your eyes won't get stressed reading this tutorial. Also the content has not occupied the full width of the page.
In this tutorial I am assuming that you are having a very basic understanding of the flask framework. Please refer the documentation if you don't. You can also create a similar kind of application using Bottle framework, a little bit of code might change.
Okay folks, the briefing is completed, fasten your seat belts and get ready for takeoff ;)
We will create a quiz related to the seven wonders of the world published by New7wonders. It is a multiple choice question type quiz, but we can modify it for fill-in-the-blanks type(After reading the tutorial you can do it for yourself) also.
First we will create some questions and corresponding options that we will be asking the user. Remember that in our code first option will always be the correct answer. But in our web app when the user is presented with the question, the options are shuffled.
Next we will write a function which will shuffle the questions and also the options(Even though dictionary is not an ordered sequence we will be shuffling it to make sure that each user is presented with different options): I am saving this program as quiz.py
When you run the above code in your command prompt or terminal(CLI) you will get output something similar to this:
Okay now lets see what actually happened?
Line 1: We have imported
Line2: The questions dictionary which we have created earlier.
Line 13: We have made a
Line 16-28: We are creating a function which will take the keys of the dictionary and shuffle them. We can also use
Line 31: We are calling our function which we created in line 16 with the parameter of the our new cloned dictionary
Line 34-40: Here we are iterating through our newly created dictionary and also the original dictionary to display the output. Even though we are not going to use this block of code directly in our further app we will be using a similar concept to publish our web app. So understanding this block of code is optional.
As we are done with the basic concept in creating the quiz shuffling we will now start concentrating on our web app.
Finally, As always I have tried to write this post in such a way that it is easy for everyone to understand. But If you didn't understand anything or have any doubt then please comment in the comment box below or contact me. I will respond to your question as soon as possible.
Also comment on how I can improve this post in such a way that it will be easy to understand even for the beginners. Please don't hesitate to comment if you want me to add a topic, or if I have missed any topic or made any typo.
Thank you, Have a nice day :)
How to clone or copy a list in python
Understanding dict.copy()? Shallow or deep?
Flask Documentation
Random module documentation
origianl_questions = { #Format is 'question':[options] 'Taj Mahal':['Agra','New Delhi','Mumbai','Chennai'], 'Great Wall of China':['China','Beijing','Shanghai','Tianjin'], 'Petra':['Ma\'an Governorate','Amman','Zarqa','Jerash'], 'Machu Picchu':['Cuzco Region','Lima','Piura','Tacna'], 'Egypt Pyramids':['Giza','Suez','Luxor','Tanta'], 'Colosseum':['Rome','Milan','Bari','Bologna'], 'Christ the Redeemer':['Rio de Janeiro','Natal','Olinda','Betim'] }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import random, copy original_questions = { #Format is 'question':[options] 'Taj Mahal':['Agra','New Delhi','Mumbai','Chennai'], 'Great Wall of China':['China','Beijing','Shanghai','Tianjin'], 'Petra':['Ma\'an Governorate','Amman','Zarqa','Jerash'], 'Machu Picchu':['Cuzco Region','Lima','Piura','Tacna'], 'Egypt Pyramids':['Giza','Suez','Luxor','Tanta'], 'Colosseum':['Rome','Milan','Bari','Bologna'], 'Christ the Redeemer':['Rio de Janeiro','Natal','Olinda','Betim'] } questions = copy.deepcopy(original_questions) def shuffle(q): """ This function is for shuffling the dictionary elements. """ selected_keys = [] i = 0 while i < len(q): current_selection = random.choice(q.keys()) if current_selection not in selected_keys: selected_keys.append(current_selection) i = i+1 return selected_keys questions_shuffled = shuffle(questions) for i in questions_shuffled: random.shuffle(questions[i]) print(''' Where is {} located? {} Correct Answer is: {} ''').format(i,questions[i],original_questions[i][0]) |
Where is Petra located? ["Ma'an Governorate", 'Zarqa', 'Jerash', 'Amman'] Correct Answer is: Ma'an Governorate Where is Machu Picchu located? ['Cuzco Region', 'Lima', 'Tacna', 'Piura'] Correct Answer is: Cuzco Region Where is Taj Mahal located? ['Mumbai', 'Agra', 'Chennai', 'New Delhi'] Correct Answer is: Agra Where is Colosseum located? ['Bari', 'Rome', 'Bologna', 'Milan'] Correct Answer is: Rome Where is Egypt Pyramids located? ['Luxor', 'Suez', 'Giza', 'Tanta'] Correct Answer is: Giza Where is Christ the Redeemer located? ['Olinda', 'Betim', 'Rio de Janeiro', 'Natal'] Correct Answer is: Rio de Janeiro Where is Great Wall of China located? ['Beijing', 'Tianjin', 'China', 'Shanghai'] Correct Answer is: China
Line 1: We have imported
random
, copy
Line2: The questions dictionary which we have created earlier.
Line 13: We have made a
deepcopy
of the original_questions
so that if we make any changes to the duplicated dictionary it won't affect the original dictionary. See this answer to understand more about cloning a list or dictionary in python. Jack answer for How to clone or copy a list in python. The person has written a very good answer and it is a must read for everyone who is a python freak.Line 16-28: We are creating a function which will take the keys of the dictionary and shuffle them. We can also use
random.shuffle
(questions.keys()
), but as we are here to learn something new, so I have created a function which will shuffle the keys. If you want to know more then see these: How to iterate through a dict in random order, how to get a random value in python dictionary.Line 31: We are calling our function which we created in line 16 with the parameter of the our new cloned dictionary
questions
, which will give the output of the keys which have been randomly shuffled.Line 34-40: Here we are iterating through our newly created dictionary and also the original dictionary to display the output. Even though we are not going to use this block of code directly in our further app we will be using a similar concept to publish our web app. So understanding this block of code is optional.
As we are done with the basic concept in creating the quiz shuffling we will now start concentrating on our web app.
Creating web app with flask
Lets first start the server. See how to start server from here: Flask - A minimal Application
from flask import Flask app = Flask(__name__) @app.route('/') def quiz(): return '<h1>Quiz Here</h1>' if __name__ == '__main__': app.run(debug=True)
Now we will extend the app by adding the questions dictionary, the functions which we created and few other things. See the code and try to understand it:
Don't start the server directly after you have typed the above code. You will have to create templates/main.html(i.e. you will have to create a folder named templates in which you will store the main.html file) which I will teach you after explaining the above code.
I am assuming that you are familiar with the code in the lines 1-32.
Line 34: I have used
Line 35: We are shuffling the questions and the result which is a list is stored in the variable
Line 36: We are starting a
Line 37: If you were given a list lets say
As you can see that the values are shuffled but when the function is called nothing is returned. We have used the same concept in our web application. The for loop will shuffle each and every list of the
Line 38: The above values are returned to the template which we will see in the next section.
templates/main.html
Line1-3: These are routine HTML tags. We are using
Line 4: In our python file we have passed
Line 5: Here
Line 6: As we know that
Line 7: We are creating a radio button.
Line 8-12: Pretty simple and I think doesn't need explanation :)
Now run the app(Start the server) and you will see something like this:
But If you will answer the questions and press submit then you will find "400 Not Found" Error, This is because we have not yet created the
We will create the
quiz.py
Line 1-38: This is familiar for you as we have discussed it earlier.
Line 41: After the user has submitted the form to
Line 45: We are using the
Line 46: We are accessing the value user selected using the
Line 47: If you remember at the starting of this post we used
Line 48-52: These are very easy to understand, I assume :)
templates/main.html doesn't have any change.
Note: If the user submits the form(options) without answering every question(s) he/she may get a bad request 400 page. Try to analyze the reason why it is happening so? Post what you think in the comment box below.
After submitting the form, depending on the number of correct answers given by the user, the web page will look something similar to this:
Note: I have written this tutorial keeping in mind that everyone should understand the code behind this easily. But if you want the web app to work more faster you will have to make more changes, so that it will serve more people more efficiently. If you have any code which is simple and effective then please don't hesitate to comment in the comment box below. 'Lets share our knowledge!'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | from flask import Flask, render_template import random, copy app = Flask(__name__) original_questions = { #Format is 'question':[options] 'Taj Mahal':['Agra','New Delhi','Mumbai','Chennai'], 'Great Wall of China':['China','Beijing','Shanghai','Tianjin'], 'Petra':['Ma\'an Governorate','Amman','Zarqa','Jerash'], 'Machu Picchu':['Cuzco Region','Lima','Piura','Tacna'], 'Egypt Pyramids':['Giza','Suez','Luxor','Tanta'], 'Colosseum':['Rome','Milan','Bari','Bologna'], 'Christ the Redeemer':['Rio de Janeiro','Natal','Olinda','Betim'] } questions = copy.deepcopy(original_questions) def shuffle(q): """ This function is for shuffling the dictionary elements. """ selected_keys = [] i = 0 while i < len(q): current_selection = random.choice(q.keys()) if current_selection not in selected_keys: selected_keys.append(current_selection) i = i+1 return selected_keys @app.route('/') def quiz(): questions_shuffled = shuffle(questions) for i in questions.keys(): random.shuffle(questions[i]) return render_template('main.html', q = questions_shuffled, o = questions) if __name__ == '__main__': app.run(debug=True) |
I am assuming that you are familiar with the code in the lines 1-32.
Line 34: I have used
@app.route()
to bind the URL to the function quiz
.Line 35: We are shuffling the questions and the result which is a list is stored in the variable
questions_shuffled
.Line 36: We are starting a
for
loop and looping through the keys of the questions
dictionary. Alternatively you can also loop through the variable questions_shuffled
.Line 37: If you were given a list lets say
l=['a','b','c','d']
. Now as we know that unlike dictionary which is an unordered sequence, list is ordered. So if you want to shuffle the list randomly we will use random.shuffle(l)
which doesn't return anything but all the value of the list are shuffled. For example on my computer, >>> import random >>> l = ['a','b','c','d'] >>> random.shuffle(l) #Noting is returned but values are shuffled >>> l ['a', 'c', 'd', 'b'] >>>
questions
dictionary.Line 38: The above values are returned to the template which we will see in the next section.
templates/main.html
1 2 3 4 5 6 7 8 9 10 11 12 | <h1>7 Wonders of the World</h1> <form action='/quiz' method='POST'> <ol> {% for i in q %} <li>Where is <u>{{i}}</u> located?</li> {% for j in o[i] %} <input type='radio' value='{{j}}' name='{{i}}' />{{j}} {% endfor %} {% endfor %} </ol> <input type="submit" value="submit" /> </form> |
POST
method and the action attribute points to '/quiz'
the URL which we will have to create.Line 4: In our python file we have passed
q
and o
as keyword parameters to the template templates/main.html. As we know that the value of q=questions_shuffled
, which is a list, we are looping through the list to get the elements of the list.Line 5: Here
{{i}}
is replaced by the list element which we get from the for
loop.Line 6: As we know that
o=questions
, which is a dictionary, we are looping through o[i]
where i
is the key of the dictionary and thus the output will be a list.Line 7: We are creating a radio button.
Line 8-12: Pretty simple and I think doesn't need explanation :)
Now run the app(Start the server) and you will see something like this:
Quiz App made with Flask framework and python- Frontend |
/quiz
page. We will create the
/quiz
page and this is the final step. So I will post the whole code for quiz.py. Please don't get annoyed ;)quiz.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | from flask import Flask, render_template, request import random, copy app = Flask(__name__) original_questions = { #Format is 'question':[options] 'Taj Mahal':['Agra','New Delhi','Mumbai','Chennai'], 'Great Wall of China':['China','Beijing','Shanghai','Tianjin'], 'Petra':['Ma\'an Governorate','Amman','Zarqa','Jerash'], 'Machu Picchu':['Cuzco Region','Lima','Piura','Tacna'], 'Egypt Pyramids':['Giza','Suez','Luxor','Tanta'], 'Colosseum':['Rome','Milan','Bari','Bologna'], 'Christ the Redeemer':['Rio de Janeiro','Natal','Olinda','Betim'] } questions = copy.deepcopy(original_questions) def shuffle(q): """ This function is for shuffling the dictionary elements. """ selected_keys = [] i = 0 while i < len(q): current_selection = random.choice(q.keys()) if current_selection not in selected_keys: selected_keys.append(current_selection) i = i+1 return selected_keys @app.route('/') def quiz(): questions_shuffled = shuffle(questions) for i in questions.keys(): random.shuffle(questions[i]) return render_template('main.html', q = questions_shuffled, o = questions) @app.route('/quiz', methods=['POST']) def quiz_answers(): correct = 0 for i in questions.keys(): answered = request.form[i] if original_questions[i][0] == answered: correct = correct+1 return '<h1>Correct Answers: <u>'+str(correct)+'</u></h1>' if __name__ == '__main__': app.run(debug=True) |
Line 41: After the user has submitted the form to
/quiz
with the POST
method the function quiz_answers
is called.Line 45: We are using the
for
loop to loop through the keys of the questions
dictionary. Line 46: We are accessing the value user selected using the
request
which we have imported from flask
.Line 47: If you remember at the starting of this post we used
questions = copy.deepcopy(original_questions)
. To be simple we are telling python I am making a deepcopy
because if I make any changes to the questions
dictionary don't apply the changes to original_questions
dictionary. Let it be the same as I have defined until I will ask you to change anything for original_questions
. And so even if I have made a lot of assignments and computations on questions
dictionary the value of the original_questions
doesn't change. As we know that the correct answer is the first element in the list of the dictionary we are checking the same.Line 48-52: These are very easy to understand, I assume :)
templates/main.html doesn't have any change.
Note: If the user submits the form(options) without answering every question(s) he/she may get a bad request 400 page. Try to analyze the reason why it is happening so? Post what you think in the comment box below.
After submitting the form, depending on the number of correct answers given by the user, the web page will look something similar to this:
Submitting the form with python flask output |
Finally, As always I have tried to write this post in such a way that it is easy for everyone to understand. But If you didn't understand anything or have any doubt then please comment in the comment box below or contact me. I will respond to your question as soon as possible.
Also comment on how I can improve this post in such a way that it will be easy to understand even for the beginners. Please don't hesitate to comment if you want me to add a topic, or if I have missed any topic or made any typo.
Thank you, Have a nice day :)
References:
How to clone or copy a list in python
Understanding dict.copy()? Shallow or deep?
Flask Documentation
Random module documentation