保存后,模型ID不存在

时间:2011-10-31 00:30:42

标签: django django-models django-admin django-signals

我有多个模型,它们与单个模型有关。保存这些模型后,我已覆盖保存以检索主模型的ID,以便将文件放在操作系统的主模型的pk键入的目录中。

例如,带一个有许多房间的建筑物。房间的任何图像都将保存在由建筑物ID标识的目录中(没有房间的子目录)。

只要在保存房间时建筑物存在,我的重写保存方法就可以正常工作。但是如果建筑物尚未保存,并且我通过django管理员向建筑物添加了一个房间,则图像仍保留在上传目录中,因为建筑物尚未存在pk。

我最初尝试覆盖保存建筑并将任何房间图像移动到新创建的建筑目录(再次关闭建筑物的pk)。尽管超级(建筑,自我).save(* args,** kwargs)首先没有设置建筑物的ID。

然后我决定post_save信号反正可能更干净并且这样做了。不幸的是,id似乎不存在于post中。在我第二次保存模型之前,我可以尝试打印ID并在触发保存后看不到任何值。

有人能指出我的方向可以解释为什么id没有被设置为this other SO answer中接受的预期输出吗?

感谢。

编辑:

以下是评论中要求的一些代码。因为我已经简化了最初的问题,所以我在这里再说一点。这里有3个楼层,包括带房间的建筑物。列表是我尝试通过print kwargs['instance']行进行简单打印的内容。在底部,我在两次背靠背保存后包含了输出。注意第一次保存后完全没有实例。这些实际上背靠背,两者之间没有任何行动。对Building_Room等内容的引用是通过表格进行的。除了数据字段外,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

2 个答案:

答案 0 :(得分:2)

好的,所以问题看起来是因为你正在使用的许多关系。看看这些帖子:

save with many-to-many relationship in django problem

Issue with ManyToMany Relationships not updating inmediatly after save

我会考虑重构代码来改变建筑物与房间之间的关系。目前你说“有很多房间,建筑物可以与许多房间相关联”。此外,两个建筑物可以与同一个房间相关联。这没有多大意义。真的一个房间应该只有一个建筑物,即

class Building(models.Model):
    name = models.CharField(...)
    ...

class Room(models.Model):
    building = models.ForeignKey(Building, unique=True)
    ....

这意味着任何房间只能链接到一个特定的建筑物。

答案 1 :(得分:0)

首先,pastylegs是对的,他的答案更好。但是如果出于某种原因(就像我现在一样)由于任何原因无法更改代码并发现自己在post_save模型实例中不存在问题,就像我们在过去几天发现自己一样,以下想法可能会有所帮助。

在我们的例子中,manytomany through table足以用于post_save。通过将post保存信号附加到直通表本身,我们基本上能够捕获我们需要进行post_saving的所有情况,并且作为两个连接表的id,以便通过表中存在的manytomany关系,这足以得到完成的工作。因此,如果您出于类似的原因发现自己,可以将post_save附加到直通表吗?

再一次,贴胎是正确的,但如果你因为某种原因无法做同样的事情,我希望这会有所帮助。