Divit Rao
Divit Rao

Reputation: 31

Select a valid choice. 6da87c51321849bdb7da80990fdab19b is not one of the available choices

I'm using answers field in form for just test purpose to see if it is returning the selected id of the value in post request when form is submitted, also I'm passing choices dynamically to the from views using get_form_kwargs(), On frontend it shows me proper choices but when one selected and submitted it shows me the error mentioned in Subject of this question

Also FYI i have not included "answerss" field in models because i just wanted to test if it returns correct id on POST request.

This is my Dynamically passed List from views.py to forms.py to fill the choices of "answerss" field created in init . This list keeps changing after every submission

Also FYI this is a Quiz app so after every submission i redirect it into the same page where next question is rendered and different options are rendered in choice field

[('d5730fbb3b1742d183d0968802859c7d', 'Africa'), ('6da87c51321849bdb7da80990fdab19b', 'Asia'), ('e0d084ff6e7544478523149186835132', 'North America')]

This is my model.py

class userAnswer(models.Model):
answer_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user_id= models.ForeignKey(CustomUser,on_delete=models.CASCADE)
question_id = models.ForeignKey(question,on_delete=models.CASCADE)
text_ans = models.CharField(max_length=100)
remaining_time = models.TimeField(default='23:00:00')
correct_Answer_id = models.ForeignKey(correctAnswer,on_delete=models.CASCADE)

This is my views.py

class Start_Game(FormView):
model = userAnswer
template_name = 'test_template.html'
form_class = Useranswer
success_url = 'game'
context_object_name = 'questions'
question_collection = []
question_id_collection = []
count = 0

def __init__(self) :
    
    if len(Start_Game.question_id_collection)!=0:
            Start_Game.question_id_collection = []
            Start_Game.question_collection = []
    find = quizz.objects.get(category=formality.question_subject)
    ids = question.objects.all().filter(quiz_id = find.quiz_id)
    for i in ids:
            Start_Game.question_id_collection.append(i.question_id)
            Start_Game.question_collection.append(i)     

def get_context_data(self,*args,**kwargs) :
    context = super().get_context_data(*args,**kwargs)
    context['data4'] = correctAnswer.objects.all().filter(question_id = 
    Start_Game.question_id_collection[Start_Game.count])
    context['data5'] = question.objects.filter(question = 
    Start_Game.question_collection[Start_Game.count]).values('question_id')
    context['data6'] = correctAnswer.objects.filter( check_answer_bool = 1, question_id = 
    Start_Game.question_collection[Start_Game.count] ).values('correct_Answer_id')
    
    context['data2'] = Start_Game.count
    context['data3'] = Start_Game.question_collection[Start_Game.count]
    # context['data4']  = Start_Game.question_id_collection[Start_Game.count]
    Start_Game.count+=1
    if Start_Game.count>len(Start_Game.question_collection)-1:
        Start_Game.count=0  
        return context
    return context

def get_form_kwargs(self, *args,**kwargs) :
    message = super(Start_Game,self).get_form_kwargs(*args,**kwargs)
    option_choice = []
    #q = correctAnswer.objects.only('answer').values_list('correct_Answer_id','answer')
    q = correctAnswer.objects.all().filter(question_id = Start_Game.question_id_collection[Start_Game.count]).values_list('correct_Answer_id','answer')
    for i in range(len(q)):
        option_choice.append(((q[i][0]).hex,q[i][1]))
        
   
    message['options'] =    option_choice      
   
    return  message

def form_valid(self, form) :
    print('selected id is ',self.request.POST.get('answers')) #checking if id is returned properly when form is submitted after selecting from MultichoiceField
    obj = form.save(commit= False)
    obj.user_id = self.request.user
    obj.question_id_id = question.objects.filter(question = Start_Game.question_collection[Start_Game.count-1]).values('question_id')
    obj.correct_Answer_id_id = correctAnswer.objects.filter( check_answer_bool = 1, question_id = Start_Game.question_id_collection[Start_Game.count-1] ).values('correct_Answer_id')
    obj.save()
    return super().form_valid(form)

My forms.py

  class Useranswer(forms.ModelForm):
     def __init__(self,*args, **kwargs) :
    
        options_availble = kwargs.pop('options',None)
        super(Useranswer,self).__init__(*args, **kwargs)
    
        self.fields["answerss"] = forms.MultipleChoiceField(choices=options_availble)
    
    class Meta :
        model = userAnswer
        fields = ('text_ans',)

This snip is before submitting the form (Please ignore Text Answer field) enter image description here

This snip is after making the submissions

enter image description here

Upvotes: 1

Views: 1039

Answers (1)

Divit Rao
Divit Rao

Reputation: 31

Solved it , so basically when ever i used to submit my form a post request was recreated so i was basically thinking that if user have filled all the required details properly in form then it would directly go to the form_valid() method but i was wrong before going to the form valid method it would initialize my __init__ method of Start_Game class in views after that it would initialize my get_form_kwargs() so in this get_form_kwargs() i have written code to generate the nex question and there options to send it to my form in forms.py so this would directly update my multichoice option in forms with next questions option and after updating multichoice option it would then compare my previously selected options value with the newly updated values so obviously this created the above error as the selected option was not available in the updated options so basically i wrote down an if condition in the below code to check if the request was post or get

def get_form(self,*args, **kwargs):
    if self.request.method == 'GET':
        self.question_and_type.clear()
        self.unanswered_question = UserAnswer.get_unanswered_question(self.request.user.UserId,
                                                                      Quiz.objects.get(category = self.slug).quizId)
        
        self.question = self.unanswered_question.first()
        self.type = self.question.type
        self.question_and_type.extend([self.question, self.type])
        return self.form_class(**self.get_form_kwargs())
    else :
        form = AnswerForm(question = self.question_and_type[0],
                          type = self.question_and_type[1], 
                          data = self.request.POST)
        return form

def get_form_kwargs(self):
    if self.request.method == 'GET' :
        kwargs =  super().get_form_kwargs()
        return dict(kwargs,question=self.question,type=self.type)

so now i would only get the new questions if request was "GET" else if it was "POST" then i would simply send the data of current question to the form

   form =  AnswerForm(question = self.question_and_type[0],
                                  type = self.question_and_type[1], 
                                  data = self.request.POST)

so that it can successfully validate if selected option was present in the available options. FYI i'm storing previous questions in self.question_and_type while 'GET' request is made . You can check my github for more details GITHUB_HERE

I think so this is not an efficient way but it worked for me and If there is another good way then feel free to comment :)

Upvotes: 1

Related Questions