Django 保存后,模型id不存在
我有多个模型与单个模型相关。在保存这些模型时,我已经覆盖了save来检索主模型的id,以便将操作系统上的文件放在主模型pk键控的目录中 例如,以一座有许多房间的建筑为例。房间的任何图像都将保存在由建筑物id键入的目录中(房间没有子目录) 只要保存房间时建筑存在,我的重写保存方法就可以正常工作。但是,如果该建筑尚未保存,并且我正在通过django管理员向该建筑添加一个房间,则该图像将保留在上载目录中,因为该建筑尚不存在pk 我最初尝试覆盖建筑物上的保存,并将所有房间图像移动到新创建的建筑物目录(再次键入建筑物的pk)。尽管super(Building,self).save(*args,**kwargs)首先未设置建筑的id 然后我决定后保存信号可能更干净,无论如何,这样做。不幸的是,post save中似乎也不存在该id。在第二次保存模型之前,我可以尝试打印ID,但在触发后期保存时看不到任何值 有人能给我指出一个方向来解释为什么id并没有被设置为中所接受的预期输出吗 谢谢 编辑: 下面是一些注释中要求的代码。由于我简化了最初的问题,这里我将包含更多内容。这里有3层,一个带房间的建筑物列表。我试图通过Django 保存后,模型id不存在,django,django-models,django-admin,django-signals,Django,Django Models,Django Admin,Django Signals,我有多个模型与单个模型相关。在保存这些模型时,我已经覆盖了save来检索主模型的id,以便将操作系统上的文件放在主模型pk键控的目录中 例如,以一座有许多房间的建筑为例。房间的任何图像都将保存在由建筑物id键入的目录中(房间没有子目录) 只要保存房间时建筑存在,我的重写保存方法就可以正常工作。但是,如果该建筑尚未保存,并且我正在通过django管理员向该建筑添加一个房间,则该图像将保留在上载目录中,因为该建筑尚不存在pk 我最初尝试覆盖建筑物上的保存,并将所有房间图像移动到新创建的建筑物目录(再
printKwargs['instance']
行简单地打印这个列表。在底部,我包含了两次背靠背保存后的输出。请注意,在第一次保存后,完全没有实例存在。实际上,它们是背靠背的,彼此之间没有任何动作。通过桌子来引用像建筑房间这样的东西。除了数据字段之外,RoomImage、BuildingImage和ListingImage都是相似的,因此我只包含了一个
class Listing(models.Model):
...
buildings = models.ManyToManyField('Building', null=True, blank=True, through = 'Building_Listing')
addresses = models.ManyToManyField(Address, null=True, blank=True)
def __unicode__(self):
return ' & '.join([a.__unicode__() for a in self.addresses.all()])
class Building(models.Model):
...
rooms = models.ManyToManyField('Room', null=True, through="Building_Room")
def __unicode__(self):
return self.description
class Room(models.Model):
...
def __unicode__(self):
return str(self.room_type)
class RoomImage(models.Model):
room = models.ForeignKey(Room)
room_photo = FileBrowseField("Image", max_length=200, blank=True, null=True)
def save(self, *args, **kwargs):
try:
listing = Building_Listing.objects.get(building=Building_Room.objects.get(room=self.room).building).listing
self.room_photo = moveFileBeforeSave(listing, self.room_photo)
except Building_Listing.DoesNotExist:
pass
except Building_Room.DoesNotExist:
pass
super(RoomImage, self).save(*args, **kwargs)
@receiver(post_save, sender=Listing, weak=False)
def save_images_on_listing_create(sender, **kwargs):
#if kwargs['created']:
listing = kwargs['instance']
print kwargs['instance']
listing_image_list = ListingImage.objects.filter(listing = listing)
listing_buildings = Building_Listing.objects.filter(listing = listing).values_list('building', flat=True)
building_image_list = BuildingImage.objects.filter(building__in = listing_buildings)
building_rooms = Building_Room.objects.filter(building__in = listing_buildings).values_list('room', flat=True)
room_image_list = RoomImage.objects.filter(room__in = building_rooms)
for image in listing_image_list:
image.save()
for image in building_image_list:
image.save()
for image in room_image_list:
image.save()
@receiver(post_save, sender=Building, weak=False)
def save_images_in_building_create(sender, **kwargs):
#if kwargs['created']:
print str(kwargs['instance'])+" : building save trigger"
building = kwargs['instance']
building_image_list = BuildingImage.objects.filter(building = building)
building_rooms = Building_Room.objects.filter(building = building).values_list('room', flat=True)
room_image_list = RoomImage.objects.filter(room__in = building_rooms)
for image in building_image_list:
image.save()
for image in room_image_list:
image.save()
一些输出:
[30/Oct/2011 19:52:05] "POST /admin/mls/building/add/?_popup=1 HTTP/1.1" 200 97
# This is the print of the instance kwarg after the first save (ie nothing)
[30/Oct/2011 19:52:10] "POST /admin/mls/listing/add/ HTTP/1.1" 302 0
[30/Oct/2011 19:52:10] "GET /admin/mls/listing/8/ HTTP/1.1" 200 72495
[30/Oct/2011 19:52:10] "GET /admin/jsi18n/ HTTP/1.1" 200 2158
1 Ben Blvd sometown, MN #this is the print of the instance kwarg after the second save
[30/Oct/2011 19:52:12] "POST /admin/mls/listing/8/ HTTP/1.1" 302 0
[30/Oct/2011 19:52:13] "GET /admin/mls/listing/8/ HTTP/1.1" 200 72497
[30/Oct/2011 19:52:13] "GET /admin/jsi18n/ HTTP/1.1" 200 2158
好的,问题看起来是因为你使用了很多关系。看看这些帖子: 我会考虑重构你的代码来改变建筑物和房间之间的关系。现在你说的是“有很多房间,一座建筑物可以与其中的一些房间相关联”。此外,两栋建筑可以与同一个房间相关联。这真的没有道理。实际上,一个房间应该只与一个建筑物相关联,即
class Building(models.Model):
name = models.CharField(...)
...
class Room(models.Model):
building = models.ForeignKey(Building, unique=True)
....
这意味着任何房间只能链接到一个特定的建筑 首先,帕斯蒂格斯是对的,他的答案更好。但是,如果出于某种原因(比如我现在)由于任何原因无法更改代码,并且发现自己在post_save model实例中不存在问题,就像我们在过去几天中发现的那样,下面的想法可能会有所帮助 在我们的例子中,通过表中的manytomany就足以进行后期保存。通过将post save信号附加到through表本身,我们基本上能够捕获我们需要进行post_保存的所有情况,并且作为through表中存在的多个关系的两个连接表的ID,这就足以完成任务。因此,如果您发现自己出于类似的原因出现在这里,是否可以将post_save附加到直通表
同样,pastylegs是对的,但如果出于任何原因您不能这样做,我希望这会有所帮助。您确定保存后的信号是附加在建筑物的保存上,而不是房间的保存上吗?你能把你的信号贴在哪里吗?如果在保存建筑后信号触发,那么您没有理由看不到id(除非您使用commit=False保存,在这种情况下,我不确定信号是否触发?)我非常确定post save已附加到正确的模型,因为我已设置了发送器,并且在第一次后立即保存第二次后也会获得预期的输出。信号/注册装饰器和相关模型代码已包含在编辑中。No commit=False。所包含的输出引用了信号。感谢您的支持我们的帮助,我的想法是困惑的…希望我正在做一些明显的事情。谢谢。完全是因为你在外键上,而不是很多想法。我认为促使我们使用很多的是我们使用的贯穿/贯穿模型。现在我们有贯穿桌子的内联线(即构建房间)。我们这样做是为了解决缺少嵌套内联的问题。单击“编辑”“在建筑上,内联显示该参照建筑的建筑管理显示。现在,在我们能够找到更好的解决方案之前,我们可以尝试在through表上进行post_save。很快就要尝试了。谢谢你的帮助,我感觉到了你的困境!你应该小心,不要(像我一样)落入基于django admin功能设计数据库和业务逻辑的陷阱-这些限制通常是由于前端代码造成的,弯曲后端设计以简化生活有时会导致问题。是的,正是我一直在想的。但这里的情况有点落后(设计糟糕的模型-->基于那些-->现在无法轻松更改的模型构建的管理员)。起初,我们认为出于某种原因需要m2m(不知道为什么),然后我们构建了管理员。因此,我们的管理员现在过于依赖我们设计错误的数据库,无法修复它。再次感谢您的帮助和建议。