views:

32

answers:

2

I've been struggling with this problem for 5 hours and I have a feeling it's a simple solution that I'm just overlooking.

I'm trying to tie in a third party module (Django Activity Stream) that uses a series of senders and receivers to post data about user activity to a database table. Everything is set up and installed correctly, but I get a 'Signal' Object has No Attribute 'Save' error when I try to run it.

I suspect the problem is in my syntax somewhere. I'm just getting started with Signals, so am probably overlooking something a veteran will spot immediately.

In views.py I have:

from django.db.models.signals import pre_save
from actstream import action    ##This is the third-party app
from models import Bird

def my_handler(sender, **kwargs):
 action.save(sender, verb='was saved')
 #return HttpResponse("Working Great")

pre_save.connect(my_handler, sender=Bird)

def animal(request):
 animal = Bird()
 animal.name = "Douglas"
 animal.save()

The Django Activity Stream app has this signals.py file:

from django.dispatch import Signal

action = Signal(providing_args=['actor','verb','target','description','timestamp'])

And then this models.py file:

from datetime import datetime
from operator import or_
from django.db import models
from django.db.models.query import QuerySet
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils.timesince import timesince as timesince_
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from actstream import action
...
def action_handler(verb, target=None, **kwargs):
    actor = kwargs.pop('sender')
    kwargs.pop('signal', None)
    action = Action(actor_content_type=ContentType.objects.get_for_model(actor),
                    actor_object_id=actor.pk,
                    verb=unicode(verb),
                    public=bool(kwargs.pop('public', True)),
                    description=kwargs.pop('description', None),
                    timestamp=kwargs.pop('timestamp', datetime.now()))
    if target:
        action.target_object_id=target.pk
        action.target_content_type=ContentType.objects.get_for_model(target)

    action.save()

action.connect(action_handler, dispatch_uid="actstream.models") 
+1  A: 

Your main problem is in the discipline in maintaining coding style, or rather in this case, lack of. You will find that it is easier to identify problems in your code if you do not use the same name to refer to multiple things within the same module; give each object a unique, meaningful name, and refer to it using only that name.

Ignacio Vazquez-Abrams
I won't argue that the coding style is messy, but the problem actually stems back to the docs of the app the OP has chosen to use. The lines of code that are raising the AttributeError are copied verbatim from the docs and are just plain wrong thanks to the original author of the app.
Gabriel Hurley
A: 

The bottom line here is that the docs for that project contain bad code. This line:

action.save(sender, verb='was saved')

isn't ever going to work. The from actstream import action ultimately imports a signal from actstream.signals, and signals do not and never have had a save method. Especially not with such an odd signature of sender, verb.

At first I thought maybe the author had done something odd with subclassing Signal, but after looking at the rest of the codebase, that's just not the case. I'm not entirely sure what the intention of those docs was supposed to be, but the right thing to do in your handler will either be to save a new Action (imported from actstream.models) instance, or to do something with your model.

Sadly, the project's repository has a pretty sorry set of tests/examples, so without downloading and trying the app myself, I can't tell you what needs to happen there. You might try contacting the author or simply try finding a better-documented/better-maintained Activity Streams app.

Gabriel Hurley
Thanks for the answer. I was considering writing this app myself, but then found what I thought was a great shortcut. Looks like I'll just end up writing it on my own anyway. I guess that's what I get for trying to cut corners! Thanks again for your clear response.
Ben S