[Fixed]-In Django how do I notify a parent when a child is saved in a foreign key relationship?

18👍

What you want to look into is Django’s signals (check out this page too), specifically the model signals–more specifically, the post_save signal. Signals are Django’s version of a plugin/hook system. The post_save signal gets sent every time a model is saved, whether it’s updated or created (and it’ll let you know if it was created). This is how you’d use signals to get notified when an Activity has a Cancellation

from django.db.models.signals import post_save

class Activity(models.Model):
    name = models.CharField(max_length=50, help_text='Some help.')
    entity = models.ForeignKey(CancellationEntity)

    @classmethod
    def cancellation_occurred (sender, instance, created, raw):
        # grab the current instance of Activity
        self = instance.activity_set.all()[0]
        # do something
    ...


class Cancellation(models.Model):
    activity = models.ForeignKey(Activity)
    date = models.DateField(default=datetime.now().date())
    description = models.CharField(max_length=250)
    ...

post_save.connect(Activity.cancellation_occurred, sender=Cancellation)

5👍

What’s wrong with the following?

class Cancellation( models.Model ):
    blah
    blah
    def save( self, **kw ):
        for a in self.activity_set.all():
            a.somethingChanged( self )
        super( Cancellation, self ).save( **kw )

It would allow you to to control the notification among models very precisely. In a way, this is the canonical “Why is OO so good?” question. I think OO is good precisely because your collection of Cancellation and Activity objects can cooperate fully.

👤S.Lott

0👍

In Django, you can use a signal to update the parent when a child is changed. To do this, you need to create a signal that listens for the post_save signal of the child model and sends a signal to update the parent model.

# models.py

from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save


class Activity(models.Model):
    name = models.CharField(max_length=50, help_text='Some help.')
    entity = models.ForeignKey(CancellationEntity)


class Cancellation(models.Model):
    activity = models.ForeignKey(Activity)
    date = models.DateField(default=datetime.now().date())
    description = models.CharField(max_length=250)

@receiver(post_save, sender=Cancellation)
def update_activity(sender, instance, **kwargs):
    activity= instance.activity
    activity.save()

In the code above, we’re creating a signal function to listen to the post_save signal of the Cancellation model. The update_activity function takes the sender and instance parameters where sender is the class of the model that sent the signal, and instance is the instance of the model that was saved. The kwargs parameter contains any additional keyword arguments.

When a Cancellation object is saved, the sender parameter is set to Cancellation, and the instance parameter is set to the Cancellation instance that was saved. The update_activity function takes the activity object and saves it, triggering its post_save signal if any.

Now, when a Cancellation object is saved, the update_activity function updates the Activity model as well.

Leave a comment