How to get hold of a session after getting signaled?

27 views
Skip to first unread message

Tobias Dacoir

unread,
Jan 30, 2015, 11:19:50 AM1/30/15
to django...@googlegroups.com
I'm using django-badges in my project which can emit a signal when a user is awarded a badge. I was able to implemented a receiver function, however the output is the following:

signals.py (from badges):
import django.dispatch

badge_awarded
= django.dispatch.Signal(providing_args=['user', 'badge'])



my receiver function test:

from badges.signals import badge_awarded
@receiver(badge_awarded)
def do_something_after_badge_awarded(sender, user, badge, **kwargs):
   
print "Badge Signal received"
   
print sender # <play.meta_badges.neueBadge object at 0x109733d90>
   
print user # user object
   
print badge # badge object
   
print kwargs



and the output was:
Badge Signal received
<play.meta_badges.neueBadge object at 0x109733d90>
player1
Test Badge 2
{'signal': <django.dispatch.dispatcher.Signal object at 0x1096da4d0>}


I want to add a message to the request, to notify or show the user that he earned a badge. Is it possible someone get hold of the request? I can freely modify the original source code from django-badges. Currently it's invoked by post_save() on a model instance. So I doubt I can get the request from there.

I found a solution to add another 3rd party app which is called django-notification, but I don't want to add too many apps to my project. Another solution might be to just set some variable in the database and in my view to query this variable - however that will also cost performance and two database hits.

Vijay Khemlani

unread,
Jan 30, 2015, 8:12:57 PM1/30/15
to django...@googlegroups.com
As far as I can tell on the project source, the only place the "badge_awarded" signal is triggered is in the "award_to" method in the Badge class, which does not handle a request object.

If you are calling something like "badge.award_to(user)" in one of your views, then you can modify the request response immediately after, without using the signal.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/5e8f655c-8385-46aa-94ae-2c5baef2034a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tobias Dacoir

unread,
Jan 31, 2015, 3:02:04 AM1/31/15
to django...@googlegroups.com
I can't just call badge.award_to(user) because I need to wait for the check logic to verify if the user should receive a badge or not.
My workaround is that I created a new table that inserts badge and user foreign keys and before the view is rendered I will check this table for any entries for that user. If there are, I will copy the data to a message and delete the object from the database again.

It's rather ugly due to the many database hits which I would like to avoid but I can't think of anything else at the moment. Apparently (using google) there is no way to get hold of the request in a post_save() signal - which I need to check all achievements.

The only real solution would be to not use this post_save() signal but manually do the checking for achievements before my view is rendered, which would require some work on the original source code. I will look into it though next week.

Stephen J. Butler

unread,
Jan 31, 2015, 4:12:10 AM1/31/15
to django...@googlegroups.com
You still could store the do_something_after_badge_awarded result in a
database table, but cache the lookups from the view for something
short, like 5 minutes. How quickly after a badge is awarded do people
need to be notified?

Also, you could use a memcached library to store/fetch the awards by
user ID. Should be pretty quick. That assumes of course that it's OK
to lose award notifications if memcached restarts. Would look
something like:

# store
mc.append(key_for_user, "{0} ".format(award_obj.pk))

# ...

# get. use a lockless cas() algo
award_objs = None
while award_objs is None:
award_ids, cas_token = mc.gets(key_for_user)
if not award_ids:
# No awards waiting for us
award_objs = []
elif mc.cas(key_for_user, "", cas_token):
# Awards didn't change on us, continue
award_objs = Awards.objects.filter(pk__in=award_ids.split())

Or you could do something with the Django cache framework. Or you
could use local files and serialization.

But I do think you should test your assumption that the DB check for
awarded awards will be too expensive. Especially if cached. Most apps
make a ton of DB calls anyway, and this one will mostly be empty.
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/ee9653c8-2c8e-479e-871b-34774862888b%40googlegroups.com.

Babatunde Akinyanmi

unread,
Jan 31, 2015, 6:42:53 AM1/31/15
to Django users

+1. You need to measure rather than assume.

> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAD4ANxWOT1Mg%3D47H89s0Xoi9m7kVA-y1Ag5qoh9vrdO9Nuc7tg%40mail.gmail.com.

Reply all
Reply to author
Forward
0 new messages