Git Product home page Git Product logo

django-activity-stream's Introduction

Django Activity Stream

image

Join the chat at https://gitter.im/django-activity-stream/Lobby

image

image

image

What is Django Activity Stream?

Django Activity Stream is a way of creating activities generated by the actions on your site.

It is designed for generating and displaying streams of interesting actions and can handle following and unfollowing of different activity sources. For example, it could be used to emulate the Github dashboard in which a user sees changes to projects they are watching and the actions of users they are following.

Action events are categorized by four main components.

  • Actor. The object that performed the activity.
  • Verb. The verb phrase that identifies the action of the activity.
  • Action Object. (Optional) The object linked to the action itself.
  • Target. (Optional) The object to which the activity was performed.

Actor, Action Object and Target are GenericForeignKeys to any arbitrary Django object and so can represent any Django model in your project. An action is a description of an action that was performed (Verb) at some instant in time by some Actor on some optional Target that results in an Action Object getting created/updated/deleted.

For example: justquick (actor) closed (verb) issue 2 (object) on django-activity-stream (target) 12 hours ago

Nomenclature of this specification is based on the Activity Streams Spec: http://activitystrea.ms/

For complete documentation see Django Activity Stream Documentation

Contributors


This project exists thanks to all the people who contribute!

image

django-activity-stream's People

Contributors

artscoop avatar asdfkaba avatar auvipy avatar benslavin avatar brunoamaral avatar cb109 avatar deepakprakash avatar dependabot[bot] avatar ehsabd avatar frwickst avatar hugokernel avatar jarus avatar jasonculverhouse avatar jazzido avatar jocelyndelalande avatar josh-j-bailey avatar joshourisman avatar justquick avatar lociii avatar michaeljones avatar nrb avatar ntend avatar olifante avatar robbyt avatar slurms avatar smileychris avatar timgates42 avatar trevershick avatar uruz avatar wadewilliams avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-activity-stream's Issues

AttributeError

Hello, when I tried visiting “127.0.0.1:8000/activity/” the page is always displaying “No actions yet” even when users comment on their status, follow each other. It won’t show any activity been done by users.
I tried creating my custom streams, but I’m getting error:

 AttributeError at /activity/actors/3/1/
 'GenericRelatedObjectManager' object has no attribute 'mystream'
 Request Method:    GET
 Request URL:   http://127.0.0.1:8000/activity/actors/3/1/
 Django Version:    1.3.1
 Exception Type:    AttributeError
 Exception Value:   'GenericRelatedObjectManager' object has no attribute 'mystream'
 Exception Location:    C:\Python27\Scripts\myweb\..\myweb\meekapp\views.py in <module>, line 33
 Python Executable: C:\Python27\python.exe
 Python Version:    2.7.2

In myapp/managers.py

from datetime import datetime
from django.contrib.contenttypes.models import ContentType
from actstream.managers import ActionManger, stream

       class MyActionManager(ActionManager):
              @stream
               def mystream(self, obj, verb='posted', time=None):
                        if time is None:
                                time=datetime.now()
                         return obj.actor_actions.filter(verb=verb, timestamp__lte=time)

in views:

 from django.contrib.auth.models import User
from actstream.models import Action

actvity

 user_instance=User.objects.all()[0]
  user_instance.actor_actions.mystream ('commented','status','rate','profile')

What I’m I doing wrong?

KeyError in gfk.py

When using model_stream(Model) in views I get this error :

Exception Type: KeyError
Exception Value: (15L, u'1')
Exception Location: site-packages/actstream/gfk.py in fetch_generic_relations, line 79

This Model works with follow() and unfollow()

Feature request: Store actions made by anonymous users

Thanks for the great app.

I'd like to be able to store actions done by anonymous users. A simple solution would be to allow actor and actor_object_id to be None. A more complicated one is to store IP as actor identifier. Is this possible and/or planned?

It doesn't scale

