0

私には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

4

1 に答える 1

3

コメントで説明したように、これに対する解決策は、返された QuerySet をリストとしてキャストすることでした。インデックスを介してアクセスするときに間違った要素を返すのは予期しない動作であるため、これは基盤となる django 実装のバグであると強く疑っていますが、どこで問題が発生しているのか正確にはわかりません。

デフォルトの動作では、間違った (予期しない) 結果が得られます。

>>> changelog = fm.changelog.all()
>>> changelog[0]
id:3 fred changed message status from Received to Read
>>> changelog[1]
id:3 fred changed message status from Received to Read

リストにキャストすると、正しい (期待される) 結果が得られます。

>>> changelog = list(fm.changelog.all())
>>> changelog[0]
id:2 fred changed message status from New to Received
>>> changelog[1]
id:3 fred changed message status from Received to Read
于 2012-12-04T14:45:02.913 に答える