Django - How to get value of radio button? - python

I'm creating quiz application, where user answers multiple choice questions and gets score. I've created everything, except calculating score. For this I should get value from radio buttons which user selected and compare it with correct answer. The problem is that, I can't get this value. Here are my codes:
models.py:
class Question(models.Model):
question_text = models.CharField(_('Sualın mətni'), max_length=250)
option_a = models.CharField(max_length = 50)
option_b = models.CharField(max_length = 50)
option_c = models.CharField(max_length = 50)
option_d = models.CharField(max_length = 50)
answer = models.CharField(max_length = 50)
views.py:
def index(request):
questions = Question.objects.all()
context = {
'questions': questions,
}
return render(request, 'index.html', context)
html:
<div class="main-container">
{% for question in questions %}
<div class="question-box">
<div class="question-text">
<p>{{ question.question_text }}</p>
</div>
<div class="question-answers">
<input class="option" type="radio" name="{{ question.id }}" value="{{ question.option_a }}">
<label>{{ question.option_a }}</label>
<input class="option" type="radio" name="{{ question.id }}" value="{{ question.option_b }}">
<label>{{ question.option_b }}</label>
<input class="option" type="radio" name="{{ question.id }}" value="{{ question.option_c }}">
<label>{{ question.option_c }}</label>
<input class="option" type="radio" name="{{ question.id }}" value="{{ question.option_d }}">
<label>{{ question.option_d }}</label>
</div>
</div>
{% endfor %}
<input type="submit" value="End quiz">
</div>

question.option_a
question.option_b
question.option_c
question.option_d
These variables hold the values as True or False

Related

How to render Model field in Django, either it contains text or image?

In models.py, question field contains text and question_img filed contains image. Questions may be text or image. If question filed contains text, question_img field should be empty and if question_img filed contains image, question filed should be empty. So, how to render text question or image question based on condition? If question field is empty then it should render question_img from Database vice-versa.
models.py:
class Questions(models.Model):
paper = models.CharField(max_length=10, default='None')
qs_no = models.IntegerField(default=None)
question = models.TextField(max_length=500)
question_img = models.ImageField(null=True, blank=True)
option_a = models.CharField(max_length=100)
option_b = models.CharField(max_length=100)
option_c = models.CharField(max_length=100)
option_d = models.CharField(max_length=100)
ans = models.CharField(max_length=50)
forms.py:
class QuestionsForm(forms.ModelForm):
paper = forms.CharField(widget=forms.Select(choices = PAPER_CHOICES))
class Meta:
model=Questions
fields=[
'paper',
'qs_no',
'question',
'question_img',
'option_a',
'option_b',
'option_c',
'option_d',
'ans',
]
views.py:
def questions(request):
if not request.user.is_superuser:
return render(request, 'login.html')
else:
if request.method == 'POST':
form = QuestionsForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('questions')
else:
return HttpResponseRedirect('questions')
else:
form = QuestionsForm()
return render(request, 'questions.html', {'form':form})
def render_questions(request):
print(f'user in render_questions is {request.user.username}', flush=True)
if not request.user.is_authenticated:
return render(request, 'login.html')
else:
global exam_session
exam_session = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
print(f"session id in render ques is {exam_session}", flush=True)
questions = Questions.objects.all()
ques = []
qs_no = 1
for q in questions:
que = {}
que['qs_no'] = qs_no
qs_no = qs_no + 1
que['question'] = q.question
que['id'] = q.id
que['option_a'] = q.option_a
que['option_b'] = q.option_b
que['option_c'] = q.option_c
que['option_d'] = q.option_d
ques.append(que)
print(f"ques: {ques}", flush=True)
return render(request, 'report.html', {'ques': ques})
template.html:
<form id="myform" name="myform" action="answer" method="POST">
{% csrf_token %}
<div class="questionContainer">
{% for question in ques %}
<div class="questiondiv" data-questionId="{{ question.id }}">
<div class="bghead1">
<h5><strong>Question {{ question.qs_no }}.</strong></h5>
</div>
<div class="font mrl">
<h5><input type="hidden" class="form-check-input" name="question" value="{{ question.question }}">{{ question.question }}</h5>
</div>
<div class="radio pad">
<label><input type="radio" class="form-check-input" name="question{{question.qs_no}}" value="{{question.option_a}}"> A) {{ question.option_a }}</label>
</div>
<div class="radio pad">
<label><input type="radio" class="form-check-input" name="question{{question.qs_no}}" value="{{question.option_b}}"> B) {{ question.option_b }}</label>
</div>
<div class="radio pad">
<label><input type="radio" class="form-check-input" name="question{{question.qs_no}}" value="{{question.option_c}}"> C) {{ question.option_c }}</label>
</div>
<div class="radio pad">
<label><input type="radio" class="form-check-input" name="question{{question.qs_no}}" value="{{question.option_d}}"> D) {{ question.option_d }}</label>
</div>
</div>
{% endfor %}
</div>
</form>
Using template if/else is a straightforward approach.
{% if question.question %}
<div class="font mrl">
<h5><input type="hidden" class="form-check-input" name="question" value="{{ question.question }}">{{ question.question }}</h5>
</div>
{% else %}
<div class="font mrl">
<h5><img src="{{ question.image.url }}"></h5>
</div>
{% endif %}

