0

I want to create a pre_save signal which will update the already created model instance whenever the sender is updated. I want to do it in pre_save signal.

The previous instance of the model will be either deleted and new instance will be created or the previous instance will be updated.

My models:

class Sales(models.Model):
    user            = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True)
    company         = models.ForeignKey(Company,on_delete=models.CASCADE,null=True,blank=True)
    party_ac        = models.ForeignKey(Ledger1,on_delete=models.CASCADE,related_name='partyledgersales')
    sales           = models.ForeignKey(Ledger1,on_delete=models.CASCADE,related_name='saleledger')
    date            = models.DateField(default=datetime.date.today,blank=False, null=True)
    sub_total       = models.DecimalField(max_digits=10,decimal_places=2,blank=True, null=True)

class Journal(models.Model):
    user            = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True)
    company         = models.ForeignKey(Company,on_delete=models.CASCADE,null=True,blank=True,related_name='Companyname')
    voucher_id      = models.PositiveIntegerField(blank=True,null=True)
    date            = models.DateField(default=datetime.date.today)
    by              = models.ForeignKey(Ledger1,on_delete=models.CASCADE,related_name='Debitledgers')
    to              = models.ForeignKey(Ledger1,on_delete=models.CASCADE,related_name='Creditledgers')
    debit           = models.DecimalField(max_digits=10,decimal_places=2,null=True)
    credit          = models.DecimalField(max_digits=10,decimal_places=2,null=True)

My pre_save signal for creation:

@receiver(pre_save, sender=Sales)
def user_created_sales(sender,instance,*args,**kwargs):
    if instance.sub_total != None:
            Journal.objects.update_or_create(user=instance.user,company=instance.company,date=instance.date,voucher_id=instance.id,by=instance.party_ac,to=instance.sales,debit=instance.sub_total,credit=instance.sub_total)

I want to create a signal which will update the Journal instance whenever the sender model or Sales model is update or delete the previous instance or create a new one.

Any idea how to perform this?

Thank you

Niladry Kar
  • 1,163
  • 4
  • 20
  • 50
  • You're showing us code of your pre_save signal handler. Is it not working? Or it raises an error? Or it does something unexpected? Explain what your current code is doing. – dirkgroten Mar 27 '19 at 12:09
  • Its working fine. I just wanted to create another pre_save signal for update i.e when the sender is updated(not created) it will update the same instance of journal model that it had created previously. Or it will delete the previous instance and create a new one – Niladry Kar Mar 27 '19 at 12:12
  • this might help https://stackoverflow.com/a/10672822/6027876 – Aarif Mar 27 '19 at 12:17

1 Answers1

1

update_or_create takes two sets of parameters:

  • kwargs which are the parameters that uniquely identify the row to fetch from the database
  • defaults which are the parameters that should be updated

Right now, you're never updating existing instances of Journal because you haven't specified defaults. You're looking for instances that match all the parameters, if one exists, you don't do anything, if it doesn't exist you create it.

You haven't told us what makes a Journal entry unique (and how it relates to a Sales entry, since there is no ForeignKey relationship between them). update: with voucher_id, you now have way of looking up the corresponding Journal entries.

But something like:

Journal.objects.update_or_create(
    user=instance.user,
    company=instance.company,
    voucher_id=instance.id,
    defaults={
        'date': instance.date,
        'debit': instance.sub_total,
        'credit': instance.sub_total,
        'by': instance.party_ac,
        'to': instance.sales}
)

would look for existing instance with the same user, company, and voucher_id and update the date, by, to, credit and debit.

dirkgroten
  • 20,112
  • 2
  • 29
  • 42
  • No the problem is still there... It is creating a new instance all the time – Niladry Kar Mar 27 '19 at 12:42
  • What makes a `Journal` instance unique to a `Sales` instance? Based on what do you fetch an existing `Journal` instance? – dirkgroten Mar 27 '19 at 13:10
  • Is there any way to delete the previous entry and create a new one? – Niladry Kar Mar 27 '19 at 13:13
  • Again, how do you define "previous" entry? Based on which parameters do you know which entry to fetch? ie which `Journal` entry "belongs" to the `Sales` entry? Why don't you have a ForeignKey from Journal to Sales? – dirkgroten Mar 27 '19 at 13:15
  • There is no relation between them, Its just a signal I have passed which will be triggered whenever a `Sales` model is created – Niladry Kar Mar 27 '19 at 13:16
  • 1
    Then there's no way to know which `Journal` entry is the "previous" one. You need to have some unique parameter or combination of parameters on your `Sales` object that defines the corresponding `Journal` object. – dirkgroten Mar 27 '19 at 13:17
  • In the code of my answer, I'm assuming the combination is user, company, party_ac and sales. But if party_ac and/or sales are also changed (because for example you create a new `Ledger1` object), then this doesn't work. Maybe you should consider adding the relationship to Sales with a OneToOneField for example. – dirkgroten Mar 27 '19 at 13:19
  • Can I have the `id` of `Sales` in unique parameter. I have updated my question, I have created a field `voucher_id` in my `Journal` model and this field is related with the primary key of `Sales` model. Can I do that? – Niladry Kar Mar 27 '19 at 13:20
  • exactly, you need a relationship. I've updated my answer. If user and company can also change, you should move them to defaults as well. – dirkgroten Mar 27 '19 at 13:23