django - get()返回了多个主题

问题描述 投票:41回答:5

当我尝试将属性与另一个具有M到M关系的属性关联时,我收到此错误:

get()返回了多个主题 - 它返回2!

你能告诉我这意味着什么,也许可以提前告诉我如何避免这个错误?

楷模

class LearningObjective(models.Model):
    learning_objective=models.TextField()

class Topic(models.Model):
    learning_objective_topic=models.ManyToManyField(LearningObjective)
    topic=models.TextField()

LearningObjective.objects.all()的输出

[<LearningObjective: lO1>, <LearningObjective: lO2>, <LearningObjective: lO3>]

Topic.objects.all()的输出

[<Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>, <Topic: Topic object>]

意见

 def create_themen(request):
     new_topic=Topic(topic=request.POST['topic'])
     new_topic.save()
     return render(request, 'topic.html', {'topic': topic.objects.all()})

 def create_learning_objective(request):
     new_learning_objective=LearningObjective(learning_objective=request.POST['learning_objective'])
     new_learning_objective.save()
     new_learning_objective_topic=Topic.objects.get(topic=request.POST['topic'])
     new_learning_objective_topic.new_learning_objective_topic.add(new_learning_objective)
     return render( request, 'learning_objective.html', {
                    'topic': Topic.objects.all(),
                    'todo': TodoList.objects.all(),
                    'learning_objective': LearningObjective.objects.all()
                  })
django django-models django-views
5个回答
90
投票

get()返回了不止一个主题 - 它返回2!

上面的错误表明在使用get()查询时,您在数据库中有多个与您传递的特定参数相关的记录,如

Model.objects.get(field_name=some_param)

为了避免将来出现此类错误,您始终需要根据架构设计进行查询。在您的情况下,您设计了一个具有M2M关系的表,因此显然该字段将有多个记录,这就是您收到上述错误的原因。

因此,您应该使用filter()来返回多个记录,而不是使用get()。如

Model.objects.filter(field_name=some_param)

请阅读有关如何在django here中进行查询的信息。


13
投票

get()返回一个对象。如果没有现有对象返回,您将收到<class>.DoesNotExist。如果您的查询返回多个对象,那么您将获得MultipleObjectsReturned。您可以查看here以获取有关get()查询的更多详细信息。

同样,如果多个项与get()查询匹配,Django会抱怨。在这种情况下,它将引发MultipleObjectsReturned,它再次是模型类本身的属性。

与之相关的M2M will return any number of query。在这种情况下,您可以使用查询接收零个,一个或多个项目。

在您的模型中,您可以关注我们:

for _topic in topic.objects.all():
    _topic.learningobjective_set.all()

您可以使用_set在M2M上执行选择查询。在上述情况下,您将过滤与每个主题相关的所有learningObjectives


3
投票

在你的Topic模型中,你允许不止一个元素具有相同的topic字段。你已经用同一个创建了两个。

topic=models.TextField(verbose_name='Thema')

现在,当您尝试添加新的learningObjective时,您似乎只想将其添加到与您在表单上发送的内容匹配的一个Topic。由于topic字段不止一个,get找到2,因此例外。

您可以使用该learningObjective字段将topic添加到所有主题:

for t in topic.objects.filter(topic=request.POST['Thema']):
    t.learningObjectivesTopic.add(neuesLernziel)

或限制Topic模型有一个独特的topic字段并继续使用get,但这可能不是你想要的。


3
投票

我有同样的问题,解决方案是obj = ClassName.objects.filter()


2
投票

获取应该返回,只有一个记录,修复此使用filter(),然后获取返回的查询集的第一个元素以获取您期望得到的对象,同样检查是否返回至少一个记录也是有用的在取出第一个元素之前避免IndexError

© www.soinside.com 2019 - 2024. All rights reserved.