diff options
Diffstat (limited to 'testapp/exam')
-rw-r--r-- | testapp/exam/forms.py | 23 | ||||
-rw-r--r-- | testapp/exam/models.py | 140 | ||||
-rw-r--r-- | testapp/exam/tests.py | 222 | ||||
-rw-r--r-- | testapp/exam/views.py | 56 |
4 files changed, 342 insertions, 99 deletions
diff --git a/testapp/exam/forms.py b/testapp/exam/forms.py index dc19783..e82ce3a 100644 --- a/testapp/exam/forms.py +++ b/testapp/exam/forms.py @@ -12,7 +12,8 @@ from taggit_autocomplete_modified import settings from string import letters, punctuation, digits import datetime -QUESTION_TYPE_CHOICES = ( +QUESTION_LANGUAGE_CHOICES = ( + ("select", "Select"), ("python", "Python"), ("bash", "Bash"), ("mcq", "MCQ"), @@ -20,7 +21,13 @@ QUESTION_TYPE_CHOICES = ( ("C++", "C++ Language"), ("java", "Java Language"), ("scilab", "Scilab"), - ) + ) + +QUESTION_TYPE_CHOICES = ( + ("select", "Select"), + ("mcq", "Multiple Choice"), + ("code", "Code"), + ) UNAME_CHARS = letters + "._" + digits PWD_CHARS = letters + punctuation + digits @@ -51,8 +58,8 @@ class UserRegisterForm(forms.Form): def clean_username(self): u_name = self.cleaned_data["username"] if u_name.strip(UNAME_CHARS): - msg = "Only letters, digits, period and underscore characters are "\ - "allowed in username" + msg = "Only letters, digits, period and underscore characters are"\ + " allowed in username" raise forms.ValidationError(msg) try: User.objects.get(username__exact=u_name) @@ -96,6 +103,7 @@ class UserRegisterForm(forms.Form): return u_name, pwd + class UserLoginForm(forms.Form): """Creates a form which will allow the user to log into the system.""" @@ -115,6 +123,7 @@ class UserLoginForm(forms.Form): raise forms.ValidationError("Invalid username/password") return user + class QuizForm(forms.Form): """Creates a form to add or edit a Quiz. It has the related fields and functions required.""" @@ -122,7 +131,6 @@ class QuizForm(forms.Form): start_date = forms.DateField(initial=datetime.date.today) duration = forms.IntegerField() active = forms.BooleanField(required=False) - tags = TagField(widget=TagAutocomplete()) description = forms.CharField(max_length=256, widget=forms.Textarea\ (attrs={'cols': 20, 'rows': 1})) @@ -139,6 +147,7 @@ class QuizForm(forms.Form): new_quiz.description = description new_quiz.save() + class QuestionForm(forms.Form): """Creates a form to add or edit a Question. It has the related fields and functions required.""" @@ -152,6 +161,8 @@ class QuestionForm(forms.Form): (attrs={'cols': 40, 'rows': 1})) options = forms.CharField(widget=forms.Textarea\ (attrs={'cols': 40, 'rows': 1}), required=False) + language = forms.CharField(max_length=20, widget=forms.Select\ + (choices=QUESTION_LANGUAGE_CHOICES)) type = forms.CharField(max_length=8, widget=forms.Select\ (choices=QUESTION_TYPE_CHOICES)) active = forms.BooleanField(required=False) @@ -165,6 +176,7 @@ class QuestionForm(forms.Form): points = self.cleaned_data['points'] test = self.cleaned_data["test"] options = self.cleaned_data['options'] + language = self.cleaned_data['language'] type = self.cleaned_data["type"] active = self.cleaned_data["active"] snippet = self.cleaned_data["snippet"] @@ -175,6 +187,7 @@ class QuestionForm(forms.Form): new_question.points = points new_question.test = test new_question.options = options + new_question.language = language new_question.type = type new_question.active = active new_question.snippet = snippet diff --git a/testapp/exam/models.py b/testapp/exam/models.py index 758091f..ca53b2c 100644 --- a/testapp/exam/models.py +++ b/testapp/exam/models.py @@ -1,12 +1,12 @@ import datetime +from random import sample from django.db import models from django.contrib.auth.models import User from taggit_autocomplete_modified.managers import TaggableManagerAutocomplete\ as TaggableManager -from django.http import HttpResponse -################################################################################ +############################################################################### class Profile(models.Model): """Profile for a user to store roll number and other details.""" user = models.OneToOneField(User) @@ -16,25 +16,30 @@ class Profile(models.Model): position = models.CharField(max_length=64) -QUESTION_TYPE_CHOICES = ( +QUESTION_LANGUAGE_CHOICES = ( ("python", "Python"), ("bash", "Bash"), - ("mcq", "MultipleChoice"), ("C", "C Language"), ("C++", "C++ Language"), ("java", "Java Language"), ("scilab", "Scilab"), + ) + + +QUESTION_TYPE_CHOICES = ( + ("mcq", "Multiple Choice"), + ("code", "Code"), ) -################################################################################ +############################################################################### class Question(models.Model): - """A question in the database.""" + """A question details in the database.""" # A one-line summary of the question. summary = models.CharField(max_length=256) - # The question text, should be valid HTML. + # The question text, should be a valid HTML. description = models.TextField() # Number of points for the question. @@ -43,31 +48,35 @@ class Question(models.Model): # Test cases for the question in the form of code that is run. test = models.TextField(blank=True) - # Any multiple choice options. Place one option per line. + # Any multiple choice options. Place one option per line. options = models.TextField(blank=True) + # The language for question. + language = models.CharField(max_length=24, + choices=QUESTION_LANGUAGE_CHOICES) + # The type of question. type = models.CharField(max_length=24, choices=QUESTION_TYPE_CHOICES) - # Is this question active or not. If it is inactive it will not be used + # Is this question active or not. If it is inactive it will not be used # when creating a QuestionPaper. active = models.BooleanField(default=True) - #Code Snippet + # Code Snippet snippet = models.CharField(max_length=256) - #Tags for the Question. + # Tags for the Question. tags = TaggableManager() def __unicode__(self): return self.summary -################################################################################ +############################################################################### class Answer(models.Model): - """Answers submitted by users. - """ - # The question for which we are an answer. + """Answers submitted by the users.""" + + # The question for which user answers. question = models.ForeignKey(Question) # The answer submitted by the user. @@ -76,7 +85,7 @@ class Answer(models.Model): # Error message when auto-checking the answer. error = models.TextField() - # Marks obtained for the answer. This can be changed by the teacher if the + # Marks obtained for the answer. This can be changed by the teacher if the # grading is manual. marks = models.FloatField(default=0.0) @@ -87,44 +96,103 @@ class Answer(models.Model): return self.answer -################################################################################ +############################################################################### class Quiz(models.Model): """A quiz that students will participate in. One can think of this as the "examination" event. """ - # The starting/ending date of the quiz. + # The start date of the quiz. start_date = models.DateField("Date of the quiz") # This is always in minutes. duration = models.IntegerField("Duration of quiz in minutes", default=20) - # Is the quiz active. The admin should deactivate the quiz once it is + # Is the quiz active. The admin should deactivate the quiz once it is # complete. active = models.BooleanField(default=True) # Description of quiz. description = models.CharField(max_length=256) - #Tags for the Quiz. - tags = TaggableManager() - class Meta: verbose_name_plural = "Quizzes" def __unicode__(self): desc = self.description or 'Quiz' - return '%s: on %s for %d minutes' % (desc, self.start_date, self.duration) + return '%s: on %s for %d minutes' % (desc, self.start_date, + self.duration) -################################################################################ +############################################################################### class QuestionPaper(models.Model): + """Question paper stores the detail of the questions.""" + + # Question paper belongs to a particular quiz. quiz = models.ForeignKey(Quiz) - questions = models.ManyToManyField(Question) + + # Questions that will be mandatory in the quiz. + fixed_questions = models.ManyToManyField(Question) + + # Questions that will be fetched randomly from the Question Set. + random_questions = models.ManyToManyField("QuestionSet") + + # Total marks for the question paper. total_marks = models.FloatField() + def get_total_marks(self): + """ Returns the total marks for the Question Paper""" + marks = 0.0 + questions = self.fixed_questions.all() + for question in questions: + marks += question.points + for question_set in self.random_questions.all(): + marks += question_set.marks * question_set.num_questions + return marks + + def _get_questions_for_answerpaper(self): + """ Returns fixed and random questions for the answer paper""" + questions = [] + questions = list(self.fixed_questions.all()) + for question_set in self.random_questions.all(): + questions += question_set.get_random_questions() + return questions + + def make_answerpaper(self, user, profile, ip): + """Creates an answer paper for the user to attempt the quiz""" + ans_paper = AnswerPaper(user=user, profile=profile, user_ip=ip) + ans_paper.start_time = datetime.datetime.now() + ans_paper.end_time = ans_paper.start_time \ + + datetime.timedelta(minutes=self.quiz.duration) + ans_paper.question_paper = self + questions = self._get_questions_for_answerpaper() + question_ids = [str(_.id) for _ in questions] + ans_paper.questions = "|".join(question_ids) + ans_paper.save() + return ans_paper + + +############################################################################### +class QuestionSet(models.Model): + """Question set contains set of questions from which random questions + will be selected for the quiz. + """ + + # Marks of each question of a particular Question Set + marks = models.FloatField() + + # Number of questions to be fetched for the quiz. + num_questions = models.IntegerField() + + # Set of questions for sampling randomly. + questions = models.ManyToManyField(Question) + + def get_random_questions(self): + """ Returns random questions from set of questions""" + return sample(self.questions.all(), self.num_questions) -################################################################################ + +############################################################################### class AnswerPaper(models.Model): """A answer paper for a student -- one per student typically. """ @@ -135,7 +203,8 @@ class AnswerPaper(models.Model): # data. profile = models.ForeignKey(Profile) - # All questions that remains to attempt to perticular Student + # All questions that are left to attempt for a particular Student + # (a list of ids separated by '|') questions = models.CharField(max_length=128) # The Quiz to which this question paper is attached to. @@ -176,8 +245,10 @@ class AnswerPaper(models.Model): return qs.count('|') + 1 def completed_question(self, question_id): - """Removes the question from the list of questions and returns -the next.""" + """ + Removes the completed question from the list of questions and + returns the next question. + """ qa = self.questions_answered if len(qa) > 0: self.questions_answered = '|'.join([qa, str(question_id)]) @@ -193,7 +264,9 @@ the next.""" return qs[0] def skip(self): - """Skip the current question and return the next available question.""" + """ + Skips the current question and returns the next available question. + """ qs = self.questions.split('|') if len(qs) == 0: return '' @@ -223,13 +296,14 @@ the next.""" answered = ', '.join(sorted(qa)) return answered if answered else 'None' - def get_total_marks(self): + def get_marks_obtained(self): """Returns the total marks earned by student for this paper.""" return sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) def get_question_answers(self): - """Return a dictionary with keys as questions and a list of the corresponding - answers. + """ + Return a dictionary with keys as questions and a list of the + corresponding answers. """ q_a = {} for answer in self.answers.all(): diff --git a/testapp/exam/tests.py b/testapp/exam/tests.py index 501deb7..ac63301 100644 --- a/testapp/exam/tests.py +++ b/testapp/exam/tests.py @@ -1,16 +1,214 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". +from django.utils import unittest +from exam.models import User, Profile, Question, Quiz, QuestionPaper,\ +QuestionSet, AnswerPaper -Replace this with more appropriate tests for your application. -""" -from django.test import TestCase +class ModelsTestCase(unittest.TestCase): + @classmethod + def setUpClass(self): + """ Initial fixtures for testing environment""" -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) + # create user profile + self.user = User.objects.create_user(username='demo_user', + password='demo', + email='demo@test.com') + self.profile = Profile.objects.create(user=self.user, roll_number=1, + institute='IIT', + department='Chemical', + position='Student') + + # create 20 questions + for i in range(1, 21): + Question.objects.create(summary='Q%d' % (i)) + + # All active questions + self.questions = Question.objects.filter(active=True) + + # Single question details + self.question = self.questions[0] + self.question.summary = 'Demo question' + self.question.language = 'Python' + self.question.type = 'Code' + self.question.options = None + self.question.description = 'Write a function' + self.question.points = 1.0 + self.question.active = True + self.question.test = 'Test Cases' + self.question.snippet = 'def myfunc()' + self.question.tags.add('python', 'function') + + # create a quiz + self.quiz = Quiz.objects.create(start_date='2014-06-16', + duration=30, active=False, + description='demo quiz') + + # create question paper + self.quest_paper = QuestionPaper.objects.create(quiz=self.quiz, + total_marks=0.0) + + # add fixed set of questions to the question paper + self.quest_paper.fixed_questions.add(self.questions[3], + self.questions[5]) + + # create two QuestionSet for random questions + # QuestionSet 1 + self.quest_set_1 = QuestionSet.objects.create(marks=2, num_questions=2) + + # add pool of questions for random sampling + self.quest_set_1.questions.add(self.questions[6], self.questions[7], + self.questions[8], self.questions[9]) + + # add question set 1 to random questions in Question Paper + self.quest_paper.random_questions.add(self.quest_set_1) + + # QuestionSet 2 + self.quest_set_2 = QuestionSet.objects.create(marks=3, num_questions=3) + + # add pool of questions + self.quest_set_2.questions.add(self.questions[11], self.questions[12], + self.questions[13], self.questions[14]) + + # add question set 2 + self.quest_paper.random_questions.add(self.quest_set_2) + + # ip address for AnswerPaper + self.ip = '127.0.0.1' + + # create answerpaper + self.answerpaper = AnswerPaper(user=self.user, profile=self.profile, + questions='1|2|3', + question_paper=self.quest_paper, + start_time='2014-06-13 12:20:19.791297', + end_time='2014-06-13 12:50:19.791297', + user_ip=self.ip) + +############################################################################### + def test_user_profile(self): + """ Test user profile""" + self.assertIs(type(self.profile), type(Profile())) + self.assertEqual(self.user.username, 'demo_user') + self.assertEqual(self.profile.user.username, 'demo_user') + self.assertEqual(self.profile.roll_number, 1) + self.assertEqual(self.profile.institute, 'IIT') + self.assertEqual(self.profile.department, 'Chemical') + self.assertEqual(self.profile.position, 'Student') + + def test_question(self): + """ Test question """ + self.assertIs(type(self.question), type(Question())) + self.assertEqual(self.question.summary, 'Demo question') + self.assertEqual(self.question.language, 'Python') + self.assertEqual(self.question.type, 'Code') + self.assertTrue(self.question.options is None) + self.assertEqual(self.question.description, 'Write a function') + self.assertEqual(self.question.points, 1.0) + self.assertTrue(self.question.active) + self.assertEqual(self.question.test, 'Test Cases') + self.assertEqual(self.question.snippet, 'def myfunc()') + tag_list = [] + for tag in self.question.tags.all(): + tag_list.append(tag.name) + self.assertEqual(tag_list, ['python', 'function']) + self.assertEqual(len(self.questions), 20) + + def test_quiz(self): + """ Test Quiz""" + self.assertIs(type(self.quiz), type(Quiz())) + self.assertEqual(self.quiz.start_date, '2014-06-16') + self.assertEqual(self.quiz.duration, 30) + self.assertTrue(self.quiz.active is False) + self.assertEqual(self.quiz.description, 'demo quiz') + + def test_questionpaper(self): + """ Test question paper""" + self.assertIs(type(self.quest_paper), type(QuestionPaper())) + self.assertEqual(self.quest_paper.quiz.description, 'demo quiz') + self.assertEqual(list(self.quest_paper.fixed_questions.all()), + [self.questions[3], self.questions[5]]) + + def test_get_random_questions(self): + """ Test get_random_questions() method of Question Paper """ + random_questions_set_1 = set(self.quest_set_1.get_random_questions()) + random_questions_set_2 = set(self.quest_set_2.get_random_questions()) + + # To check whether random questions are from random_question_set + boolean = set(self.quest_set_1.questions.all()).\ + intersection(random_questions_set_1)\ + == random_questions_set_1 + self.assertTrue(boolean) + self.assertEqual(len(random_questions_set_1), 2) + self.assertFalse(random_questions_set_1 == random_questions_set_2) + + def test_get_questions_for_answerpaper(self): + """ Test get_questions_for_answerpaper() method of Question Paper""" + questions = self.quest_paper._get_questions_for_answerpaper() + fixed = list(self.quest_paper.fixed_questions.all()) + quest_set = self.quest_paper.random_questions.all() + total_random_questions = 0 + available_questions = [] + for qs in quest_set: + total_random_questions += qs.num_questions + available_questions += qs.questions.all() + self.assertEqual(total_random_questions, 5) + self.assertEqual(len(available_questions), 8) + self.assertEqual(len(questions), 7) + + def test_make_answerpaper(self): + """ Test make_answerpaper() method of Question Paper""" + answerpaper = self.quest_paper.make_answerpaper(self.user, + self.profile, self.ip) + self.assertIs(type(answerpaper), type(AnswerPaper())) + paper_questions = set((answerpaper.questions).split('|')) + self.assertEqual(len(paper_questions), 7) + fixed = {'4', '6'} + boolean = fixed.intersection(paper_questions) == fixed + self.assertTrue(boolean) + + def test_answerpaper(self): + """ Test Answer Paper""" + self.assertIs(type(self.answerpaper), type(AnswerPaper())) + self.assertEqual(self.answerpaper.user.username, 'demo_user') + self.assertEqual(self.answerpaper.profile_id, 1) + self.assertEqual(self.answerpaper.user_ip, self.ip) + questions = self.answerpaper.questions + num_questions = len(questions.split('|')) + self.assertEqual(questions, '1|2|3') + self.assertEqual(num_questions, 3) + self.assertEqual(self.answerpaper.question_paper, self.quest_paper) + self.assertEqual(self.answerpaper.question_paper, self.quest_paper) + self.assertEqual(self.answerpaper.start_time, + '2014-06-13 12:20:19.791297') + self.assertEqual(self.answerpaper.end_time, + '2014-06-13 12:50:19.791297') + + def test_current_question(self): + """ Test current_question() method of Answer Paper""" + current_question = self.answerpaper.current_question() + self.assertTrue(current_question is not None) + + def test_completed_question(self): + """ Test completed_question() method of Answer Paper""" + question = self.answerpaper.completed_question(3) + self.assertTrue(question is not None) + self.assertEqual(self.answerpaper.questions_left(), 2) + + def test_questions_left(self): + """ Test questions_left() method of Answer Paper""" + self.assertEqual(self.answerpaper.questions_left(), 2) + + def test_skip(self): + """ Test skip() method of Answer Paper""" + self.assertTrue(self.answerpaper.skip() is not None) + + def test_answered_str(self): + """ Test answered_str() method of Answer Paper""" + self.assertEqual(self.answerpaper.get_answered_str(), 'None') + + def test_get_marks_obtained(self): + """ Test get_marks_obtained() method of Answer Paper""" + self.assertEqual(self.answerpaper.get_marks_obtained(), 0) + + def test_get_question_answer(self): + """ Test get_question_answer() method of Answer Paper""" + self.assertEqual(self.answerpaper.get_question_answers(), {}) diff --git a/testapp/exam/views.py b/testapp/exam/views.py index 92dd029..76773cb 100644 --- a/testapp/exam/views.py +++ b/testapp/exam/views.py @@ -166,7 +166,7 @@ def results_user(request): papers = AnswerPaper.objects.filter(user=user) quiz_marks = [] for paper in papers: - marks_obtained = paper.get_total_marks() + marks_obtained = paper.get_marks_obtained() max_marks = paper.question_paper.total_marks percentage = round((marks_obtained/max_marks)*100, 2) temp = paper.question_paper.quiz.description, marks_obtained,\ @@ -187,7 +187,6 @@ def edit_quiz(request): duration = request.POST.getlist('duration') active = request.POST.getlist('active') description = request.POST.getlist('description') - tags = request.POST.getlist('tags') for j, quiz_id in enumerate(quiz_list): quiz = Quiz.objects.get(id=quiz_id) @@ -196,14 +195,6 @@ def edit_quiz(request): quiz.active = active[j] quiz.description = description[j] quiz.save() - edit_tags = tags[j] - quiz.save() - for tag in quiz.tags.all(): - quiz.tags.remove(tag) - tags_split = edit_tags.split(', ') - for i in range(0, len(tags_split)-1): - tag = tags_split[i].strip() - quiz.tags.add(tag) return my_redirect("/exam/manage/showquiz/") @@ -222,7 +213,6 @@ def edit_question(request): type = request.POST.getlist('type') active = request.POST.getlist('active') snippet = request.POST.getlist('snippet') - tags = request.POST.getlist('tags') for j, question_id in enumerate(question_list): question = Question.objects.get(id=question_id) question.summary = summary[j] @@ -233,14 +223,7 @@ def edit_question(request): question.active = active[j] question.snippet = snippet[j] question.type = type[j] - edit_tags = tags[j] question.save() - for tag in question.tags.all(): - question.tags.remove(tag) - tags_split = edit_tags.split(',') - for i in range(0, len(tags_split)-1): - tag = tags_split[i].strip() - question.tags.add(tag) return my_redirect("/exam/manage/questions") @@ -331,10 +314,6 @@ def add_quiz(request, quiz_id=None): if quiz_id is None: form.save() quiz = Quiz.objects.order_by("-id")[0] - tags = form['tags'].data.split(',') - for tag in tags: - tag = tag.strip() - quiz.tags.add(tag) return my_redirect("/exam/manage/designquestionpaper") else: d = Quiz.objects.get(id=quiz_id) @@ -344,12 +323,6 @@ def add_quiz(request, quiz_id=None): d.description = form['description'].data d.save() quiz = Quiz.objects.get(id=quiz_id) - for tag in quiz.tags.all(): - quiz.tags.remove(tag) - tags = form['tags'].data.split(',') - for i in range(0, len(tags)-1): - tag = tags[i].strip() - quiz.tags.add(tag) return my_redirect("/exam/manage/showquiz") else: return my_render_to_response('exam/add_quiz.html', @@ -368,14 +341,6 @@ def add_quiz(request, quiz_id=None): form.initial['duration'] = d.duration form.initial['description'] = d.description form.initial['active'] = d.active - form_tags = d.tags.all() - form_tags_split = form_tags.values('name') - initial_tags = "" - for tag in form_tags_split: - initial_tags = initial_tags + str(tag['name']).strip() + "," - if (initial_tags == ","): - initial_tags = "" - form.initial['tags'] = initial_tags return my_render_to_response('exam/add_quiz.html', {'form': form}, context_instance=ci) @@ -398,7 +363,7 @@ def show_all_questionpapers(request, questionpaper_id=None): if request.method == "POST" and request.POST.get('add') == "add": return my_redirect("/exam/manage/designquestionpaper/" + - questionpaper_id) + questionpaper_id) if request.method == "POST" and request.POST.get('delete') == "delete": data = request.POST.getlist('papers') @@ -545,7 +510,7 @@ def manual_questionpaper(request, questionpaper_id=None): msg = 'No matching Question found...' tags = Tag.objects.all() context = {'data': {'questions': fetched_questions, - 'tags': tags, 'msg': msg}} + 'tags': tags, 'msg': msg}} return my_render_to_response('exam/manual_questionpaper.html', context, context_instance=ci) @@ -578,7 +543,7 @@ def manual_questionpaper(request, questionpaper_id=None): msg = 'No matching Question found...' tags = Tag.objects.all() context = {'data': {'questions': fetched_questions, - 'tags': tags, 'msg': msg}} + 'tags': tags, 'msg': msg}} return my_render_to_response('exam/manual_questionpaper.html', context, context_instance=ci) @@ -665,7 +630,8 @@ def start(request, questionpaper_id=None): # Make user directory. user_dir = get_user_dir(user) - questions = [str(_.id) for _ in questionpaper.questions.all()] + questions = [str(_.id) for _ in\ + questionpaper._get_questions_for_answerpaper()] random.shuffle(questions) new_paper.questions = "|".join(questions) @@ -822,7 +788,7 @@ def complete(request, reason=None, questionpaper_id=None): else: q_paper = QuestionPaper.objects.get(id=questionpaper_id) paper = AnswerPaper.objects.get(user=user, question_paper=q_paper) - obt_marks = paper.get_total_marks() + obt_marks = paper.get_marks_obtained() tot_marks = paper.question_paper.total_marks if obt_marks == paper.question_paper.total_marks: context = {'message': "Hurray ! You did an excellent job.\ @@ -953,14 +919,6 @@ def show_all_quiz(request): form.initial['duration'] = d.duration form.initial['active'] = d.active form.initial['description'] = d.description - form_tags = d.tags.all() - form_tags_split = form_tags.values('name') - initial_tags = "" - for tag in form_tags_split: - initial_tags = initial_tags + str(tag['name']).strip() + "," - if (initial_tags == ","): - initial_tags = "" - form.initial['tags'] = initial_tags forms.append(form) return my_render_to_response('exam/edit_quiz.html', {'forms': forms, 'data': data}, |