Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
05305b3
Added installation instructions to clone from github repo.
david-haber Nov 3, 2014
a10c1c4
Formatting
david-haber Nov 3, 2014
9b3832d
Merge pull request #59 from david-haber/master
stephenmuss Nov 3, 2014
e61a57a
Ensured tests pass in Django 1.3
stephenmuss Nov 8, 2014
67372af
Fix ModelForm deprecation warnings when using Django>=1.7
stnatic Jan 6, 2015
1385933
Merge pull request #64 from stnatic/master
stephenmuss Jan 6, 2015
48ef2e2
Preparation for PyPI release
stephenmuss Jan 6, 2015
fe8390f
increase message character limit to 2048 to support Apple's 2kb paylo…
Oct 17, 2015
7ec1325
Remove warning for ManyToManyField
swmerko Dec 10, 2015
d47b385
Merge pull request #69 from swmerko/patch-1
stephenmuss Dec 10, 2015
a37c319
Adapts forms to Django 1.8.
diegomaser Mar 1, 2016
d2b80ca
Travis: Added Django 1.8 and removed < 1.6
stephenmuss Mar 1, 2016
91bfdc7
Merge pull request #71 from diegomartin/master
stephenmuss Mar 1, 2016
0e92509
Updated requirements in README
stephenmuss Mar 1, 2016
483e544
Add latest version of Django to travis config.
hairychris Mar 26, 2016
efcceb6
Upgrade migrations from south, supports 1.6 --> 1.9 now.
chrisfranklin Mar 26, 2016
78d5b2f
Merge pull request #72 from hairychris/patch-1
stephenmuss Mar 26, 2016
fbfa04d
Merge pull request #68 from cjgendron/increase_message_char_limit
stephenmuss Mar 26, 2016
bb6d585
Removed unnecessary dist/egg-info
stephenmuss Mar 26, 2016
23a7ad8
adding support for Django1.10
valenmope Oct 20, 2016
2de7b91
replace old patterns
valenmope Oct 20, 2016
7a3639d
remove urlpatterns
valenmope Oct 21, 2016
869f797
fix on urls
valenmope Oct 21, 2016
c86f76c
Merge pull request #77 from valenmope/master
stephenmuss Oct 21, 2016
7fdb7c7
remove empty string to make urls compatible for django 1.10
aesmail Nov 14, 2016
de1e96c
remove deprecated current_app parameter to request object
aesmail Nov 14, 2016
bceeb12
remove old, unnecessary {% load url from future %}
aesmail Nov 14, 2016
423520d
remove old, unnecessary {% load url from future %}
aesmail Nov 14, 2016
664fb83
Merge pull request #78 from aesmail/master
stephenmuss Nov 15, 2016
bdea63d
handle gevent_openssl swallowing the ZeroReturnError
Dec 8, 2016
9600c49
Merge pull request #80 from joshowen/openfolio
stephenmuss Dec 9, 2016
c6041b2
django 1.7
stanleytang Nov 3, 2014
97d0435
remove default block type
stanleytang Nov 4, 2014
12fdf6a
dont set device last_notified_ati
alvinchow86 Nov 15, 2017
54ea302
Merge branch 'master' into django_upgrade
ZhbL Mar 28, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
*.swp
build
.DS_Store
dist
*.egg-info
env/
13 changes: 8 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
language: python
python:
- "2.6"
- "2.7"
script: ./runtests.sh
env:
- DJANGO_VERSION=1.3.7
- DJANGO_VERSION=1.4.16
- DJANGO_VERSION=1.5.11
- DJANGO_VERSION=1.6.8
- DJANGO_VERSION=1.7.1
- DJANGO_VERSION=1.7.8
- DJANGO_VERSION=1.8.2
- DJANGO_VERSION=1.9.4

install:
- pip install -q Django==$DJANGO_VERSION
- pip install -r requirements.txt
- python setup.py -q install
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2012, Stephen Muss
Copyright (c) 2015, Stephen Muss
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
38 changes: 30 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
django-ios-notifications
=================

[![Build Status](https://travis-ci.org/stephenmuss/django-ios-notifications.svg?branch=master)](https://travis-ci.org/stephenmuss/django-ios-notifications)

Django iOS Notifications makes it easy to send push notifications to iOS devices.


Expand All @@ -10,23 +12,43 @@ Installation

Minimum Requirements

* Python 2.6 or greater
* Django 1.3 or greater
* Python 2.7
* Django 1.6 or greater

Two hard dependencies:

* `pyOpenSSL >= 0.10`
* `django-fields >= 0.1.2`
* `django-fields >= 0.2.2`

* * *

1. You can install with pip: `pip install django-ios-notifications`.
1. You can install with pip:
* `pip install django-ios-notifications` to get the latest release version
* `pip install git+https://github.com/stephenmuss/django-ios-notifications.git#egg=django-ios-notifications` to install the latest bleeding-edge/development version
2. Add `ios_notifications` to `INSTALLED_APPS` in settings file.
3. If you want to use the API for registering devices you will need to make the appropriate changes to your urls file.
* `url(r'^ios-notifications/', include('ios_notifications.urls'))`
4. Create required database tables.
* `./manage.py syncdb`
* If using south `./manage.py migrate ios_notifications`
4. Create required database tables.
* `./manage.py syncdb`
* If using south `./manage.py migrate ios_notifications` also see older django note below.


Django 1.6 or below
-------------------

You must configure south by adding the following lines to your settings file.

```
SOUTH_MIGRATION_MODULES = {
'ios_notifications': 'ios_notifications.south_migrations',
}
```


Notes on Upgrading to 0.2.0
-----------------
If you are upgrading to 0.2.0 from an older verion and you use password protection in any of your `APNService`s you will need to renter the password and resave the model for each one.
This is due to changes in more recent versions of `django-fields`.


Setting up the APN Services
Expand Down Expand Up @@ -287,7 +309,7 @@ The `call_feedback_service` command takes one required argument:
A full example: `./manage.py call_feedback_service --feedback-service=123`

__NOTE:__ You may experience some issues testing the feedback service in a sandbox enviroment.
This occurs when an app was the last push enabled app for that particular APN Service on the device
This occurs when an app was the last push enabled app for that particular APN Service on the device
Once the app is removed it tears down the persistent connection to the APN service. If you want to
test a feedback service, ensure that you have at least one other app on the device installed which
receives notifications from the same APN service.
Expand Down
2 changes: 1 addition & 1 deletion ios_notifications/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-

VERSION = '0.2'
VERSION = '0.2.0'
18 changes: 7 additions & 11 deletions ios_notifications/admin.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
# -*- coding: utf-8 -*-

try:
from django.conf.urls import patterns, url
except ImportError: # deprecated since Django 1.4
from django.conf.urls.defaults import patterns, url

from django.conf.urls import url
from django.contrib import admin
from django.template.response import TemplateResponse
from django.shortcuts import get_object_or_404

from .models import Device, Notification, APNService, FeedbackService
from .forms import APNServiceForm

Expand All @@ -34,9 +29,10 @@ class NotificationAdmin(admin.ModelAdmin):

def get_urls(self):
urls = super(NotificationAdmin, self).get_urls()
notification_urls = patterns('',
url(r'^(?P<id>\d+)/push-notification/$', self.admin_site.admin_view(self.admin_push_notification),
name='admin_push_notification'),)
notification_urls = [
url(r'^(?P<id>\d+)/push-notification/$', self.admin_site.admin_view(self.admin_push_notification),
name='admin_push_notification'),
]
return notification_urls + urls

def admin_push_notification(self, request, **kwargs):
Expand All @@ -46,9 +42,9 @@ def admin_push_notification(self, request, **kwargs):
service = notification.service
num_devices = service.device_set.filter(is_active=True).count()
notification.service.push_notification_to_devices(notification)
request.current_app = 'ios_notifications'
return TemplateResponse(request, 'admin/ios_notifications/notification/push_notification.html',
{'notification': notification, 'num_devices': num_devices, 'sent': request.method == 'POST'},
current_app='ios_notifications')
{'notification': notification, 'num_devices': num_devices, 'sent': request.method == 'POST'})

admin.site.register(Device, DeviceAdmin)
admin.site.register(Notification, NotificationAdmin)
Expand Down
3 changes: 2 additions & 1 deletion ios_notifications/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import re

import django
from django.http import HttpResponseNotAllowed, QueryDict
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import get_object_or_404
Expand All @@ -27,7 +28,7 @@ def route(self, request, **kwargs):
if method in self.allowed_methods:
if hasattr(self, method.lower()):
if method == 'PUT':
request.PUT = QueryDict(request.raw_post_data).copy()
request.PUT = QueryDict(request.body if django.VERSION >= (1, 4) else request.raw_post_data).copy()
return getattr(self, method.lower())(request, **kwargs)

return HttpResponseNotImplemented()
Expand Down
7 changes: 6 additions & 1 deletion ios_notifications/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-03-26 01:00
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion

import django_fields.fields


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
Expand Down
21 changes: 21 additions & 0 deletions ios_notifications/migrations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""
Django migrations for email_log app.

This package does not contain South migrations. South migrations can be found
in the ``south_migrations`` package.
"""

SOUTH_ERROR_MESSAGE = """\n
For South support, customize the SOUTH_MIGRATION_MODULES setting like so:

SOUTH_MIGRATION_MODULES = {
'ios_notifications': 'ios_notifications.south_migrations',
}
"""

# Ensure the user is not using Django 1.6 or below with South
try:
from django.db import migrations # noqa
except ImportError:
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured(SOUTH_ERROR_MESSAGE)
6 changes: 4 additions & 2 deletions ios_notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ class Notification(models.Model):
Represents a notification which can be pushed to an iOS device.
"""
service = models.ForeignKey(APNService)
message = models.CharField(max_length=200, blank=True, help_text='Alert message to display to the user. Leave empty if no alert should be displayed to the user.')
message = models.CharField(max_length=2048, blank=True, help_text='Alert message to display to the user. Leave empty if no alert should be displayed to the user.')
badge = models.PositiveIntegerField(null=True, blank=True, help_text='New application icon badge number. Set to None if the badge number must not be changed.')
silent = models.NullBooleanField(null=True, blank=True, help_text='set True to send a silent notification')
sound = models.CharField(max_length=30, blank=True, help_text='Name of the sound to play. Leave empty if no sound should be played.')
Expand Down Expand Up @@ -293,7 +293,7 @@ class Device(models.Model):
is_active = models.BooleanField(default=True)
deactivated_at = models.DateTimeField(null=True, blank=True)
service = models.ForeignKey(APNService)
users = models.ManyToManyField(get_setting('AUTH_USER_MODEL'), null=True, blank=True, related_name='ios_devices')
users = models.ManyToManyField(get_setting('AUTH_USER_MODEL'), blank=True, related_name='ios_devices')
added_at = models.DateTimeField(auto_now_add=True)
last_notified_at = models.DateTimeField(null=True, blank=True)
platform = models.CharField(max_length=30, blank=True, null=True)
Expand Down Expand Up @@ -346,6 +346,8 @@ def call(self):
try:
while True:
data = self.connection.recv(38) # 38 being the length in bytes of the binary format feedback tuple.
if len(data) == 0:
raise OpenSSL.SSL.ZeroReturnError()
timestamp, token_length, token = struct.unpack(self.fmt, data)
device_token = hexlify(token)
device_tokens.append(device_token)
Expand Down
Loading