#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
работает.