diff options
author | Prabhu Ramachandran | 2011-11-08 15:40:08 +0530 |
---|---|---|
committer | Prabhu Ramachandran | 2011-11-08 15:40:08 +0530 |
commit | 4694d217dd7d5659afdad7ba5937adb85c15371c (patch) | |
tree | 2dd78e791414abb6dbd6cf597892942dee0fce8f | |
parent | bed96635b1b0aac8548b6df85e96ee256e5e5bcb (diff) | |
download | online_test-4694d217dd7d5659afdad7ba5937adb85c15371c.tar.gz online_test-4694d217dd7d5659afdad7ba5937adb85c15371c.tar.bz2 online_test-4694d217dd7d5659afdad7ba5937adb85c15371c.zip |
ENH: Command to load questions from XML file.
Added manage command to load questions from XML file. Updated README
and including a simple set of sample questions for testing.
-rw-r--r-- | README.txt | 47 | ||||
-rw-r--r-- | exam/management/__init__.py | 0 | ||||
-rw-r--r-- | exam/management/commands/__init__.py | 0 | ||||
-rw-r--r-- | exam/management/commands/load_questions.py | 64 | ||||
-rw-r--r-- | sample_questions.xml | 37 |
5 files changed, 127 insertions, 21 deletions
@@ -4,12 +4,31 @@ Installation To install/deploy this app follow the steps below: 1. Clone this repository. + 2. cd to the cloned repo. - 3. Run $ python manage.py syncdb - [ enter password etc.] - 4. Run $ python manage.py runserver <desired_ip>:<desired_port> - 5. Go to http://server_ip:server_port/admin - 6. Login with your credentials and add questions to the database. + + 3. Run:: + + $ python manage.py syncdb + [ enter password etc.] + + 4. Add questions by editing the sample_questions.xml or any other xml + file in the same format and then run the following:: + + $ python manage.py load_questions sample_questions.xml + + Note that you can supply multiple xml files as arguments and all of + those will be added to the database. + + 5. Now, run:: + + $ python manage.py runserver <desired_ip>:<desired_port> + + 6. Go to http://server_ip:server_port/admin + + 7. Login with your credentials and look at the questions and modify if + needed. + 7. Now ask users to login at: http://server_ip:server_port/exam @@ -19,20 +38,6 @@ To install/deploy this app follow the steps below: WARNING: django is running in debug mode for this currently, CHANGE it during deployment -A sample question -================== - -Here is an example of a good question and tests for it. On the admin -interface after you login, add a new question with the following fields: - - Summary: Fibonnaci - - Question: Write function called "fib" which takes a single integer - argument (say "n") and returns a list of the first "n" fibonacci - numbers. For example fib(3) -> [1, 1, 2]. - - Points: 1 +The file sample_questions.xml is a template that you can use for your +own questions. - Test: - assert fib(3) == [1, 1, 2] - assert fib(6) == [1, 1, 2, 3, 5, 8] diff --git a/exam/management/__init__.py b/exam/management/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/exam/management/__init__.py diff --git a/exam/management/commands/__init__.py b/exam/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/exam/management/commands/__init__.py diff --git a/exam/management/commands/load_questions.py b/exam/management/commands/load_questions.py new file mode 100644 index 0000000..336ed92 --- /dev/null +++ b/exam/management/commands/load_questions.py @@ -0,0 +1,64 @@ +# System library imports. +from os.path import basename +from xml.dom.minidom import parse +from htmlentitydefs import name2codepoint +import re + +# Django imports. +from django.core.management.base import BaseCommand + +# Local imports. +from exam.models import Question + +def decode_html(html_str): + """Un-escape or decode HTML strings to more usable Python strings. + From here: http://wiki.python.org/moin/EscapingHtml + """ + return re.sub('&(%s);' % '|'.join(name2codepoint), + lambda m: unichr(name2codepoint[m.group(1)]), html_str) + +def clear_questions(): + """Delete all questions from the database.""" + for question in Question.objects.all(): + question.delete() + +def load_questions(filename): + """Load questions from the given XML file.""" + q_bank = parse(filename).getElementsByTagName("question") + + for question in q_bank: + + summary_node = question.getElementsByTagName("summary")[0] + summary = (summary_node.childNodes[0].data).strip() + + desc_node = question.getElementsByTagName("description")[0] + description = (desc_node.childNodes[0].data).strip() + + points_node = question.getElementsByTagName("points")[0] + points = int((points_node.childNodes[0].data).strip()) \ + if points_node else 1 + + test_node = question.getElementsByTagName("test")[0] + test = decode_html((test_node.childNodes[0].data).strip()) + + new_question = Question(summary=summary, + description=description, + points=points, + test=test) + new_question.save() + +class Command(BaseCommand): + args = '<q_file1.xml q_file2.xml>' + help = 'loads the questions from given XML files' + + def handle(self, *args, **options): + """Handle the command.""" + # Delete existing stuff. + clear_questions() + + # Load from files. + for fname in args: + self.stdout.write('Importing from {0} ... '.format(basename(fname))) + load_questions(fname) + self.stdout.write('Done\n') + diff --git a/sample_questions.xml b/sample_questions.xml new file mode 100644 index 0000000..104ea32 --- /dev/null +++ b/sample_questions.xml @@ -0,0 +1,37 @@ +<question_bank> + +<question> +<summary> +Factorial +</summary> +<description> +Write a function called "fact" which takes a single integer argument (say "n") +and returns the factorial of the number. +For example fact(3) -> 6 +</description> +<points>2</points> +<test> +assert fact(0) == 1 +assert fact(5) == 120 +</test> +</question> + +<question> +<summary> +Simple function +</summary> +<description> +Create a simple function called "sqr" which takes a single argument and +returns the square of the argument +For example sqr(3) -> 9. +</description> +<points>1</points> +<test> +import math +assert sqr(3) == 9 +assert abs(sqr(math.sqrt(2)) - 2.0) < 1e-14 +</test> +</question> + + +</question_bank> |