Hi there, besides some minor issues my app now runs really well…
the minor issues:
I have messages that I want to display after a correct input has been received and the form submitted and then hidden after forwarding the word.
and more importantly,
Is it normal that the CBV really gets absolutely crazy or is it bad code?
class WordFormView(FormView):
'''shows the form to enter the meaning of the word.
Forwards to a random new word, once the word is answered correctly.
After three incorrect guesses, the word should be skipped
Todo 1: Implement logic for wrong answers
'''
template_name = 'VocabTrainer/templates/word_form.html'
form_class = AnswerWord
success_url = None
def get_context_data(self, **kwargs):
'''set the context data accordingly - now we can use the current_word in word_form'''
context = super().get_context_data(**kwargs)
word_id = self.kwargs.get('pk')
context['current_word'] = Word.objects.get(pk=word_id)
context['learned_words'] = self.request.session.get('learned_words', [])
return context
def form_valid(self, form):
'''checks whether the form is valid'''
# user_input defines that the field is the form field 'translation'
user_input = form.cleaned_data['translation']
# here we pass the current word from get_context_data into this function
current_word = self.get_context_data()['current_word']
# save the current word language in a variable current language
current_language = current_word.language
if user_input == current_word.text:
messages.success(self.request, 'correct!')
learned_words = self.request.session.get('learned_words', [])
learned_words.append(current_word.pk)
self.request.session['learned_words'] = learned_words
#mark the current word as learned
Word.objects.filter(pk=current_word.pk).update(learned=True)
# if the user input is the correct value, forward to a random word:
# filter Word by the language line that we are in
language_words = Word.objects.filter(language=current_language).exclude(learned=True)
# remove the current_word.pk so that the next word will not be the same
#all_language_words_except_current = language_words.exclude(pk=current_word.pk)
# Todo 2: Implement a list with "learned words" and put the current word if answered correctly to "learned
# words" and remove it from the word-list
# maybe user handling first with users having their own list of "known words and unknown words
if language_words.exists():
#
random_word = random.choice(language_words)
self.success_url = reverse('word-form', kwargs={'language':current_language, 'pk':random_word.pk})
else:
Word.objects.all().update(learned=False)
return HttpResponseRedirect(reverse('index'))
# I don't like that I'm repeating myself here
else:
messages.error(self.request, 'try again')
return self.render_to_response(self.get_context_data(form=self.form_class()))
return super().form_valid(form)
the accompanying word_form.html:
<div class="card">
<form method="post" action="">
{% csrf_token %}
<fieldset>
<legend> <h3> <em>{{ current_word.word.abstract_word }}</em> in {{ current_word.language }}</h3> </legend>
<em> {{ current_word.definition }}</em>
{{ form.as_p }}
<button type="submit">Check</button>
</fieldset>
</form>
{% if messages %}
{% for message in messages %}
<span class="message">{{ message }}</span>
{% endfor %}
{% endif %}
</div>
For the first “small isue”: I want the messages to be displayed in between the clicking and the forwarding, which I seem unable to achieve. I am sure there is a solution (could be JS, even though I think there should be a way to get this without js - I tried time.sleep but that breaks alot of the code…
regarding the worse issue: readability… I think the code is rather long and I fear I am doing “too much” in the cbv-logic, what are your thoughts?