私には2つのクラスがあり、それらの間には1対多の関係があります。
テストを実行すると、関連するマネージャー('changelog')からアクセスできる2つの子オブジェクトを含む親オブジェクト('fm')が生成されます。
次のコードが実行され、「changelog」リストにUserMessageStatusUpdate
、プロパティが異なる2つの異なるオブジェクトが含まれていることが示されます。
>>> logging.debug(fm.changelog.all())
DEBUG [<UserMessageStatusUpdate: fred changed message status from New to Received>,
<UserMessageStatusUpdate: fred changed message status from Received to Read>]
それらをループすることもできます:
>>> for m in fm.changelog.all():
....logging.debug(m)
DEBUG fred changed message status from New to Received
DEBUG fred changed message status from Received to Read
ただし、インデックスで各オブジェクトにアクセスしようとすると、まったく別のものが得られます。
>>> logging.debug(fm.changelog.all()[0])
DEBUG fred changed message status from Received to Read
>>> logging.debug(fm.changelog.all()[1])
DEBUG fred changed message status from Received to Read
一体何がここで起こっているのですか?
[更新1]
モデル_str_()メソッドにIDを追加したので、インデックスによるアクセスメソッドが同じレコードを2回返していることがわかります。
>>> logging.debug(fm.changelog.all()[0])
DEBUG id:3 fred changed message status from Received to Read
>>> logging.debug(fm.changelog.all()[1])
DEBUG id:3 fred changed message status from Received to Read
では、なぜマネージャーがインデックス経由でアクセスしたときに同じレコードを返すのかという問題があります。(これはデフォルトManager
であり、特別なことは何もありません。)
[更新2]
@stevejalimでこれを調査すると、fm.changelog.all()
オブジェクトが明示的にケースである場合、テストは合格しますlist
:
>>> changelog = list(fm.changelog.all())
>>> logging.debug(changelog[0])
DEBUG id:2 fred changed message status from New to Received
>>> logging.debug(changelog[1])
DEBUG id:3 fred changed message status from Received to Read
fm.changelog.all()を見てください:
>>> logging.debug(type(fm.changelog.all()))
DEBUG <class 'django.db.models.query.QuerySet'>
この問題は、QuerySetがジェネレーターを返し、インデックスでアイテムに直接アクセスできないことに関連しているようです。または、RelatedManager
クラスのこの行に関連している可能性があります:https ://github.com/django/django/blob/stable/1.4.x/django/db/models/fields/related.py#L458
def get_query_set(self):
try:
return self.instance._prefetched_objects_cache[rel_field.related_query_name()]
基本的には謎ですが、リストにキャストすることでうまくいきます。1