Django: доступ к объектам ManyToManyField после сохранения - PullRequest
2 голосов
/ 04 февраля 2010

Это сбивает меня с толку ... Когда я сохраняю свою модель, объекты книги остаются неизменными.Но если я открою счет и сохраню его снова, изменения будут внесены.Что я делаю не так?

class Invoice(models.Model):
    ...
    books = models.ManyToManyField(Book,blank=True,null=True)
    ...

    def save(self, *args, **kwargs):
        super(Invoice, self).save(*args, **kwargs)
        for book in self.books.all():
            book.quantity -= 1
            if book.quantity == 0:
                book.sold = True;
            book.save()

Редактировать: Я пытался использовать сигнал post_save, но он работает так же.Никаких изменений при первом сохранении, изменения сохраняются во второй раз.

Обновление: Кажется, будет решена с этим кодом:

class InvoiceAdmin(admin.ModelAdmin):
    ...

    def save_model(self, request, obj, form, change):
        obj.save()
        for bk in form.cleaned_data['books']:
            book = Book.objects.get(pk=bk.id)
            book.quantity -= 1
            if book.quantity == 0:
                book.sold = True;
            book.save()

Ответы [ 2 ]

4 голосов
/ 17 августа 2012

Вот как я обошел это, действительно непонятное поведение. Подключите приемник сигнала к событию models.signals.m2m_changed, которое вызывается при каждом изменении поля m2m. Встроенные комментарии объясняют, почему.

class Gig(models.Model):
    def slugify(self):
        # Add venue name, date and artists to slug
        self.slug = slugify(self.venue.name) + "-"
        self.slug += self.date.strftime("%d-%m-%Y") + "-"
        self.slug += "-".join([slugify(artist.name) for artist in self.artists.all()]) 
        self.save()


@receiver(models.signals.m2m_changed, sender=Gig.artist.through)
def gig_artists_changed(sender, instance, **kwargs):
    # This callback function get's called twice. 
    # 1 first change appears to be adding an empty list
    # 2nd change is adding the actual artists
    if instance.artist.all() and not instance.slug:                                                                                                                                                               
        instance.slugify()
1 голос
/ 04 февраля 2010

Это потому, что отношение m2m сохраняется после сохранения вашей модели, чтобы получить PK родительского объекта. В вашем случае второе сохранение работает, как и ожидалось, потому что модель уже имеет PK и связанные книги из первого сохранения (это делается в сигнале).

Я еще не нашел решения, лучше всего внести изменения в представлении администратора , я думаю.

...