{"id":13714640,"url":"https://github.com/django-notifications/django-notifications","last_synced_at":"2025-05-14T02:05:04.481Z","repository":{"id":4039513,"uuid":"5140859","full_name":"django-notifications/django-notifications","owner":"django-notifications","description":"GitHub notifications alike app for Django","archived":false,"fork":false,"pushed_at":"2025-04-02T15:45:29.000Z","size":7352,"stargazers_count":1876,"open_issues_count":42,"forks_count":438,"subscribers_count":42,"default_branch":"master","last_synced_at":"2025-05-11T18:48:32.504Z","etag":null,"topics":["django","notification","package","python"],"latest_commit_sha":null,"homepage":"http://pypi.python.org/pypi/django-notifications-hq/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/django-notifications.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.txt","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-07-22T10:41:02.000Z","updated_at":"2025-05-10T17:42:02.000Z","dependencies_parsed_at":"2024-05-09T01:52:10.607Z","dependency_job_id":"67787bc9-3a2b-4bba-8e7e-e244be5f7c3a","html_url":"https://github.com/django-notifications/django-notifications","commit_stats":{"total_commits":264,"total_committers":68,"mean_commits":"3.8823529411764706","dds":0.821969696969697,"last_synced_commit":"8558bfafcc628747d1d31f170f61ad056534b735"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/django-notifications%2Fdjango-notifications","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/django-notifications%2Fdjango-notifications/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/django-notifications%2Fdjango-notifications/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/django-notifications%2Fdjango-notifications/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/django-notifications","download_url":"https://codeload.github.com/django-notifications/django-notifications/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052692,"owners_count":22006716,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","notification","package","python"],"created_at":"2024-08-03T00:00:34.985Z","updated_at":"2025-05-14T02:04:59.452Z","avatar_url":"https://github.com/django-notifications.png","language":"Python","funding_links":[],"categories":["Python","Backend","D"],"sub_categories":["Django"],"readme":"# `django-notifications` Documentation\n\n[![build-status](https://travis-ci.org/django-notifications/django-notifications.svg)](https://travis-ci.org/django-notifications/django-notifications)\n[![Coverage Status](https://coveralls.io/repos/github/django-notifications/django-notifications/badge.svg?branch=master)](https://coveralls.io/github/django-notifications/django-notifications?branch=master)\n\n\n[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)\n\nThe major difference between `django-notifications` and `django-activity-stream`:\n\n- `django-notifications` is for building something like Github \"Notifications\"\n- While `django-activity-stream` is for building Github \"News Feed\"\n\nNotifications are actually actions events, which are categorized by four main components.\n\n-   `Actor`. The object that performed the activity.\n-   `Verb`. The verb phrase that identifies the action of the activity.\n-   `Action Object`. *(Optional)* The object linked to the action\n    itself.\n-   `Target`. *(Optional)* The object to which the activity was\n    performed.\n\n`Actor`, `Action Object` and `Target` are `GenericForeignKeys` to any\narbitrary Django object. An action is a description of an action that\nwas performed (`Verb`) at some instant in time by some `Actor` on some\noptional `Target` that results in an `Action Object` getting\ncreated/updated/deleted.\n\nFor example: [justquick](https://github.com/justquick/) `(actor)`\n*closed* `(verb)` [issue\n2](https://github.com/justquick/django-activity-stream/issues/2)\n`(action_object)` on\n[activity-stream](https://github.com/justquick/django-activity-stream/)\n`(target)` 12 hours ago\n\nNomenclature of this specification is based on the Activity Streams\nSpec: \u003chttp://activitystrea.ms/specs/atom/1.0/\u003e\n\n## Requirements\n\n-   Python 3.7, 3.8, 3.9, 3.10, 3.11\n-   Django 3.2, 4.0, 4.1\n\n## Installation\n\nInstallation is easy using `pip` and will install all required\nlibraries.\n```bash\n$ pip install django-notifications-hq\n```\nor get it from source\n\n```bash\n$ git clone https://github.com/django-notifications/django-notifications\n$ cd django-notifications\n$ python setup.py sdist\n$ pip install dist/django-notifications-hq*\n```\n\nNote that [django-model-utils](http://pypi.python.org/pypi/django-model-utils)\nwill be installed: this is required for the pass-through QuerySet manager.\n\nThen to add the Django Notifications to your project add the app\n`notifications` to your `INSTALLED_APPS` and urlconf.\n\nThe app should go somewhere after all the apps that are going to be\ngenerating notifications like `django.contrib.auth`\n\n```python\nINSTALLED_APPS = (\n    'django.contrib.auth',\n    ...\n    'notifications',\n    ...\n)\n```\n\nAdd the notifications urls to your urlconf:\n\n```python\nurlpatterns = [\n    ...\n    path('inbox/notifications/', include('notifications.urls', namespace='notifications')),\n    ...\n]\n```\n\nTo run schema migration, execute\n`python manage.py migrate notifications`.\n\n## Generating Notifications\n\nGenerating notifications is probably best done in a separate signal.\n\n```python\nfrom django.db.models.signals import post_save\nfrom notifications.signals import notify\nfrom myapp.models import MyModel\n\ndef my_handler(sender, instance, created, **kwargs):\n    notify.send(instance, verb='was saved')\n\npost_save.connect(my_handler, sender=MyModel)\n```\nTo generate an notification anywhere in your code, simply import the\nnotify signal and send it with your actor, recipient, and verb.\n\n```python\nfrom notifications.signals import notify\n\nnotify.send(user, recipient=user, verb='you reached level 10')\n```\n\nThe complete syntax is.\n\n```python\nnotify.send(actor, recipient, verb, action_object, target, level, description, public, timestamp, **kwargs)\n```\n\nArguments:\n\n-   **actor**: An object of any type. (Required) Note: Use\n    **sender** instead of **actor** if you intend to use keyword\n    arguments\n-   **recipient**: A **Group** or a **User QuerySet** or a list of\n    **User**. (Required)\n-   **verb**: An string. (Required)\n-   **action\\_object**: An object of any type. (Optional)\n-   **target**: An object of any type. (Optional)\n-   **level**: One of Notification.LEVELS (\\'success\\', \\'info\\',\n    \\'warning\\', \\'error\\') (default=info). (Optional)\n-   **description**: An string. (Optional)\n-   **public**: An boolean (default=True). (Optional)\n-   **timestamp**: An tzinfo (default=timezone.now()). (Optional)\n\n### Extra data\n\nYou can attach arbitrary data to your notifications by doing the\nfollowing:\n\n-   Add to your settings.py:\n    `DJANGO_NOTIFICATIONS_CONFIG = { 'USE_JSONFIELD': True}`\n\nThen, any extra arguments you pass to `notify.send(...)` will be\nattached to the `.data` attribute of the notification object. These will\nbe serialised using the JSONField\\'s serialiser, so you may need to take\nthat into account: using only objects that will be serialised is a good\nidea.\n\n### Soft delete\n\nBy default, `delete/(?P\u003cslug\u003e\\d+)/` deletes specified notification\nrecord from DB. You can change this behaviour to \\\"mark\n`Notification.deleted` field as `True`\\\" by:\n\n-   Add to your settings.py:\n    `DJANGO_NOTIFICATIONS_CONFIG = { 'SOFT_DELETE': True}`\n\nWith this option, QuerySet methods `unread` and `read` contain one more\nfilter: `deleted=False`. Meanwhile, QuerySet methods `deleted`,\n`active`, `mark_all_as_deleted`, `mark_all_as_active` are turned on. See\nmore details in QuerySet methods section.\n\n## API\n\n### QuerySet methods\n\nUsing `django-model-utils`, we get the ability to add queryset methods\nto not only the manager, but to all querysets that will be used,\nincluding related objects. This enables us to do things like:\n\n```python\n    Notification.objects.unread()\n```\n\nwhich returns all unread notifications. To do this for a single user, we\ncan do:\n\n```python\n    user = User.objects.get(pk=pk)\n    user.notifications.unread()\n```\n\nThere are some other QuerySet methods, too.\n\n#### `qs.unsent()`\n\nReturn all of the unsent notifications, filtering the current queryset.\n(emailed=False)\n\n#### `qs.sent()`\n\nReturn all of the sent notifications, filtering the current queryset.\n(emailed=True)\n\n#### `qs.unread()`\n\nReturn all of the unread notifications, filtering the current queryset.\nWhen `SOFT_DELETE=True`, this filter contains `deleted=False`.\n\n#### `qs.read()`\n\nReturn all of the read notifications, filtering the current queryset.\nWhen `SOFT_DELETE=True`, this filter contains `deleted=False`.\n\n#### `qs.mark_all_as_read()` \\| `qs.mark_all_as_read(recipient)`\n\nMark all of the unread notifications in the queryset (optionally also\nfiltered by `recipient`) as read.\n\n#### `qs.mark_all_as_unread()` \\| `qs.mark_all_as_unread(recipient)`\n\nMark all of the read notifications in the queryset (optionally also\nfiltered by `recipient`) as unread.\n\n#### `qs.mark_as_sent()` \\| `qs.mark_as_sent(recipient)`\n\nMark all of the unsent notifications in the queryset (optionally also\nfiltered by `recipient`) as sent.\n\n#### `qs.mark_as_unsent()` \\| `qs.mark_as_unsent(recipient)`\n\nMark all of the sent notifications in the queryset (optionally also\nfiltered by `recipient`) as unsent.\n\n#### `qs.deleted()`\n\nReturn all notifications that have `deleted=True`, filtering the current\nqueryset. Must be used with `SOFT_DELETE=True`.\n\n#### `qs.active()`\n\nReturn all notifications that have `deleted=False`, filtering the\ncurrent queryset. Must be used with `DELETE=True`.\n\n#### `qs.mark_all_as_deleted()` \\| `qs.mark_all_as_deleted(recipient)`\n\nMark all notifications in the queryset (optionally also filtered by\n`recipient`) as `deleted=True`. Must be used with `DELETE=True`.\n\n#### `qs.mark_all_as_active()` \\| `qs.mark_all_as_active(recipient)`\n\nMark all notifications in the queryset (optionally also filtered by\n`recipient`) as `deleted=False`. Must be used with `SOFT_DELETE=True`.\n\n### Model methods\n\n#### `obj.timesince([datetime])`\n\nA wrapper for Django\\'s `timesince` function.\n\n#### `obj.mark_as_read()`\n\nMark the current object as read.\n\n### Template tags\n\nPut `{% load notifications_tags %}` in the template before\nyou actually use notification tags.\n\n### `notifications_unread`\n\n```python\n    {% notifications_unread %}\n```\n\nGive the number of unread notifications for a user, or nothing (an empty\nstring) for an anonymous user.\n\nStoring the count in a variable for further processing is advised, such\nas:\n\n```python\n    {% notifications_unread as unread_count %}\n    ...\n    {% if unread_count %}\n        You have \u003cstrong\u003e{{ unread_count }}\u003c/strong\u003e unread notifications.\n    {% endif %}\n```\n\n## Live-updater API\n\nTo ensure users always have the most up-to-date notifications,\n`django-notifications` includes a simple javascript API for\nupdating specific fields within a django template.\n\nThere are two possible API calls that can be made:\n\n1.  `api/unread_count/` that returns a javascript object with 1 key:\n    `unread_count` eg:\n\n        {\"unread_count\":1}\n\n2.  `api/unread_list/` that returns a javascript object with 2 keys:\n    `unread_count` and `unread_list` eg:\n\n        {\n         \"unread_count\":1,\n         \"unread_list\":[--list of json representations of notifications--]\n        }\n\n    Representations of notifications are based on the django method:\n    `model_to_dict`\n\n    Query string arguments:\n\n    -   **max** - maximum length of unread list.\n    -   **mark\\_as\\_read** - mark notification in list as read.\n\n    For example, get `api/unread_list/?max=3\u0026mark_as_read=true` returns\n    3 notifications and mark them read (remove from list on next\n    request).\n\n    The list outputs `target_url`, `actor_url`, `action_object_url`.\n    This URL is generated from standard Django `Model.get_absolute_url()` or\n    you can override the URL just for notifications by implementing\n    `Model.get_url_for_notifications(notification, request)`.\n\n### How to use:\n\n1.  Put `{% load notifications_tags %}` in the template before you\n    actually use notification tags.\n\n2.  In the area where you are loading javascript resources add the\n    following tags in the order below:\n\n        \u003cscript src=\"{% static 'notifications/notify.js' %}\" type=\"text/javascript\"\u003e\u003c/script\u003e\n        {% register_notify_callbacks callbacks='fill_notification_list,fill_notification_badge' %}\n\n    `register_notify_callbacks` takes the following arguments:\n\n    1.  `badge_class` (default `live_notify_badge`) - The identifier\n        `class` of the element to show the unread count,\n        that will be periodically updated.\n    2.  `menu_class` (default `live_notify_list`) - The identifier\n        `class` of the element to insert a list of unread\n        items, that will be periodically updated.\n    3.  `refresh_period` (default `15`) - How often to fetch unread\n        items from the server (integer in seconds).\n    4.  `fetch` (default `5`) - How many notifications to fetch each\n        time.\n    5.  `callbacks` (default `\u003cempty string\u003e`) - A comma-separated list\n        of javascript functions to call each period.\n    6.  `api_name` (default `list`) - The name of the API to call (this\n        can be either `list` or `count`).\n    7. ``mark_as_read`` (default ``False``) - Marks notifications as read when fetched.\n\n3.  To insert a live-updating unread count, use the following template:\n\n        {% live_notify_badge %}\n\n    `live_notify_badge` takes the following arguments:\n\n    -  `badge_class` (default `live_notify_badge`) - The identifier\n        `class` for the `\u003cspan\u003e` element that will be created to show\n        the unread count.\n\n4.  To insert a live-updating unread list, use the following template:\n\n        {% live_notify_list %}\n\n    `live_notify_list` takes the following arguments:\n\n    -  `list_class` (default `live_notify_list`) - The identifier\n        `class` for the `\u003cul\u003e` element that will be created to insert\n        the list of notifications into.\n\n### Using the live-updater with bootstrap\n\nThe Live-updater can be incorporated into bootstrap with minimal code.\n\nTo create a live-updating bootstrap badge containing the unread count,\nsimply use the template tag:\n\n    {% live_notify_badge badge_class=\"badge\" %}\n\nTo create a live-updating bootstrap dropdown menu containing a selection\nof recent unread notifications, simply use the template tag:\n\n    {% live_notify_list list_class=\"dropdown-menu\" %}\n\n### Customising the display of notifications using javascript callbacks\n\nWhile the live notifier for unread counts should suit most use cases,\nusers may wish to alter how unread notifications are shown.\n\nThe `callbacks` argument of the `register_notify_callbacks` dictates\nwhich javascript functions are called when the unread api call is made.\n\nTo add a custom javascript callback, simply add this to the list, like\nso:\n\n    {% register_notify_callbacks callbacks='fill_notification_badge,my_special_notification_callback' %}\n\nThe above would cause the callback to update the unread count badge, and\nwould call the custom function\n`my_special_notification_callback`. All callback\nfunctions are passed a single argument by convention called\n`data`, which contains the entire result from the API.\n\nFor example, the below function would get the recent list of unread\nmessages and log them to the console:\n\n```javascript\nfunction my_special_notification_callback(data) {\n    for (var i=0; i \u003c data.unread_list.length; i++) {\n        msg = data.unread_list[i];\n        console.log(msg);\n    }\n}\n```\n\n### Testing the live-updater\n\n1.  Clone the repo\n2.  Run `./manage.py runserver`\n3.  Browse to `yourserverip/test/`\n4.  Click \\'Make a notification\\' and a new notification should appear\n    in the list in 5-10 seconds.\n\n## Serializing the django-notifications Model\n\nSee here - \u003chttp://www.django-rest-framework.org/api-guide/relations/#generic-relationships\u003e\n\nIn this example the target object can be of type Foo or Bar and the\nappropriate serializer will be used.\n\n```python\nclass GenericNotificationRelatedField(serializers.RelatedField):\n\n    def to_representation(self, value):\n        if isinstance(value, Foo):\n            serializer = FooSerializer(value)\n        if isinstance(value, Bar):\n            serializer = BarSerializer(value)\n\n        return serializer.data\n\n\nclass NotificationSerializer(serializers.Serializer):\n    recipient = PublicUserSerializer(User, read_only=True)\n    unread = serializers.BooleanField(read_only=True)\n    target = GenericNotificationRelatedField(read_only=True)\n```\n\nThanks to @DaWy\n\n### `AbstractNotification` model\n\nIn case you need to customize the notification model in order to add\nfield or customised features that depend on your application, you can\ninherit and extend the `AbstractNotification` model, example:\n\n```python\n#In your_app/models.py\n\nfrom django.db import models\nfrom notifications.base.models import AbstractNotification\n\n\nclass Notification(AbstractNotification):\n    # custom field example\n    category = models.ForeignKey('myapp.Category',\n                                 on_delete=models.CASCADE)\n\n    class Meta(AbstractNotification.Meta):\n        abstract = False\n```\n\nYou will require to define `NOTIFICATIONS_NOTIFICATION_MODEL` setting in\n`setting.py` as follows:\n\n```python\n# In your_project/settings.py\n\nNOTIFICATIONS_NOTIFICATION_MODEL = 'your_app.Notification'\n```\n\n## Notes\n\n### Email Notification\n\nSending email to users has not been integrated into this library. So for\nnow you need to implement it if needed. There is a reserved field\n`Notification.emailed` to make it easier.\n\n### Sample App\n\nA sample app has been implemented in\n`notifications/tests/sample_notifications` that extends\n`django-notifications` with the sole purpose of testing its\nextensibility. You can run the SAMPLE APP by setting the environment\nvariable `SAMPLE_APP` as follows\n\n```bash\nexport SAMPLE_APP=1\n# Run the Django development server with sample_notifications app installed\npython manage.py runserver\n# Unset SAMPLE_APP to remove sample_notifications app from list of INSTALLED_APPS\nunset SAMPLE_APP\n```\n\n## `django-notifications` Team\n\nCore contributors (in alphabetical order):\n\n-   [Alvaro Leonel](https://github.com/AlvaroLQueiroz)\n-   [Federico Capoano](https://github.com/nemesisdesign)\n-   [Samuel Spencer](https://github.com/LegoStormtroopr)\n-   [Yang Yubo](https://github.com/yangyubo)\n-   [YPCrumble](https://github.com/YPCrumble)\n-   [Zhongyuan Zhang](https://github.com/zhang-z)\n\n## Contribute\n\nWe are looking for contributors, for anyone who\\'d like to contribute\nand willing to put time and energy on this project, please contact [Yang\nYubo](https://github.com/yangyubo).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjango-notifications%2Fdjango-notifications","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdjango-notifications%2Fdjango-notifications","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjango-notifications%2Fdjango-notifications/lists"}