From 652222d2b8b0ad9c23e61cf4880f85dc40d699d0 Mon Sep 17 00:00:00 2001 From: John Pham Date: Thu, 7 Dec 2017 08:38:29 +0800 Subject: [PATCH] Django 2.0 support --- .travis.yml | 11 ++++++++++ README.rst | 2 +- notifications/migrations/0001_initial.py | 10 ++++----- notifications/models.py | 8 +++---- .../templatetags/notifications_tags.py | 21 ++++++++++++++++--- notifications/tests/settings.py | 8 ++++++- notifications/tests/tests.py | 5 ++++- notifications/tests/urls.py | 9 ++++++-- notifications/views.py | 14 +++++++++++-- 9 files changed, 69 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6517450..f05f7ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,8 @@ env: - DJANGO=1.8 - DJANGO=1.9 - DJANGO=1.10 + - DJANGO=1.11 + - DJANGO=2.0 install: # command to install dependencies - "pip install coveralls" @@ -26,5 +28,14 @@ matrix: env: DJANGO=1.9 - python: "3.3" env: DJANGO=1.10 + - python: "3.3" + env: DJANGO=1.11 + - python: "3.3" + env: DJANGO=2.0 + - python: "2.7" + env: DJANGO=2.0 + + + after_success: - coveralls diff --git a/README.rst b/README.rst index 09ab515..88a3310 100644 --- a/README.rst +++ b/README.rst @@ -29,7 +29,7 @@ Requirements ============ - Python 2.7, 3.3, 3.4, 3.5 -- Django 1.7, 1.8, 1.9, 1.10 +- Django 1.7, 1.8, 1.9, 1.10, 1.11, 2.0 Installation ============ diff --git a/notifications/migrations/0001_initial.py b/notifications/migrations/0001_initial.py index a63192b..80f3000 100644 --- a/notifications/migrations/0001_initial.py +++ b/notifications/migrations/0001_initial.py @@ -18,7 +18,7 @@ class Migration(migrations.Migration): name='Notification', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('level', models.CharField(default=b'info', max_length=20, choices=[(b'success', b'success'), (b'info', b'info'), (b'warning', b'warning'), (b'error', b'error')])), + ('level', models.CharField(default='info', max_length=20, choices=[('success', 'success'), ('info', 'info'), ('warning', 'warning'), ('error', 'error')])), ('unread', models.BooleanField(default=True)), ('actor_object_id', models.CharField(max_length=255)), ('verb', models.CharField(max_length=255)), @@ -27,10 +27,10 @@ class Migration(migrations.Migration): ('action_object_object_id', models.CharField(max_length=255, null=True, blank=True)), ('timestamp', models.DateTimeField(default=django.utils.timezone.now)), ('public', models.BooleanField(default=True)), - ('action_object_content_type', models.ForeignKey(related_name=b'notify_action_object', blank=True, to='contenttypes.ContentType', null=True)), - ('actor_content_type', models.ForeignKey(related_name=b'notify_actor', to='contenttypes.ContentType')), - ('recipient', models.ForeignKey(related_name=b'notifications', to=settings.AUTH_USER_MODEL)), - ('target_content_type', models.ForeignKey(related_name=b'notify_target', blank=True, to='contenttypes.ContentType', null=True)), + ('action_object_content_type', models.ForeignKey(related_name='notify_action_object', blank=True, to='contenttypes.ContentType', null=True, on_delete=models.CASCADE)), + ('actor_content_type', models.ForeignKey(related_name='notify_actor', to='contenttypes.ContentType', on_delete=models.CASCADE)), + ('recipient', models.ForeignKey(related_name='notifications', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), + ('target_content_type', models.ForeignKey(related_name='notify_target', blank=True, to='contenttypes.ContentType', null=True, on_delete=models.CASCADE)), ], options={ 'ordering': ('-timestamp',), diff --git a/notifications/models.py b/notifications/models.py index 6e470dd..7b61449 100644 --- a/notifications/models.py +++ b/notifications/models.py @@ -169,22 +169,22 @@ class Notification(models.Model): LEVELS = Choices('success', 'info', 'warning', 'error') level = models.CharField(choices=LEVELS, default=LEVELS.info, max_length=20) - recipient = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, related_name='notifications') + recipient = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, related_name='notifications', on_delete=models.CASCADE) unread = models.BooleanField(default=True, blank=False) - actor_content_type = models.ForeignKey(ContentType, related_name='notify_actor') + actor_content_type = models.ForeignKey(ContentType, related_name='notify_actor', on_delete=models.CASCADE) actor_object_id = models.CharField(max_length=255) actor = GenericForeignKey('actor_content_type', 'actor_object_id') verb = models.CharField(max_length=255) description = models.TextField(blank=True, null=True) - target_content_type = models.ForeignKey(ContentType, related_name='notify_target', blank=True, null=True) + target_content_type = models.ForeignKey(ContentType, related_name='notify_target', blank=True, null=True, on_delete=models.CASCADE) target_object_id = models.CharField(max_length=255, blank=True, null=True) target = GenericForeignKey('target_content_type', 'target_object_id') action_object_content_type = models.ForeignKey(ContentType, blank=True, null=True, - related_name='notify_action_object') + related_name='notify_action_object', on_delete=models.CASCADE) action_object_object_id = models.CharField(max_length=255, blank=True, null=True) action_object = GenericForeignKey('action_object_content_type', 'action_object_object_id') diff --git a/notifications/templatetags/notifications_tags.py b/notifications/templatetags/notifications_tags.py index be4b7c9..0d0a59e 100644 --- a/notifications/templatetags/notifications_tags.py +++ b/notifications/templatetags/notifications_tags.py @@ -1,12 +1,16 @@ # -*- coding: utf-8 -*- -from django.core.urlresolvers import reverse +from django import get_version +from distutils.version import StrictVersion +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse from django.template import Library from django.utils.html import format_html register = Library() -@register.assignment_tag(takes_context=True) def notifications_unread(context): user = user_context(context) if not user: @@ -14,6 +18,12 @@ def notifications_unread(context): return user.notifications.unread().count() +if StrictVersion(get_version()) >= StrictVersion('2.0'): + notifications_unread = register.simple_tag(takes_context=True)(notifications_unread) +else: + notifications_unread = register.assignment_tag(takes_context=True)(notifications_unread) + + # Requires vanilla-js framework - http://vanilla-js.com/ @register.simple_tag def register_notify_callbacks(badge_class='live_notify_badge', @@ -79,6 +89,11 @@ def user_context(context): request = context['request'] user = request.user - if user.is_anonymous(): + try: + user_is_anonymous = user.is_anonymous() + except TypeError: # Django >= 1.11 + user_is_anonymous = user.is_anonymous + + if user_is_anonymous: return None return user diff --git a/notifications/tests/settings.py b/notifications/tests/settings.py index 02808af..90ee936 100644 --- a/notifications/tests/settings.py +++ b/notifications/tests/settings.py @@ -12,12 +12,18 @@ DATABASES = { } } - +# Django < 2.0 MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', ) +# Django >= 2.0 +MIDDLEWARE = [ + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +] + INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', diff --git a/notifications/tests/tests.py b/notifications/tests/tests.py index 6d56603..f4851ea 100644 --- a/notifications/tests/tests.py +++ b/notifications/tests/tests.py @@ -14,7 +14,10 @@ except ImportError: from django.conf import settings from django.contrib.auth.models import User, Group from django.core.exceptions import ImproperlyConfigured -from django.core.urlresolvers import reverse +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse from django.utils.timezone import utc, localtime from django.utils import timezone import pytz diff --git a/notifications/tests/urls.py b/notifications/tests/urls.py index 711f614..4cb649c 100644 --- a/notifications/tests/urls.py +++ b/notifications/tests/urls.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- - +from distutils.version import StrictVersion +from django import get_version from django.conf.urls import include, url from django.contrib import admin from django.contrib.auth.views import login @@ -9,8 +10,12 @@ import notifications.tests.views urlpatterns = [ url(r'^login/$', login, name='login'), # needed for Django 1.6 tests - url(r'^admin/', include(admin.site.urls)), url(r'^test_make/', notifications.tests.views.make_notification), url(r'^test/', notifications.tests.views.live_tester), url(r'^', include(notifications.urls, namespace='notifications')), ] + +if StrictVersion(get_version()) >= StrictVersion('2.0'): + urlpatterns.append(url(r'^admin/', admin.site.urls)) +else: + urlpatterns.append(url(r'^admin/', include(admin.site.urls))) diff --git a/notifications/views.py b/notifications/views.py index a60747d..249637f 100644 --- a/notifications/views.py +++ b/notifications/views.py @@ -121,7 +121,12 @@ def delete(request, slug=None): def live_unread_notification_count(request): - if not request.user.is_authenticated(): + try: + user_is_authenticated = request.user.is_authenticated() + except TypeError: # Django >= 1.11 + user_is_authenticated = request.user.is_authenticated + + if not user_is_authenticated: data = {'unread_count':0} else: data = { @@ -131,7 +136,12 @@ def live_unread_notification_count(request): def live_unread_notification_list(request): - if not request.user.is_authenticated(): + try: + user_is_authenticated = request.user.is_authenticated() + except TypeError: # Django >= 1.11 + user_is_authenticated = request.user.is_authenticated + + if not user_is_authenticated: data = { 'unread_count':0, 'unread_list':[]