私は何日も前からレンガの壁に真っ向から突っ込んできました。私より賢くて経験豊富な人にアドバイスを求める時が来ました.
コンテキスト:私の Web アプリの一部として、ユーザーが多肢選択式の質問で構成されるクイズに答えることができるクイズ アプリケーションを構築しています。質問はすべてユーザーが作成したものなので、同時に興味深い問題がいくつかあります。
a) クイズ質問フォーム (radioselect ウィジェット) をその場で動的に作成する必要があります。回答オプションと質問テキストの両方がユーザー生成 (モデル 'Question' と 'Answer') であるため、ビューでクエリを実行し、変数をフォームの init に渡す必要があります。そうすれば、選択肢を入力し、ラベルを質問テキストで上書きできます。
forms.py から:
#it's not very clean, there's a lot of legacy code in there...
class AnsweredQuestionForm(forms.ModelForm):
class Meta:
model = AnsweredQuestion
widget = {
'id': forms.TextInput, # needed for formset that I was using
}
question_field = forms.ModelChoiceField(
empty_label='Gee, this is tough. Can you show me some hints?',
widget=forms.RadioSelect,
queryset=Question.objects.all(),
required=True,
help_text='',
error_messages={'required': 'Please pick an answer'},
)
def __init__(self, *args, **kwargs): # I'm using django crispy-forms
self.helper = FormHelper()
self.helper.form_method = 'POST'
self.helper.form_id = ''
self.helper.form_class = ''
self.helper.form_action = ''
self.helper.form_tag = False
self.helper.help_text_inline = True
self.helper.render_unmentioned_fields = False
self.helper.form_error_title = 'Form Errors'
self.helper.layout = Layout(
Field('question_field'),
Field('id', css_class='hidden'),
)
self.question = kwargs.pop('question', None)
super(AnsweredQuestionForm, self).__init__(*args, **kwargs)
self.fields['question_field'].label = self.question.question_text
self.fields['question_field'].queryset = self.question.answers.all()
b) これは、クイズの質問フォームがモデルフォームであることを意味します (与えられた回答のインスタンスを保存する「AnsweredQuestions」というモデルがあります。クイズ用のモデル「TakenQuiz」もあります)。ユーザーがクイズを開始したときに TakenQuiz のインスタンスを作成し、クイズの質問に答えてフォームが保存されたときに AnsweredQuestion のインスタンスを作成します。
models.py から
class AnsweredQuestion(models.Model):
question = models.ForeignKey(Question, null=True, blank=True)
given_answer = models.ForeignKey(Answer, null=True, blank=True)
taken_quiz = models.ForeignKey(TakenQuiz, related_name="answered_questions", null=True, blank=True)
date = models.DateTimeField(editable=False)
correct = models.BooleanField(default=False)
class Meta:
verbose_name = 'answered question'
verbose_name_plural = 'answered questions'
def save(self, *args, **kwargs):
""" On save, update timestamp."""
if not self.id:
self.date = datetime.datetime.now()
super(AnsweredQuestion, self).save(*args, **kwargs)
def __unicode__(self):
return unicode(self.given_answer)
views.py から (テスト ビュー):
def take_quiz(request, category_slug, course_slug, module_slug, quiz_number):
user = request.user
category = Category.objects.get(slug=category_slug)
course = Course.objects.get(category=category, slug=course_slug)
module = Module.objects.get(course=course, slug=module_slug)
quiz = module.quizzes.get(number=quiz_number)
quiz_questions = Question.objects.filter(quiz=quiz)
...
else:
taken_quiz = TakenQuiz()
aq_form = AnsweredQuestionForm(question=question)
c) クイズは可変数のクイズ質問で構成できます。最大制限のみを設定します。したがって、ほとんどすべてが動的です:(
だからここに私の具体的な質問があります:
フォームウィザードを使用している場合、URL パラメータにアクセスしてクエリに使用するにはどうすればよいですか? (ちなみに、そのためのクラスベースの汎用ビューは嫌いです)質問の数を動的にしようとしましたが、変数(len(quiz_questions)をウィザードに正確に渡す方法をまだ理解していません...私のURL次のようになりますが、残念ながら、すべてをテンプレート コンテキストまたはフォームの init に渡す必要があります。
urls.py から:
url(r'^(?P<category_slug>[-\w]+)/(?P<course_slug>[-\w]+)/(?P<module_slug>[-\w]+)/(?P<quiz_number>\d+)/$', quiz_wizard, name='quiz_wizard'), quiz_wizard = QuizWizard.as_view(named_quiz_forms) named_quiz_forms = [('quiz_question_%d' % i, AnsweredQuestionForm) for i in xrange(0, len(quiz_questions))]
必要なことをするためにフォームウィザードを曲げようとする必要さえありますか? 私は Google の調査とソース コードに多くの時間を費やしましたが、いくつかの問題の潜在的な解決策を見つけましたが、すべてではありませんでした。特に、それらすべてを同時にではありません...
おそらく、少なくともこれらすべてを上書きする必要があります。
class QuizWizard(NamedUrlSessionWizardView): def get_form(self, step=None, data=None, files=None): form = super(QuizWizard, self).get_form(step, data, files) ... return form def get_form_kwargs(self, step): return {} def get_form_instance(self, step): return self.instance_dict.get(step, None)
最後に: フォームウィザードを使用できない場合、クイズをどのように処理すればよいでしょうか? フォームウィザードを使用することは、私にとってはすっきりしているように思えました。ウィザードの大きな利点は、クイズ全体が完了して検証されるまでフォーム データをどこかに保存する必要がないことと、ウィザードがステップ数と現在のステップを追跡してくれることです。私は初心者で、この種の高度なものをゼロから作成するのはそれほど得意ではありません。
ご協力いただきありがとうございます。アドバイスやヘルプをいただければ幸いです。