Taking value of selected radio buttons from one page in Django

I want to take value of selected radio buttons in a single page. To explain this here is my code in models.py file
class Quiz(models.Model):
Description = models.CharField(max_length=200)
def __str__(self):
return str(self.Description)
class Question(models.Model):
Question_Text = models.CharField(max_length=500)
Option1 = models.CharField(max_length=100)
Option2 = models.CharField(max_length=100)
Option3 = models.CharField(max_length=100, blank=True)
Option4 = models.CharField(max_length=100, blank=True)
Answer = models.CharField(max_length=100)
QuizID = models.ForeignKey(Quiz, on_delete=models.CASCADE)
def __str__(self):
return str(self.Question_Text)
I want user to choose one option from "Option1, Option2, Option3, Option4" fields and I want to get value of the selected radio button.
Here's my try:
disp.html
<form action="" method="post">
{% csrf_token %}
{% for q in question %}
{{ q.Question_Text }} <br>
<input type="radio" id="question_{{ q.Option1 }}" name="{{ q.id }}" value="{{ q.Option1 }}">
<label for="question_{{ q.Option1 }}">{{ q.Option1 }}</label> <br>
<input type="radio" id="question_{{ q.Option2 }}" name="{{ q.id }}" value="{{ q.Option2 }}">
<label for="question_{{ q.Option2 }}">{{ q.Option2 }}</label> <br>
{% if q.Option3 %}
<input type="radio" id="question_{{ q.Option3 }}" name="{{ q.id }}" value="{{ q.Option3 }}">
<label for="question_{{ q.Option3 }}">{{ q.Option3 }}</label> <br>
{% endif %}
{% if q.Option4 %}
<input type="radio" id="question_{{ q.Option4 }}" name="{{ q.id }}" value="{{ q.Option4 }}">
<label for="question_{{ q.Option4 }}">{{ q.Option4 }}</label> <br>
{% endif %}
{% endfor %}
<br> <input type="submit" class="btn btn-primary" value="Submit">
</form>
Now I want to get value of the selected radio button. Since the number of records may vary and hence I cannot take value of the selected radio buttons manually like:
first = request.POST.get("11")
second = request.POST.get("18")
third = request.POST.get("19")
Here 11,18 and 19 are the value of id field of records in Question Model.
So I tried for loop to do this in the following way but I am getting "None" as value.
view.py
def disp(request):
quiz = get_object_or_404(Quiz, id = 4)
question = get_list_or_404(Question, QuizID = quiz)
if request.method == "POST":
for q in question:
response = request.POST.get("q.id")
print(response)
return render(request, 'quiz/disp.html', {'question' : question, 'quiz' : quiz})
Please help me in getting the value of the selected radio button or if there's another way to get the value of selected radio button, please suggest me
POST <QueryDict> contains only keys of type <str>. Which means that request.POST.get(18) will return None and request.POST.get('18') will return the value (assuming that the key exists in POST <QueryDict>).
if request.method == "POST":
for q in question:
# convert the q.id into str
response = request.POST.get(str(q.id))
print(response)
OR
you may loop through the POST data and check for valid keys. Since, POST data contains other data like csrfmiddlewaretoken.
Change the value of radio button name attribute into the form of question_{{ q.id }}.
<input type="radio" id="question_{{ q.Option1 }}" name="question_{{ q.id }}" value="{{ q.Option1 }}">
Loop through POST and check if the key contains question_
if request.method == "POST":
for k, v in request.POST.items():
if 'question_' in k:
# do something
In view.py, you are using "q.id" as a HTTP param name while I think you intended it to be 11, 18, 19 etc. Try this :-
if request.method == "POST":
for q in question:
response = request.POST.get(q.id)
print(response)
I would reconfigure the Question model to use Choices:
SOME = 'win'
OTHER = 'lin'
Answer_CHOICES = (
(SOME, 'Some Answer'),
(OTHER, 'Other Answer'),
)
class Question(models.Model):
....
Options = models.CharField(choices=Answer_CHOICES, max_length=100)
....
Check the Choices field and how you may use it. Also, check crispy forms which automatically handle the form input for you.