It runs 1 query for each activity, just try to follow 1000 users:
follow(user1, user2)

On user1 activity runs more than 2000 queries, on following users runs more than 1000 queries.
The concept is nice, the implementation in real work doesn't scale.

Buildout install issue.

I'm trying to install your app through zc.buildout in conjunction with the django recipe, but get the following error:

Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 1712, in main
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 1700, in with_ei_usage
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 1716, in
File "/usr/lib/python2.6/distutils/core.py", line 152, in setup
dist.run_commands()
File "/usr/lib/python2.6/distutils/dist.py", line 975, in run_commands
self.run_command(cmd)
File "/usr/lib/python2.6/distutils/dist.py", line 995, in run_command
cmd_obj.run()
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 211, in run
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 427, in easy_install
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 476, in install_item
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 655, in install_eggs
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 930, in build_and_install
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/command/easy_install.py", line 919, in run_setup
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/sandbox.py", line 62, in run_setup
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/sandbox.py", line 105, in run
File "/usr/local/lib/python2.6/dist-packages/setuptools-0.6c11-py2.6.egg/setuptools/sandbox.py", line 64, in
File "setup.py", line 2, in
File "/tmp/easy_install-Q3wUFP/django-activity-stream-0.2.1/actstream/init.py", line 1, in
#
File "/tmp/easy_install-Q3wUFP/django-activity-stream-0.2.1/actstream/signals.py", line 1, in
ImportError: No module named django.dispatch
An error occured when trying to install django-activity-stream 0.2.1. Look above this message for any errors that were output by easy_install.
While:
Installing production.
Getting distribution for 'django-activity-stream'.
Error: Couldn't install: django-activity-stream 0.2.1

Seems like the egg build is failing as it requires a not yet available django? Help. Thanks.
Also can you maybe upload a compiled egg to PyPi?

Thanks, your app rocks!

test_zzzz_no_orphaned_actions doesn't make sense, failed

I' m not sure what this test was going for....

def test_zzzz_no_orphaned_actions(self):
    actions = actor_stream(self.user1).count()
    self.user2.delete()
    self.assertEqual(actions, actor_stream(self.user1).count() + 1)

actor_stream(self.user1) changes from:

[<Action: admin commented on CoolGroup 0 minutes ago>, <Action: admin started following Two 0 minutes ago>, <Action: admin joined CoolGroup 0 minutes ago>]

to

[<Action: admin commented on CoolGroup 3 minutes ago>, <Action: admin started following 3 minutes ago>, <Action: admin joined CoolGroup 3 minutes ago>]

all streams including own?

What would be the best way to retrieve a feed of all streams of all types including one's own activities?

AttributeError

Hello, when I tried visiting “127.0.0.1:8000/activity/” the page is always displaying “No actions yet” even when users comment on their status, follow each other. It won’t show any activity been done by users.
I tried creating my custom streams, but I’m getting error:

 AttributeError at /activity/actors/3/1/
 'GenericRelatedObjectManager' object has no attribute 'mystream'
 Request Method:    GET
 Request URL:   http://127.0.0.1:8000/activity/actors/3/1/
 Django Version:    1.3.1
 Exception Type:    AttributeError
 Exception Value:   'GenericRelatedObjectManager' object has no attribute 'mystream'
 Exception Location:    C:\Python27\Scripts\myweb\..\myweb\meekapp\views.py in <module>, line 33
 Python Executable: C:\Python27\python.exe
 Python Version:    2.7.2

In myapp/managers.py

from datetime import datetime
from django.contrib.contenttypes.models import ContentType
from actstream.managers import ActionManger, stream

class MyActionManager(ActionManager):
@stream
def mystream(self, obj, verb='posted', time=None):
if time is None:
time=datetime.now()
return obj.actor_actions.filter(verb=verb, timestamp__lte=time)

in views:

 from django.contrib.auth.models import User
from actstream.models import Action

