単一のモデルに関連する複数のモデルがあります。これらのモデルの保存時に、メイン モデルの pk をキーとするディレクトリに OS 上のファイルを配置するために、メイン モデルの ID を取得するために save をオーバーライドしました。
たとえば、多くの部屋がある建物を考えてみましょう。部屋の画像はすべて、建物の ID をキーとするディレクトリに保存されます (部屋のサブディレクトリはありません)。
部屋が保存されたときに建物が存在する限り、オーバーライドされた保存メソッドは正常に機能します。ただし、建物がまだ保存されておらず、django admin を介して建物に部屋を追加している場合、建物の pk がまだ存在しないため、画像はアップロード ディレクトリに残ります。
最初に、建物の保存を上書きし、部屋の画像を新しく作成された建物ディレクトリに移動しようとしました(再び建物の pk をキーオフしました)。super(Building, self).save(*args, **kwargs) にもかかわらず、最初に建物の ID が設定されていませんでした。
次に、とにかく post_save シグナルがおそらくよりクリーンであると判断し、そのようにしました。残念ながら、ID は投稿保存にも存在しないようです。ID を印刷しようとしても、モデルを 2 回目に保存するまでポスト保存がトリガーされたときに値が表示されません。
この他の SO 回答で受け入れられた出力が期待されるように id が設定されていない理由を説明する方向に誰かが私を向けることができますか?
ありがとう。
編集:
コメントで要求されたコードを次に示します。最初の質問を単純化したので、ここにもう少し含めます。ここには 3 つのレベルがあり、部屋のある建物のリストです。リストは、私が行を介して単純に印刷しようとしたものですprint kwargs['instance']
. 下部には、2 回連続して保存した後の出力が含まれています。最初の保存後にインスタンスが完全に存在しないことに注意してください。これらは文字通り背中合わせで、間にアクションはありませんでした。Building_Room などへの参照は、テーブルを介して行われます。RoomImage、BuildingImage、および ListingImage は、データ フィールドを除けばすべて似ているため、1 つだけ含めました。
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