Менеджер возвращает объекты модели один раз за запрос (менеджер удаляет объекты после их однократного возврата)
-
03-07-2019 - |
Вопрос
Поведение не было связано с проблемой, представленной ниже.Объяснение смотрите в нижней части поста.Спасибо.
Привет,
В настоящее время я сталкиваюсь с тем, что менеджер по умолчанию для конкретной модели возвращает объекты для этой модели только один раз за запрос или за сеанс оболочки.Ниже приведена расшифровка 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()
[]
Такое поведение характерно только для одной из моих моделей;другие модели, похоже, запрашивают правильно.Я не думаю, что это имеет какое-либо отношение к определению моей Модели, которое по сути таково:
class Entry(models.Model):
user = models.ForeignKey(User, related_name='entries')
blog = models.ForeignKey(Blog, related_name='entries')
positive = models.BooleanField()
Прошу прощения, что мое описание немного расплывчато;Я не понимаю, как могло возникнуть такое поведение, и не знаю, куда копаться дальше.
SQL-код, сгенерированный диспетчером для QuerySet, каждый раз один и тот же (и, очевидно, правильный):
(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 и SQLite, поставляемый в комплекте с Python 2.6.1 на компьютере Mac OS 10.5.
В ответ на один из комментариев я попытался переименовать related_name
параметры для entries1
и entries2
чтобы избежать возможного конфликта, но это не изменило поведения.
РЕШЕНО (думаю)
Извините всех, проблема на самом деле не имела отношения к проблеме, которую я представил.У меня была небрежная ошибка в одном из моих сигналов на вход:
В 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()
Решение
Извините всех, проблема на самом деле не имела отношения к проблеме, которую я представил.У меня была небрежная ошибка в одном из моих сигналов на вход:
В 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()