actvity

 user_instance=User.objects.all()[0]
  user_instance.actor_actions.mystream ('commented','status','rate','profile')

What I’m I doing wrong?

No i18n

Having the verb as well as the structure of the sentence hardcoded in the models prevents from using this in other languages.

You should use gettext to translate both action.verb and the pattern sentence (not every language order words the same way).

Otherwise, nice app !

user_stream returns empty set on follow >1

In managers.py the following code:

    qs = self.get_query_set()
    for follow in Follow.objects.filter(user=object).select_related('actor'):
        if follow.actor:
            qs &= follow.actor.actor_actions.public(**kwargs)
    return qs

It iterates over the Follow objects applying a filter to the default queryset (all items). It appears on testing here that if you follow >1 object this always returns an empty set.

Should this not instead build a Q object of OR comparisons to the actor_actions?

actstream_follow will create duplicate 'follow' records in database

If you hit the actstream_follow view multiple times, multiple Follow records get created.
I could check for existing follow records... but i'm lazy.
I am fairly new to Python/Django, but I altered your models.py on my machine and added a unique_together clause in the Meta class of Follow. Then i catch an "IntegrityError" in the follow() method. If an IntegrityError is raised the follow method still returns a Follow object but it returns the existing object instead of creating a new one and it DOESNT fire the signal.

I don't know if this fix is very Python'ish though.

I also wasn't able to get the tests to pass either but I think that's because I dont' know how to get them to run for a standalone django app without a project.

diff --git a/actstream/models.py b/actstream/models.py
index 699ebf5..0f1bd0a 100644
--- a/actstream/models.py
+++ b/actstream/models.py
@@ -8,6 +8,7 @@ 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 django.db import IntegrityError

 from actstream.signals import action

@@ -36,7 +37,10 @@ class Follow(models.Model):
     actor = generic.GenericForeignKey()

     objects = FollowManager()
-    
+
+    class Meta:
+        unique_together = (("user", "content_type", "object_id"),)
+
     def __unicode__(self):
         return u'%s -> %s' % (self.user, self.actor)

@@ -157,10 +161,15 @@ def follow(user, actor, send_action=True):
         follow(request.user, group)

     """
-    if send_action:
-        action.send(user, verb=_('started following'), target=actor)
-    return Follow.objects.create(user = user, object_id = actor.pk, 
-        content_type = ContentType.objects.get_for_model(actor))
+    try:
+        follow = Follow.objects.create(user = user, object_id = actor.pk, 
+            content_type = ContentType.objects.get_for_model(actor))
+        if send_action:
+            action.send(user, verb=_('started following'), target=actor)
+        return follow
+    except IntegrityError:
+        return Follow.objects.filter(user = user, object_id = actor.pk,
+            content_type = ContentType.objects.get_for_model(actor)).all()[0]

 def unfollow(user, actor, send_action=False):
     """
diff --git a/setup.py b/setup.py
old mode 100644
new mode 100755

0.4.1 install error

IndentationError: ('expected an indented block', ('/Users/pete/projects/test/lib/python2.7/site-packages/actstream/serializers.py', 86, 0, 'from pprint import pprint\n'))

full output follows:

$ pip install django-activity-stream==0.4.1
Downloading/unpacking django-activity-stream==0.4.1
  Downloading django-activity-stream-0.4.1.tar.gz
  Storing download in cache at /Users/pete/.pip/cache/http%3A%2F%2Fpypi.python.org%2Fpackages%2Fsource%2Fd%2Fdjango-activity-stream%2Fdjango-activity-stream-0.4.1.tar.gz
  Running setup.py egg_info for package django-activity-stream

Installing collected packages: django-activity-stream
  Running setup.py install for django-activity-stream
    Sorry: IndentationError: ('expected an indented block', ('/Users/pete/projects/test/lib/python2.7/site-packages/actstream/serializers.py', 86, 0, 'from pprint import pprint\n'))