How to pass form id if there are several forms on page and no submit buttons Django 1.10?

I have a page with list of questions. Each of them has radio button form with "Yes", "Maybe", "No" kind of choices. This form's submits by making a choice.
http://prntscr.com/embo1m
I can't understand how to connect question id with it's form. How to get it in it's view with response?
models.py
class Answer(models.Model):
user = models.ForeignKey(User)
apartment = models.ForeignKey(Apartment)
question = models.ForeignKey(Question)
choice = models.IntegerField(default=2)
def __str__(self):
return str(self.choice)
views.py
def questions_list(request, apartment_pk):
context = {}
context['apartment'] = get_object_or_404(Apartment, pk=apartment_pk)
context['questions'] = get_list_or_404(Question)
context['answer_form'] = AnswerForm
context['username'] = auth.get_user(request).username
if request.method == 'POST':
form = AnswerForm(request.POST or None)
if form.is_valid():
print(form.cleaned_data)
return render(request, 'main/questions.html', context)
forms.py
class AnswerForm(ModelForm):
choice = ChoiceField(label='', widget=RadioSelect, choices=ANSWERS)
question_id = CharField(widget=HiddenInput(), required=False)
class Meta:
model = Answer
fields = ('choice', 'question_id')
template
<h1>{{ apartment.title }}</h1>
{% for question in questions %}
<h3>{{ question.title }}</h3>
<form id="question_{{ question.id }}" name="question_{{ question.id }}" action="/apartments/{{ apartment.id }}/" method="post">
{% csrf_token %}
{% for radio in answer_form.choice %}
<label><input name="choice" type="radio" value="{{ radio.choice_value }}" onchange="question_{{ question.id }}.submit()">{{ radio.choice_label }}</label>
{% endfor %}
{{ answer_form.hidden_field }}
</form>
{% endfor %}
EDIT:
Tried to pass question id as <input type="hidden" name="q_id" value="{{ question.id }}">
<h1>{{ apartment.title }}</h1>
{% for question in questions %}
<h3>{{ question.title }}</h3>
<form id="question_{{ question.id }}" name="question_{{ question.id }}" action="/apartments/{{ apartment.id }}/" method="post">
{% csrf_token %}
<input type="hidden" name="q_id" value="{{ question.id }}">
{% for radio in answer_form.choice %}
<label><input name="choice" type="radio" value="{{ radio.choice_value }}" onchange="question_{{ question.id }}.submit()">{{ radio.choice_label }}</label>
{% endfor %}
</form>
{% endfor %}
And changed my form to
class AnswerForm(Form):
choice = ChoiceField(label='', widget=RadioSelect, choices=ANSWERS)
But there's no hidden input in form from response...
<tr><th></th><td><ul id="id_choice">
<li><label for="id_choice_0"><input id="id_choice_0" name="choice" type="radio" value="0" required /> Точно ні</label></li>
<li><label for="id_choice_1"><input id="id_choice_1" name="choice" type="radio" value="1" required /> Скоріше ні</label></li>
<li><label for="id_choice_2"><input checked="checked" id="id_choice_2" name="choice" type="radio" value="2" required /> Не можу відповісти</label></li>
<li><label for="id_choice_3"><input id="id_choice_3" name="choice" type="radio" value="3" required /> Скоріше так</label></li>
<li><label for="id_choice_4"><input id="id_choice_4" name="choice" type="radio" value="4" required /> Точно так</label></li>
</ul></td></tr>
Cleaned data {'choice': '2'}
Pass the question id as hidden value as shown below:
<input type="hidden" name="q_id" value="{{ question.id }}">
{% for radio in answer_form.choice %}
<label><input name="choice" type="radio" value="{{ radio.choice_value }}" onchange="question_{{ question.id }}.submit()">{{ radio.choice_label }}</label>
{% endfor %}

