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

时间:2014-02-27 09:06:55

标签: django django-models django-views

当我尝试将属性与另一个具有 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()
                  })

7 个答案:

答案 0 :(得分:90)

  

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

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

Model.objects.get(field_name=some_param)

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

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

Model.objects.filter(field_name=some_param)

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

答案 1 :(得分: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上执行选择查询。在上述情况下,您将过滤与每个主题相关的所有learningObjective

答案 2 :(得分: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 :(得分:3)

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

答案 4 :(得分:2)

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

答案 5 :(得分:0)

要添加到CrazyGeek的答案中,getget_or_create查询仅在数据库中存在一个对象实例,filter适用于两个或更多实例时才起作用。

如果查询可以用于单个或多个实例,则最好在div中添加ID并使用if语句,例如

def updateUserCollection(request):
    data = json.loads(request.body)
    card_id = data['card_id']
    action = data['action']

    user = request.user
    card = Cards.objects.get(card_id=card_id)

    if data-action == 'add':
        collection = Collection.objects.get_or_create(user=user, card=card)
        collection.quantity + 1
        collection.save()

    elif data-action == 'remove':
        collection = Cards.objects.filter(user=user, card=card)
        collection.quantity = 0
        collection.update()

注意:.save()成为.update(),用于更新多个对象。希望这对某人有帮助,让我头痛了一整天。

答案 6 :(得分:-1)

不要:-

xyz = Blogs.objects.get(user_id=id)

使用:-

xyz = Blogs.objects.all().filter(user_id=id)