Successfully installed django-activity-stream
Cleaning up...

Template "actor.html" error because of user_ctype

variable "user_ctype" should be named "ctype" in the actor.html template. It causes a crash when rendering otherwise (while trying to lookup the url with an empty content_type_id).
(from git head)

Generic Relation: 'Action' object has no attribute actions_with_..

I have a Message model whose instances are referenced in Action's action_object.

When I try to delete some messages from the admin interface I get this error:

'Action' object has no attribute 'actions_with_messages_message_as_action_object'

Is this an error on my part? I'm I missing something? Thanks

object_id field of Follow model can't be unique

There is a problem with Follow model, object_id is a TextField and it's defined in unique_together. With mysql it throws error on syncdb, because it has no length specified. Maybe object_id it should be changed (also in Action model) to charfield with max_length argument. Django documentation says:
"For maximum flexibility you can use a TextField which doesn't have a maximum length defined, however this may incur significant performance penalties depending on your database backend."
https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/

Object must be a Django Model not ModelBase

I recently upgraded from django-activity-stream 0.3.9 to 0.4.0, and my code now raises the ModelNotActionable exception. I went through the code, but I cannot determine why this is happening. I am running Django 1.3.1. If this isn't a bug, any assistance would be greatly appreciated.

settings.py

...
ACTSTREAM_ACTION_MODELS = ['auth.User', 'item.Item']
...

view.py

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from actstream.actions import follow
from actstream import action
from models import Item
from django.core.urlresolvers import reverse

def follow_item(request, item_id=None):
    item = get_item_or_404(Item, id=item_id)
    follow(request.user, item)
    action.send(request.user, verb='is now following', target=item)
    return HttpResponseRedirect(reverse('item', kwargs={'item_id': item_id}))

models.py

from django.db import models

class Item(models.Model):
    title = models.CharField(max_length=140)

    def __unicode__(self):
        return self.title

    @models.permalink
    def get_absolute_url(self):
        return ('item', kwargs={'item_id': str(self.id)})

ACTSTREAM_ACTION_MODELS is not backwards compatible

I was just bitten by this when upgrading from an older version.
I didn't have ACTSTREAM_ACTION_MODELS set, and all my action calls raised ModelNotActionable.
I think it would be better to ignore ACTSTREAM_ACTION_MODELS if the setting doesn't exist in settings.py.
This way it still can be used for limiting models, but it doesn't break backwards compatibility.

Bad merge in activity_tags.py

Importing activity_tags.py generates a syntax error because of an improperly resolved merge. Search for "<<<<<< HEAD". This issue was created in commit 5f85920, the merge from lincoln-loop.

ModelNotActionable: Model Item not recognized

Similar to #74. The recent v0.4.1 fixed the "Object must be a Django Model not ModelBase" exception value. However, I am now receiving a new exception...

Django Version: 1.3.1
Exception Type: ModelNotActionable
Exception Value: Model Item not recognized, add "item.item" to ACTSTREAM_ACTION_MODELS

# settings.py
...
ACTSTREAM_ACTIONS_MODELS = ('auth.User', 'item.Item')
...

I believe the error is in actstream/settings.py. When populating the MODEL dict, get_mode('item', 'Item') [line 6] the is returning None. Thus, an exception is raised when calling either actstream.actions.follow() or actstream.actions.action().

However, get_model('item', 'Item') returns the instance correctly if called in my view.

# item/views.py
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from actstream.actions import follow
from actstream import action
from models import Item
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.db.models import get_model

@login_required
def follow_item(request, item_id=None):
    item = get_item_or_404(Item, id=item_id)

    # Check get_model
    import logging
    logger = logging.get_logger(__name__)
    logger.error('Item Model Instance:', get_model('item', 'Item'))

    follow(request.user, item)
    action.send(request.user, verb='is now following', target=item)
    return HttpResponseRedirect(reverse('item', kwargs={'item_id': item_id}))