Not getting score in my mcq app- Django

For my MCQ app, I created a view
def process_data(request):
question_set=Question.objects.all()
choice_list=[]
question_set
for k, v in request.POST.items():
if k.startswith('choice'):
choice_list.append(v)
i=0
score=0
print type(question_set)
for question in question_set:
if question.answer1==choice_list[i]:
#print question.answer1
i=i+1
score=score+1
return HttpResponse(score)
html page contains the form look like this.
{% extends 'quiz/base.html' %}
{% block content%}
<h1>You are at quiz page</h1>
<form action="{% url 'quiz:process_data' %}" method="post">
{% csrf_token %}
{% for question in question_set %}
<h3>{{question.question_no}}.{{question.question_text }}</h3>
<input type="radio" name="choice{{ question.question_no}}" value="{{ question.option1 }}">{{ question.option1 }}<br>
<input type="radio" name="choice{{ question.question_no}}" value="{{ question.option2 }}">{{ question.option2 }}<br>
<input type="radio" name="choice{{ question.question_no}}" value="{{ question.option3 }}">{{ question.option3 }}<br>
<input type="radio" name="choice{{ question.question_no}}" value="{{ question.option4 }}">{{ question.option4 }}<br>
<input type="radio" name="choice{{ question.question_no}}" value="{{ question.option5 }}">{{ question.option5 }}<br>
{% endfor %}
<input type="Submit" name="Submit">
</form>
{% endblock%}
and this is the model for Questions
class Question(models.Model):
question_no=models.IntegerField(default=0)
question_text=models.CharField(max_length=1000)
option1=models.CharField(max_length=100)
option2=models.CharField(max_length=100)
option3=models.CharField(max_length=100)
option4=models.CharField(max_length=100)
option5=models.CharField(max_length=100)
answer1=models.CharField(max_length=100)
def __str__(self):
return self.question_text
The problem is that the score is not getting correctly. So that I tested it with the print statement and realized that only first questions answer is getting. How can I get the score correctly? Thank you
The problem is with how you have handled this call request.POST.item. The call to item function returns an unordered dictionary. This is causing your second for-loop to match user inputs against wrong question. Below is a sample code of what I mean:
user_inputs = request.POST.items() # key: choice<question_no> and value: <user_choice>
for question in question_set:
user_choice = user_inputs.get('choice'+question.question_no)
if user_choice == question.answer1:
//count the score

list the unicode array separately in template in python

