I am creating a django project and I tried with a guide. I have my code working in Development, but once I pushed code to production, I get errors on ajax requests. I see the error is happening on the views level where I get the keys and the key is a field named "text". In development, using this for submission of quizzes works perfectly well, but in development, it doesn't. I tried using pk for the submission and it returns errors and is unable to create an accurate result instance. Below are my model's instances and views.
Error
File "/home/django/.local/lib/python3.9/site-packages/django/db/models/query.py", line 435, in get
raise self.model.DoesNotExist(
quiz.models.Question.DoesNotExist: Question matching query does not exist.
models.py
from django.db import models
import random
from account.models import Profile
from django.urls import reverse
import datetime
from django.utils import timezone
from ckeditor_uploader.fields import RichTextUploadingField
class PublishedBookManager(models.Manager):
def get_queryset(self):
return super(PublishedBookManager, self).get_queryset().filter(publish_book=True)
class Book(models.Model):
name = models.CharField(max_length=120)
description = models.TextField()
created_by = models.ForeignKey(Profile, default=1, null=True, on_delete=models.SET_NULL)
number_of_questions = models.IntegerField()
number_of_sections = models.IntegerField()
time = models.IntegerField(help_text="duration of the quiz in minutes")
required_score_to_pass = models.IntegerField(help_text="required score in %")
start_date = models.DateTimeField(default=timezone.now)
publish_book = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
objects = models.Manager()
published = PublishedBookManager()
def __str__(self):
return f"{self.name}"
def get_absolute_url(self):
return reverse('quiz:book-detail-view', args=[self.pk])
class PublishedQuizManager(models.Manager):
def get_queryset(self):
return super(PublishedQuizManager, self).get_queryset().filter(publish_quiz=True)
class Quiz(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=120)
description = models.TextField()
created_by = models.ForeignKey(Profile, default=1, null=True, on_delete=models.SET_NULL)
number_of_questions = models.IntegerField()
time = models.IntegerField(help_text="duration of the quiz in minutes")
required_score_to_pass = models.IntegerField(help_text="required score in %")
completed_users = models.ManyToManyField(Profile, blank=True, related_name='completed_users_quiz')
publish_quiz = models.BooleanField(default=False)
start_date = models.DateTimeField(default=timezone.now)
deadline_date = models.DateTimeField(default=timezone.now)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
objects = models.Manager()
published = PublishedQuizManager()
def __str__(self):
return f"{self.book.name} = {self.name}"
def get_questions(self):
questions = list(self.question_set.all())
random.shuffle(questions)
return questions[:self.number_of_questions]
class Meta:
verbose_name_plural = 'Quizes'
def get_absolute_url(self):
return reverse('quiz:quiz-view', kwargs={'book_pk': self.book.pk, "pk": self.pk})
class Question(models.Model):
# text = models.TextField()
text = RichTextUploadingField(unique=True)
second_text = models.TextField()
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.text)
def get_answers(self):
return self.answer_set.all()
def get_absolute_url(self):
return reverse('quiz:quiz-view', kwargs={'question_pk': self.pk,})
class Answer(models.Model):
text = models.CharField(max_length=255)
correct = models.BooleanField(default=False)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"question: {self.question.text}, answer: {self.text}, correct: {self.correct}"
class Result(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
user = models.ForeignKey(Profile, on_delete=models.CASCADE)
score = models.FloatField()
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.pk)
views.py
def save_quiz_view(request, pk, book_pk, question_pk):
# if request.user in
quiz = Quiz.objects.get(pk=pk)
# Submition of result only occurs if a user is not in the completed users field. If they are already
# in the completed users ManyToMany field, then it won't save. But if not, it will save.
if request.is_ajax() and not request.user.profile in quiz.completed_users.all():
questions = []
data = request.POST
data_ = dict(data.lists())
data_.pop('csrfmiddlewaretoken')
# try:
# question = get_object_or_404(Question, pk=pk)
# questions.append(question)
# except Question.DoesNotExist:
# pass
for k in data_.keys():
# print('key: ', k)
# question = Question.objects.get(text=k)
question = Question.objects.get(text=k)
questions.append(question)
# print(questions)
user = request.user.profile
quiz = Quiz.objects.get(pk=pk)
if request.user.is_authenticated:
if not user in quiz.completed_users.all():
quiz.completed_users.add(user)
score = 0
multiplier = 100 / quiz.number_of_questions
results = []
correct_answer = None
for q in questions:
a_selected = request.POST.get(q.text)
if a_selected != "":
question_answers = Answer.objects.filter(question=q)
for a in question_answers:
if a_selected == a.text:
if a.correct:
score = 1
correct_answer = a.text
else:
if a.correct:
correct_answer = a.text
results.append({str(q): {'correct_answer': correct_answer, 'answered': a_selected}})
else:
results.append({str(q): 'not answered'})
score_ = score #* multiplier
Result.objects.create(quiz=quiz, user=user, score=score_)
if score_:#>= quiz.required_score_to_pass:
return JsonResponse({'passed': True, 'score': score_, 'results': results})
else:
return JsonResponse({'passed': False, 'score': score_, 'results': results})
CodePudding user response:
Let's try to see what Django manual saying about it...
This exception is raised by the ORM when an expected object is not found. For example, QuerySet.get() will raise it when no object is found for the given lookups.
Try to run:
for k in data_.keys():
try:
question = Question.objects.get(text=k)
except Question.DoesNotExist:
print(f'question with text "{k}" is not found')
questions.append(question)
And check if you have this text inside DB by running SQL query manually:
select * from question where text = 'not found k';
CodePudding user response:
Always use a try.. Except block when you want to get or rather you can do
q=Question.objects.filter(a=blah, b=blah)
If q is not None
my_q = q.first()
Get will always throw an error if it see nothing... Filter will not