Skip to content

Commit

Permalink
Merge ae4b2ad into b42e971
Browse files Browse the repository at this point in the history
  • Loading branch information
pandafy committed Apr 16, 2020
2 parents b42e971 + ae4b2ad commit 4755576
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 8 deletions.
10 changes: 9 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
language: python

python:
- "3.5"
- "3.6"
- "3.7"
- "3.8"

env:
- DJANGO=2.2
- DJANGO=3.0

install:
# command to install dependencies
- "pip install coveralls"
- "pip install pytz" # Needed for tests
- pip install -q Django==$DJANGO
- "pip install ."
# command to run tests

script:
- coverage run --branch --source=notifications manage.py test
- export SAMPLE_APP=1; coverage run --branch --source=notifications manage.py test
- unset SAMPLE_APP; coverage run --branch --source=notifications manage.py test

matrix:
exclude:
- python: "3.5"
env: DJANGO=3.0
- python: "3.5"
env: SAMPLE_APP=1 DJANGO=3.0


after_success:
Expand Down
13 changes: 13 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,19 @@ 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.

Sample App
----------
A sample app has been implemented in ``notifications/tests/sample_notifications`` that extends ``django-notifications`` with the sole purpose of testing its extensibility.
You can run the SAMPLE APP by setting the environment variable ``SAMPLE_APP`` as follows

.. code-block:: shell
export SAMPLE_APP=1
# Run the Django development server with sample_notifications app installed
python manage.py runserver
# Unset SAMPLE_APP to remove sample_notifications app from list of INSTALLED_APPS
unset SAMPLE_APP
``django-notifications`` Team
==============================
Expand Down
3 changes: 2 additions & 1 deletion notifications/admin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
''' Django notifications admin file '''
# -*- coding: utf-8 -*-
from django.contrib import admin
from notifications.base.admin import AbstractNotificationAdmin
from swapper import load_model

Notification = load_model('notifications', 'Notification')


class NotificationAdmin(admin.ModelAdmin):
class NotificationAdmin(AbstractNotificationAdmin):
raw_id_fields = ('recipient',)
list_display = ('recipient', 'actor',
'level', 'target', 'unread', 'public')
Expand Down
12 changes: 12 additions & 0 deletions notifications/base/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from django.contrib import admin


class AbstractNotificationAdmin(admin.ModelAdmin):
raw_id_fields = ('recipient',)
list_display = ('recipient', 'actor',
'level', 'target', 'unread', 'public')
list_filter = ('level', 'unread', 'public', 'timestamp',)

def get_queryset(self, request):
qs = super(AbstractNotificationAdmin, self).get_queryset(request)
return qs.prefetch_related('actor')
1 change: 1 addition & 0 deletions notifications/tests/sample_notifications/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default_app_config = 'notifications.tests.sample_notifications.apps.SampleNotificationsConfig'
10 changes: 10 additions & 0 deletions notifications/tests/sample_notifications/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import swapper
from django.contrib import admin
from notifications.base.admin import AbstractNotificationAdmin

Notification = swapper.load_model('notifications', 'Notification')


@admin.register(Notification)
class NotificationAdmin(AbstractNotificationAdmin):
pass
6 changes: 6 additions & 0 deletions notifications/tests/sample_notifications/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from notifications.apps import Config as NotificationConfig


class SampleNotificationsConfig(NotificationConfig):
name = 'notifications.tests.sample_notifications'
label = 'sample_notifications'
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 3.0.5 on 2020-04-11 12:15

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import jsonfield.fields


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
]

