【问题标题】:Django Rest Framework API , calling get_queryset twiceDjango Rest Framework API,调用 get_queryset 两次
【发布时间】:2021-07-17 17:38:27
【问题描述】:

我正在开发一个 API,在收到请求时,我将创建一些记录,然后返回结果。所有这些都按预期工作,但 get_queryset 被调用了两次,并且对象被创建了两次。语句 print("create quiz") 执行两次。我究竟做错了什么?请帮忙。

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)  
             

插入数据的测验模型。

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,)
      

根据 ClassID、主题、类别,提取问题列表并创建测验。问题被添加到 quiz_question_quiz 模型中(多对多关系)。

【问题讨论】:

  • 您在上面分享的代码中的缩进看起来不对。您应该设置适当的缩进。
  • 代码正在编译和执行,所以缩进看起来是正确的。你能告诉我为什么你认为它错了吗?
  • 是的,现在看起来很好(在您 1 分钟前进行的编辑之后)
  • 好的,谢谢。知道我做错了什么吗?
  • 您应该只在 get_queryset 方法中“获取查询集”(不应在其中进行写入操作)。如果您可以共享您的附属模型并在该视图中定义您想要的操作,那么我可以向您展示在 DRF 中执行此操作的正确方法。

标签: django django-rest-framework django-views django-serializer


【解决方案1】:

如果get_queryset 被调用两次 - 这并不意味着它被评估两次,所以总的来说它是安全的。 如果你真的需要知道什么在调用get_queryset 方法,你可以打印当前调用堆栈并查看:

import traceback
...
    def get_queryset(self):
        for line in traceback.format_stack():
            print(line.strip())
        ...

【讨论】: