Skip to content

Commit 7ee1e5a

Browse files
author
Kevin Renskers
committed
0.2.1: December 7, 2011
- New model DisabledNotificationsTypeBackend: instead of saving what backend a user wants to use, we save what he does not want to use instead
1 parent d7e2d3a commit 7ee1e5a

File tree

8 files changed

+148
-22
lines changed

8 files changed

+148
-22
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@
2323
- Define __getattr__ for easy access to kwargs
2424
- Start of new settings app, where users can select which types they're interested in
2525
- Users can also select backends per type
26+
27+
0.2.1: December 7, 2011
28+
- New model DisabledNotificationsTypeBackend: instead of saving what backend a user wants to use, we save what he does not want to use instead

notifications/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.2'
1+
__version__ = '0.2.1'

notifications/backend/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from notifications.engine import NotificationEngine
2+
13
class BackendConfigError(Exception):
24
pass
35

@@ -18,6 +20,9 @@ def __init__(self, user=None, subject=None, text=None):
1820
self.subject = subject
1921
self.text = text
2022

23+
def is_registered(self):
24+
return self.__class__.__name__ in NotificationEngine._backends
25+
2126
def _queue(self):
2227
"""
2328
This will add the notification to the database queue. A cron job will then get the notification,
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# encoding: utf-8
2+
import datetime
3+
from south.db import db
4+
from south.v2 import SchemaMigration
5+
from django.db import models
6+
7+
class Migration(SchemaMigration):
8+
9+
def forwards(self, orm):
10+
11+
# Removing unique constraint on 'SelectedNotificationsType', fields ['user', 'notification_type']
12+
db.delete_unique('notifications_selectednotificationstype', ['user_id', 'notification_type'])
13+
14+
# Deleting model 'SelectedNotificationsType'
15+
db.delete_table('notifications_selectednotificationstype')
16+
17+
# Adding model 'DisabledNotificationsTypeBackend'
18+
db.create_table('notifications_disablednotificationstypebackend', (
19+
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
20+
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
21+
('notification_type', self.gf('django.db.models.fields.CharField')(max_length=255)),
22+
('notification_backends', self.gf('django.db.models.fields.TextField')()),
23+
))
24+
db.send_create_signal('notifications', ['DisabledNotificationsTypeBackend'])
25+
26+
# Adding unique constraint on 'DisabledNotificationsTypeBackend', fields ['user', 'notification_type']
27+
db.create_unique('notifications_disablednotificationstypebackend', ['user_id', 'notification_type'])
28+
29+
30+
def backwards(self, orm):
31+
32+
# Removing unique constraint on 'DisabledNotificationsTypeBackend', fields ['user', 'notification_type']
33+
db.delete_unique('notifications_disablednotificationstypebackend', ['user_id', 'notification_type'])
34+
35+
# Adding model 'SelectedNotificationsType'
36+
db.create_table('notifications_selectednotificationstype', (
37+
('notification_type', self.gf('django.db.models.fields.CharField')(max_length=255)),
38+
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
39+
('notification_backends', self.gf('django.db.models.fields.TextField')()),
40+
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
41+
))
42+
db.send_create_signal('notifications', ['SelectedNotificationsType'])
43+
44+
# Adding unique constraint on 'SelectedNotificationsType', fields ['user', 'notification_type']
45+
db.create_unique('notifications_selectednotificationstype', ['user_id', 'notification_type'])
46+
47+
# Deleting model 'DisabledNotificationsTypeBackend'
48+
db.delete_table('notifications_disablednotificationstypebackend')
49+
50+
51+
models = {
52+
'auth.group': {
53+
'Meta': {'object_name': 'Group'},
54+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
55+
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
56+
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
57+
},
58+
'auth.permission': {
59+
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
60+
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
61+
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
62+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
63+
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
64+
},
65+
'auth.user': {
66+
'Meta': {'object_name': 'User'},
67+
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
68+
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'unique': 'True', 'null': 'True'}),
69+
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
70+
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
71+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
72+
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
73+
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
74+
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
75+
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
76+
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
77+
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
78+
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
79+
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
80+
},
81+
'contenttypes.contenttype': {
82+
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
83+
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
84+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
85+
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
86+
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
87+
},
88+
'notifications.disablednotificationstypebackend': {
89+
'Meta': {'unique_together': "(['user', 'notification_type'],)", 'object_name': 'DisabledNotificationsTypeBackend'},
90+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
91+
'notification_backends': ('django.db.models.fields.TextField', [], {}),
92+
'notification_type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
93+
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
94+
},
95+
'notifications.notificationbackendsettings': {
96+
'Meta': {'unique_together': "(['user', 'notification_backend'],)", 'object_name': 'NotificationBackendSettings'},
97+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
98+
'notification_backend': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
99+
'settings': ('django.db.models.fields.TextField', [], {'default': "'{}'"}),
100+
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
101+
},
102+
'notifications.notificationqueue': {
103+
'Meta': {'object_name': 'NotificationQueue'},
104+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
105+
'notification_backend': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
106+
'subject': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
107+
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
108+
'tries': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
109+
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"})
110+
}
111+
}
112+
113+
complete_apps = ['notifications']

notifications/models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ def __unicode__(self):
2525
return self.text
2626

2727

28-
class SelectedNotificationsType(models.Model):
28+
class DisabledNotificationsTypeBackend(models.Model):
2929
"""
30-
A model for saving which types of notification a user is interested in,
31-
and which backends are selected for each of them
30+
In this model we save which backends a user does NOT want to use for a notification type.
31+
By saving what he does NOT want, new users and new types/backends default to everything.
3232
"""
3333
user = models.ForeignKey(User)
3434
notification_type = models.CharField(max_length=255)

notifications/templates/notifications/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
{% for backend_class_name, backend_class in notification_backends.items %}
2626
<td>
2727
{% if backend_class_name in type_dict.type_class.allowed_backends %}
28-
<input type="checkbox" name="{{ type_class_name }}" value="{{ backend_class_name }}"{% if backend_class_name in type_dict.selected_backends %} checked="checked"{% endif %} />
28+
<input type="checkbox" name="{{ type_class_name }}" value="{{ backend_class_name }}"{% if backend_class_name not in type_dict.disabled_backends %} checked="checked"{% endif %} />
2929
{% endif %}
3030
</td>
3131
{% endfor %}

notifications/type/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,22 @@ def _get_backends(self, user):
8787
Only backends that validate (all required settings are available) apply.
8888
"""
8989

90-
from notifications.models import SelectedNotificationsType
90+
from notifications.models import DisabledNotificationsTypeBackend
9191

92-
user_selected_backends = []
92+
disabled_backends = []
9393

9494
try:
95-
user_selected_backends = SelectedNotificationsType.objects.get(user=user, notification_type=self.__class__.__name__).get_backends()
96-
except SelectedNotificationsType.DoesNotExist:
95+
disabled_backends = DisabledNotificationsTypeBackend.objects.get(user=user, notification_type=self.__class__.__name__).get_backends()
96+
except DisabledNotificationsTypeBackend.DoesNotExist:
9797
pass
9898

9999
backends = {}
100100
for backend_name in self.allowed_backends:
101-
if backend_name in user_selected_backends:
101+
if backend_name not in disabled_backends:
102102
subject = self.get_subject(backend_name, user)
103103
text = self.get_text(backend_name, user)
104104
backend = self._all_backends[backend_name](user=user, subject=subject, text=text)
105-
if backend.validate():
105+
if backend.is_registered() and backend.validate():
106106
backends[backend_name] = backend
107107

108108
if not backends and not notification_settings.FAIL_SILENT:

notifications/views.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@
33
from django.http import HttpResponseRedirect
44
from django.views.generic.base import TemplateView
55
from notifications.engine import NotificationEngine
6-
from notifications.models import SelectedNotificationsType
6+
from notifications.models import DisabledNotificationsTypeBackend
77

88

99
class IndexView(TemplateView):
1010
template_name = 'notifications/index.html'
1111

1212
def get_context_data(self, **kwargs):
13-
selected_backends = {}
13+
disabled_backends = {}
1414

15-
for obj in SelectedNotificationsType.objects.filter(user=self.request.user):
16-
selected_backends[obj.notification_type] = obj.get_backends()
15+
for obj in DisabledNotificationsTypeBackend.objects.filter(user=self.request.user):
16+
disabled_backends[obj.notification_type] = obj.get_backends()
1717

1818
notification_types = {}
1919
for class_name, type_class in NotificationEngine._types.items():
2020
notification_types[class_name] = {
2121
'type_class': type_class,
22-
'selected_backends': selected_backends.get(class_name, [])
22+
'disabled_backends': disabled_backends.get(class_name, [])
2323
}
2424

2525
context = super(IndexView, self).get_context_data(**kwargs)
@@ -28,16 +28,21 @@ def get_context_data(self, **kwargs):
2828
return context
2929

3030
def post(self, request, **kwargs):
31-
SelectedNotificationsType.objects.filter(user=request.user).delete()
31+
DisabledNotificationsTypeBackend.objects.filter(user=request.user).delete()
3232

33-
for type_name in NotificationEngine._types.keys():
34-
backends = request.POST.getlist(type_name)
33+
for type_name, type_class in NotificationEngine._types.items():
34+
allowed_backends = type_class().allowed_backends
35+
enabled_backends = request.POST.getlist(type_name)
3536

36-
if backends:
37-
SelectedNotificationsType.objects.create(
37+
# Subtract the enabled backends from allowed_backends, the difference is disabled_backends
38+
disabled_backends = list(allowed_backends)
39+
[disabled_backends.remove(x) for x in enabled_backends]
40+
41+
if disabled_backends:
42+
DisabledNotificationsTypeBackend.objects.create(
3843
user = request.user,
3944
notification_type = type_name,
40-
notification_backends = ','.join(backends)
45+
notification_backends = ','.join(disabled_backends)
4146
)
4247

4348
messages.success(request, 'Your notification settings have been saved')

0 commit comments

Comments
 (0)