'Django Rest Framework API , calling get_queryset twice
I am working on an API, where on receiving a request, I will create a few records and then return the result. All this is working as expected but get_queryset is being called twice and the object gets created twice. The statment print("create quiz") is executed twice. What am I doing wrong? Any help please.
class CreateQuiz(generics.ListCreateAPIView):
serializer_class = QuizSerializer
def get_queryset(self):
classId = self.kwargs.get('classId',None)
subject = self.kwargs.get('subject',None)
category = Category.objects.filter(class_id=classId,category=subject).values_list('id',flat=True)[0]
subcategory=self.kwargs.get('chapter',None)
total_marks = 30
questionIDs = Question.objects.raw('''somesql''',params=[category,subcategory,total_marks,category,subcategory,total_marks])
questions= MCQuestion.objects.filter(question_ptr_id__in=questionIDs).prefetch_related('answer_set__question')
essayquestions= Essay_Question.objects.filter(question_ptr_id__in=questionIDs)
user = User.objects.get(id=1)
if MCQuestion.objects.filter(question_ptr_id__in=questionIDs).prefetch_related('answer_set__question').exists():
print("create quiz")
quiztitle ="Practice"
quiz = Quiz()
quiz.category_id = category
quiz.title = quiztitle
quiz.owner= user
quiz.single_attempt = False
quiz.durationtest="10:00"
quiz.random_order=True
subcatdescr = SubCategory.objects.filter(id=subcategory).values_list('sub_category',flat=True)[0]
subcatprint=" "
if subcatprint==" ":
subcatprint = subcatdescr
else:
subcatprint = subcatprint+" , "+subcatdescr
quiz.title = "Practice Exam : "+ quiz.category.class_id.classVal +" "+quiz.category.category +" ("+subcatprint+") "
quiz.save()
quizid = Quiz.objects.filter(id=quiz.id).values_list('id',flat=True)[0]
try:
with connection.cursor() as cursor:
cursor.execute("INSERT INTO quiz_subcategory_quiz(subcategory_id,quiz_id) VALUES (%s,%s)",(subcategory,quiz.id,))
except Exception:
print("Did not create quiz subcategory")
category_description = Category.objects.filter(id=category)
for obj in questionIDs:
print(quiz.id)
with connection.cursor() as questioncursor:
questioncursor.execute("INSERT INTO quiz_question_quiz(question_id,quiz_id) VALUES (%s,%s)",(obj.id,quiz.id,))
else:
response = JsonResponse({"error": "there was an error"})
response.status_code = 403 # To announce that the user isn't allowed to publish
return Quiz.objects.filter(id=quizid)
Quiz Model where inserting the data.
class Quiz(models.Model):
title = models.CharField(
verbose_name=_("Title"),
max_length=300, blank=False)
url = models.SlugField(
max_length=60, blank=False,
help_text=_("a user friendly url"),
verbose_name=_("user friendly url"),default=uuid.uuid4)
category = models.ForeignKey(
Category, null=True, blank=True,
verbose_name=_("Category"), on_delete=models.CASCADE)
DIFFICULTY_LEVEL=[
('1','Beginner'),
('2','Intermediate'),
('3','Advanced'),
('4','Exppert'),
]
difficulty = models.CharField(
max_length=2,
choices=DIFFICULTY_LEVEL,
default=2,
)
durationtest = models.CharField(max_length=6,blank=True,null=True)
owner = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
created_at = models.DateTimeField(auto_now_add=True,blank=True,null=True,)
Depending on the ClassID, Subject, Category a list of questions are pulled and a quiz is created. The questions are added in quiz_question_quiz model (many to many relationship).
Solution 1:[1]
The second get_queryset
call performed by renderers.BrowsableAPIRenderer
.
In the real case, when your clients requests your API as format=json
, BrowsableAPIRenderer
is not executed.
Solution 2:[2]
If get_queryset
is called twice - it does not mean it is evaluated twice, so in general it is safe.
If you really need to know what is calling get_queryset
method you can just print the current call stack and see:
import traceback
...
def get_queryset(self):
for line in traceback.format_stack():
print(line.strip())
...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Igor Che |
Solution 2 | Alex Paramonov |