Сохранение после записи, идентификатор модели отсутствует - PullRequest
2 голосов
/ 31 октября 2011

У меня есть несколько моделей, которые относятся к одной модели. При сохранении этих моделей я перезаписал сохранение, чтобы получить идентификатор основной модели, чтобы поместить файлы в ОС в каталог с ключом pk основной модели.

Например, возьмем здание с множеством комнат. Любые изображения комнат будут сохранены в каталоге с ключом идентификатора здания (без подкаталога для комнат).

Мои переопределенные методы сохранения работают нормально, пока здание существует, когда комната сохраняется. Однако, если здание еще не сохранено, и я добавляю комнату в здание через администратора django, изображение остается в каталоге загрузки, поскольку pk для здания еще не существует.

Первоначально я попытался переопределить сохранение при построении и переместить любые изображения комнат во вновь созданный каталог зданий (опять же отключил pk здания). Несмотря на супер (Building, self) .save (* args, ** kwargs), сначала идентификатор здания не был установлен.

Затем я решил, что сигнал post_save, вероятно, все-таки чище и сделал так. К сожалению, идентификатор не существует в записи, кроме как. Я могу попытаться напечатать идентификатор и не вижу значения, когда после сохранения будет запущено сохранение, пока я не сохраню модель во второй раз.

Может ли кто-нибудь указать мне направление, которое могло бы объяснить, почему идентификатор не устанавливается так, как ожидалось бы, как принято в этом другом ответе SO ?

Спасибо.

Edit:

Вот код, запрошенный в комментарии. Я включил немного больше здесь, поскольку я упростил первоначальный вопрос. Здесь есть 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 ]

2 голосов
/ 31 октября 2011

Хорошо, проблема в том, что проблема в том, что вы используете множество отношений.Взгляните на это сообщение:

сохранить с отношением многие-ко-многим в задаче django

Проблема с отношениями ManyToMany, не обновляющимися сразу после сохранения

Я бы подумал о рефакторинге вашего кода, чтобы изменить отношения между зданием и его комнатами.В данный момент вы говорите: «Есть много комнат, и здание может ассоциироваться с рядом этих комнат».Кроме того, два здания могут быть связаны с одной и той же комнатой.Это на самом деле не имеет смысла.Действительно, комната должна быть связана с одним и только одним строением, то есть

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

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

. Это означает, что любая комната может быть связана только с одним конкретным зданием.

0 голосов
/ 31 октября 2011

Во-первых, пастилеги прав и его ответ лучше. Но если по какой-то причине (как я прямо сейчас) по какой-либо причине не можете изменить код и оказаться в экземпляре модели post_save несуществующих проблем, как мы обнаружили в последние несколько дней, следующая идея может помочь.

В нашем случае многостраничной таблицы было достаточно для post_save. Прикрепив сигнал сохранения после записи к самой сквозной таблице, мы в основном смогли отследить все случаи, для которых нам нужно было выполнить post_saving, и, будучи идентификаторами двух связанных таблиц для многотомного отношения, существующего в сквозной таблице, этого было достаточно, чтобы получить работа сделана Так что, если вы оказались здесь по тем же причинам, можете ли вы вместо этого прикрепить post_save к сквозной таблице?

Опять же, пастилеги правы, но если вы не можете сделать то же самое по какой-либо причине, я надеюсь, что это полезно.

...