You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

序列化Django模型QuerySet时出现'QuerySet' object has no attribute '_meta'错误求助

Hey there! Let's break down your problem and fix it step by step.

Why You're Getting the "'QuerySet' object has no attribute '_meta'" Error

The core issue here is simple: model_to_dict() is designed to work with a single Django model instance, but you're passing it a QuerySet (a collection of Question objects) from Question.objects.filter(category=category_id). QuerySets don't have the _meta attribute that model_to_dict uses to introspect model fields—only individual model instances do.

Fixing the Serialization & Session Storage

First, let's fix how you save your question list to the session. We need to convert the QuerySet into a JSON-serializable format that plays nicely with Django's session system.

  1. Improve the Model's Serialization Method
    Your existing serialize() method uses __dict__, which includes internal Django attributes (like _state) that can't be serialized. Let's rewrite it to explicitly include only the fields you need:

    class Question(models.Model):
        # ... (your existing fields and methods)
        
        def serialize(self):
            return {
                'id': self.id,
                'question_text': self.question_text,
                'correct_answer': self.correct_answer,
                'publication_date': self.publication_date.isoformat(),
                'question_hint': self.question_hint,
                'question_thumbnail': self.question_thumbnail.url if self.question_thumbnail else '',
                'category_id': self.category.id if self.category else None,
                'difficulty_level': self.difficulty_level
            }
    
  2. Update the Question View to Store a Serialized List
    Instead of passing the QuerySet directly to model_to_dict, convert each question in the QuerySet to its serialized form, then dump the whole list to JSON for the session:

    def question(request, category_name, category_id):
        # Initialize session data if it doesn't exist
        if 'questions' not in request.session:
            questions_by_category = Question.objects.filter(category=category_id)
            # Convert QuerySet to a list of serialized dicts
            serialized_questions = [q.serialize() for q in questions_by_category]
            request.session["questions"] = json.dumps(serialized_questions)
            # Track the current question index in the session
            request.session["current_question_index"] = 0
        
        # Retrieve session data
        serialized_questions = json.loads(request.session["questions"])
        current_index = request.session.get("current_question_index", 0)
        
        # Handle edge case: no questions in the category
        if not serialized_questions:
            return render(request, 'quiz/no_questions.html')
        
        # Handle end of quiz
        if current_index >= len(serialized_questions):
            return render(request, 'quiz/quiz_ended.html')
        
        # Get the current question instance (for accessing choice_set)
        current_question = Question.objects.get(id=serialized_questions[current_index]['id'])
        # Note: Use .first() or .all() instead of .get() if multiple choices exist
        choice = current_question.choice_set.first()
        form = ChoiceForm()  # Initialize empty form for GET requests
        
        context = {
            'question': current_question,
            'choice': choice,
            'form': form
        }
        return render(request, 'quiz/question.html', context)
    

Implementing the "Next Question" Flow

Now let's adjust the accept_choice view to track the user's progress and load the next question:

def accept_choice(request):
    if request.method == 'POST':
        selected_answer = request.POST.get('choiceRadioGroup')
        print(f'Selected answer: {selected_answer}')
        
        # Update the current question index
        current_index = request.session.get("current_question_index", 0)
        current_index += 1
        request.session["current_question_index"] = current_index
        
        # Retrieve session data to determine next step
        serialized_questions = json.loads(request.session["questions"])
        
        if current_index < len(serialized_questions):
            # Get category data for redirect
            next_question_data = serialized_questions[current_index]
            category = QuestionCategory.objects.get(id=next_question_data['category_id'])
            # Redirect to the next question page
            return redirect('question', category_name=category.name, category_id=category.id)
        else:
            # Quiz is finished
            return render(request, 'quiz/quiz_ended.html', {'final_answer': selected_answer})
    
    # If accessed via GET, redirect back to the current question
    serialized_questions = json.loads(request.session["questions"])
    current_index = request.session.get("current_question_index", 0)
    category_id = serialized_questions[current_index]['category_id']
    category = QuestionCategory.objects.get(id=category_id)
    return redirect('question', category_name=category.name, category_id=category_id)

Key Notes to Avoid Future Issues

  • Session Data Handling: Always use json.dumps() when storing complex data in the session, and json.loads() when retrieving it—Django sessions only support serializable data types.
  • ChoiceSet Safety: If a Question can have multiple Choice objects, replace choice_set.get() with choice_set.all() (then loop through choices in your template) or choice_set.first() to avoid exceptions.
  • Edge Cases: Add checks for empty question lists and index out-of-bounds scenarios to prevent crashes.

内容的提问来源于stack exchange,提问作者Ojonugwa Jude Ochalifu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:09:32