When I tried to relate an attribute with another one which has an M to M relation I received this error:
get() returned more than one topic -- it returned 2!
Can you guys tell me what that means and maybe tell me in advance how to avoid this error ?
models
class LearningObjective(models.Model):
learning_objective=models.TextField()
class Topic(models.Model):
learning_objective_topic=models.ManyToManyField(LearningObjective)
topic=models.TextField()
output of LearningObjective.objects.all()
[<LearningObjective: lO1>, <LearningObjective: lO2>, <LearningObjective: lO3>]
output of 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>]
views
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()
})
get()
returned more than one topic -- it returned 2!
The above error indicatess that you have more than one record in the DB related to the specific parameter you passed while querying using get()
such as
Model.objects.get(field_name=some_param)
To avoid this kind of error in the future, you always need to do query as per your schema design. In your case you designed a table with a many-to-many relationship so obviously there will be multiple records for that field and that is the reason you are getting the above error.
So instead of using get()
you should use filter()
which will return multiple records. Such as
Model.objects.filter(field_name=some_param)
Please read about how to make queries in django here.
get()
returns a single object. If there is no existing object to return, you will receive <class>.DoesNotExist
. If your query returns more than one object, then you will get MultipleObjectsReturned
. You can check here for more details about get() queries.
Similarly, Django will complain if more than one item matches the get() query. In this case, it will raise MultipleObjectsReturned, which again is an attribute of the model class itself.
M2M will return any number of query that it is related to. In this case you can receive zero, one or more items with your query.
In your models you can us following:
for _topic in topic.objects.all():
_topic.learningobjective_set.all()
you can use _set
to execute a select query on M2M. In above case, you will filter all learningObjective
s related to each topic
Get is supposed to return, one and exactly one record, to fix this use filter()
, and then take first element of the queryset returned to get the object you were expecting from get, also it would be useful to check if atleast one record is returned before taking out the first element to avoid IndexError
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With