2015-04-21 01:53:28 +00:00
`` django-notifications `` Documentation
=======================================
2012-07-22 13:14:44 +00:00
2015-12-09 13:36:16 +00:00
2015-03-29 07:00:59 +00:00
|build-status| |coveralls|
2015-03-29 05:07:51 +00:00
2015-04-21 01:53:28 +00:00
`django-notifications <https://github.com/django-notifications/django-notifications> `_ is a GitHub notification alike app for Django, it was derived from `django-activity-stream <https://github.com/justquick/django-activity-stream> `_
2012-07-22 13:14:44 +00:00
2015-04-21 02:37:24 +00:00
The major difference between `` django-notifications `` and `` django-activity-stream `` :
* `` django-notifications `` is for building something like Github "Notifications"
* While `` django-activity-stream `` is for building Github "News Feed"
2012-07-22 13:14:44 +00:00
Notifications are actually actions events, which are categorized by four main components.
2017-07-23 02:06:14 +00:00
* `` 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.
2012-07-22 13:14:44 +00:00
`` Actor `` , `` Action Object `` and `` Target `` are `` GenericForeignKeys `` to any arbitrary Django object.
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.
2017-06-25 23:27:43 +00:00
For example: `justquick <https://github.com/justquick/> `_ `` (actor) `` *closed* `` (verb) `` `issue 2 <https://github.com/justquick/django-activity-stream/issues/2> `_ `` (action_object) `` on `activity-stream <https://github.com/justquick/django-activity-stream/> `_ `` (target) `` 12 hours ago
2012-07-22 13:14:44 +00:00
Nomenclature of this specification is based on the Activity Streams Spec: `<http://activitystrea.ms/specs/atom/1.0/>`_
2015-12-07 03:17:37 +00:00
Requirements
============
2015-12-07 07:13:38 +00:00
- Python 2.7, 3.3, 3.4, 3.5
2017-12-07 00:38:29 +00:00
- Django 1.7, 1.8, 1.9, 1.10, 1.11, 2.0
2015-12-07 03:17:37 +00:00
2012-07-22 13:14:44 +00:00
Installation
============
2012-10-24 23:10:39 +00:00
Installation is easy using `` pip `` and will install all required libraries.
2012-07-22 13:14:44 +00:00
::
2012-10-25 04:46:06 +00:00
$ pip install django-notifications-hq
2012-07-22 13:14:44 +00:00
or get it from source
::
2015-04-21 01:53:28 +00:00
$ git clone https://github.com/django-notifications/django-notifications
2012-07-22 13:14:44 +00:00
$ cd django-notifications
2018-05-31 12:33:14 +00:00
$ python setup.py sdist
$ pip install dist/django-notifications-hq*a
2012-07-22 13:14:44 +00:00
2012-10-24 23:10:39 +00:00
Note that `django-model-utils <http://pypi.python.org/pypi/django-model-utils> `_ will be installed: this is required for the pass-through QuerySet manager.
2012-07-22 13:14:44 +00:00
Then to add the Django Notifications to your project add the app `` notifications `` to your `` INSTALLED_APPS `` and urlconf.
2017-06-27 02:44:22 +00:00
The app should go somewhere after all the apps that are going to be generating notifications like `` django.contrib.auth ``
::
2012-07-22 13:14:44 +00:00
INSTALLED_APPS = (
'django.contrib.auth',
...
'notifications',
...
)
Add the notifications urls to your urlconf::
2015-03-29 07:00:59 +00:00
2016-05-16 08:25:31 +00:00
import notifications.urls
2015-03-29 07:00:59 +00:00
2015-12-17 10:10:08 +00:00
urlpatterns = [
2012-07-22 13:14:44 +00:00
...
2015-12-17 10:10:08 +00:00
url('^inbox/notifications/', include(notifications.urls, namespace='notifications')),
2012-07-22 13:14:44 +00:00
...
2015-12-17 10:10:08 +00:00
]
2012-07-22 13:14:44 +00:00
2012-10-24 23:10:39 +00:00
The method of installing these urls, importing rather than using `` 'notifications.urls' `` , is required to ensure that the urls are installed in the `` notifications `` namespace.
2015-12-07 03:17:37 +00:00
To run schema migration, execute `` python manage.py migrate notifications `` .
2015-02-24 11:25:50 +00:00
2012-07-22 13:14:44 +00:00
Generating Notifications
=========================
Generating notifications is probably best done in a separate signal.
::
from django.db.models.signals import post_save
2015-12-12 10:33:46 +00:00
from notifications.signals import notify
2012-07-22 13:14:44 +00:00
from myapp.models import MyModel
def my_handler(sender, instance, created, **kwargs):
notify.send(instance, verb='was saved')
post_save.connect(my_handler, sender=MyModel)
2017-06-25 23:27:43 +00:00
To generate an notification anywhere in your code, simply import the notify signal and send it with your actor, recipient, and verb.
2012-07-22 13:14:44 +00:00
::
2015-12-30 08:28:43 +00:00
from notifications.signals import notify
2012-07-22 13:14:44 +00:00
2014-01-31 14:37:49 +00:00
notify.send(user, recipient=user, verb='you reached level 10')
2015-03-29 07:00:59 +00:00
2017-08-29 07:46:26 +00:00
The complete syntax is.
2015-03-29 07:00:59 +00:00
2017-06-25 23:27:43 +00:00
::
2017-06-27 02:44:22 +00:00
2017-07-23 02:04:08 +00:00
notify.send(actor, recipient, verb, action_object, target, level, description, public, timestamp, **kwargs)
2017-06-27 02:44:22 +00:00
Arguments:
2018-03-21 10:11:50 +00:00
* **actor** : An object of any type. (Required) Note: Use **sender** instead of **actor** if you intend to use keyword arguments
2017-06-27 02:44:22 +00:00
* **recipient** : A **Group** or a **User QuerySet** or a list of **User** . (Required)
* **verb** : An string. (Required)
* **action_object** : An object of any type. (Optional)
* **target** : An object of any type. (Optional)
* **level** : One of Notification.LEVELS ('success', 'info', 'warning', 'error') (default=info). (Optional)
* **description** : An string. (Optional)
* **public** : An boolean (default=True). (Optional)
* **timestamp** : An tzinfo (default=timezone.now()). (Optional)
2012-07-22 13:14:44 +00:00
2012-10-23 23:06:39 +00:00
Extra data
----------
You can attach arbitrary data to your notifications by doing the following:
2018-05-30 05:21:16 +00:00
* Add to your settings.py: `` DJANGO_NOTIFICATIONS_CONFIG = { 'USE_JSONFIELD': True} ``
2012-10-23 23:06:39 +00:00
2015-04-11 05:28:52 +00:00
Then, any extra arguments you pass to `` notify.send(...) `` will be attached to the `` .data `` attribute of the notification object.
These will be serialised using the JSONField's serialiser, so you may need to take that into account: using only objects that will be serialised is a good idea.
Soft delete
-----------
By default, `` delete/(?P<slug>\d+)/ `` deletes specified notification record from DB.
You can change this behaviour to "mark `` Notification.deleted `` field as `` True `` " by:
2018-05-30 05:21:16 +00:00
* Add to your settings.py: `` DJANGO_NOTIFICATIONS_CONFIG = { 'SOFT_DELETE': True} ``
2015-04-11 05:28:52 +00:00
With this option, QuerySet methods `` unread `` and `` read `` contain one more filter: `` deleted=False `` .
Meanwhile, QuerySet methods `` deleted `` , `` active `` , `` mark_all_as_deleted `` , `` mark_all_as_active `` are turned on.
See more details in QuerySet methods section.
2012-10-23 23:06:39 +00:00
2012-07-22 13:14:44 +00:00
API
====
2012-10-24 23:10:39 +00:00
QuerySet methods
2014-05-07 02:46:48 +00:00
-----------------
2012-10-24 23:10:39 +00:00
Using `` django-model-utils `` , we get the ability to add queryset methods to not only the manager, but to all querysets that will be used, including related objects. This enables us to do things like::
Notification.objects.unread()
2015-03-29 07:00:59 +00:00
2012-10-24 23:10:39 +00:00
which returns all unread notifications. To do this for a single user, we can do::
user = User.objects.get(pk=pk)
user.notifications.unread()
There are some other QuerySet methods, too.
2017-06-25 23:27:43 +00:00
`` qs.unsent() ``
~~~~~~~~~~~~~~~
Return all of the unsent notifications, filtering the current queryset. (emailed=False)
2017-08-29 08:16:23 +00:00
`` qs.sent() ``
2017-06-25 23:27:43 +00:00
~~~~~~~~~~~~~~~
Return all of the sent notifications, filtering the current queryset. (emailed=True)
2012-10-24 23:10:39 +00:00
`` qs.unread() ``
~~~~~~~~~~~~~~~
Return all of the unread notifications, filtering the current queryset.
2018-05-30 05:18:33 +00:00
When `` SOFT_DELETE=True `` , this filter contains `` deleted=False `` .
2012-10-24 23:10:39 +00:00
`` qs.read() ``
~~~~~~~~~~~~~~~
Return all of the read notifications, filtering the current queryset.
2018-05-30 05:18:33 +00:00
When `` SOFT_DELETE=True `` , this filter contains `` deleted=False `` .
2012-10-24 23:10:39 +00:00
`` qs.mark_all_as_read() `` | `` qs.mark_all_as_read(recipient) ``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark all of the unread notifications in the queryset (optionally also filtered by `` recipient `` ) as read.
`` qs.mark_all_as_unread() `` | `` qs.mark_all_as_unread(recipient) ``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark all of the read notifications in the queryset (optionally also filtered by `` recipient `` ) as unread.
2017-06-25 23:27:43 +00:00
`` qs.mark_as_sent() `` | `` qs.mark_as_sent(recipient) ``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark all of the unsent notifications in the queryset (optionally also filtered by `` recipient `` ) as sent.
2017-07-26 05:01:52 +00:00
`` qs.mark_as_unsent() `` | `` qs.mark_as_unsent(recipient) ``
2017-06-25 23:27:43 +00:00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2017-07-23 02:04:08 +00:00
Mark all of the sent notifications in the queryset (optionally also filtered by `` recipient `` ) as unsent.
2017-06-25 23:27:43 +00:00
2015-04-11 05:28:52 +00:00
`` qs.deleted() ``
~~~~~~~~~~~~~~~~
Return all notifications that have `` deleted=True `` , filtering the current queryset.
2018-05-30 05:18:33 +00:00
Must be used with `` SOFT_DELETE=True `` .
2015-04-11 05:28:52 +00:00
`` qs.active() ``
~~~~~~~~~~~~~~~
Return all notifications that have `` deleted=False `` , filtering the current queryset.
2018-05-30 05:18:33 +00:00
Must be used with `` DELETE=True `` .
2015-04-11 05:28:52 +00:00
`` qs.mark_all_as_deleted() `` | `` qs.mark_all_as_deleted(recipient) ``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark all notifications in the queryset (optionally also filtered by `` recipient `` ) as `` deleted=True `` .
2018-05-30 05:18:33 +00:00
Must be used with `` DELETE=True `` .
2015-04-11 05:28:52 +00:00
`` qs.mark_all_as_active() `` | `` qs.mark_all_as_active(recipient) ``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark all notifications in the queryset (optionally also filtered by `` recipient `` ) as `` deleted=False `` .
2018-05-30 05:18:33 +00:00
Must be used with `` SOFT_DELETE=True `` .
2015-04-11 05:28:52 +00:00
2012-10-24 23:10:39 +00:00
Model methods
-------------
`` obj.timesince([datetime]) ``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A wrapper for Django's `` timesince `` function.
2012-07-22 13:14:44 +00:00
2012-10-24 23:10:39 +00:00
`` obj.mark_as_read() ``
~~~~~~~~~~~~~~~~~~~~~~
2012-07-22 13:14:44 +00:00
2012-10-24 23:10:39 +00:00
Mark the current object as read.
2012-07-22 13:14:44 +00:00
2012-10-24 23:10:39 +00:00
Template tags
-------------
2012-07-22 13:14:44 +00:00
2013-02-28 08:29:30 +00:00
Put `{% load notifications_tags %}` in the template before you actually use notification tags.
2012-07-22 13:14:44 +00:00
2012-10-24 23:10:39 +00:00
`` notifications_unread ``
~~~~~~~~~~~~~~~~~~~~~~~~
2012-07-22 13:14:44 +00:00
::
{% notifications_unread %}
Give the number of unread notifications for a user, or nothing (an empty string) for an anonymous user.
Storing the count in a variable for further processing is advised, such as::
{% notifications_unread as unread_count %}
...
{% if unread_count %}
You have <strong>{{ unread_count }}</strong> unread notifications.
{% endif %}
2015-07-20 09:51:00 +00:00
Live-updater API
================
2015-12-12 10:33:46 +00:00
To ensure users always have the most up-to-date notifications, `django-notifications` includes a simple javascript API
2015-07-20 09:51:00 +00:00
for updating specific fields within a django template.
There are two possible API calls that can be made:
2015-07-20 10:10:33 +00:00
2016-09-24 21:22:33 +00:00
1. `` api/unread_count/ `` that returns a javascript object with 1 key: `` unread_count `` eg::
2015-07-20 10:10:33 +00:00
2015-07-20 09:51:00 +00:00
{"unread_count":1}
2016-09-24 21:22:33 +00:00
#. `` api/unread_list/ `` that returns a javascript object with 2 keys: `unread_count` and `unread_list` eg::
2015-07-20 10:10:33 +00:00
2016-09-24 21:22:33 +00:00
{
"unread_count":1,
"unread_list":[--list of json representations of notifications--]
}
2015-07-20 10:10:33 +00:00
2016-09-24 21:22:33 +00:00
Representations of notifications are based on the django method: `` model_to_dict ``
Query string arguments:
2016-09-25 12:11:08 +00:00
- **max** - maximum length of unread list.
- **mark_as_read** - mark notification in list as read.
2016-09-24 21:22:33 +00:00
2016-09-25 12:11:08 +00:00
For example, get `` api/unread_list/?max=3&mark_as_read=true `` returns 3 notifications and mark them read (remove from list on next request).
2015-07-20 09:51:00 +00:00
How to use:
2015-07-20 10:10:33 +00:00
-----------
2017-07-23 02:04:08 +00:00
1. Put `` {% load notifications_tags %} `` in the template before you actually use notification tags.
2. In the area where you are loading javascript resources add the following tags in the order below::
2015-07-20 10:10:33 +00:00
2015-07-20 09:51:00 +00:00
<script src="{% static 'notifications/notify.js' %}" type="text/javascript"></script>
{% register_notify_callbacks callbacks='fill_notification_list,fill_notification_badge' %}
2017-07-23 02:04:08 +00:00
`` register_notify_callbacks `` takes the following arguments:
2015-07-20 10:10:33 +00:00
2017-07-23 02:04:08 +00:00
1. `` badge_class `` (default `` live_notify_badge `` ) - The identifier `class` of the element to show the unread count, that will be periodically updated.
#. `` menu_class `` (default `` live_notify_list `` ) - The identifier `class` of the element to insert a list of unread items, that will be periodically updated.
#. `` refresh_period `` (default `` 15 `` ) - How often to fetch unread items from the server (integer in seconds).
#. `` fetch `` (default `` 5 `` ) - How many notifications to fetch each time.
#. `` callbacks `` (default `` <empty string> `` ) - A comma-separated list of javascript functions to call each period.
#. `` api_name `` (default `` list `` ) - The name of the API to call (this can be either `` list `` or `` count `` ).
2015-07-20 10:10:33 +00:00
2017-07-23 02:04:08 +00:00
3. To insert a live-updating unread count, use the following template::
2015-07-20 09:51:00 +00:00
{% live_notify_badge %}
2017-07-23 02:04:08 +00:00
`` live_notify_badge `` takes the following arguments:
2015-07-20 10:10:33 +00:00
2017-07-02 23:23:22 +00:00
1. `` badge_class `` (default `` live_notify_badge `` ) - The identifier `` class `` for the `` <span> `` element that will be created to show the unread count.
2015-07-20 10:10:33 +00:00
2017-07-23 02:04:08 +00:00
4. To insert a live-updating unread list, use the following template::
2015-07-20 10:10:33 +00:00
2015-07-20 09:51:00 +00:00
{% live_notify_list %}
2015-11-13 10:41:38 +00:00
2017-07-23 02:04:08 +00:00
`` live_notify_list `` takes the following arguments:
2015-07-20 10:10:33 +00:00
2017-07-02 23:23:22 +00:00
1. `` list_class `` (default `` live_notify_list `` ) - The identifier `` class `` for the `` <ul> `` element that will be created to insert the list of notifications into.
2015-07-20 09:51:00 +00:00
Using the live-updater with bootstrap
2015-07-20 10:10:33 +00:00
-------------------------------------
2015-07-20 09:51:00 +00:00
The Live-updater can be incorporated into bootstrap with minimal code.
2015-07-20 10:10:33 +00:00
To create a live-updating bootstrap badge containing the unread count, simply use the template tag::
2015-07-20 09:51:00 +00:00
2017-12-17 11:13:26 +00:00
{% live_notify_badge badge_class="badge" %}
2015-07-20 09:51:00 +00:00
2015-07-20 10:10:33 +00:00
To create a live-updating bootstrap dropdown menu containing a selection of recent unread notifications, simply use the template tag::
2015-07-20 09:51:00 +00:00
2017-12-17 11:13:26 +00:00
{% live_notify_list list_class="dropdown-menu" %}
2015-07-20 10:10:33 +00:00
2015-07-20 09:51:00 +00:00
Customising the display of notifications using javascript callbacks
2015-07-20 10:10:33 +00:00
-------------------------------------------------------------------
2015-07-20 09:51:00 +00:00
While the live notifier for unread counts should suit most use cases, users may wish to alter how
unread notifications are shown.
2015-07-20 10:10:33 +00:00
The `` callbacks `` argument of the `` register_notify_callbacks `` dictates which javascript functions are called when
2015-11-13 10:41:38 +00:00
the unread api call is made.
2015-07-20 09:51:00 +00:00
2015-07-20 10:10:33 +00:00
To add a custom javascript callback, simply add this to the list, like so::
2015-07-20 09:51:00 +00:00
{% register_notify_callbacks callbacks='fill_notification_badge,my_special_notification_callback' %}
The above would cause the callback to update the unread count badge, and would call the custom function `my_special_notification_callback` .
All callback functions are passed a single argument by convention called `data` , which contains the entire result from the API.
2015-07-20 10:10:33 +00:00
For example, the below function would get the recent list of unread messages and log them to the console::
2015-07-20 09:51:00 +00:00
function my_special_notification_callback(data) {
for (var i=0; i < data.unread_list.length; i++) {
msg = data.unread_list[i];
console.log(msg);
}
}
2015-12-12 07:09:20 +00:00
Testing the live-updater
------------------------
1. Clone the repo
2018-05-30 04:10:24 +00:00
2. Run `./manage.py runserver`
3. Browse to `yourserverip/test/`
4. Click 'Make a notification' and a new notification should appear in the list in 5-10 seconds.
2015-12-12 07:09:20 +00:00
2017-06-27 02:17:32 +00:00
Serializing the django-notifications Model
2017-06-27 02:46:02 +00:00
==========================================
2017-06-27 02:17:32 +00:00
See here - http://www.django-rest-framework.org/api-guide/relations/#generic-relationships
2017-06-27 02:44:22 +00:00
In this example the target object can be of type Foo or Bar and the appropriate serializer will be used.
::
class GenericNotificationRelatedField(serializers.RelatedField):
2017-06-27 02:17:32 +00:00
2017-06-27 02:44:22 +00:00
def to_representation(self, value):
if isinstance(value, Foo):
serializer = FooSerializer(value)
if isinstance(value, Bar):
serializer = BarSerializer(value)
2017-06-27 02:17:32 +00:00
2017-06-27 02:44:22 +00:00
return serializer.data
2017-06-27 02:17:32 +00:00
2017-06-27 02:44:22 +00:00
class NotificationSerializer(serializers.Serializer):
recipient = PublicUserSerializer(User, read_only=True)
unread = serializers.BooleanField(read_only=True)
target = GenericNotificationRelatedField(read_only=True)
2017-06-27 02:17:32 +00:00
2017-06-27 02:44:22 +00:00
Thanks to @DaWy
2017-06-27 02:17:32 +00:00
2017-03-03 03:11:59 +00:00
Notes
=====
Email Notification
------------------
Sending email to users has not been integrated into this library. So for now you need to implement it if needed. There is a reserved field `Notification.emailed` to make it easier.
2015-04-21 01:53:28 +00:00
`` django-notifications `` Team
==============================
Core contributors (in alphabetical order):
2017-06-24 01:44:33 +00:00
- `Alvaro Leonel <https://github.com/AlvaroLQueiroz> `_
2015-04-21 01:53:28 +00:00
- `Samuel Spencer <https://github.com/LegoStormtroopr> `_
- `Yang Yubo <https://github.com/yangyubo> `_
2015-04-21 02:39:58 +00:00
- `Zhongyuan Zhang <https://github.com/zhang-z> `_
2015-04-21 01:53:28 +00:00
2015-03-29 05:07:51 +00:00
.. |build-status| image :: https://travis-ci.org/django-notifications/django-notifications.svg
:target: https://travis-ci.org/django-notifications/django-notifications
.. |coveralls| image :: https://coveralls.io/repos/django-notifications/django-notifications/badge.png?branch=master
:alt: Code coverage on coveralls
:scale: 100%
:target: https://coveralls.io/r/django-notifications/django-notifications?branch=master