0

am trying to create a notification system that tracks all the activities of my users. to achieve this I have created two models, The Contribution model and Notifition model

class Contribution(models.Model):
    slug            =   models.SlugField(unique=True, blank=True, null=True)
    user            =   models.ForeignKey(User, on_delete=models.PROTECT)
    amount          =   models.DecimalField(default=0.00, max_digits=6, decimal_places=2)
    zanaco_id       =   models.CharField(max_length=20, blank=True, unique=True, null=True)

class Notification(models.Model):
    slug        =   models.SlugField(unique=True, blank=True)
    content_type    =   models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id       =   models.PositiveIntegerField()
    content_object  =   GenericForeignKey('content_type', 'object_id')
    message         =   models.TextField(null=True)

I want to create a Notification object each time a user creates an object in the Contribution table, but am having some difficulties in getting the object created from CreateView

class ContributionAdd(CreateView):
    model           =   Contribution
    fields          = ['user', 'amount', 'zanaco_id']
    template_name   =   'contribution_add.html'


    def form_valid(self, form, *args, **kwargs):
        activity_ct = ContentType.objects.get_for_model("????")
        Notification.objects.create(content_type=activity_ct, object_id="?????",content_object=???,)
        return super().form_valid(form)

how can I achieve the task above ? is their a way doing this using mixins ?

2 Answers2

2

The object is created in the super form_valid method so until that is called you cannot access it. Instead call the super method first and use self.object to refer to the created object:

class ContributionAdd(CreateView):
    model           =   Contribution
    fields          = ['user', 'amount', 'zanaco_id']
    template_name   =   'contribution_add.html'


    def form_valid(self, form):
        response = super().form_valid(form) # call super first
        Notification.objects.create(content_object=self.object) # Why even pass the other values just pass `content_object` only
        return response
Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
1

An elegant way to do this would be using a post save signal:

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

@receiver(post_save, sender=Contribution)
def createNotification(sender, instance, created, **kwargs):
    if created:
        Notification.objects.create(content_type=activity_ct, object_id="?????",content_object=???,)
Harris Irfan
  • 208
  • 1
  • 7