The output is: ERROR:item.views: <class 'item.models.Item'>, as expected.

I'm not exactly sure why get_model() is returning None when called from actstream/settings.py. From looking at django.db.models, it seems like the best explanation would be that AppCache isn't fully loaded.

As before, if I comment out all the references to check_actionable_model() in actstream/actions.py, everything works as expected. Any assistance is greatly appreciated.

Error If an actionable model is deleted from the db

During the db schema restructuring, I renamed one of my models (which was actionable).
The change was also done in ACTSTREAM_ACTION_MODELS.

The change caused the old content type to be dropped from the db (as expected)

Regarding actstream, I expected that any stream generated on the older models should not be seen anymore.
However, an exception popped up when i tried to generate a stream for an actor.
Below is the traceback:

Traceback:
File "/home/nanda/projects/proj/env/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response

  1.                     response = callback(request, _callback_args, *_callback_kwargs)
    
    File "/home/nanda/projects/proj/env/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  2.             return view_func(request, _args, *_kwargs)
    
    File "/home/nanda/projects/proj/src/apps/users/views.py" in user_profile
  3. recent_activities = actor_stream(for_user)
    
    File "/home/nanda/projects/proj/env/lib/python2.7/site-packages/actstream/decorators.py" in wrapped
  4.         return func(manager, _args, *_kwargs).fetch_generic_relations()
    
    File "/home/nanda/projects/proj/env/lib/python2.7/site-packages/actstream/gfk.py" in fetch_generic_relations
  5.             objects = model_class._default_manager.select_related()
    

Exception Type: AttributeError at /users/pages/nanda/
Exception Value: 'NoneType' object has no attribute '_default_manager'

Deleting an object does not delete it's activity

Consider such a signal which aims to create an activity when a user registers:

def user_registered_activity(sender, **kwargs):
    if not kwargs.get('created', False):
        return None
    action.send(kwargs['instance'], verb='registered')
signals.post_save.connect(user_registered_activity, 
    sender=models.get_model('auth', 'user'))

Well guess what happens when the user is deleted: the actions are not.

To keep our database sane, i use this snippet:

def delete_object_activities(sender, **kwargs):
    """
    This signal attempts to delete any activity which is related to Action
    through a generic relation. This should keep the Action table sane.
    """
    Action.objects.filter(
        action_object_object_id=kwargs['instance'].pk,
        action_object_content_type=ContentType.objects.get_for_model(
                                                        kwargs['instance'])
        ).delete()
    Action.objects.filter(
        actor_object_id=kwargs['instance'].pk,
        actor_content_type=ContentType.objects.get_for_model(
                                                        kwargs['instance'])
        ).delete()
    Action.objects.filter(
        target_object_id=kwargs['instance'].pk,
        target_content_type=ContentType.objects.get_for_model(
                                                        kwargs['instance'])
        ).delete()
signals.pre_delete.connect(delete_object_activities)

In general, i'd recommend to just add the full snippet to actstream:

from django.db.models import signals                                               
from django.db import models
from django.contrib.contenttypes.models import ContentType                         

from actstream import action                                                       
from actstream.models import Action                                                

def user_registered_activity(sender, **kwargs):                                    
    if not kwargs.get('created', False):                                           
        return None
    action.send(kwargs['instance'], verb='registered')                             
signals.post_save.connect(user_registered_activity, 
    sender=models.get_model('auth', 'user'))

def delete_object_activities(sender, **kwargs):
    """
    This signal attempts to delete any activity which is related to Action         
    through a generic relation. This should keep the Action table sane.            
    """     
    Action.objects.filter(
        action_object_object_id=kwargs['instance'].pk,                             
        action_object_content_type=ContentType.objects.get_for_model(              
                                                        kwargs['instance']) 
        ).delete()                                                                 
    Action.objects.filter(
        actor_object_id=kwargs['instance'].pk,
        actor_content_type=ContentType.objects.get_for_model(                      
                                                        kwargs['instance'])        
        ).delete()
    Action.objects.filter(                                                         
        target_object_id=kwargs['instance'].pk,                                    
        target_content_type=ContentType.objects.get_for_model(                     
                                                        kwargs['instance'])        
        ).delete()
