Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Django model signals are not working?

I am trying to create activity streams of users from their status.

models:

class Status(models.Model):     body = models.TextField(max_length=200)     image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name)     privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')     pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)     user = models.ForeignKey(User)  class Activity(models.Model):     actor = models.ForeignKey(User)     action = models.CharField(max_length=100)     content_type = models.ForeignKey(ContentType)     object_id = models.PositiveIntegerField()     content_object = generic.GenericForeignKey('content_type', 'object_id')     pub_date = models.DateTimeField(auto_now_add=True, auto_now=False) 

However, although I create a new status, it does not create a new activity from the post_save signal.

signals:

from django.contrib.contenttypes.models import ContentType from django.db.models.signals import post_save from status.models import Status from models import Activity  def create_activity_item(sender, instance, signal, *args, **kwargs):     if kwargs.get('created', True):         ctype = ContentType.objects.get_for_model(instance)          if ctype.name == 'Status':             action = ' shared '              activity = Activity.objects.get_or_create(                 actor = instance.user,                 action = action,                 content_type = ctype,                 object_id = instance.id,                 pub_date = instance.pubdate             )  post_save.connect(create_activity_item, sender=Status) 

What am I doing wrong? Please help me solve this problem. I will be very much grateful. Thank you.

Update:

However doing like this creates the activity:

@receiver(post_save, sender=Status) def create(sender, instance, **kwargs):     if kwargs.get('created',True):         ctype = ContentType.objects.get_for_model(instance)         activity = Activity.objects.get_or_create(             actor = instance.user,             action = ' shared ',             content_type = ctype,             object_id = instance.id,             pub_date = instance.pub_date         ) 

Why doesn't the above works then?

like image 355
Kakar Avatar asked Jan 25 '15 09:01

Kakar


People also ask

How do Django signals work?

Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place.

Are Django signals synchronous?

Like most of Django, they are fully "synchronous".

Should I use signals Django?

Only use signals to avoid introducing circular dependencies. If you have two apps, and one app wants to trigger behaviour in an app it already knows about, don't use signals. The app should just import the function it needs and call it directly.

What are built-in signals in Django?

Django provides a set of built-in signals that let user code get notified by Django itself of certain actions. These include some useful notifications: Sent before or after a model’s save () method is called. Sent before or after a model’s delete () method or queryset’s delete () method is called. Sent when a ManyToManyField on a model is changed.

How to import activity signals in Django?

from django.apps import AppConfig class ActivityAppConfig (AppConfig): name = 'activity' def ready (self): import activity.signals And don't forget to add dispatch_uid to your connect () call: post_save.connect (create_activity_item, sender=Status, dispatch_uid="create_activity_item")

What happens when you save a user model in Django?

You can get confused from this piece of code if you are new to Django, So what is happening is when the User model is saved, a signal is fired called create_profile which creates a Profile instance with a foreign key pointing to the instance of the user. The other method save_profile just saves the instance.

What is a signal dispatcher in Django?

Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.


1 Answers

Seems like your post_save.connect is not executed. You should import signals somewhere. For django 1.7 it is recommended to do this in the app's config ready() function. Read the "Where should this code live?" side note in the docs.

For example if your app is called activity:

activity/__init__.py

default_app_config = 'activity.apps.ActivityAppConfig' 

activity/apps.py

from django.apps import AppConfig  class ActivityAppConfig(AppConfig):     name = 'activity'      def ready(self):         import activity.signals 

And don't forget to add dispatch_uid to your connect() call:

post_save.connect(create_activity_item, sender=Status,                   dispatch_uid="create_activity_item") 

UPDATE: name attribute of ContentType is always in lower case. So you should change the if statement to:

if ctype.name == 'status': 
like image 136
catavaran Avatar answered Oct 02 '22 06:10

catavaran