operations = [
migrations.CreateModel(
name='Notification',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('level', models.CharField(choices=[('success', 'success'), ('info', 'info'), ('warning', 'warning'), ('error', 'error')], default='info', max_length=20)),
('unread', models.BooleanField(db_index=True, default=True)),
('actor_object_id', models.CharField(max_length=255)),
('verb', models.CharField(max_length=255)),
('description', models.TextField(blank=True, null=True)),
('target_object_id', models.CharField(blank=True, max_length=255, null=True)),
('action_object_object_id', models.CharField(blank=True, max_length=255, null=True)),
('timestamp', models.DateTimeField(db_index=True, default=django.utils.timezone.now)),
('public', models.BooleanField(db_index=True, default=True)),
('deleted', models.BooleanField(db_index=True, default=False)),
('emailed', models.BooleanField(db_index=True, default=False)),
('data', jsonfield.fields.JSONField(blank=True, null=True)),
('details', models.CharField(blank=True, max_length=64, null=True)),
('action_object_content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notify_action_object', to='contenttypes.ContentType')),
('actor_content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notify_actor', to='contenttypes.ContentType')),
('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to=settings.AUTH_USER_MODEL)),
('target_content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notify_target', to='contenttypes.ContentType')),
],
options={
'ordering': ('-timestamp',),
'abstract': False,
'index_together': {('recipient', 'unread')},
},
),
]
Empty file.
9 changes: 9 additions & 0 deletions notifications/tests/sample_notifications/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.db import models
from notifications.base.models import AbstractNotification


class Notification(AbstractNotification):
details = models.CharField(max_length=64, blank=True, null=True)

class Meta(AbstractNotification.Meta):
abstract = False
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from notifications.templatetags.notifications_tags import register
22 changes: 22 additions & 0 deletions notifications/tests/sample_notifications/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
from unittest import skipUnless

import swapper
from notifications.tests.tests import AdminTest as BaseAdminTest
from notifications.tests.tests import NotificationTest as BaseNotificationTest

Notification = swapper.load_model('notifications', 'Notification')


@skipUnless(os.environ.get('SAMPLE_APP', False), 'Running tests on standard django-notifications models')
class AdminTest(BaseAdminTest):

@classmethod
def setUpClass(cls):
super().setUpClass()
BaseAdminTest.app_name = 'sample_notifications'


@skipUnless(os.environ.get('SAMPLE_APP', False), 'Running tests on standard django-notifications models')
class NotificationTest(BaseNotificationTest):
pass
17 changes: 13 additions & 4 deletions notifications/tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


BASE_DIR = os.path.abspath(os.path.dirname(__file__))
SECRET_KEY = 'secret_key' # noqa
SECRET_KEY = 'secret_key' # noqa

DEBUG = True
TESTING = True
Expand All @@ -26,7 +26,7 @@
# Django >= 2.0
MIDDLEWARE = MIDDLEWARE_CLASSES

INSTALLED_APPS = (
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
Expand All @@ -35,7 +35,7 @@
'django.contrib.sessions',
'notifications.tests',
'notifications',
)
]

ROOT_URLCONF = 'notifications.tests.urls'
STATIC_URL = '/static/'
Expand All @@ -48,8 +48,11 @@
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'loaders' : [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
],
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
Expand All @@ -68,3 +71,9 @@
'USE_JSONFIELD': True,
}
USE_TZ = True

if os.environ.get('SAMPLE_APP', False):
INSTALLED_APPS.remove('notifications')
INSTALLED_APPS.append('notifications.tests.sample_notifications')
NOTIFICATIONS_NOTIFICATION_MODEL = 'sample_notifications.Notification'
TEMPLATES[0]['DIRS'] += [os.path.join(BASE_DIR, '../templates')]
5 changes: 3 additions & 2 deletions notifications/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from django.test.utils import CaptureQueriesContext
from django.utils import timezone
from django.utils.timezone import localtime, utc
from notifications.models import notify_handler
from notifications.base.models import notify_handler
from notifications.signals import notify
from notifications.utils import id2slug
from swapper import load_model
Expand Down Expand Up @@ -519,6 +519,7 @@ def test_has_notification(self):


class AdminTest(TestCase):
app_name = "notifications"
def setUp(self):
self.message_count = 10
self.from_user = User.objects.create_user(username="from", password="pwd", email="example@example.com")
Expand All @@ -538,7 +539,7 @@ def test_list(self):
self.client.login(username='to', password='pwd')

with CaptureQueriesContext(connection=connection) as context:
response = self.client.get(reverse('admin:notifications_notification_changelist'))
response = self.client.get(reverse('admin:{0}_notification_changelist'.format(self.app_name)))
self.assertLessEqual(len(context), 6)

self.assertEqual(response.status_code, 200, response.content)

0 comments on commit 4755576

Please sign in to comment.