Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 0bcfa9424b8827fb66cbc160509c44672ae0dfe1 @codeinthehole committed May 16, 2012
Showing with 158 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +2 −0 MANIFEST.in
  3. +76 −0 README.rst
  4. +33 −0 async_messages/__init__.py
  5. +15 −0 async_messages/middleware.py
  6. +19 −0 release.sh
  7. +12 −0 setup.py
@@ -0,0 +1 @@
+dist
@@ -0,0 +1,2 @@
+include *.rst
+exclude tests/*
@@ -0,0 +1,76 @@
+=====================
+django-async-messages
+=====================
+
+Simple asynchronous messages for django.
+
+Questions
+=========
+
+What problem does this solve?
+-----------------------------
+
+Suppose a user instigates an expensive task that you are processing offline (eg
+using Celery). This library provides a simple mechanism for notifying the user
+when the task is finished.
+
+For instance, you might use Celery to generate a large report and then
+use this library to notify the user that their report is ready to be downloaded.
+
+How does it work?
+-----------------
+
+A cache is used to persist the messages, and middleware is used to pick these up
+and add them to Django's messages. All very simple.
+
+Aren't there other libraries that do this?
+------------------------------------------
+
+Yes, there are - but they solve the problm in different ways:
+
+* `django-offline-messages`_ - this provides an alternative storage backend that
+ Django's messages framework can use.
+
+* `django-notifications`_
+
+.. _`django-offline-messages`: https://github.com/dym/django-offline-messages
+.. _`django-notifications`: https://github.com/jtauber/django-notification
+
+Install
+-------
+
+From PyPI (stable)::
+
+ pip install django-async-messages
+
+From Github (unstable)::
+
+ pip install
+ git+git://github.com/codeinthehole/django-async-messages#egg=djang-async-messages
+
+Add ``async_messages.middleware.AsyncMiddleware`` to your ``INSTALLED_APPS``.
+Ensure it comes after ``django.contrib.messages.middleware.MessageMiddleware``.
+
+You need to have a cache set up in you settings for this to work. As usual,
+memcache is the best choice.
+
+Use
+---
+
+Send a message to a single user::
+
+ >>> from async_messages import message_user
+ >>> from django.contrib.auth.models import User
+ >>> barry = User.objects.get(username='barry')
+ >>> message_user(barry, "Barry, your report is ready")
+
+Send a message to lots of users::
+
+ >>> from async_messages import message_users
+ >>> staff = User.objects.filter(is_staff=True)
+ >>> message_users(staff, "All budgets must be spent by the end of the day")
+
+Specify message level::
+
+ >>> from django.contrib.messages import constants
+ >>> message_users(staff, "Boom!", constants.WARNING)
@@ -0,0 +1,33 @@
+from django.core.cache import cache
+from django.contrib.messages import constants
+
+
+def message_user(user, message, level=constants.INFO):
+ """
+ Send a message to a particular user.
+ """
+ cache.set(_user_key(user), (message, level))
+
+
+def message_users(users, message, level=constants.INFO):
+ """
+ Send a message to a group of users.
+ """
+ for user in users:
+ message_user(user, message, level)
+
+
+def get_message(user):
+ """
+ Fetch a message for given user. Returns None if no such message exists.
+ """
+ key = _user_key(user)
+ result = cache.get(key)
+ if result:
+ cache.delete(key)
+ return result[0], result[1]
+ return None, None
+
+
+def _user_key(user):
+ return '_async_message_%d' % user.id
@@ -0,0 +1,15 @@
+from django.contrib import messages
+
+from async_messages import get_message
+
+
+class AsyncMiddleware(object):
+
+ def process_request(self, request):
+ # Check for message for this user and, if it exists,
+ # call the messages API with it
+ if not request.user.is_authenticated():
+ return
+ msg, level = get_message(request.user)
+ if msg:
+ messages.add_message(request, level, msg)
@@ -0,0 +1,19 @@
+#!/bin/bash
+# Cut a release to PyPi and update Github with tag.
+
+# Ensure there are no uncomitted changes
+git diff --quiet HEAD
+[ $? -ne 0 ] && echo "Uncommitted changes!" && exit 1
+
+# Pluck release number out of setup.py
+RELEASE_NUM=`grep version setup.py | cut -d\' -f2`
+git tag | grep $RELEASE_NUM > /dev/null && \
+ echo "New version number required ($RELEASE_NUM already used)" && exit 1
+
+# Push to PyPi
+./setup.py sdist upload
+
+# Tag in Git
+git tag $RELEASE_NUM -m "Tagging release $RELEASE_NUM"
+git push origin master
+git push --tags
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+from setuptools import setup, find_packages
+
+setup(name='django-async-messages',
+ version='0.1',
+ url='https://github.com/codeinthehole/django-async-messages',
+ author="David Winterbottom",
+ author_email="david.winterbottom@gmail.com",
+ description="Send asynchronous messages to users",
+ long_description=open('README.rst').read(),
+ packages=find_packages(exclude=['tests']),
+ )

0 comments on commit 0bcfa94

Please sign in to comment.