I have been developin a quiz app in django 3.8 and it was working rather well but when i updated to the latest django the code is breaking. The code is supposed to calculate the marks of the the student after they submit the answers after which it redirects to view the results.. here is my views.py code for that particular functionality
def calculate_marks_view(request):
if request.COOKIES.get('course_id') is not None:
course_id = request.COOKIES.get('course_id')
course=QMODEL.Course.objects.get(id=course_id)
total_marks=0
questions=QMODEL.Question.objects.all().filter(course=course)
for i in range(len(questions)):
selected_ans = request.COOKIES.get(str(i+1))
actual_answer = questions[i].answer
if selected_ans == actual_answer:
total_marks = total_marks + questions[i].marks
student = Student.objects.get(user_id=request.user.id)
result = QMODEL.Result()
result.marks=total_marks
result.exam=course
result.student=student
result.save()
return HttpResponseRedirect('view-result')
And this is the django html code to display the options and the questions and the submit answers
{% extends 'student/studentbase.html' %}
{% block content %}
{%load static%}
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style type="text/css">
body, p, a, h1, h2, h3, h4, h5, h6 {
font-family: 'Quicksand', sans-serif;
}
</style>
</head>
<div class="jumbotron my-4">
<form class="form" autocomplete="off" onsubmit="return saveAns()" action="/student/calculate-marks" method="POST">
{% csrf_token %}
<h2 style="text-align: center;">Topic: {{course.course_name}}</h2>
{% for q in questions%}
<h3 class="text-danger">{{ forloop.counter }}. {{q.question}}</h3><h4 style="text-align: right;">[{{q.marks}} Marks]</h4>
<input type="hidden" name="csrfmiddlewaretoken" value="C24rUotmdHawVQJL3KrqiWxvti8UffOFYUc8TRbZtLt36AVLdP3jbkzUVe3beRAa">
<div class="form-check mx-4" style="display: flex; align-items: center;">
<input class="form-check-input" type="radio" name="{{ forloop.counter }}" id="{{q.option1}}" value="Option1">
<label class="form-check-label" for="option1" style="margin-left:18px;">
{{q.option1}}
</label>
</div>
<div class="form-check mx-4" style="display: flex; align-items: center;">
<input class="form-check-input" type="radio" name="{{ forloop.counter }}" id="{{q.option2}}" value="Option2">
<label class="form-check-label" for="option2" style="margin-left:18px;">
{{q.option2}}
</label>
</div>
<div class="form-check mx-4" style="display: flex; align-items: center;">
<input class="form-check-input" type="radio" name="{{ forloop.counter }}" id="{{q.option3}}" value="Option3",style="margin-left: 8px;">
<label class="form-check-label" for="option3" style="margin-left:18px;">
{{q.option3}}
</label>
</div>
<div class="form-check mx-4" style="display: flex; align-items: center;"s>
<input class="form-check-input" type="radio" name="{{ forloop.counter }}" id="{{q.option4}}" value="Option4">
<label class="form-check-label" for="option4" style="margin-left:18px;" >
{{q.option4}}
</label>
</div>
{% endfor %}
<input class="btn btn-success btn-lg" style="border-radius: 5px;" type="submit" value="Submit Answers">
</form>
</div>
<script>
function saveAns(){
var ele = document.getElementsByTagName('input');
for(i = 0; i < ele.length; i++) {
if(ele[i].type="radio") {
if(ele[i].checked){
setCookie(ele[i].name,ele[i].value,3)
}
}
}
}
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
</script>
<br><br><br><br><br><br>
{% endblock content %}
I need help sorting out this error the code throws. I am stuck for days, someone please help, this is the stack trace django throws.
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing.
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django’s CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function passes a request to the template’s render method.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.
You’re seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
I cannot tell why it is throwing this error yet the csrf tag is there. please note that the settings.py Middleware is configured as below
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Somebody help me out.
I was trying to calculate the total score after they submit the answers. but it throws that error. I have tried adding the @csrf_protect from django.views.decorators.csrf but doesnot help.
Assuming you're still working locally, you should add this to your settings:
CSRF_TRUSTED_ORIGINS = ["127.0.0.1:8000"]
In your production environment this should be the same as your production url https://www.yourdomain.com