序列化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.
Improve the Model's Serialization Method
Your existingserialize()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 }Update the Question View to Store a Serialized List
Instead of passing the QuerySet directly tomodel_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, andjson.loads()when retrieving it—Django sessions only support serializable data types. - ChoiceSet Safety: If a
Questioncan have multipleChoiceobjects, replacechoice_set.get()withchoice_set.all()(then loop through choices in your template) orchoice_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

