マネージャーはモデルオブジェクトをリクエストごとに1回返します(マネージャーはオブジェクトを1回返すとオブジェクトをドロップします)

StackOverflow https://stackoverflow.com/questions/613706

  •  03-07-2019
  •  | 
  •  

質問

以下に示すように、動作は問題とは無関係でした。説明については、投稿の下部をご覧ください。ありがとう。


こんにちは、

現在、特定のモデルのデフォルトマネージャーがこのモデルのオブジェクトを返すのは、リクエストごとまたはシェルセッションごとに1回だけです。以下は、ビューで停止したPDBトランスクリプトです(ただし、PDBなしでも動作が発生します):

#Nothing up my sleeves (using the default Manager):
(Pdb) p Entry.objects
<django.db.models.manager.Manager object at 0x18523b0>

#Now you see them...
(Pdb) Entry.objects.all()
[<Entry: Entry 1>, <Entry: Entry 2>, <Entry: Entry 3>, <Entry: Entry 4]

#Now you don't!
(Pdb) Entry.objects.all()
[]

いつでもオブジェクトを取得すると、そのオブジェクトは後のクエリセットに表示されなくなります。

#(New Request from above)

#If I only request one object then it is the one that disappears
(Pdb) Entry.objects.all()[0]
[<Entry: Entry 1>]

#Here Entry 1 is missing
(Pdb) Entry.objects.all()
[<Entry: Entry 2>, <Entry: Entry 3>, <Entry: Entry 4]

#And now they're all gone.
(Pdb) Entry.objects.all()
[]

この動作は、私のモデルの1つのみです。他のモデルは正しくクエリを実行しているようです。私はそれが私のモデルの定義とは何の関係もないと思いますが、それは基本的にです:

class Entry(models.Model):
    user = models.ForeignKey(User, related_name='entries')
    blog = models.ForeignKey(Blog, related_name='entries')
    positive = models.BooleanField()

説明が少し曖昧であることをおizeびします。この動作がどのように発生するかについて混乱しているため、次にどこを探すべきかわかりません。

ManagerがQuerySet用に生成するSQLは、毎回同じ(明らかに明らかに)です:

(Pdb) p Entry.objects.all().query.as_sql()
('SELECT "myapp_entry"."id", "myapp_entry"."user_id", "myapp_entry"."blog_id", "myapp_entry"."positive" FROM "myapp_entry"', ())
(Pdb) p Entry.objects.all()
[<Entry: Entry 1>, <Entry: Entry 2>, <Entry: Entry 3>, <Entry: Entry 4]

(Pdb) p Entry.objects.all().query.as_sql()
('SELECT "myapp_entry"."id", "myapp_entry"."user_id", "myapp_entry"."blog_id", "myapp_entry"."positive" FROM "myapp_entry"', ())
(Pdb) Entry.objects.all()
[]

Django 1.0.2、Python 2.6.1、およびMac OS 10.5マシンでPython 2.6.1に同梱されているSQLiteを使用しています。

コメントの1つに応じて、 related_name パラメーターの名前を entries1 および entries2 に変更して競合を回避しようとしましたが、動作を変更します。


解決済み(私は思う)

申し訳ありませんが、問題は実際に私が提示した問題とは無関係でした。エントリーのシグナルの1つに不注意なバグがありました:

myapp .__ init __ で:

post_init.connect(entry_initialized, sender=Entry)

myapp.signals で:

def entry_initialized(sender, instance, *args, **kwargs):
    try:
        #Disconnect signal to avoid infinite recursion
        post_init.disconnect(entry_initialized, sender=Entry)

        #Intializing a new Entry here would cause the recursion
        #Check to see if there is a previous entry by this user in this blog
        #In this app entries are unique by (User, Blog)
        #And what we want to do is remove the old Entry if the positive fields don't match
        prev_instance = Entry.objects.get(user=instance.user, blog=instance.blog)

        #This is an error: it is not appropriate to delete without some checking
        prev_instance.delete()

        post_init.connect(verification_initialized, sender=Verification)
    except:
        post_init.connect(verification_initialized, sender=Verification)

コードの正しいバージョンは次のようになります。

        #Only delete if this is a different Entry with same user/blog and the positive field is different.
        if not instance.id == prev_instance and not instance.positive == prev_instance.positive:
            prev_instance.delete()
役に立ちましたか?

解決

申し訳ありませんが、問題は実際に私が提示した問題とは無関係でした。エントリーのシグナルの1つに不注意なバグがありました:

myapp .__ init __ で:

post_init.connect(entry_initialized, sender=Entry)

myapp.signals で:

def entry_initialized(sender, instance, *args, **kwargs):
    try:
        #Disconnect signal to avoid infinite recursion
        post_init.disconnect(entry_initialized, sender=Entry)

        #Intializing a new Entry here would cause the recursion
        #Check to see if there is a previous entry by this user in this blog
        #In this app entries are unique by (User, Blog)
        #And what we want to do is remove the old Entry if the positive fields don't match
        prev_instance = Entry.objects.get(user=instance.user, blog=instance.blog)

        #This is an error: it is not appropriate to delete without some checking
        prev_instance.delete()

        post_init.connect(verification_initialized, sender=Verification)
    except:
        post_init.connect(verification_initialized, sender=Verification)

コードの正しいバージョンは次のようになります。

        #Only delete if this is a different Entry with same user/blog and the positive field is different.
        if not instance.id == prev_instance and not instance.positive == prev_instance.positive:
            prev_instance.delete()
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top