diff --git a/notifications/admin.py b/notifications/admin.py
index 3d9c172..95fb2b0 100644
--- a/notifications/admin.py
+++ b/notifications/admin.py
@@ -9,10 +9,11 @@ Notification = load_model('notifications', 'Notification')
class NotificationAdmin(AbstractNotificationAdmin):
raw_id_fields = ('recipient',)
+ readonly_fields = ('action_object_url', 'actor_object_url', 'target_object_url')
list_display = ('recipient', 'actor',
'level', 'target', 'unread', 'public')
list_filter = ('level', 'unread', 'public', 'timestamp',)
-
+
def get_queryset(self, request):
qs = super(NotificationAdmin, self).get_queryset(request)
return qs.prefetch_related('actor')
diff --git a/notifications/base/models.py b/notifications/base/models.py
index 43f9ee3..bcc8bed 100644
--- a/notifications/base/models.py
+++ b/notifications/base/models.py
@@ -11,9 +11,10 @@ from django.core.exceptions import ImproperlyConfigured
from django.db import models
from django.db.models.query import QuerySet
from django.utils import timezone
+from django.utils.html import format_html
+
from jsonfield.fields import JSONField
from model_utils import Choices
-
from notifications import settings as notifications_settings
from notifications.signals import notify
from notifications.utils import id2slug
@@ -24,6 +25,12 @@ if StrictVersion(get_version()) >= StrictVersion('1.8.0'):
else:
from django.contrib.contenttypes.generic import GenericForeignKey # noqa
+try:
+ # Django >= 1.7
+ from django.urls import reverse, NoReverseMatch
+except ImportError:
+ # Django <= 1.6
+ from django.core.urlresolvers import reverse, NoReverseMatch # pylint: disable=no-name-in-module,import-error
EXTRA_DATA = notifications_settings.get_config()['USE_JSONFIELD']
@@ -252,6 +259,33 @@ class AbstractNotification(models.Model):
self.unread = True
self.save()
+ def actor_object_url(self):
+ try:
+ url = reverse("admin:{0}_{1}_change".format(self.actor_content_type.app_label,
+ self.actor_content_type.model),
+ args=(self.actor_object_id,))
+ return format_html("{id}", url=url, id=self.actor_object_id)
+ except NoReverseMatch:
+ return self.actor_object_id
+
+ def action_object_url(self):
+ try:
+ url = reverse("admin:{0}_{1}_change".format(self.action_object_content_type.app_label,
+ self.action_content_type.model),
+ args=(self.action_object_id,))
+ return format_html("{id}", url=url, id=self.action_object_object_id)
+ except NoReverseMatch:
+ return self.action_object_object_id
+
+ def target_object_url(self):
+ try:
+ url = reverse("admin:{0}_{1}_change".format(self.target_content_type.app_label,
+ self.target_content_type.model),
+ args=(self.target_object_id,))
+ return format_html("{id}", url=url, id=self.target_object_id)
+ except NoReverseMatch:
+ return self.target_object_id
+
def notify_handler(verb, **kwargs):
"""
@@ -270,6 +304,7 @@ def notify_handler(verb, **kwargs):
timestamp = kwargs.pop('timestamp', timezone.now())
Notification = load_model('notifications', 'Notification')
level = kwargs.pop('level', Notification.LEVELS.info)
+ actor_for_concrete_model = kwargs.pop('actor_for_concrete_model', True)
# Check if User or Group
if isinstance(recipient, Group):
@@ -284,7 +319,7 @@ def notify_handler(verb, **kwargs):
for recipient in recipients:
newnotify = Notification(
recipient=recipient,
- actor_content_type=ContentType.objects.get_for_model(actor),
+ actor_content_type=ContentType.objects.get_for_model(actor, for_concrete_model=actor_for_concrete_model),
actor_object_id=actor.pk,
verb=str(verb),
public=public,
@@ -296,9 +331,10 @@ def notify_handler(verb, **kwargs):
# Set optional objects
for obj, opt in optional_objs:
if obj is not None:
+ for_concrete_model = kwargs.pop(f'{opt}_for_concrete_model', True)
setattr(newnotify, '%s_object_id' % opt, obj.pk)
setattr(newnotify, '%s_content_type' % opt,
- ContentType.objects.get_for_model(obj))
+ ContentType.objects.get_for_model(obj, for_concrete_model=for_concrete_model))
if kwargs and EXTRA_DATA:
newnotify.data = kwargs.copy()
diff --git a/notifications/templatetags/notifications_tags.py b/notifications/templatetags/notifications_tags.py
index 8e9d425..b589f71 100644
--- a/notifications/templatetags/notifications_tags.py
+++ b/notifications/templatetags/notifications_tags.py
@@ -41,7 +41,9 @@ def register_notify_callbacks(badge_class='live_notify_badge', # pylint: disabl
refresh_period=15,
callbacks='',
api_name='list',
- fetch=5):
+ fetch=5,
+ nonce=None
+ ):
refresh_period = int(refresh_period) * 1000
if api_name == 'list':
@@ -68,7 +70,10 @@ def register_notify_callbacks(badge_class='live_notify_badge', # pylint: disabl
fetch_count=fetch
)
- script = ""
diff --git a/notifications/tests/templates/test_live.html b/notifications/tests/templates/test_live.html
index c8c92c5..eb66c1c 100644
--- a/notifications/tests/templates/test_live.html
+++ b/notifications/tests/templates/test_live.html
@@ -2,7 +2,7 @@
-{% register_notify_callbacks callbacks='fill_notification_list,fill_notification_badge' fetch=20 refresh_period=5 %}
+{% register_notify_callbacks callbacks='fill_notification_list,fill_notification_badge' fetch=20 refresh_period=5 nonce='{{nonce}}' %}
There are this many notifications pending: {% live_notify_badge %}
diff --git a/notifications/tests/tests.py b/notifications/tests/tests.py
index d472adf..dafe35f 100644
--- a/notifications/tests/tests.py
+++ b/notifications/tests/tests.py
@@ -449,7 +449,7 @@ class NotificationTestPages(TestCase):
request = factory.get('/notification/live_updater')
request.user = self.to_user
- render(request, 'notifications/test_tags.html', {'request': request})
+ render(request, 'notifications/test_tags.html', {'request': request, 'nonce': 'nonce-T5esDNXMnDe5lKMQ6ZzTUw=='})
# TODO: Add more tests to check what is being output.