signals.pre_delete.connect(delete_object_activities)

ACTSTREAM_ACTION_MODELS in settings

The ACTSTREAM_ACTION_MODELS setting expects the app to be located in the project root directory, but many of us store the apps in a "apps" directory, if so the ACTSTREAM_ACTION_MODELS setting fails.

Key error across multiple django.sites on Follow and user_stream

When using activity-stream on across multiple sites hosted on the same database (using django.sites) key errors show up after a an action is added for a follow on a different site.

To reproduce:

  1. Create a multi-site django installation
  2. On site1 'follow' an object
  3. Trigger adding an action to the db by updating the followed object
  4. Visit site2 calling user_stream( request.user) and key error occurs, referring to the user object:

KeyError at /
(3L, 1L)
/home/martin/methodmint/submod/external/actstream/gfk.py in fetch_generic_relations, line 69

Interestingly, if you then follow the same model (not the same object) on site2 the error disappears.

Also, django-activity-stream doesn't respect on_site managers when generating the above lists (this may be a separate issue - although implementing that would probably fix this one too?)

KeyError in fetch_generic_relations with existing pks

Traceback (most recent call last):
File "", line 1, in
File "/home/neelesh/projects/epsilon/local/lib/python2.7/site-packages/actstream/decorators.py", line 21, in wrapped
return func(manager, _args, *kwargs)[offset:limit].fetch_generic_relations()
File "/home/neelesh/projects/epsilon/local/lib/python2.7/site-packages/actstream/gfk.py", line 60, in fetch_generic_relations
(gfk_name, item_id) = items
[smart_unicode(o.pk)]
KeyError: u'1'

It looks like items_ is keyed with numbers and looked up with string keys.

Nomenclature at activitystrea.ms is not followed

According to the spec at http://activitystrea.ms/specs/atom/1.0/ (the link http://martin.atkins.me.uk/specs/activitystreams/atomactivity redirects there now), every activity MUST contain an action object, while a target is always optional. Although the difference between an action object and a target is a bit unclear going by the descriptions alone, in the example "John saved a movie to his wishlist" it is the wishlist, not the movie that is the target, meaning that in "John saved a movie" the movie is an action object. Since being able to do without both a target and an action object is quite handy, like in "John reached level 10", how about extending the generalized format with:

"<actor> <verb> <action_object> <time>"

ModelNotActionable error!

Im getting a weird error, maybe I didn't use it correctly. My first time using this library.

It's says that "Object <class 'blog.models.Blog'> must be a Django Model not <class 'django.db.models.base.ModelBase'>"

when i tried to do this...

blog = Blog.objects.get(id=2)
action.send(request.user, verb='has changed visibility to %s' % (visibility), action_object=blog)

Am I not using it correctly?

if without action_object, the api works.

user_stream should include stream_for_model

user_stream should include stream_for_model.
If someone follows group and some user(actor) added(verb) news(action object) to that group(target) then this action should be in user_stream.

action_handler should check for actor, verb *and* target

Right now, action_handler uses
activity = Activity.objects.get_or_create(
actor_content_type = ContentType.objects.get_for_model(actor),
actor_object_id = actor.pk,
verb = verb
)[0]
however, this means that if an actor performs the same verb with different targets, only one instance for that actor and verb is saved.

Here's the changes:
diff --git a/actstream/models.py b/actstream/models.py
old mode 100644
new mode 100755
index 17e894f..a04e58e
--- a/actstream/models.py
+++ b/actstream/models.py
@@ -153,14 +153,19 @@ model_stream.doc = Activity.objects.stream_for_model.doc

 def action_handler(verb, target=None, **kwargs):
     actor = kwargs.pop('sender')
