Сохранение экземпляра модели с использованием сигнала предварительного сохранения

#django #django-models #django-signals

#django #django-модели #django-сигналы

Вопрос:

Это мои модели:

 class Stockdata(models.Model):
    user        = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True,related_name='user_stock')
    company     = models.ForeignKey(Company,on_delete=models.CASCADE,null=True,blank=True)
    stock_name  = models.CharField(max_length=32)

class Stock_journal(models.Model):
    user                = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True,related_name='user_closing')
    company             = models.ForeignKey(Company,on_delete=models.CASCADE,null=True,blank=True)
    stockitem           = models.OneToOneField(Stockdata,on_delete=models.CASCADE,null=True,blank=True,related_name='closingstock')
    closing_stock       = models.DecimalField(max_digits=10,decimal_places=2,null=True)
 

Это мой сигнал:

 @receiver(post_save, sender=Stockdata)
def create_default_stock_ledger(sender, instance, created, **kwargs):
    if created:
        Stock_journal.objects.create(user=instance.User,company=instance.Company,stockitem=instance)
 

Я хочу передать сигнал pre_save того же, что я сделал в своем сигнале post_save, т.Е. Я хочу выполнить функцию сигнала pre_save вместо сигнала post_save..

Когда я пытаюсь выполнить это с помощью сигнала предварительного сохранения, я получаю следующую ошибку:

 save() prohibited to prevent data loss due to unsaved related object 'stockitem'.
 

Есть идеи, как это сделать?

Спасибо

Комментарии:

1. Вы только что заменили post_save на pre_save ? У него разные аргументы.

2. Да, я сделал то же самое, используя pre_save, который выдает мне сообщение об ошибке

Ответ №1:

Вы присваиваете несохраненный объект stockitem(Stockdata) объекту OneToOneField, и, таким образом, он выдает ошибку.

Когда вы присваиваете объект stockitem (Stockdata) объекту OneToOneField, идентификатор не генерируется, поскольку вы не сохранили объект stockitem, и, следовательно, как сообщает ошибка, это приведет к потере данных при сохранении модели Stock_journal.

Комментарии:

1. Это не будет работать для сигнала предварительного сохранения, поскольку Stockdata еще не сохранен. В то время как в post_save у вас есть экземпляр Stockdata, который сохранен в базе данных.

Ответ №2:

pre_save имеет другие аргументы, чем post_save . Когда вы используете created , вы на самом деле используете raw .

В тот момент, когда вы вызываете Stock_journal.objects.create , ваш экземпляр даже не сохраняется (т. Е. Существует в базе данных), поэтому вы не можете использовать instance его при Stack_journal создании.

Подробнее о raw из документов django:

raw — логическое значение; True, если модель сохраняется точно так, как она представлена (т. Е. При загрузке приспособления). Не следует запрашивать / изменять другие записи в базе данных, поскольку база данных может еще не находиться в согласованном состоянии.

Комментарии:

1.Я знаю pre_save , что сигналы имеют разные аргументы, я использовал это для pre_save (sender,instance,*args,**kwargs)

2. Ну, на самом деле это не имеет значения, если вы пытаетесь сохранить связанный объект, ссылаясь на instance , у вас возникнет эта проблема — django не может сохранить его, не зная instance id , и он этого не знает, потому instance что его еще нет в базе данных. Вот почему post_save работает.