The Following is my view.py
def UpdatePage(request):
templatevar = {}
user_name = request.session['login_user_email']
update_form = Update_Page()
if user_name:
home_page_form = Home_Page
templatevar['varobj']=models.ProfileDetail.objects.filter(email=user_name)
if request.method=='POST':
update_name=request.POST['name']
update_age=request.POST['age']
update_gender=request.POST.get('gender')
update_interested_in=request.POST.getlist('interested_in')
for i in update_interested_in:
print i
update_dob=request.POST.get('dob')
update_country=request.POST['country']
update_about_you=request.POST['about_you']
update_profile_detail=models.ProfileDetail.objects.filter(email=user_name).update(name=update_name,age=update_age,gender=update_gender,
interested_in=update_interested_in,dob=update_dob,country=update_country,about_you=update_about_you)
if update_profile_detail:
details_updated="Your Profile Details are Updated"
return HttpResponseRedirect('homepage',{'details_updated':details_updated})
return render(request,'update.html',{'user_name':user_name,'update_form':update_form,'templatevar':templatevar})
The Following is my Template View
<html>
<head>
<title>Update Here</title>
</head>
<body style="text-align:center">
<h3 style="text-align:right"><div>Home</div><div>Log Out</div></h3>
{{user_name}}
<h3>Update Here</h3>
<!--{{update_form.as_p}}-->
{% for all in templatevar.varobj %}
<p>Age:{{all.age}}<br></p>
<p>Gender:{{all.gender}}<br></p>
<p>Interested In:{{all.interested_in}}<br></p>
{%for i in all.interested_in%}
{{i}}
{%endfor%}
<p>DOB:{{all.dob}}<br></p>
<p>Country:{{all.country}}<br></p>
<p>About You:{{all.about_you}}<br></p>
{% endfor %}
<form action="" method="post">
{% csrf_token %}
{% for all in templatevar.varobj %}
<p><label for="id_name">People Call You As:</label> <input id="id_name" name="name" type="text" value="{{all.name}}" /></p>
<p><label for="id_email">Your Email:</label> <input id="id_email" name="email" type="email" value="{{user_name}}" readonly /></p>
<p><label for="id_age">Age:</label> <input id="id_age" name="age" type="number"value="{{all.age}}" /></p>
<p><label for="id_gender_0">Gender:</label> <ul id="id_gender">
<li><label for="id_gender_0"><input id="id_gender_0" name="gender" type="radio" value="Male" {% if all.gender == "Male" %}checked="checked"{% endif %} /> Male</label></li>
<li><label for="id_gender_1"><input id="id_gender_1" name="gender" type="radio" value="Female" {% if all.gender == "Female" %}checked="checked"{% endif %} /> Female</label></li>
<p><label for="id_interested_in_0">Interested In:</label>
<ul id="id_interested_in">
<li><label for="id_interested_in_0">
<input id="id_interested_in_0" name="interested_in" type="checkbox" value="Sports" {% if all.interested_in == "Sports" %}checked="checked"{% endif %}/> Sports</label></li>
<li><label for="id_interested_in_1"><input id="id_interested_in_1" name="interested_in" type="checkbox" value="Music" {% if all.interested_in == "Music" %}checked="checked"{% endif %} /> Music</label></li>
<li><label for="id_interested_in_2"><input id="id_interested_in_2" name="interested_in" type="checkbox" value="Gardening" {% if all.interested == "Gardening" %}checked="checked"{% endif %}/> Gardening</label></li>
<p><label for="id_dob">Date Of Birth:</label> <input id="id_dob" name="dob" type="text" value="{{all.dob}}" placeholder = "YYYY-MM-DD" /></p>
<p><label for="id_country">Your From:</label> <select id="id_country" maxlength="3" name="country">
<option value="India">India</option>
<option value="Australia">Australia</option>
<option value="America">America</option>
</select></p>
<p><label for="id_about_you">About You:</label> <textarea cols="40" id="id_about_you" name="about_you" rows="10" value="">{{all.about_you}}
</textarea></p>
{% endfor %}
<input type="submit" value="Update" />
</form>
</body>
</html>
The following is my model view:
class ProfileDetail(models.Model):
name = models.CharField(max_length=100,null=True)
email = models.EmailField(max_length=50,unique=True,null=True)
age = models.IntegerField(max_length=3,null=True)
gender = models.CharField(max_length=10,null=True)
interested_in = models.CharField(max_length=10,null=True)
dob = models.DateField(null=True)
country = models.CharField(max_length=25,null=True)
about_you = models.CharField(max_length=200,null=True)
def __str__(self):
return self.interested_in
I need to display the check box value separately as
Sports
Music
Gardening
and not the following
Interested In:[u'Sports', u'Music', u'Gardening']
How to display separately and check the values
Your error is that you are trying to store a list into a char field, that's why you are seeing the repr of the list.
First, in your view, change the line:
update_interested_in=request.POST.getlist('interested_in')
to
update_interested_in = ','.join(request.POST.getlist('interested_in'))
Then add a method to your model.py that splits the string:
class ProfileDetail(models.Model):
...
def interested_in_list(self):
return self.interested_in.split(',')
You can then use the join template filter:
{{ all.interested_in_list|join:"<br/>"|safe }}
If you have to construct the checkboxes yourself, you can use something like:
{% for interest in all.interested_in_list %}
<input name="interested_in" type="checkbox" value="{{ interest }}"> {{ interest }}
{% endfor %}

Categories

Resources