-    activity = Activity.objects.get_or_create(
-        actor_content_type = ContentType.objects.get_for_model(actor),
-        actor_object_id = actor.pk,
-        verb = verb
-    )[0]
     if target:
-        activity.target_object_id = target.pk
-        activity.target_content_type = ContentType.objects.get_for_model(target)
-        activity.save()
+        activity = Activity.objects.get_or_create(
+            actor_content_type = ContentType.objects.get_for_model(actor),
+            actor_object_id = actor.pk,
+            target_object_id = target.pk,
+            target_content_type = ContentType.objects.get_for_model(target),
+            verb = verb
+        )[0]
+    else:
+        activity = Activity.objects.get_or_create(
+            actor_content_type = ContentType.objects.get_for_model(actor),
+            actor_object_id = actor.pk,
+            verb = verb
+        )[0]

from actstream import action does not initialize the action_handler

I create Actions by doing action.send(user, 'add', target=otherobject) in my views and that works while running a django server. However when testing those views I noticed that no Action models were being created. After adding 'from actstream.actions import action' to my test it does work (this makes sense since the actions module connects the action_handler to that signal), so I guess that running the django server imports actions module through some other path.

Still, this extra import seems awkward for the tests, so I want to suggest to change init.py to import 'action' from actions (which imports it from signals) so that all the proper initialization will done in that case as well. What do you think?

Best regards,
Gijsbert

settings.I18N causes endless loop

As you can see, Action.unicode renders a template when settings.I18N is true: https://github.com/justquick/django-activity-stream/blob/master/actstream/models.py#L87

So when Django Debug Toolbar template panel wants to show the context of a template which has an Action instance, it will call the unicode representation of the Action instance. Which will render a template (action_short.txt with context 'action'), which DJDT wants to add to the template panel with the context. So it will call the unicode representation of the Action instance which is part of the context. And so on :)

I didn't notice it on uWSGI because it's so brave at fixing my runtime, but with runserver/strace/pdb this is obvious.

Why are we using a template in unicode anyway ? Isn't there a better way (use gettext like blocktrans) ?

AttributeError running migrations with south

Hello,

There is something strange with south and actstream. When I run

python manage.py schemamigration --auto looks

I get an error: http://dpaste.com/679130/

I took a look at the source code and I found that the variable "opts" is not used in the models.py file. I think it's obsolete or something like that. Can you check this error, please?

actor_url tag causes TemplateSyntaxError

I fixed the parameter issue with actor_url, but I get this when I go to /activity/:

TemplateSyntaxError at /activity/

Accepted format {% actor_url [actor_instance] %}

Error importing Feed

Hi,

Tried to integrate this for my project but got the following error:

TemplateSyntaxError at /
Caught an exception while rendering: cannot import name Feed
Request Method: GET
Request URL: http://127.0.0.1:8000/en/
Exception Type: TemplateSyntaxError
Exception Value:
Caught an exception while rendering: cannot import name Feed
Exception Location: /Library/Python/2.6/site-packages/django/template/debug.py in render_node, line 81

I guess this project requires Django 1.2 as I was unable to import Feed from django.contrib.syndication.views in shell?

-Jori

FollowAdmin does not match Follow

django.core.exceptions.ImproperlyConfigured

ImproperlyConfigured: FollowAdmin.list_display[2], 'actor' is not a callable or an attribute of 'FollowAdmin' or found in the model 'Follow'.

FollowAdmin should be updated in 6b744ff

delete_orphaned_actions causes exception on login

Hi!

You've doing a realy greay app! We use it a lot in our project, it saved us a ton of time.

After updating to last version, where delete_orphaned_actions was added, we have big problems :)

On user log in, session is cleaning up itself. Here's where delete_orphaned_actions comes, sees that object is deleted and tries to lookup for it in activity stream.

