- About Pinax
- Overview
- Documentation
- Change Log
- History
- Contribute
- Code of Conduct
- Connect with Pinax
- License
Pinax is an open-source platform built on the Django Web Framework. It is an ecosystem of reusable Django apps, themes, and starter project templates. This collection can be found at http://pinaxproject.com.
pinax-notifications
is a user notification management app for the Django web framework.
Many sites need to notify users when certain events have occurred and to allow
configurable options as to how those notifications are to be received. pinax-notifications
serves this need.
- Submission of notification messages by other apps
- Notification messages via email (configurable by user)
- Ability to supply your own backend notification channels
- Ability to scope notifications at the site level
Django \ Python | 2.7 | 3.4 | 3.5 | 3.6 |
---|---|---|---|---|
1.11 | * | * | * | * |
2.0 | * | * | * |
To install pinax-notifications:
$ pip install pinax-notifications
Add pinax.notifications
to your INSTALLED_APPS
setting:
INSTALLED_APPS = [
# other apps
"pinax.notifications",
]
Add pinax.notifications.urls
to your project urlpatterns:
urlpatterns = [
# other urls
url(r"^notifications/", include("pinax.notifications.urls", namespace="pinax_notifications")),
]
Integrating notification support into your app is a three-step process:
- create your notice types
- create your notice templates
- send notifications
You need to call NoticeType.create(label, display, description)
once to
create the notice types for your application in the database.
label
is the internal shortname that will be used for the typedisplay
is what the user sees as the name of the notification typedescription
is a short description
For example:
from pinax.notifications.models import NoticeType
NoticeType.create(
"friends_invite",
"Invitation Received",
"you have received an invitation"
)
One way to create notice types is using a custom AppConfig
. Here is an example:
# myapp/signals/handlers.py
from django.conf import settings
from django.utils.translation import ugettext_noop as _
def create_notice_types(sender, **kwargs):
if "pinax.notifications" in settings.INSTALLED_APPS:
from pinax.notifications.models import NoticeType
print("Creating notices for myapp")
NoticeType.create("friends_invite", _("Invitation Received"), _("you have received an invitation"))
NoticeType.create("friends_accept", _("Acceptance Received"), _("an invitation you sent has been accepted"))
else:
print("Skipping creation of NoticeTypes as notification app not found")
Notice that the code is wrapped in a conditional clause so if
pinax-notifications
is not installed, your app will proceed anyway.
Note that the display and description arguments are marked for translation by
using ugettext_noop. That will enable you to use Django's makemessages
management command and use pinax-notifications
i18n capabilities.
# myapp/apps.py
from django.apps import AppConfig
from django.db.models.signals import post_migrate
from myapp.signals import handlers
class MyAppConfig(AppConfig):
name = 'myapp'
verbose_name = 'My App'
def ready(self):
post_migrate.connect(handlers.create_notice_types, sender=self)
This will call the handler to create notices after the application is migrated.
# myapp/__init__.py
default_app_config = 'myapp.apps.MyAppConfig'
Default templates are provided by the pinax-templates
app in the
notifications
section of that project.
Reference pinax-templates installation instructions to include these templates in your project.
View live pinax-templates
examples and source at Pinax Templates!
Override the default pinax-templates
templates by copying them into your project
subdirectory pinax/notifications/
on the template path and modifying as needed.
For example if your project doesn't use Bootstrap, copy the desired templates
then remove Bootstrap and Font Awesome class names from your copies.
Remove class references like class="btn btn-success"
and class="icon icon-pencil"
as well as
bootstrap
from the {% load i18n bootstrap %}
statement.
Since bootstrap
template tags and filters are no longer loaded, you'll also need to update
{{ form|bootstrap }}
to {{ form }}
since the "bootstrap" filter is no longer available.
Base template for other templates.
This template allows the user to specify which notices they want to receive.
This template is rendered by the sole view in pinax.notifications.views
with the context
containing a list of available notice_types
as well as the request.user
's settings
for those notice types.
Four templates included with pinax-templates
support the
single email backend that is included with pinax-notifications
.
Renders to the email subject.
Renders to the email body.
Renders the entire email body. Contains full.txt
.
Renders the entire email subject. Contains short.txt
.
In addition to the extra context supplied via the send
call in your
site or app, these templates are rendered with the following context variables:
default_http_protocol
-https
ifsettings.PINAX_USE_SSL
is True, otherwisehttp
current_site
-Site.objects.get_current()
base_url
- the default http protocol combined with the current site domainrecipient
- the user who is getting the noticesender
- the value supplied to thesender
kwarg of thesend
method (often this is not set and will beNone
)notice
- display value of the notice type
You can override default templates shipped with pinax-templates
by adding alternative templates
to a directory on the template path called pinax/notifications/<notice_type_label>/
.
For the example NoticeType above we might override short.txt
to surround the notice with asterisks:
{# pinax/notifications/friends_invite/short.txt #}
{% autoescape off %}{% load i18n %}{% blocktrans %}*** {{ notice }} ***{% endblocktrans %}{% endautoescape %}
If any of the four email backend templates are missing from the alternative directory, the appropriate installed default template is used.
There are two different ways of sending out notifications. We have support for blocking and non-blocking methods of sending notifications. The most simple way to send out a notification, for example::
from pinax.notifications.models import send_now, send, queue
send([to_user], "friends_invite", {"from_user": from_user})
One thing to note is that send
is a proxy around either send_now
or
queue
. They all have the same signature::
send(users, label, extra_context)
The parameters are:
users
is an iterable ofUser
objects to send the notification to.label
is the label you used in the previous step to identify the notice type.extra_content
is a dictionary to add custom context entries to the template used to render to notification. This is optional.
Lets first break down what each does.
This is a blocking call that will check each user for elgibility of the notice and actually peform the send.
This is a non-blocking call that will queue the call to send_now
to
be executed at a later time. To later execute the call you need to use
the emit_notices
management command.
A proxy around send_now
and queue
. It gets its behavior from a global
setting named PINAX_NOTIFICATIONS_QUEUE_ALL
. By default it is False
. This
setting is meant to help control whether you want to queue any call to send
.
send
also accepts now
and queue
keyword arguments. By default each option
is set to False
to honor the global setting which is False
. This enables
you to override on a per call basis whether it should call send_now
or
queue
.
In case you want to use pinax-notifications
in your reusable app, you can wrap
the import of pinax-notifications
in a conditional clause that tests if it's
installed before sending a notice. As a result your app or project still
functions without notification.
For example:
from django.conf import settings
if "notification" in settings.INSTALLED_APPS:
from pinax.notifications import models as notification
else:
notification = None
and then, later:
if notification:
notification.send([to_user], "friends_invite", {"from_user": from_user})
The following allows you to specify the behavior of pinax-notifications
in
your project. Please be aware of the native Django settings which can affect
the behavior of pinax-notifications
.
Defaults to:
[
("email", "pinax.notifications.backends.email.EmailBackend"),
]
Formerly named NOTIFICATION_BACKENDS
.
This is a proposed common setting across the Pinax ecosystem. It currently may not be consistant across all apps.
Defaults to False
.
This is used to specify the beginning of URLs in the default email_body.txt
file. A common use-case for overriding this default might be https
for use on
more secure projects.
Formerly named DEFAULT_HTTP_PROTOCOL
and defaulted to "http".
There is not set default for this setting. It allows users to specify their own notification language.
Example model in a languages
app::
from django.conf import settings
class Language(models.Model):
user = models.ForeignKey(User)
language = models.CharField(max_length=10, choices=settings.LANGUAGES)
Setting this value in settings.py
::
PINAX_NOTIFICATIONS_LANGUAGE_MODEL = "languages.Language"
Formerly named NOTIFICATION_LANGUAGE_MODULE
.
Defaults to webmaster@localhost
and is a standard Django setting.
Default e-mail address to use for various automated correspondence from
pinax.notifications.backends.email
.
Defaults to a tuple of all available languages and is a standard Django setting.
The default for this is specifically used for things like the Django admin. However, if you need to specify a subset of languages for your site's front end you can use this setting to override the default. In which case this is the definated pattern of usage::
gettext = lambda s: s
LANGUAGES = (
("en", gettext("English")),
("fr", gettext("French")),
)
It defaults to False
.
By default, calling notification.send
will send the notification immediately,
however, if you set this setting to True, then the default behavior of the
send
method will be to queue messages in the database for sending via the
emit_notices
command.
Formerly named NOTIFICATION_QUEUE_ALL
.
It defaults to -1
.
It defines how long to wait for the lock to become available. Default of -1
means to never wait for the lock to become available. This only applies when
using crontab setup to execute the emit_notices
management command to send
queued messages rather than sending immediately.
Formerly named NOTIFICATION_LOCK_WAIT_TIMEOUT
.
Sometimes you have a site that has groups or teams. Perhaps you are using pinax-teams. If this is the case you likely want users who might be members of multiple teams to be able to set their notification preferences on a per team or group basis.
You will need to to simply override NoticeSettingsView
to provide your own
scoping object.
I think it's best if we just demonstrate via code:
# views.py
from pinax.notifications.views import NoticeSettingsView
class TeamNoticeSettingsView(NoticeSettingsView):
@property
def scoping(self):
return self.request.team
Then override the url:
# urls.py
from django.conf.urls import url
from .views import TeamNoticeSettingsView
urlpatterns = [
# other urls
url(r"^notifications/settings/$", TeamNoticeSettingsView.as_view(), name="notification_notice_settings"),
]
- Remove unneeded compatibility
- Fix bytestring decoding bug
- Update django>=1.11 in requirements
- Update CI config
- Add sorting guidance for 3rd-party app imports
- Improve documentation and markup
- Standardize documentation layout
- Drop Django v1.8, v1.10 support
- Fix another silly documentation error
- Fix installation documentation
- Add Django 2.0 compatibility testing
- Drop Django 1.9 and Python 3.3 support
- Move documentation into README
- Convert CI and coverage to CircleCi and CodeCov
- Add PyPi-compatible long description
- BI: To support changes to
render_to_string
in Django 1.10 and above, your noticefull.txt
andshort.txt
plain text templates must now be autoescaped explicitly using the{% autoescape %}
tag. (#68)
- initial support for Django 1.10
- fix compatability with Django migrations
- add Django migrations
- renamed app as pinax-notifications
- added the ability to override NoticeSetting model
- added documentation on scoping notifications
- fixed a deprecation warning
- added Russian locale
- added travis integration for tests/lints
- added created_notice_type wrapper
- cleaned up some small bugs identified by pylint
- removed unused
message.py
module - removed
captureas
templatetag - added
notice_settings.html
template - other minor fixes and tweaks, mostly to code style
- pluggable backends
- BI: renamed Notice.user to Notice.recipient
- BI: renamed {{ user }} context variable in notification templates to {{ recipient }}
- BI: added nullable Notice.sender and modified send_now and queue to take an optional sender
- added received and sent methods taking a User instance to Notice.objects
- New default behavior: single notice view now marks unseen notices as seen
- no longer optionally depend on mailer; use django.core.mail.send_mail and we now encourge use of Django 1.2+ for mailer support
- notifications are not sent to inactive users
- users which do not exist when sending notification are now ignored
- BI: split settings part of notices view to its own view notice_settings
- added support for DEFAULT_HTTP_PROTOCOL allowing https absolute URLs
BI = backward incompatible change
This app was originally named django-notification
but was renamed to
bring a common package name like notification
under the pinax
namespace
to avoid conflicts with other like named packages.
In addition, we wanted to take the opportunity to rename it to the plural
form, notifications
to be in line with the convention we've adopted
across the ecosystem.
For an overview on how contributing to Pinax works read this blog post and watch the included video, or read our How to Contribute section. For concrete contribution ideas, please see our Ways to Contribute/What We Need Help With section.
In case of any questions we recommend you join our Pinax Slack team and ping us there instead of creating an issue on GitHub. Creating issues on GitHub is of course also valid but we are usually able to help you faster if you ping us in Slack.
We also highly recommend reading our blog post on Open Source and Self-Care.
In order to foster a kind, inclusive, and harassment-free community, the Pinax Project has a code of conduct. We ask you to treat everyone as a smart human programmer that shares an interest in Python, Django, and Pinax with you.
For updates and news regarding the Pinax Project, please follow us on Twitter @pinaxproject and check out our Pinax Project blog.
Copyright (c) 2012-2019 James Tauber and contributors under the MIT license.