mirror of
https://github.com/Hopiu/django-notifications.git
synced 2026-04-30 09:54:42 +00:00
catchup
This commit is contained in:
commit
1b85a996df
30 changed files with 350 additions and 983 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,3 +6,4 @@ MANIFEST
|
||||||
.coverage
|
.coverage
|
||||||
htmlcov
|
htmlcov
|
||||||
/.idea/
|
/.idea/
|
||||||
|
*.egg-info
|
||||||
|
|
|
||||||
12
.travis.yml
12
.travis.yml
|
|
@ -1,27 +1,27 @@
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- "2.6"
|
|
||||||
- "2.7"
|
- "2.7"
|
||||||
- "3.3"
|
- "3.3"
|
||||||
- "3.4"
|
- "3.4"
|
||||||
|
- "3.5"
|
||||||
env:
|
env:
|
||||||
- DJANGO=1.6
|
|
||||||
- DJANGO=1.7
|
- DJANGO=1.7
|
||||||
- DJANGO=1.8
|
- DJANGO=1.8
|
||||||
|
- DJANGO=1.9
|
||||||
install:
|
install:
|
||||||
# command to install dependencies
|
# command to install dependencies
|
||||||
- "pip install coveralls"
|
- "pip install coveralls"
|
||||||
- "pip install pytz" # Needed for tests
|
- "pip install pytz" # Needed for tests
|
||||||
- pip install -q Django==$DJANGO --use-mirrors
|
- pip install -q Django==$DJANGO
|
||||||
- "pip install ."
|
- "pip install ."
|
||||||
# command to run tests
|
# command to run tests
|
||||||
script:
|
script:
|
||||||
- coverage run --branch --source=notifications manage.py test
|
- coverage run --branch --source=notifications manage.py test
|
||||||
matrix:
|
matrix:
|
||||||
exclude:
|
exclude:
|
||||||
- python: "2.6"
|
- python: "3.5"
|
||||||
env: DJANGO=1.7
|
env: DJANGO=1.7
|
||||||
- python: "2.6"
|
- python: "3.3"
|
||||||
env: DJANGO=1.8
|
env: DJANGO=1.9
|
||||||
after_success:
|
after_success:
|
||||||
- coveralls
|
- coveralls
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,38 @@
|
||||||
Changelog
|
Changelog
|
||||||
==========
|
=========
|
||||||
|
|
||||||
|
1.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
The first major version that requires Django 1.7+.
|
||||||
|
|
||||||
|
- Drop support for Django 1.6 and below (@zhang-z)
|
||||||
|
- Django 1.9 compability (@illing2005)
|
||||||
|
- Now depends on Django built-in migration facility, "south_migrations" dependence was removed (@zhang-z)
|
||||||
|
- Make django-notification compatible with django-model-utils >= 2.4 ( #87, #88, #90 ) (@zhang-z)
|
||||||
|
- Fix a RemovedInDjango110Warning in unittest (@zhang-z)
|
||||||
|
- Fix pep8 & use setuptools (@areski)
|
||||||
|
- Fix typo- in doc (@areski, @zhang-z)
|
||||||
|
- Add app_name in urls.py (@zhang-z)
|
||||||
|
- Use Django's vendored copy of six (@funkybob)
|
||||||
|
- Tidy with flake8 (@funkybob)
|
||||||
|
- Remove custom now() function (@funkybob, @yangyubo)
|
||||||
|
- notify.send() accepts User or Group (@Evidlo)
|
||||||
|
|
||||||
|
0.8.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
0.8 is the last major version supports Django 1.4~1.6, version 0.8.0 will go into bugfix mode, no new features will be accepted.
|
||||||
|
|
||||||
|
- Bugfixes for live-updater, and added a live tester page (@LegoStormtroopr)
|
||||||
|
- Class-based classes (@alazaro)
|
||||||
|
- Fixed urls in tests (@alazaro)
|
||||||
|
- Added app_label to Notification model in order to fix a Django 1.9 deprecation warning (@Heldroe)
|
||||||
|
- django-model-utils compatible issue (must >=2.0.3 and <2.4) (@zhang-z)
|
||||||
|
- Reliable setup.py versioning (@yangyubo)
|
||||||
|
|
||||||
0.7.1
|
0.7.1
|
||||||
------
|
-----
|
||||||
|
|
||||||
- Able to pass level when adding notification (@Arthur)
|
- Able to pass level when adding notification (@Arthur)
|
||||||
- Fix deprecation notice in Django 1.8 (@ashokfernandez)
|
- Fix deprecation notice in Django 1.8 (@ashokfernandez)
|
||||||
|
|
@ -12,7 +42,7 @@ Changelog
|
||||||
- Add missing migration for Notification model (@shezadkhan137)
|
- Add missing migration for Notification model (@shezadkhan137)
|
||||||
|
|
||||||
0.7.0
|
0.7.0
|
||||||
------
|
-----
|
||||||
|
|
||||||
- Add filters and displays to Django model Admin
|
- Add filters and displays to Django model Admin
|
||||||
- Support Django 1.8, compatible with both django-south (django < 1.7) and built-in schema migration (django >= 1.7)
|
- Support Django 1.8, compatible with both django-south (django < 1.7) and built-in schema migration (django >= 1.7)
|
||||||
|
|
@ -20,14 +50,14 @@ Changelog
|
||||||
- Test fixtures, and integrated with travis-ci
|
- Test fixtures, and integrated with travis-ci
|
||||||
|
|
||||||
0.6.2
|
0.6.2
|
||||||
------
|
-----
|
||||||
|
|
||||||
- Fix README.rst reStructuredText syntax format
|
- Fix README.rst reStructuredText syntax format
|
||||||
- Use relative imports
|
- Use relative imports
|
||||||
- Add contributors to AUTHORS.txt
|
- Add contributors to AUTHORS.txt
|
||||||
|
|
||||||
0.6.1
|
0.6.1
|
||||||
------
|
-----
|
||||||
|
|
||||||
- Add support for custom user model
|
- Add support for custom user model
|
||||||
- mark_as_unread
|
- mark_as_unread
|
||||||
|
|
@ -35,13 +65,13 @@ Changelog
|
||||||
- Use different `now` function according to the `USE_TZ` setting
|
- Use different `now` function according to the `USE_TZ` setting
|
||||||
|
|
||||||
0.6.0
|
0.6.0
|
||||||
------
|
-----
|
||||||
|
|
||||||
- Improve documentation
|
- Improve documentation
|
||||||
- Add unicode support at admin panel or shell
|
- Add unicode support at admin panel or shell
|
||||||
|
|
||||||
0.5.5
|
0.5.5
|
||||||
------
|
-----
|
||||||
|
|
||||||
Support for arbitrary data attribute.
|
Support for arbitrary data attribute.
|
||||||
|
|
||||||
|
|
@ -51,7 +81,7 @@ Support for arbitrary data attribute.
|
||||||
Fix package descriptions and doc links.
|
Fix package descriptions and doc links.
|
||||||
|
|
||||||
0.5
|
0.5
|
||||||
-----
|
---
|
||||||
|
|
||||||
First version based on `django-activity-stream <https://github.com/justquick/django-activity-stream>`_ v0.4.3
|
First version based on `django-activity-stream <https://github.com/justquick/django-activity-stream>`_ v0.4.3
|
||||||
|
|
||||||
|
|
|
||||||
43
README.rst
43
README.rst
|
|
@ -1,6 +1,7 @@
|
||||||
``django-notifications`` Documentation
|
``django-notifications`` Documentation
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
|
|
||||||
|build-status| |coveralls|
|
|build-status| |coveralls|
|
||||||
|
|
||||||
`django-notifications <https://github.com/django-notifications/django-notifications>`_ is a GitHub notification alike app for Django, it was derived from `django-activity-stream <https://github.com/justquick/django-activity-stream>`_
|
`django-notifications <https://github.com/django-notifications/django-notifications>`_ is a GitHub notification alike app for Django, it was derived from `django-activity-stream <https://github.com/justquick/django-activity-stream>`_
|
||||||
|
|
@ -24,6 +25,12 @@ For example: `justquick <https://github.com/justquick/>`_ ``(actor)`` *closed* `
|
||||||
|
|
||||||
Nomenclature of this specification is based on the Activity Streams Spec: `<http://activitystrea.ms/specs/atom/1.0/>`_
|
Nomenclature of this specification is based on the Activity Streams Spec: `<http://activitystrea.ms/specs/atom/1.0/>`_
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
- Python 2.7, 3.3, 3.4, 3.5
|
||||||
|
- Django 1.7, 1.8, 1.9
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
|
|
@ -58,34 +65,15 @@ Add the notifications urls to your urlconf::
|
||||||
|
|
||||||
import notifications
|
import notifications
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = [
|
||||||
...
|
...
|
||||||
url('^inbox/notifications/', include(notifications.urls)),
|
url('^inbox/notifications/', include(notifications.urls, namespace='notifications')),
|
||||||
...
|
...
|
||||||
)
|
]
|
||||||
|
|
||||||
The method of installing these urls, importing rather than using ``'notifications.urls'``, is required to ensure that the urls are installed in the ``notifications`` namespace.
|
The method of installing these urls, importing rather than using ``'notifications.urls'``, is required to ensure that the urls are installed in the ``notifications`` namespace.
|
||||||
|
|
||||||
|
To run schema migration, execute ``python manage.py migrate notifications``.
|
||||||
How to migrate schema
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
For Django 1.4~1.6
|
|
||||||
------------------
|
|
||||||
|
|
||||||
`django-south` support is shipped with `django-notifications`.
|
|
||||||
|
|
||||||
#. Install latest version (>=1.0) `django-south <http://pypi.python.org/pypi/South/>`_
|
|
||||||
#. Execute ``manage.py migrate notifications`` to migrate `django-notifications` schema
|
|
||||||
|
|
||||||
Note: If you use a `custom user model <https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#auth-custom-user>`_ in your application, you may want to check `reverse dependencies <http://south.aeracode.org/wiki/Dependencies>`_ of South to run your migrations in the correct order.
|
|
||||||
|
|
||||||
For Django 1.7
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Django 1.7 has built-in support for migrations. No need to install `django-south`.
|
|
||||||
|
|
||||||
#. Execute ``manage.py migrate notifications``
|
|
||||||
|
|
||||||
Generating Notifications
|
Generating Notifications
|
||||||
=========================
|
=========================
|
||||||
|
|
@ -95,7 +83,7 @@ Generating notifications is probably best done in a separate signal.
|
||||||
::
|
::
|
||||||
|
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from notifications import notify
|
from notifications.signals import notify
|
||||||
from myapp.models import MyModel
|
from myapp.models import MyModel
|
||||||
|
|
||||||
def my_handler(sender, instance, created, **kwargs):
|
def my_handler(sender, instance, created, **kwargs):
|
||||||
|
|
@ -107,11 +95,12 @@ To generate an notification anywhere in your code, simply import the notify sign
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
from notifications import notify
|
from notifications.signals import notify
|
||||||
|
|
||||||
notify.send(user, recipient=user, verb='you reached level 10')
|
notify.send(user, recipient=user, verb='you reached level 10')
|
||||||
|
|
||||||
notify.send(comment.user, recipient=user, verb=u'replied', action_object=comment,
|
// "recipient" can also be a Group, the notification will be sent to all the Users in the Group
|
||||||
|
notify.send(comment.user, recipient=group, verb=u'replied', action_object=comment,
|
||||||
description=comment.comment, target=comment.content_object)
|
description=comment.comment, target=comment.content_object)
|
||||||
|
|
||||||
notify.send(follow_instance.user, recipient=follow_instance.follow_object, verb=u'has followed you',
|
notify.send(follow_instance.user, recipient=follow_instance.follow_object, verb=u'has followed you',
|
||||||
|
|
@ -245,7 +234,7 @@ Storing the count in a variable for further processing is advised, such as::
|
||||||
Live-updater API
|
Live-updater API
|
||||||
================
|
================
|
||||||
|
|
||||||
To ensure users always have the most up-to-date notfications, `django-notifications` includes a simple javascript API
|
To ensure users always have the most up-to-date notifications, `django-notifications` includes a simple javascript API
|
||||||
for updating specific fields within a django template.
|
for updating specific fields within a django template.
|
||||||
|
|
||||||
There are two possible API calls that can be made:
|
There are two possible API calls that can be made:
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,4 @@ if __name__ == "__main__":
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "notifications.tests.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "notifications.tests.settings")
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
|
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,13 @@
|
||||||
try:
|
# -*- coding: utf-8 -*-
|
||||||
from notifications.signals import notify
|
"""
|
||||||
except ImportError:
|
django-notifications
|
||||||
pass
|
~~~~~
|
||||||
|
A GitHub notification alike app for Django.
|
||||||
|
:copyright: (c) 2015 by django-notifications team.
|
||||||
|
:license: BSD, see LICENSE.txt for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
try:
|
# PEP 386-compliant version number: N.N[.N]+[{a|b|c|rc}N[.N]+][.postN][.devN]
|
||||||
from notifications.urls import urlpatterns
|
__version__ = '1.0'
|
||||||
urls = (urlpatterns, 'notifications', 'notifications')
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
__version_info__ = {
|
|
||||||
'major': 0,
|
|
||||||
'minor': 8,
|
|
||||||
'micro': 0,
|
|
||||||
'releaselevel': 'final',
|
|
||||||
'serial': 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_version(release_level=True):
|
|
||||||
"""
|
|
||||||
Return the formatted version information
|
|
||||||
"""
|
|
||||||
vers = ["%(major)i.%(minor)i.%(micro)i" % __version_info__]
|
|
||||||
if release_level and __version_info__['releaselevel'] != 'final':
|
|
||||||
vers.append('%(releaselevel)s%(serial)i' % __version_info__)
|
|
||||||
return ''.join(vers)
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = get_version()
|
|
||||||
|
|
||||||
|
default_app_config = 'notifications.apps.Config'
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Notification
|
from .models import Notification
|
||||||
|
|
||||||
|
|
||||||
class NotificationAdmin(admin.ModelAdmin):
|
class NotificationAdmin(admin.ModelAdmin):
|
||||||
list_display = ('recipient', 'actor',
|
list_display = ('recipient', 'actor',
|
||||||
'level', 'target', 'unread', 'public')
|
'level', 'target', 'unread', 'public')
|
||||||
|
|
|
||||||
11
notifications/apps.py
Normal file
11
notifications/apps.py
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Config(AppConfig):
|
||||||
|
name = "notifications"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
super(Config, self).ready()
|
||||||
|
# this is for backwards compability
|
||||||
|
import notifications.signals
|
||||||
|
notifications.notify = notifications.signals.notify
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models, migrations
|
from django.db import models, migrations
|
||||||
import notifications.models
|
from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
@ -15,6 +15,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='notification',
|
model_name='notification',
|
||||||
name='timestamp',
|
name='timestamp',
|
||||||
field=models.DateTimeField(default=notifications.models.now),
|
field=models.DateTimeField(default=timezone.now),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import datetime
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
from django import get_version
|
from django import get_version
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from distutils.version import StrictVersion
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
if StrictVersion(get_version()) >= StrictVersion('1.8.0'):
|
if StrictVersion(get_version()) >= StrictVersion('1.8.0'):
|
||||||
|
|
@ -12,30 +12,20 @@ else:
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from six import text_type
|
from django.utils.six import text_type
|
||||||
from .utils import id2slug
|
from .utils import id2slug
|
||||||
|
|
||||||
from .signals import notify
|
from .signals import notify
|
||||||
|
|
||||||
from model_utils import managers, Choices
|
from model_utils import Choices
|
||||||
from jsonfield.fields import JSONField
|
from jsonfield.fields import JSONField
|
||||||
|
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
def now():
|
|
||||||
# Needs to be be a function as USE_TZ can change based on if we are testing or not.
|
|
||||||
_now = datetime.datetime.now
|
|
||||||
if getattr(settings, 'USE_TZ'):
|
|
||||||
try:
|
|
||||||
from django.utils import timezone
|
|
||||||
_now = timezone.now
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
return _now()
|
|
||||||
|
|
||||||
|
|
||||||
#SOFT_DELETE = getattr(settings, 'NOTIFICATIONS_SOFT_DELETE', False)
|
# SOFT_DELETE = getattr(settings, 'NOTIFICATIONS_SOFT_DELETE', False)
|
||||||
def is_soft_delete():
|
def is_soft_delete():
|
||||||
#TODO: SOFT_DELETE = getattr(settings, ...) doesn't work with "override_settings" decorator in unittest
|
# TODO: SOFT_DELETE = getattr(settings, ...) doesn't work with "override_settings" decorator in unittest
|
||||||
# But is_soft_delete is neither a very elegant way. Should try to find better approach
|
# But is_soft_delete is neither a very elegant way. Should try to find better approach
|
||||||
return getattr(settings, 'NOTIFICATIONS_SOFT_DELETE', False)
|
return getattr(settings, 'NOTIFICATIONS_SOFT_DELETE', False)
|
||||||
|
|
||||||
|
|
@ -170,27 +160,23 @@ class Notification(models.Model):
|
||||||
verb = models.CharField(max_length=255)
|
verb = models.CharField(max_length=255)
|
||||||
description = models.TextField(blank=True, null=True)
|
description = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
target_content_type = models.ForeignKey(ContentType, related_name='notify_target',
|
target_content_type = models.ForeignKey(ContentType, related_name='notify_target', blank=True, null=True)
|
||||||
blank=True, null=True)
|
|
||||||
target_object_id = models.CharField(max_length=255, blank=True, null=True)
|
target_object_id = models.CharField(max_length=255, blank=True, null=True)
|
||||||
target = GenericForeignKey('target_content_type',
|
target = GenericForeignKey('target_content_type', 'target_object_id')
|
||||||
'target_object_id')
|
|
||||||
|
|
||||||
action_object_content_type = models.ForeignKey(ContentType,
|
action_object_content_type = models.ForeignKey(ContentType, blank=True, null=True,
|
||||||
related_name='notify_action_object', blank=True, null=True)
|
related_name='notify_action_object')
|
||||||
action_object_object_id = models.CharField(max_length=255, blank=True,
|
action_object_object_id = models.CharField(max_length=255, blank=True, null=True)
|
||||||
null=True)
|
action_object = GenericForeignKey('action_object_content_type', 'action_object_object_id')
|
||||||
action_object = GenericForeignKey('action_object_content_type',
|
|
||||||
'action_object_object_id')
|
|
||||||
|
|
||||||
timestamp = models.DateTimeField(default=now)
|
timestamp = models.DateTimeField(default=timezone.now)
|
||||||
|
|
||||||
public = models.BooleanField(default=True)
|
public = models.BooleanField(default=True)
|
||||||
deleted = models.BooleanField(default=False)
|
deleted = models.BooleanField(default=False)
|
||||||
emailed = models.BooleanField(default=False)
|
emailed = models.BooleanField(default=False)
|
||||||
|
|
||||||
data = JSONField(blank=True, null=True)
|
data = JSONField(blank=True, null=True)
|
||||||
objects = managers.PassThroughManager.for_queryset_class(NotificationQuerySet)()
|
objects = NotificationQuerySet.as_manager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('-timestamp', )
|
ordering = ('-timestamp', )
|
||||||
|
|
@ -212,7 +198,7 @@ class Notification(models.Model):
|
||||||
return u'%(actor)s %(verb)s %(action_object)s %(timesince)s ago' % ctx
|
return u'%(actor)s %(verb)s %(action_object)s %(timesince)s ago' % ctx
|
||||||
return u'%(actor)s %(verb)s %(timesince)s ago' % ctx
|
return u'%(actor)s %(verb)s %(timesince)s ago' % ctx
|
||||||
|
|
||||||
def __str__(self):#Adds support for Python 3
|
def __str__(self): # Adds support for Python 3
|
||||||
return self.__unicode__()
|
return self.__unicode__()
|
||||||
|
|
||||||
def timesince(self, now=None):
|
def timesince(self, now=None):
|
||||||
|
|
@ -249,31 +235,48 @@ def notify_handler(verb, **kwargs):
|
||||||
Handler function to create Notification instance upon action signal call.
|
Handler function to create Notification instance upon action signal call.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Pull the options out of kwargs
|
||||||
kwargs.pop('signal', None)
|
kwargs.pop('signal', None)
|
||||||
recipient = kwargs.pop('recipient')
|
recipient = kwargs.pop('recipient')
|
||||||
actor = kwargs.pop('sender')
|
actor = kwargs.pop('sender')
|
||||||
newnotify = Notification(
|
optional_objs = [
|
||||||
recipient = recipient,
|
(kwargs.pop(opt, None), opt)
|
||||||
actor_content_type=ContentType.objects.get_for_model(actor),
|
for opt in ('target', 'action_object')
|
||||||
actor_object_id=actor.pk,
|
]
|
||||||
verb=text_type(verb),
|
public = bool(kwargs.pop('public', True))
|
||||||
public=bool(kwargs.pop('public', True)),
|
description = kwargs.pop('description', None)
|
||||||
description=kwargs.pop('description', None),
|
timestamp = kwargs.pop('timestamp', timezone.now())
|
||||||
timestamp=kwargs.pop('timestamp', now()),
|
level = kwargs.pop('level', Notification.LEVELS.info)
|
||||||
level=kwargs.pop('level', Notification.LEVELS.info),
|
|
||||||
)
|
|
||||||
|
|
||||||
for opt in ('target', 'action_object'):
|
# Check if User or Group
|
||||||
obj = kwargs.pop(opt, None)
|
if isinstance(recipient, Group):
|
||||||
if not obj is None:
|
recipients = recipient.user_set.all()
|
||||||
setattr(newnotify, '%s_object_id' % opt, obj.pk)
|
else:
|
||||||
setattr(newnotify, '%s_content_type' % opt,
|
recipients = [recipient]
|
||||||
ContentType.objects.get_for_model(obj))
|
|
||||||
|
|
||||||
if len(kwargs) and EXTRA_DATA:
|
for recipient in recipients:
|
||||||
newnotify.data = kwargs
|
newnotify = Notification(
|
||||||
|
recipient=recipient,
|
||||||
|
actor_content_type=ContentType.objects.get_for_model(actor),
|
||||||
|
actor_object_id=actor.pk,
|
||||||
|
verb=text_type(verb),
|
||||||
|
public=public,
|
||||||
|
description=description,
|
||||||
|
timestamp=timestamp,
|
||||||
|
level=level,
|
||||||
|
)
|
||||||
|
|
||||||
newnotify.save()
|
# Set optional objects
|
||||||
|
for obj, opt in optional_objs:
|
||||||
|
if obj is not None:
|
||||||
|
setattr(newnotify, '%s_object_id' % opt, obj.pk)
|
||||||
|
setattr(newnotify, '%s_content_type' % opt,
|
||||||
|
ContentType.objects.get_for_model(obj))
|
||||||
|
|
||||||
|
if len(kwargs) and EXTRA_DATA:
|
||||||
|
newnotify.data = kwargs
|
||||||
|
|
||||||
|
newnotify.save()
|
||||||
|
|
||||||
|
|
||||||
# connect the signal
|
# connect the signal
|
||||||
|
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
try:
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
except ImportError: # django < 1.5
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
else:
|
|
||||||
User = get_user_model()
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding model 'Notification'
|
|
||||||
db.create_table('notifications_notification', (
|
|
||||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
|
||||||
('recipient', self.gf('django.db.models.fields.related.ForeignKey')(related_name='notifications', to=User)),
|
|
||||||
('readed', self.gf('django.db.models.fields.BooleanField')(default=False)),
|
|
||||||
('actor_content_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='notify_actor', to=orm['contenttypes.ContentType'])),
|
|
||||||
('actor_object_id', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
|
||||||
('verb', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
|
||||||
('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
|
|
||||||
('target_content_type', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='notify_target', null=True, to=orm['contenttypes.ContentType'])),
|
|
||||||
('target_object_id', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
|
|
||||||
('action_object_content_type', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='notify_action_object', null=True, to=orm['contenttypes.ContentType'])),
|
|
||||||
('action_object_object_id', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
|
|
||||||
('timestamp', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
|
|
||||||
('public', self.gf('django.db.models.fields.BooleanField')(default=True)),
|
|
||||||
))
|
|
||||||
db.send_create_signal('notifications', ['Notification'])
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting model 'Notification'
|
|
||||||
db.delete_table('notifications_notification')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
'auth.permission': {
|
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'readed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding field 'Notification.data'
|
|
||||||
db.add_column('notifications_notification', 'data',
|
|
||||||
self.gf('django.db.models.fields.TextField')(null=True, blank=True),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting field 'Notification.data'
|
|
||||||
db.delete_column('notifications_notification', 'data')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
'auth.permission': {
|
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'readed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding field 'Notification.unread'
|
|
||||||
db.add_column('notifications_notification', 'unread',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=True),
|
|
||||||
keep_default=True)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting field 'Notification.unread'
|
|
||||||
db.delete_column('notifications_notification', 'unread')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
'auth.permission': {
|
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'readed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'unread': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import DataMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
class Migration(DataMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
""
|
|
||||||
orm['notifications.Notification'].objects.filter(readed=True).update(unread=False)
|
|
||||||
orm['notifications.Notification'].objects.filter(readed=False).update(unread=True)
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
"Write your backwards methods here."
|
|
||||||
orm['notifications.Notification'].objects.filter(unread=True).update(readed=False)
|
|
||||||
orm['notifications.Notification'].objects.filter(unread=False).update(readed=True)
|
|
||||||
|
|
||||||
models = {
|
|
||||||
'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
'auth.permission': {
|
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'readed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'unread': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
symmetrical = True
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Deleting field 'Notification.readed'
|
|
||||||
db.delete_column('notifications_notification', 'readed')
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Adding field 'Notification.readed'
|
|
||||||
db.add_column('notifications_notification', 'readed',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=True)
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
'auth.permission': {
|
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'unread': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding field 'Notification.level'
|
|
||||||
db.add_column('notifications_notification', 'level',
|
|
||||||
self.gf('django.db.models.fields.CharField')(default='info', max_length=20),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting field 'Notification.level'
|
|
||||||
db.delete_column('notifications_notification', 'level')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
'auth.permission': {
|
|
||||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'level': ('django.db.models.fields.CharField', [], {'default': "'info'", 'max_length': '20'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': "orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'unread': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from south.utils import datetime_utils as datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Deleting field 'Notification.data'
|
|
||||||
db.delete_column(u'notifications_notification', 'data')
|
|
||||||
|
|
||||||
# Adding field 'Notification.deleted'
|
|
||||||
db.add_column(u'notifications_notification', 'deleted',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Adding field 'Notification.emailed'
|
|
||||||
db.add_column(u'notifications_notification', 'emailed',
|
|
||||||
self.gf('django.db.models.fields.BooleanField')(default=False),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Adding field 'Notification.data'
|
|
||||||
db.add_column(u'notifications_notification', 'data',
|
|
||||||
self.gf('django.db.models.fields.TextField')(null=True, blank=True),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
# Deleting field 'Notification.deleted'
|
|
||||||
db.delete_column(u'notifications_notification', 'deleted')
|
|
||||||
|
|
||||||
# Deleting field 'Notification.emailed'
|
|
||||||
db.delete_column(u'notifications_notification', 'emailed')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
u'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
u'auth.permission': {
|
|
||||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
u'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
u'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
u'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'emailed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'level': ('django.db.models.fields.CharField', [], {'default': "'info'", 'max_length': '20'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': u"orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'unread': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from south.utils import datetime_utils as datetime
|
|
||||||
from south.db import db
|
|
||||||
from south.v2 import SchemaMigration
|
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(SchemaMigration):
|
|
||||||
|
|
||||||
def forwards(self, orm):
|
|
||||||
# Adding field 'Notification.data'
|
|
||||||
db.add_column(u'notifications_notification', 'data',
|
|
||||||
self.gf('jsonfield.fields.JSONField')(null=True, blank=True),
|
|
||||||
keep_default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def backwards(self, orm):
|
|
||||||
# Deleting field 'Notification.data'
|
|
||||||
db.delete_column(u'notifications_notification', 'data')
|
|
||||||
|
|
||||||
|
|
||||||
models = {
|
|
||||||
u'auth.group': {
|
|
||||||
'Meta': {'object_name': 'Group'},
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
|
||||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
|
||||||
},
|
|
||||||
u'auth.permission': {
|
|
||||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
|
||||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
|
||||||
},
|
|
||||||
u'auth.user': {
|
|
||||||
'Meta': {'object_name': 'User'},
|
|
||||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
|
||||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
|
||||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
|
||||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
|
||||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
|
||||||
},
|
|
||||||
u'contenttypes.contenttype': {
|
|
||||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
|
||||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
|
||||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
|
||||||
},
|
|
||||||
u'notifications.notification': {
|
|
||||||
'Meta': {'ordering': "('-timestamp',)", 'object_name': 'Notification'},
|
|
||||||
'action_object_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_action_object'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
'action_object_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'actor_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notify_actor'", 'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
'actor_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
|
||||||
'data': ('jsonfield.fields.JSONField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
|
||||||
'emailed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
|
||||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
|
||||||
'level': ('django.db.models.fields.CharField', [], {'default': "'info'", 'max_length': '20'}),
|
|
||||||
'public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notifications'", 'to': u"orm['auth.User']"}),
|
|
||||||
'target_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notify_target'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
|
||||||
'target_object_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
|
||||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
|
||||||
'unread': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
|
||||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
complete_apps = ['notifications']
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.template import Library
|
from django.template import Library
|
||||||
from django.template.base import TemplateSyntaxError
|
|
||||||
from django.template import Node
|
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
|
|
||||||
|
|
||||||
@register.assignment_tag(takes_context=True)
|
@register.assignment_tag(takes_context=True)
|
||||||
def notifications_unread(context):
|
def notifications_unread(context):
|
||||||
user = user_context(context)
|
user = user_context(context)
|
||||||
|
|
@ -13,34 +12,40 @@ def notifications_unread(context):
|
||||||
return ''
|
return ''
|
||||||
return user.notifications.unread().count()
|
return user.notifications.unread().count()
|
||||||
|
|
||||||
|
|
||||||
# Requires vanilla-js framework - http://vanilla-js.com/
|
# Requires vanilla-js framework - http://vanilla-js.com/
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def register_notify_callbacks(badge_id='live_notify_badge',menu_id='live_notify_list',refresh_period=15,callbacks="",api_name='list',fetch=5):
|
def register_notify_callbacks(badge_id='live_notify_badge',
|
||||||
refresh_period=int(refresh_period)*1000
|
menu_id='live_notify_list',
|
||||||
|
refresh_period=15,
|
||||||
|
callbacks='',
|
||||||
|
api_name='list',
|
||||||
|
fetch=5):
|
||||||
|
refresh_period = int(refresh_period)*1000
|
||||||
|
|
||||||
if api_name=='list':
|
if api_name == 'list':
|
||||||
api_url = reverse('notifications:live_unread_notification_list')
|
api_url = reverse('notifications:live_unread_notification_list')
|
||||||
elif api_name=='count':
|
elif api_name == 'count':
|
||||||
api_url = reverse('notifications:live_unread_notification_count')
|
api_url = reverse('notifications:live_unread_notification_count')
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
definitions = """
|
||||||
definitions="""
|
|
||||||
notify_badge_id='{badge_id}';
|
notify_badge_id='{badge_id}';
|
||||||
notify_menu_id='{menu_id}';
|
notify_menu_id='{menu_id}';
|
||||||
notify_api_url='{api_url}';
|
notify_api_url='{api_url}';
|
||||||
notify_fetch_count='{fetch_count}';
|
notify_fetch_count='{fetch_count}';
|
||||||
notify_unread_url='{unread_url}';
|
notify_unread_url='{unread_url}';
|
||||||
notify_mark_all_unread_url='{mark_all_unread_url}';
|
notify_mark_all_unread_url='{mark_all_unread_url}';
|
||||||
notify_refresh_period={refresh};""".format(
|
notify_refresh_period={refresh};
|
||||||
badge_id=badge_id,
|
""".format(
|
||||||
menu_id=menu_id,
|
badge_id=badge_id,
|
||||||
refresh=refresh_period,
|
menu_id=menu_id,
|
||||||
api_url=api_url,
|
refresh=refresh_period,
|
||||||
unread_url=reverse('notifications:unread'),
|
api_url=api_url,
|
||||||
mark_all_unread_url=reverse('notifications:mark_all_as_read'),
|
unread_url=reverse('notifications:unread'),
|
||||||
fetch_count=fetch
|
mark_all_unread_url=reverse('notifications:mark_all_as_read'),
|
||||||
)
|
fetch_count=fetch
|
||||||
|
)
|
||||||
|
|
||||||
script = "<script>"+definitions
|
script = "<script>"+definitions
|
||||||
for callback in callbacks.split(','):
|
for callback in callbacks.split(','):
|
||||||
|
|
@ -50,19 +55,23 @@ def register_notify_callbacks(badge_id='live_notify_badge',menu_id='live_notify_
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def live_notify_badge(context,badge_id='live_notify_badge',classes=""):
|
def live_notify_badge(context, badge_id='live_notify_badge', classes=""):
|
||||||
user = user_context(context)
|
user = user_context(context)
|
||||||
if not user:
|
if not user:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
html="<span id='{badge_id}' class='{classes}'>{unread}</span>".format(badge_id=badge_id,classes=classes,unread=user.notifications.unread().count())
|
html = "<span id='{badge_id}' class='{classes}'>{unread}</span>".format(
|
||||||
|
badge_id=badge_id, classes=classes, unread=user.notifications.unread().count()
|
||||||
|
)
|
||||||
return html
|
return html
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def live_notify_list(list_id='live_notify_list',classes=""):
|
def live_notify_list(list_id='live_notify_list', classes=""):
|
||||||
html="<ul id='{list_id}' class='{classes}'></ul>".format(list_id=list_id,classes=classes)
|
html = "<ul id='{list_id}' class='{classes}'></ul>".format(list_id=list_id, classes=classes)
|
||||||
return html
|
return html
|
||||||
|
|
||||||
|
|
||||||
def user_context(context):
|
def user_context(context):
|
||||||
if 'user' not in context:
|
if 'user' not in context:
|
||||||
return None
|
return None
|
||||||
|
|
@ -71,4 +80,4 @@ def user_context(context):
|
||||||
user = request.user
|
user = request.user
|
||||||
if user.is_anonymous():
|
if user.is_anonymous():
|
||||||
return None
|
return None
|
||||||
return user
|
return user
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
from .tests import *
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import os
|
import os
|
||||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
SECRET_KEY = 'secret_key'
|
SECRET_KEY = 'secret_key'
|
||||||
SOUTH_TESTS_MIGRATE = True
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
TESTING = True
|
TESTING = True
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': 'test.sqlite3',
|
'NAME': 'test.sqlite3',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,14 +35,30 @@ STATICFILES_DIRS = [
|
||||||
]
|
]
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, "static-files")
|
STATIC_ROOT = os.path.join(BASE_DIR, "static-files")
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# Need to skip migrations for now as migrations created with python2 break with python3
|
# Need to skip migrations for now as migrations created with python2 break with python3
|
||||||
# See https://code.djangoproject.com/ticket/23455
|
# See https://code.djangoproject.com/ticket/23455
|
||||||
class DisableMigrations(object):
|
class DisableMigrations(object):
|
||||||
def __contains__(self, item):
|
def __contains__(self, item):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
return "notmigrations"
|
return "notmigrations"
|
||||||
|
|
||||||
MIGRATION_MODULES = DisableMigrations()
|
MIGRATION_MODULES = DisableMigrations()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ except ImportError:
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User, Group
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.utils.timezone import utc, localtime
|
from django.utils.timezone import utc, localtime
|
||||||
|
|
@ -34,10 +34,11 @@ class NotificationTest(TestCase):
|
||||||
to_user = User.objects.create(username="to", password="pwd", email="example@example.com")
|
to_user = User.objects.create(username="to", password="pwd", email="example@example.com")
|
||||||
notify.send(from_user, recipient=to_user, verb='commented', action_object=from_user)
|
notify.send(from_user, recipient=to_user, verb='commented', action_object=from_user)
|
||||||
notification = Notification.objects.get(recipient=to_user)
|
notification = Notification.objects.get(recipient=to_user)
|
||||||
delta = timezone.now().replace(tzinfo=utc) - localtime(notification.timestamp,pytz.timezone(settings.TIME_ZONE))
|
delta = timezone.now().replace(tzinfo=utc) - localtime(notification.timestamp, pytz.timezone(settings.TIME_ZONE))
|
||||||
self.assertTrue(delta.seconds < 60)
|
self.assertTrue(delta.seconds < 60)
|
||||||
# The delta between the two events will still be less than a second despite the different timezones
|
# The delta between the two events will still be less than a second despite the different timezones
|
||||||
# The call to now and the immediate call afterwards will be within a short period of time, not 8 hours as the test above was originally.
|
# The call to now and the immediate call afterwards will be within a short period of time, not 8 hours as the
|
||||||
|
# test above was originally.
|
||||||
|
|
||||||
@override_settings(USE_TZ=False)
|
@override_settings(USE_TZ=False)
|
||||||
@override_settings(TIME_ZONE='Asia/Shanghai')
|
@override_settings(TIME_ZONE='Asia/Shanghai')
|
||||||
|
|
@ -56,8 +57,13 @@ class NotificationManagersTest(TestCase):
|
||||||
self.message_count = 10
|
self.message_count = 10
|
||||||
self.from_user = User.objects.create(username="from2", password="pwd", email="example@example.com")
|
self.from_user = User.objects.create(username="from2", password="pwd", email="example@example.com")
|
||||||
self.to_user = User.objects.create(username="to2", password="pwd", email="example@example.com")
|
self.to_user = User.objects.create(username="to2", password="pwd", email="example@example.com")
|
||||||
|
self.to_group = Group.objects.create(name="to2_g")
|
||||||
|
self.to_group.user_set.add(self.to_user)
|
||||||
for i in range(self.message_count):
|
for i in range(self.message_count):
|
||||||
notify.send(self.from_user, recipient=self.to_user, verb='commented', action_object=self.from_user)
|
notify.send(self.from_user, recipient=self.to_user, verb='commented', action_object=self.from_user)
|
||||||
|
# Send notification to group
|
||||||
|
notify.send(self.from_user, recipient=self.to_group, verb='commented', action_object=self.from_user)
|
||||||
|
self.message_count += 1
|
||||||
|
|
||||||
def test_unread_manager(self):
|
def test_unread_manager(self):
|
||||||
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
||||||
|
|
@ -71,19 +77,19 @@ class NotificationManagersTest(TestCase):
|
||||||
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
||||||
n = Notification.objects.filter(recipient=self.to_user).first()
|
n = Notification.objects.filter(recipient=self.to_user).first()
|
||||||
n.mark_as_read()
|
n.mark_as_read()
|
||||||
self.assertEqual(Notification.objects.read().count(),1)
|
self.assertEqual(Notification.objects.read().count(), 1)
|
||||||
for n in Notification.objects.read():
|
for n in Notification.objects.read():
|
||||||
self.assertFalse(n.unread)
|
self.assertFalse(n.unread)
|
||||||
|
|
||||||
def test_mark_all_as_read_manager(self):
|
def test_mark_all_as_read_manager(self):
|
||||||
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
||||||
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
||||||
self.assertEqual(Notification.objects.unread().count(),0)
|
self.assertEqual(Notification.objects.unread().count(), 0)
|
||||||
|
|
||||||
def test_mark_all_as_unread_manager(self):
|
def test_mark_all_as_unread_manager(self):
|
||||||
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
||||||
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
||||||
self.assertEqual(Notification.objects.unread().count(),0)
|
self.assertEqual(Notification.objects.unread().count(), 0)
|
||||||
Notification.objects.filter(recipient=self.to_user).mark_all_as_unread()
|
Notification.objects.filter(recipient=self.to_user).mark_all_as_unread()
|
||||||
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
||||||
|
|
||||||
|
|
@ -129,54 +135,60 @@ class NotificationTestPages(TestCase):
|
||||||
def logout(self):
|
def logout(self):
|
||||||
self.client.post(reverse('admin:logout')+'?next=/', {})
|
self.client.post(reverse('admin:logout')+'?next=/', {})
|
||||||
|
|
||||||
def login(self,username,password):
|
def login(self, username, password):
|
||||||
self.logout()
|
self.logout()
|
||||||
response = self.client.post(reverse('login'), {'username': username, 'password': password})
|
response = self.client.post(reverse('login'), {'username': username, 'password': password})
|
||||||
self.assertEqual(response.status_code,302)
|
self.assertEqual(response.status_code, 302)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def test_all_messages_page(self):
|
def test_all_messages_page(self):
|
||||||
self.login('to','pwd')
|
self.login('to', 'pwd')
|
||||||
response = self.client.get(reverse('notifications:all'))
|
response = self.client.get(reverse('notifications:all'))
|
||||||
|
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(len(response.context['notifications']),len(self.to_user.notifications.all()))
|
self.assertEqual(len(response.context['notifications']), len(self.to_user.notifications.all()))
|
||||||
|
|
||||||
def test_unread_messages_pages(self):
|
def test_unread_messages_pages(self):
|
||||||
self.login('to','pwd')
|
self.login('to', 'pwd')
|
||||||
response = self.client.get(reverse('notifications:unread'))
|
response = self.client.get(reverse('notifications:unread'))
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(len(response.context['notifications']),len(self.to_user.notifications.unread()))
|
self.assertEqual(len(response.context['notifications']), len(self.to_user.notifications.unread()))
|
||||||
self.assertEqual(len(response.context['notifications']), self.message_count)
|
self.assertEqual(len(response.context['notifications']), self.message_count)
|
||||||
|
|
||||||
for i,n in enumerate(self.to_user.notifications.all()):
|
for i, n in enumerate(self.to_user.notifications.all()):
|
||||||
if i%3 == 0:
|
if i % 3 == 0:
|
||||||
response = self.client.get(reverse('notifications:mark_as_read',args=[id2slug(n.id)]))
|
response = self.client.get(reverse('notifications:mark_as_read', args=[id2slug(n.id)]))
|
||||||
self.assertEqual(response.status_code,302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
response = self.client.get(reverse('notifications:unread'))
|
response = self.client.get(reverse('notifications:unread'))
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(len(response.context['notifications']),len(self.to_user.notifications.unread()))
|
self.assertEqual(len(response.context['notifications']), len(self.to_user.notifications.unread()))
|
||||||
self.assertTrue(len(response.context['notifications']) < self.message_count)
|
self.assertTrue(len(response.context['notifications']) < self.message_count)
|
||||||
|
|
||||||
response = self.client.get(reverse('notifications:mark_all_as_read'))
|
response = self.client.get(reverse('notifications:mark_all_as_read'))
|
||||||
self.assertRedirects(response,reverse('notifications:all'))
|
self.assertRedirects(response, reverse('notifications:all'))
|
||||||
response = self.client.get(reverse('notifications:unread'))
|
response = self.client.get(reverse('notifications:unread'))
|
||||||
self.assertEqual(len(response.context['notifications']),len(self.to_user.notifications.unread()))
|
self.assertEqual(len(response.context['notifications']), len(self.to_user.notifications.unread()))
|
||||||
self.assertEqual(len(response.context['notifications']),0)
|
self.assertEqual(len(response.context['notifications']), 0)
|
||||||
|
|
||||||
def test_next_pages(self):
|
def test_next_pages(self):
|
||||||
self.login('to','pwd')
|
self.login('to', 'pwd')
|
||||||
response = self.client.get(reverse('notifications:mark_all_as_read')+"?next="+reverse('notifications:unread'))
|
response = self.client.get(reverse('notifications:mark_all_as_read'), data={
|
||||||
self.assertRedirects(response,reverse('notifications:unread'))
|
"next": reverse('notifications:unread'),
|
||||||
|
})
|
||||||
|
self.assertRedirects(response, reverse('notifications:unread'))
|
||||||
|
|
||||||
slug = id2slug(self.to_user.notifications.first().id)
|
slug = id2slug(self.to_user.notifications.first().id)
|
||||||
response = self.client.get(reverse('notifications:mark_as_read',args=[slug])+"?next="+reverse('notifications:unread'))
|
response = self.client.get(reverse('notifications:mark_as_read', args=[slug]), data={
|
||||||
self.assertRedirects(response,reverse('notifications:unread'))
|
"next": reverse('notifications:unread'),
|
||||||
|
})
|
||||||
|
self.assertRedirects(response, reverse('notifications:unread'))
|
||||||
|
|
||||||
slug = id2slug(self.to_user.notifications.first().id)
|
slug = id2slug(self.to_user.notifications.first().id)
|
||||||
response = self.client.get(reverse('notifications:mark_as_unread',args=[slug])+"?next="+reverse('notifications:unread'))
|
response = self.client.get(reverse('notifications:mark_as_unread', args=[slug]), {
|
||||||
self.assertRedirects(response,reverse('notifications:unread'))
|
"next": reverse('notifications:unread'),
|
||||||
|
})
|
||||||
|
self.assertRedirects(response, reverse('notifications:unread'))
|
||||||
|
|
||||||
def test_delete_messages_pages(self):
|
def test_delete_messages_pages(self):
|
||||||
self.login('to', 'pwd')
|
self.login('to', 'pwd')
|
||||||
|
|
@ -213,64 +225,64 @@ class NotificationTestPages(TestCase):
|
||||||
self.assertEqual(len(response.context['notifications']), len(self.to_user.notifications.unread()))
|
self.assertEqual(len(response.context['notifications']), len(self.to_user.notifications.unread()))
|
||||||
self.assertEqual(len(response.context['notifications']), self.message_count-1)
|
self.assertEqual(len(response.context['notifications']), self.message_count-1)
|
||||||
|
|
||||||
|
|
||||||
def test_unread_count_api(self):
|
def test_unread_count_api(self):
|
||||||
self.login('to', 'pwd')
|
self.login('to', 'pwd')
|
||||||
|
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_count'))
|
response = self.client.get(reverse('notifications:live_unread_notification_count'))
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(list(data.keys()),['unread_count'])
|
self.assertEqual(list(data.keys()), ['unread_count'])
|
||||||
self.assertEqual(data['unread_count'],10)
|
self.assertEqual(data['unread_count'], 10)
|
||||||
|
|
||||||
|
|
||||||
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_count'))
|
response = self.client.get(reverse('notifications:live_unread_notification_count'))
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(list(data.keys()),['unread_count'])
|
self.assertEqual(list(data.keys()), ['unread_count'])
|
||||||
self.assertEqual(data['unread_count'],0)
|
self.assertEqual(data['unread_count'], 0)
|
||||||
|
|
||||||
notify.send(self.from_user, recipient=self.to_user, verb='commented', action_object=self.from_user)
|
notify.send(self.from_user, recipient=self.to_user, verb='commented', action_object=self.from_user)
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_count'))
|
response = self.client.get(reverse('notifications:live_unread_notification_count'))
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(list(data.keys()),['unread_count'])
|
self.assertEqual(list(data.keys()), ['unread_count'])
|
||||||
self.assertEqual(data['unread_count'],1)
|
self.assertEqual(data['unread_count'], 1)
|
||||||
|
|
||||||
def test_unread_list_api(self):
|
def test_unread_list_api(self):
|
||||||
self.login('to', 'pwd')
|
self.login('to', 'pwd')
|
||||||
|
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_list'))
|
response = self.client.get(reverse('notifications:live_unread_notification_list'))
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(sorted(list(data.keys())),['unread_count','unread_list'])
|
self.assertEqual(sorted(list(data.keys())), ['unread_count', 'unread_list'])
|
||||||
self.assertEqual(data['unread_count'],10)
|
self.assertEqual(data['unread_count'], 10)
|
||||||
self.assertEqual(len(data['unread_list']),5)
|
self.assertEqual(len(data['unread_list']), 5)
|
||||||
|
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_list')+"?max=12")
|
response = self.client.get(reverse('notifications:live_unread_notification_list'), data={"max": "12"})
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(sorted(list(data.keys())),['unread_count','unread_list'])
|
self.assertEqual(sorted(list(data.keys())), ['unread_count', 'unread_list'])
|
||||||
self.assertEqual(data['unread_count'],10)
|
self.assertEqual(data['unread_count'], 10)
|
||||||
self.assertEqual(len(data['unread_list']),10)
|
self.assertEqual(len(data['unread_list']), 10)
|
||||||
|
|
||||||
# Test with a bad 'max' value
|
# Test with a bad 'max' value
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_list')+"?max=this_is_wrong")
|
response = self.client.get(reverse('notifications:live_unread_notification_list'), data={
|
||||||
|
"max": "this_is_wrong",
|
||||||
|
})
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(sorted(list(data.keys())),['unread_count','unread_list'])
|
self.assertEqual(sorted(list(data.keys())), ['unread_count', 'unread_list'])
|
||||||
self.assertEqual(data['unread_count'],10)
|
self.assertEqual(data['unread_count'], 10)
|
||||||
self.assertEqual(len(data['unread_list']),5)
|
self.assertEqual(len(data['unread_list']), 5)
|
||||||
|
|
||||||
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_list'))
|
response = self.client.get(reverse('notifications:live_unread_notification_list'))
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(sorted(list(data.keys())),['unread_count','unread_list'])
|
self.assertEqual(sorted(list(data.keys())), ['unread_count', 'unread_list'])
|
||||||
self.assertEqual(data['unread_count'],0)
|
self.assertEqual(data['unread_count'], 0)
|
||||||
self.assertEqual(len(data['unread_list']),0)
|
self.assertEqual(len(data['unread_list']), 0)
|
||||||
|
|
||||||
notify.send(self.from_user, recipient=self.to_user, verb='commented', action_object=self.from_user)
|
notify.send(self.from_user, recipient=self.to_user, verb='commented', action_object=self.from_user)
|
||||||
response = self.client.get(reverse('notifications:live_unread_notification_list'))
|
response = self.client.get(reverse('notifications:live_unread_notification_list'))
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(sorted(list(data.keys())),['unread_count','unread_list'])
|
self.assertEqual(sorted(list(data.keys())), ['unread_count', 'unread_list'])
|
||||||
self.assertEqual(data['unread_count'],1)
|
self.assertEqual(data['unread_count'], 1)
|
||||||
self.assertEqual(len(data['unread_list']),1)
|
self.assertEqual(len(data['unread_list']), 1)
|
||||||
self.assertEqual(data['unread_list'][0]['verb'],'commented')
|
self.assertEqual(data['unread_list'][0]['verb'], 'commented')
|
||||||
|
|
||||||
def test_live_update_tags(self):
|
def test_live_update_tags(self):
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
@ -281,9 +293,9 @@ class NotificationTestPages(TestCase):
|
||||||
request = self.factory.get('/notification/live_updater')
|
request = self.factory.get('/notification/live_updater')
|
||||||
request.user = self.to_user
|
request.user = self.to_user
|
||||||
|
|
||||||
page = render(request, 'notifications/test_tags.html', {'request':request})
|
render(request, 'notifications/test_tags.html', {'request': request})
|
||||||
|
|
||||||
#TODO: Add more tests to check what is being output.
|
# TODO: Add more tests to check what is being output.
|
||||||
|
|
||||||
def test_anon_user_gets_nothing(self):
|
def test_anon_user_gets_nothing(self):
|
||||||
response = self.client.post(reverse('notifications:live_unread_notification_count'))
|
response = self.client.post(reverse('notifications:live_unread_notification_count'))
|
||||||
|
|
@ -296,4 +308,3 @@ class NotificationTestPages(TestCase):
|
||||||
data = json.loads(response.content.decode('utf-8'))
|
data = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(data['unread_count'],0)
|
self.assertEqual(data['unread_count'],0)
|
||||||
self.assertEqual(data['unread_list'],[])
|
self.assertEqual(data['unread_list'],[])
|
||||||
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from django.conf.urls import include, patterns, url
|
from django.conf.urls import include, url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth.views import login
|
||||||
|
|
||||||
from notifications import urls
|
import notifications.urls
|
||||||
|
import notifications.tests.views
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = [
|
||||||
url(r'^login/$', 'django.contrib.auth.views.login', name='login'), # needed for Django 1.6 tests
|
url(r'^login/$', login, name='login'), # needed for Django 1.6 tests
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
url(r'^test_make/', 'notifications.tests.views.make_notification'),
|
url(r'^test_make/', notifications.tests.views.make_notification),
|
||||||
url(r'^test/', 'notifications.tests.views.live_tester'),
|
url(r'^test/', notifications.tests.views.live_tester),
|
||||||
url(r'^', include(urls, 'notifications')),
|
url(r'^', include(notifications.urls, namespace='notifications')),
|
||||||
)
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
from django.conf import settings
|
from django.shortcuts import render
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.shortcuts import get_object_or_404, render
|
|
||||||
|
|
||||||
from notifications import notify
|
from notifications import notify
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
def live_tester(request):
|
def live_tester(request):
|
||||||
notify.send(sender=request.user, recipient=request.user, verb='you loaded the page')
|
notify.send(sender=request.user, recipient=request.user, verb='you loaded the page')
|
||||||
|
|
||||||
data = {
|
return render(request, 'test_live.html', {
|
||||||
'unread_count': request.user.notifications.unread().count(),
|
'unread_count': request.user.notifications.unread().count(),
|
||||||
'notifications': request.user.notifications.all()
|
'notifications': request.user.notifications.all()
|
||||||
}
|
})
|
||||||
return render(request,'test_live.html',data)
|
|
||||||
|
|
||||||
def make_notification(request):
|
def make_notification(request):
|
||||||
|
|
||||||
the_notification = random.choice([
|
the_notification = random.choice([
|
||||||
|
|
@ -22,7 +21,7 @@ def make_notification(request):
|
||||||
'jumping the shark',
|
'jumping the shark',
|
||||||
'testing the app',
|
'testing the app',
|
||||||
'attaching the plumbus',
|
'attaching the plumbus',
|
||||||
])
|
])
|
||||||
|
|
||||||
notify.send(sender=request.user, recipient=request.user, verb='you asked for a notification - you are '+the_notification)
|
|
||||||
|
|
||||||
|
notify.send(sender=request.user, recipient=request.user,
|
||||||
|
verb='you asked for a notification - you are ' + the_notification)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns('notifications.views',
|
app_name = 'notifications'
|
||||||
|
urlpatterns = [
|
||||||
url(r'^$', views.AllNotificationsList.as_view(), name='all'),
|
url(r'^$', views.AllNotificationsList.as_view(), name='all'),
|
||||||
url(r'^unread/$', views.UnreadNotificationsList.as_view(), name='unread'),
|
url(r'^unread/$', views.UnreadNotificationsList.as_view(), name='unread'),
|
||||||
url(r'^mark-all-as-read/$', 'mark_all_as_read', name='mark_all_as_read'),
|
url(r'^mark-all-as-read/$', views.mark_all_as_read, name='mark_all_as_read'),
|
||||||
url(r'^mark-as-read/(?P<slug>\d+)/$', 'mark_as_read', name='mark_as_read'),
|
url(r'^mark-as-read/(?P<slug>\d+)/$', views.mark_as_read, name='mark_as_read'),
|
||||||
url(r'^mark-as-unread/(?P<slug>\d+)/$', 'mark_as_unread', name='mark_as_unread'),
|
url(r'^mark-as-unread/(?P<slug>\d+)/$', views.mark_as_unread, name='mark_as_unread'),
|
||||||
url(r'^delete/(?P<slug>\d+)/$', 'delete', name='delete'),
|
url(r'^delete/(?P<slug>\d+)/$', views.delete, name='delete'),
|
||||||
url(r'^api/unread_count/$', 'live_unread_notification_count', name='live_unread_notification_count'),
|
url(r'^api/unread_count/$', views.live_unread_notification_count, name='live_unread_notification_count'),
|
||||||
url(r'^api/unread_list/$', 'live_unread_notification_list', name='live_unread_notification_list'),
|
url(r'^api/unread_list/$', views.live_unread_notification_list, name='live_unread_notification_list'),
|
||||||
)
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ import sys
|
||||||
if sys.version > '3':
|
if sys.version > '3':
|
||||||
long = int
|
long = int
|
||||||
|
|
||||||
|
|
||||||
def slug2id(slug):
|
def slug2id(slug):
|
||||||
return long(slug) - 110909
|
return long(slug) - 110909
|
||||||
|
|
||||||
|
|
||||||
def id2slug(id):
|
def id2slug(id):
|
||||||
return id + 110909
|
return id + 110909
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,8 @@ def live_unread_notification_list(request):
|
||||||
try:
|
try:
|
||||||
num_to_fetch = request.GET.get('max', 5) # If they don't specify, make it 5.
|
num_to_fetch = request.GET.get('max', 5) # If they don't specify, make it 5.
|
||||||
num_to_fetch = int(num_to_fetch)
|
num_to_fetch = int(num_to_fetch)
|
||||||
num_to_fetch = max(1,num_to_fetch) # if num_to_fetch is negative, force at least one fetched notifications
|
num_to_fetch = max(1, num_to_fetch) # if num_to_fetch is negative, force at least one fetched notifications
|
||||||
num_to_fetch = min(num_to_fetch,100) # put a sane ceiling on the number retrievable
|
num_to_fetch = min(num_to_fetch, 100) # put a sane ceiling on the number retrievable
|
||||||
except ValueError:
|
except ValueError:
|
||||||
num_to_fetch = 5 # If casting to an int fails, just make it 5.
|
num_to_fetch = 5 # If casting to an int fails, just make it 5.
|
||||||
|
|
||||||
|
|
@ -157,8 +157,7 @@ def live_unread_notification_list(request):
|
||||||
struct['action_object'] = str(n.action_object)
|
struct['action_object'] = str(n.action_object)
|
||||||
unread_list.append(struct)
|
unread_list.append(struct)
|
||||||
data = {
|
data = {
|
||||||
'unread_count':request.user.notifications.unread().count(),
|
'unread_count': request.user.notifications.unread().count(),
|
||||||
'unread_list':unread_list
|
'unread_list': unread_list
|
||||||
}
|
}
|
||||||
return JsonResponse(data)
|
return JsonResponse(data)
|
||||||
|
|
||||||
|
|
|
||||||
113
setup.py
113
setup.py
|
|
@ -1,66 +1,63 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distutils.core import setup
|
import re
|
||||||
from version import __version__
|
import ast
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
setup(name='django-notifications-hq',
|
|
||||||
version=__version__,
|
|
||||||
|
|
||||||
description='GitHub notifications alike app for Django.',
|
_version_re = re.compile(r'__version__\s+=\s+(.*)')
|
||||||
|
|
||||||
long_description=open('README.rst').read(),
|
with open('notifications/__init__.py', 'rb') as f:
|
||||||
|
version = str(ast.literal_eval(_version_re.search(
|
||||||
|
f.read().decode('utf-8')).group(1)))
|
||||||
|
|
||||||
author='django-notifications team',
|
|
||||||
|
|
||||||
author_email='yang@yangyubo.com',
|
setup(
|
||||||
|
name='django-notifications-hq',
|
||||||
url='http://github.com/django-notifications/django-notifications',
|
version=version,
|
||||||
|
description='GitHub notifications alike app for Django.',
|
||||||
install_requires=[
|
long_description=open('README.rst').read(),
|
||||||
'django>=1.4',
|
author='django-notifications team',
|
||||||
'django-model-utils>=2.0.3,<2.4',
|
author_email='yang@yangyubo.com',
|
||||||
'six>=1.9.0',
|
url='http://github.com/django-notifications/django-notifications',
|
||||||
'jsonfield>=1.0.3',
|
install_requires=[
|
||||||
],
|
'django>=1.7',
|
||||||
|
'django-model-utils>=2.0.3',
|
||||||
test_requires=[
|
'jsonfield>=1.0.3',
|
||||||
'django>=1.4',
|
'pytz'
|
||||||
'django-model-utils>=2.0.3,<2.4',
|
],
|
||||||
'six>=1.9.0',
|
test_requires=[
|
||||||
'jsonfield>=1.0.3',
|
'django>=1.7',
|
||||||
'pytz'
|
'django-model-utils>=2.0.3',
|
||||||
],
|
'jsonfield>=1.0.3',
|
||||||
|
'pytz'
|
||||||
packages=['notifications',
|
],
|
||||||
'notifications.templatetags',
|
packages=[
|
||||||
'notifications.migrations',
|
'notifications',
|
||||||
'notifications.south_migrations'
|
'notifications.templatetags',
|
||||||
],
|
'notifications.migrations',
|
||||||
|
],
|
||||||
package_data={'notifications': [
|
package_data={
|
||||||
'templates/notifications/*.html', 'static/notifications/*.js']},
|
'notifications': ['templates/notifications/*.html', 'static/notifications/*.js']
|
||||||
|
},
|
||||||
classifiers=['Development Status :: 5 - Production/Stable',
|
classifiers=[
|
||||||
'Environment :: Web Environment',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Framework :: Django',
|
'Environment :: Web Environment',
|
||||||
'Intended Audience :: Developers',
|
'Framework :: Django',
|
||||||
'License :: OSI Approved :: BSD License',
|
'Intended Audience :: Developers',
|
||||||
'Operating System :: OS Independent',
|
'License :: OSI Approved :: BSD License',
|
||||||
# Specify the Python versions you support here. In particular, ensure
|
'Operating System :: OS Independent',
|
||||||
# that you indicate whether you support Python 2, Python 3 or both.
|
# Specify the Python versions you support here. In particular, ensure
|
||||||
'Programming Language :: Python',
|
# that you indicate whether you support Python 2, Python 3 or both.
|
||||||
'Programming Language :: Python :: 2',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2.6',
|
'Programming Language :: Python :: 2',
|
||||||
'Programming Language :: Python :: 2.7',
|
'Programming Language :: Python :: 2.7',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.2',
|
'Programming Language :: Python :: 3.3',
|
||||||
'Programming Language :: Python :: 3.3',
|
'Programming Language :: Python :: 3.4',
|
||||||
'Programming Language :: Python :: 3.4',
|
'Topic :: Utilities'
|
||||||
'Topic :: Utilities'
|
],
|
||||||
],
|
keywords='django notifications github action event stream',
|
||||||
|
license='MIT',
|
||||||
keywords='django notifications github action event stream',
|
)
|
||||||
|
|
||||||
license='MIT',
|
|
||||||
)
|
|
||||||
|
|
|
||||||
20
version.py
20
version.py
|
|
@ -1,20 +0,0 @@
|
||||||
__version_info__ = {
|
|
||||||
'major': 0,
|
|
||||||
'minor': 7,
|
|
||||||
'micro': 1,
|
|
||||||
'releaselevel': 'final',
|
|
||||||
'serial': 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_version(release_level=True):
|
|
||||||
"""
|
|
||||||
Return the formatted version information
|
|
||||||
"""
|
|
||||||
vers = ["%(major)i.%(minor)i.%(micro)i" % __version_info__]
|
|
||||||
if release_level and __version_info__['releaselevel'] != 'final':
|
|
||||||
vers.append('%(releaselevel)s%(serial)i' % __version_info__)
|
|
||||||
return ''.join(vers)
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = get_version()
|
|
||||||
Loading…
Reference in a new issue