web-dev-qa-db-ja.com

django-get()は複数のトピックを返しました

M to 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()
                  })
_
45
BoJack Horseman

get()は複数のトピックを返しました-2を返しました!

上記のエラーは、次のようなget()を使用してクエリを実行中に渡した特定のパラメーターに関連するDBに複数のレコードがあることを示しています

_Model.objects.get(field_name=some_param)
_

将来この種のエラーを回避するには、スキーマ設計に従って常にクエリを実行する必要があります。あなたの場合、M2M関係でテーブルを設計したので、明らかにそのフィールドには複数のレコードがあり、それが上記のエラーを受け取っている理由です。

したがって、get()を使用する代わりに、複数のレコードを返すfilter()を使用する必要があります。といった

_Model.objects.filter(field_name=some_param)
_

Django here でクエリを作成する方法についてお読みください。

97
CrazyGeek

get() は、単一のオブジェクトを返します。返す既存のオブジェクトがない場合、<class>.DoesNotExistを受け取ります。クエリが複数のオブジェクトを返す場合、MultipleObjectsReturnedを取得します。 get()クエリの詳細については、 here を確認してください。

同様に、Djangoは、get()クエリに複数のアイテムが一致した場合に文句を言います。この場合、モデルクラス自体の属性であるMultipleObjectsReturnedを発生させます。

M2Mは任意の数のクエリを返します それが関連しています。この場合、クエリでゼロ、1つまたは複数のアイテムを受け取ることができます。

あなたのモデルでは次のことができます:

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

_setを使用して、M2Mで選択クエリを実行できます。上記の場合、各トピックに関連するすべてのlearningObjectivesをフィルターします

13
FallenAngel

Topicモデルでは、複数の要素が同じtopicフィールドを持つことを許可しています。同じもので2つを既に作成しました。

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

これで、新しいlearningObjectiveを追加しようとすると、フォームで送信しているものと一致する1つのTopicのみに追加したいようです。同じtopicフィールドを持つ複数のgetが2を検出しているため、例外です。

learningObjectiveフィールドを持つすべてのトピックにtopicを追加できます。

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

またはTopicモデルを一意のtopicフィールドを持つように制限し、getを使用し続けますが、それはあなたが望むものではないかもしれません。

3
Yeray Diaz Diaz

私は同じ問題を抱えていましたが、解決策はobj = ClassName.objects.filter()でした

3
Nitesh

Getは、この使用法を修正するために正確に1つのレコードを返すことになっています filter() 。また、IndexErrorを避けるために、最初の要素を取り出す前に、少なくとも1つのレコードが返されるかどうかを確認すると便利です。

2
lmc