But session_key is not int, so it crashes, cause lookup waits for something PositiveInteger.

Traceback:
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/core/handlers/base.py" in get_response
  100.                     response = callback(request, *callback_args, **callback_kwargs)
File "/home/brabadu/experiments/42cc/42-kavyarnya/kavyarnya/core/decorators.py" in wrapper
  42.             return func(request, *args, **kwargs)
File "/home/brabadu/experiments/42cc/42-kavyarnya/kavyarnya/core/decorators.py" in wrapper
  69.             output = func(request, *args, **kwargs)
File "/home/brabadu/experiments/42cc/42-kavyarnya/kavyarnya/users/views.py" in login
  141.             form.save(request)
File "/home/brabadu/experiments/42cc/42-kavyarnya/kavyarnya/users/forms.py" in save
  232.         auth.login(request, self.user)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/contrib/auth/__init__.py" in login
  80.         request.session.cycle_key()
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/contrib/sessions/backends/base.py" in cycle_key
  250.         self.delete(key)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/contrib/sessions/backends/db.py" in delete
  76.             Session.objects.get(session_key=session_key).delete()
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/base.py" in delete
  665.         delete_objects(seen_objs, using)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/query.py" in delete_objects
  1371.                     signals.post_delete.send(sender=cls, instance=instance)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/dispatch/dispatcher.py" in send
  172.             response = receiver(signal=self, sender=sender, **named)
File "/home/brabadu/experiments/42cc/42-kavyarnya/lib/actstream/models.py" in delete_orphaned_actions
  270.         Q(target_object_id=pk, target_content_type=ctype)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/manager.py" in filter
  141.         return self.get_query_set().filter(*args, **kwargs)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/query.py" in filter
  561.         return self._filter_or_exclude(False, *args, **kwargs)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/query.py" in _filter_or_exclude
  579.             clone.query.add_q(Q(*args, **kwargs))
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/sql/query.py" in add_q
  1167.                     self.add_q(child, used_aliases, force_having=force_having)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/sql/query.py" in add_q
  1167.                     self.add_q(child, used_aliases, force_having=force_having)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/sql/query.py" in add_q
  1170.                             can_reuse=used_aliases, force_having=force_having)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/sql/query.py" in add_filter
  1105.                 connector)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/sql/where.py" in add
  67.             value = obj.prepare(lookup_type, value)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/sql/where.py" in prepare
  316.             return self.field.get_prep_lookup(lookup_type, value)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/fields/__init__.py" in get_prep_lookup
  882.         return super(IntegerField, self).get_prep_lookup(lookup_type, value)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/fields/__init__.py" in get_prep_lookup
  292.             return self.get_prep_value(value)
File "/home/brabadu/experiments/42cc/42-kavyarnya/.env/lib/python2.6/site-packages/django/db/models/fields/__init__.py" in get_prep_value
  876.         return int(value)

Exception Type: ValueError at /login/
Exception Value: invalid literal for int() with base 10: '6350ecd21ae1e3982ab02c6290b7da8a'

Next parameter after following

Based on the documentation you should be able to (un)follow with optional 'next' as GET parameter. I'm trying to do this but the view won't redirect. I'm not familiar with the syntax

return type('Deleted', (HttpResponse,), {'status_code':204})()

but it seems to me that there's no redirect (extra HttpResponseRedirect was in the imports).

Cool app otherwise. Somethings I'm missing are the ability to follow objects and get updates once they are used as targets (i.e. I follow a post and will get updates on new comments) and ability to translate verbs. I'll have to fork this soon :)

unregistered template tags

I noticed a couple template tags that were coded but are not registered/exposed to templates. To solve this locally, I'm simply adding this to a new templatetag and loading in templates.

from actstream.templatetags.activity_tags import do_activity_follow_url, do_activity_follow_label
register.tag('activity_follow_url', do_activity_follow_url)
register.tag('activity_follow_label', do_activity_follow_label)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.