Подтвердить что ты не робот

Django - get() возвращает более одной темы

Когда я попытался связать атрибут с другим, который имеет отношение 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()
                  })
4b9b3361

Ответ 1

get() вернулась более чем одна тема - она ​​вернула 2!

Приведенная выше ошибка указывает, что у вас более одной записи в БД, связанной с определенным параметром, который вы передавали, при запросе с использованием get(), например

Model.objects.get(field_name=some_param)

Чтобы избежать такой ошибки в будущем, вам всегда нужно делать запрос в соответствии с вашим дизайном схемы. В вашем случае вы создали таблицу с отношением M2M, поэтому очевидно, что для этого поля будет несколько записей, и именно по этой причине вы получаете указанную выше ошибку.

Поэтому вместо использования get() вам следует использовать filter(), который будет возвращать несколько записей. Например,

Model.objects.filter(field_name=some_param)

Пожалуйста, прочитайте о том, как делать запросы в django здесь.

Ответ 2

get() возвращает один объект. Если для возврата объекта нет существующего объекта, вы получите <class>.DoesNotExist. Если ваш запрос возвращает более одного объекта, вы получите MultipleObjectsReturned. Вы можете проверить здесь для получения более подробной информации о запросах get().

Аналогично, Django будет жаловаться, если более чем один элемент соответствует запросу get(). В этом случае он будет вызывать MultipleObjectsReturned, который снова является атрибутом самого класса модели.

M2M вернет любое количество запросов, с которыми оно связано. В этом случае вы можете получить нулевой, один или несколько элементов с вашим запросом.

В ваших моделях вы можете:

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

вы можете использовать _set для выполнения запроса select на M2M. В приведенном выше случае вы будете фильтровать все learningObjective, относящиеся к каждой теме

Ответ 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, но это может быть не то, что вы хотите.

Ответ 4

У меня была та же проблема и решение было obj = ClassName.objects.filter()

Ответ 5

Get должен возвращать одну и одну запись, чтобы исправить это использование filter(), а затем взять первый элемент набора запросов вернулся, чтобы получить объект, который вы ожидали от get, также было бы полезно проверить, вернется ли хотя бы одна запись, прежде чем вынимать первый элемент, чтобы избежать IndexError

Ответ 6

Начиная с django 1.6, вы можете использовать метод filter() с методом first() вместо метода get() следующим образом:

Model.objects.filter(field_name=some_param).first()