Initial commit of the new events app

This commit is contained in:
Roberto Rosario
2015-01-10 19:01:57 -04:00
parent 9c0f8feaed
commit bbab21d228
23 changed files with 179 additions and 96 deletions

View File

@@ -5,14 +5,9 @@ from datetime import timedelta
from acls.api import class_permissions from acls.api import class_permissions
from documents.models import Document from documents.models import Document
from mayan.celery import app from mayan.celery import app
from history.api import register_history_type
from navigation.api import register_links, register_top_menu from navigation.api import register_links, register_top_menu
from rest_api.classes import APIEndPoint from rest_api.classes import APIEndPoint
from .events import (HISTORY_DOCUMENT_AUTO_CHECKED_IN,
HISTORY_DOCUMENT_CHECKED_OUT,
HISTORY_DOCUMENT_CHECKED_IN,
HISTORY_DOCUMENT_FORCEFUL_CHECK_IN)
from .links import (checkin_document, checkout_document, checkout_info, from .links import (checkin_document, checkout_document, checkout_info,
checkout_list) checkout_list)
from .models import DocumentCheckout from .models import DocumentCheckout
@@ -48,10 +43,6 @@ class_permissions(Document, [
]) ])
initialize_document_checkout_extra_methods() initialize_document_checkout_extra_methods()
register_history_type(HISTORY_DOCUMENT_CHECKED_OUT)
register_history_type(HISTORY_DOCUMENT_CHECKED_IN)
register_history_type(HISTORY_DOCUMENT_AUTO_CHECKED_IN)
register_history_type(HISTORY_DOCUMENT_FORCEFUL_CHECK_IN)
register_links(Document, [checkout_info], menu_name='form_header') register_links(Document, [checkout_info], menu_name='form_header')
register_links(['checkouts:checkout_info', 'checkouts:checkout_document', 'checkouts:checkin_document'], [checkout_document, checkin_document], menu_name="sidebar") register_links(['checkouts:checkout_info', 'checkouts:checkout_document', 'checkouts:checkin_document'], [checkout_document, checkin_document], menu_name="sidebar")

View File

@@ -1,5 +1,11 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from events.classes import Event
event_document_check_out = Event(name='checkouts_document_check_out', label=_('Document checked out'))
HISTORY_DOCUMENT_CHECKED_OUT = { HISTORY_DOCUMENT_CHECKED_OUT = {
'namespace': 'checkouts', 'name': 'document_checked_out', 'namespace': 'checkouts', 'name': 'document_checked_out',
'label': _(u'Document checked out'), 'label': _(u'Document checked out'),
@@ -7,6 +13,8 @@ HISTORY_DOCUMENT_CHECKED_OUT = {
'expressions': {'fullname': 'user.get_full_name() if user.get_full_name() else user'} 'expressions': {'fullname': 'user.get_full_name() if user.get_full_name() else user'}
} }
event_document_check_in = Event(name='checkouts_document_check_in', label=_('Document checked in'))
HISTORY_DOCUMENT_CHECKED_IN = { HISTORY_DOCUMENT_CHECKED_IN = {
'namespace': 'checkouts', 'name': 'document_checked_in', 'namespace': 'checkouts', 'name': 'document_checked_in',
'label': _(u'Document checked in'), 'label': _(u'Document checked in'),
@@ -14,12 +22,16 @@ HISTORY_DOCUMENT_CHECKED_IN = {
'expressions': {'fullname': 'user.get_full_name() if user.get_full_name() else user'} 'expressions': {'fullname': 'user.get_full_name() if user.get_full_name() else user'}
} }
event_document_auto_check_in = Event(name='checkouts_document_auto_check_in', label=_('Document automatically checked in'))
HISTORY_DOCUMENT_AUTO_CHECKED_IN = { HISTORY_DOCUMENT_AUTO_CHECKED_IN = {
'namespace': 'checkouts', 'name': 'document_auto_checked_in', 'namespace': 'checkouts', 'name': 'document_auto_checked_in',
'label': _(u'Document automatically checked in'), 'label': _(u'Document automatically checked in'),
'summary': _(u'Document "%(document)s" automatically checked in.'), 'summary': _(u'Document "%(document)s" automatically checked in.'),
} }
event_document_forceful_check_in = Event(name='checkouts_document_forceful_check_in', label=_('Document forcefully checked in'))
HISTORY_DOCUMENT_FORCEFUL_CHECK_IN = { HISTORY_DOCUMENT_FORCEFUL_CHECK_IN = {
'namespace': 'checkouts', 'name': 'document_forefull_check_in', 'namespace': 'checkouts', 'name': 'document_forefull_check_in',
'label': _(u'Document forcefully checked in'), 'label': _(u'Document forcefully checked in'),

View File

@@ -8,12 +8,11 @@ from django.utils.timezone import now
from acls.models import AccessEntry from acls.models import AccessEntry
from documents.models import Document from documents.models import Document
from history.api import create_history
from permissions.models import Permission from permissions.models import Permission
from .events import (HISTORY_DOCUMENT_AUTO_CHECKED_IN, from .events import (event_document_auto_check_in,
HISTORY_DOCUMENT_CHECKED_IN, event_document_check_in,
HISTORY_DOCUMENT_FORCEFUL_CHECK_IN) event_document_forceful_check_in)
from .exceptions import DocumentNotCheckedOut from .exceptions import DocumentNotCheckedOut
from .literals import STATE_CHECKED_OUT, STATE_CHECKED_IN from .literals import STATE_CHECKED_OUT, STATE_CHECKED_IN
from .permissions import PERMISSION_DOCUMENT_RESTRICTIONS_OVERRIDE from .permissions import PERMISSION_DOCUMENT_RESTRICTIONS_OVERRIDE
@@ -48,11 +47,11 @@ class DocumentCheckoutManager(models.Manager):
else: else:
if user: if user:
if self.document_checkout_info(document).user_object != user: if self.document_checkout_info(document).user_object != user:
create_history(HISTORY_DOCUMENT_FORCEFUL_CHECK_IN, source_object=document, data={'user': user, 'document': document}) event_document_forceful_check_in.commit(actor=user, target=document)
else: else:
create_history(HISTORY_DOCUMENT_CHECKED_IN, source_object=document, data={'user': user, 'document': document}) event_document_check_in.commit(actor=user, target=document)
else: else:
create_history(HISTORY_DOCUMENT_AUTO_CHECKED_IN, source_object=document, data={'document': document}) event_document_auto_check_in.commit(target=document)
document_checkout.delete() document_checkout.delete()

View File

@@ -8,9 +8,8 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from documents.models import Document from documents.models import Document
from history.api import create_history
from .events import HISTORY_DOCUMENT_CHECKED_OUT from .events import event_document_check_out
from .exceptions import DocumentAlreadyCheckedOut from .exceptions import DocumentAlreadyCheckedOut
from .managers import DocumentCheckoutManager from .managers import DocumentCheckoutManager
@@ -48,7 +47,7 @@ class DocumentCheckout(models.Model):
result = super(DocumentCheckout, self).save(*args, **kwargs) result = super(DocumentCheckout, self).save(*args, **kwargs)
if new_checkout: if new_checkout:
create_history(HISTORY_DOCUMENT_CHECKED_OUT, source_object=self.document, data={'user': self.user_object, 'document': self.document}) event_document_check_out.commit(actor=self.user_object, target=self.document)
return result return result
@models.permalink @models.permalink

View File

@@ -8,7 +8,6 @@ from acls.api import class_permissions
from common.classes import ModelAttribute from common.classes import ModelAttribute
from common.utils import encapsulate, validate_path from common.utils import encapsulate, validate_path
from dynamic_search.classes import SearchModel from dynamic_search.classes import SearchModel
from history.api import register_history_type
from history.permissions import PERMISSION_HISTORY_VIEW from history.permissions import PERMISSION_HISTORY_VIEW
from main.api import register_maintenance_links from main.api import register_maintenance_links
from navigation.api import (register_links, register_model_list_columns) from navigation.api import (register_links, register_model_list_columns)
@@ -18,8 +17,6 @@ from rest_api.classes import APIEndPoint
from statistics.classes import StatisticNamespace from statistics.classes import StatisticNamespace
from documents import settings as document_settings from documents import settings as document_settings
from .events import (HISTORY_DOCUMENT_CREATED,
HISTORY_DOCUMENT_DELETED, HISTORY_DOCUMENT_EDITED)
from .links import (document_clear_image_cache, from .links import (document_clear_image_cache,
document_clear_transformations, document_content, document_clear_transformations, document_content,
document_delete, document_delete,
@@ -63,11 +60,6 @@ from .settings import THUMBNAIL_SIZE
from .statistics import DocumentStatistics, DocumentUsageStatistics from .statistics import DocumentStatistics, DocumentUsageStatistics
from .widgets import document_thumbnail from .widgets import document_thumbnail
# History setup
register_history_type(HISTORY_DOCUMENT_CREATED)
register_history_type(HISTORY_DOCUMENT_EDITED)
register_history_type(HISTORY_DOCUMENT_DELETED)
# Register document type links # Register document type links
register_links(DocumentType, [document_type_edit, document_type_filename_list, document_type_delete]) register_links(DocumentType, [document_type_edit, document_type_filename_list, document_type_delete])
register_links([DocumentType, 'documents:document_type_create', 'documents:document_type_list'], [document_type_list, document_type_create], menu_name='secondary_menu') register_links([DocumentType, 'documents:document_type_create', 'documents:document_type_list'], [document_type_list, document_type_create], menu_name='secondary_menu')

View File

@@ -1,5 +1,11 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from events.classes import Event
event_document_create = Event(name='documents_document_create', label=_('Document created'))
HISTORY_DOCUMENT_CREATED = { HISTORY_DOCUMENT_CREATED = {
'namespace': 'documents', 'name': 'document_created', 'namespace': 'documents', 'name': 'document_created',
'label': _(u'Document creation'), 'label': _(u'Document creation'),
@@ -8,6 +14,8 @@ HISTORY_DOCUMENT_CREATED = {
'expressions': {'fullname': 'user[0]["fields"]["username"] if isinstance(user, list) else user.get_full_name() if user.get_full_name() else user.username'} 'expressions': {'fullname': 'user[0]["fields"]["username"] if isinstance(user, list) else user.get_full_name() if user.get_full_name() else user.username'}
} }
event_document_edited = Event(name='documents_document_edit', label=_('Document edited'))
HISTORY_DOCUMENT_EDITED = { HISTORY_DOCUMENT_EDITED = {
'namespace': 'documents', 'name': 'document_edited', 'namespace': 'documents', 'name': 'document_edited',
'label': _(u'Document edited'), 'label': _(u'Document edited'),
@@ -17,11 +25,3 @@ HISTORY_DOCUMENT_EDITED = {
'fullname': 'user[0]["fields"]["username"] if isinstance(user, list) else user.get_full_name() if user.get_full_name() else user.username', 'fullname': 'user[0]["fields"]["username"] if isinstance(user, list) else user.get_full_name() if user.get_full_name() else user.username',
} }
} }
HISTORY_DOCUMENT_DELETED = {
'namespace': 'documents', 'name': 'document_deleted',
'label': _(u'Document deleted'),
'summary': _(u'Document "%(document)s" deleted by %(fullname)s.'),
'details': _(u'Document "%(document)s" deleted on %(datetime)s by %(fullname)s.'),
'expressions': {'fullname': 'user.get_full_name() if user.get_full_name() else user.username'}
}

View File

@@ -19,6 +19,8 @@ from django.core.exceptions import ValidationError
from django.utils.translation import ugettext from django.utils.translation import ugettext
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from actstream import registry
from acls.utils import apply_default_acls from acls.utils import apply_default_acls
from common.settings import TEMPORARY_DIRECTORY from common.settings import TEMPORARY_DIRECTORY
from converter.api import (convert, get_page_count, from converter.api import (convert, get_page_count,
@@ -26,10 +28,9 @@ from converter.api import (convert, get_page_count,
from converter.exceptions import UnknownFileFormat from converter.exceptions import UnknownFileFormat
from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
DEFAULT_PAGE_NUMBER) DEFAULT_PAGE_NUMBER)
from history.api import create_history
from mimetype.api import get_mimetype from mimetype.api import get_mimetype
from .events import HISTORY_DOCUMENT_CREATED from .events import event_document_create
from .exceptions import NewDocumentVersionNotAllowed from .exceptions import NewDocumentVersionNotAllowed
from .literals import LANGUAGE_CHOICES from .literals import LANGUAGE_CHOICES
from .managers import (DocumentManager, DocumentPageTransformationManager, from .managers import (DocumentManager, DocumentPageTransformationManager,
@@ -119,9 +120,9 @@ class Document(models.Model):
if user: if user:
self.add_as_recent_document_for_user(user) self.add_as_recent_document_for_user(user)
create_history(HISTORY_DOCUMENT_CREATED, self, {'user': user}) event_document_create.commit(actor=user, target=self)
else: else:
create_history(HISTORY_DOCUMENT_CREATED, self) event_document_create.commit(target=self)
def get_cached_image_name(self, page, version): def get_cached_image_name(self, page, version):
document_version = DocumentVersion.objects.get(pk=version) document_version = DocumentVersion.objects.get(pk=version)
@@ -582,3 +583,5 @@ class RecentDocument(models.Model):
# Quick hack to break the DocumentPage and DocumentPageTransformation circular dependency # Quick hack to break the DocumentPage and DocumentPageTransformation circular dependency
# Can be remove once the transformations are moved to the converter app # Can be remove once the transformations are moved to the converter app
DocumentPage.add_to_class('get_transformation_list', lambda document_page: DocumentPageTransformation.objects.get_for_document_page_as_list(document_page)) DocumentPage.add_to_class('get_transformation_list', lambda document_page: DocumentPageTransformation.objects.get_for_document_page_as_list(document_page))
registry.register(Document)

View File

@@ -23,11 +23,10 @@ from common.widgets import two_state_template
from converter.literals import (DEFAULT_FILE_FORMAT_MIMETYPE, DEFAULT_PAGE_NUMBER, from converter.literals import (DEFAULT_FILE_FORMAT_MIMETYPE, DEFAULT_PAGE_NUMBER,
DEFAULT_ROTATION, DEFAULT_ZOOM_LEVEL) DEFAULT_ROTATION, DEFAULT_ZOOM_LEVEL)
from filetransfers.api import serve_file from filetransfers.api import serve_file
from history.api import create_history
from navigation.utils import resolve_to_name from navigation.utils import resolve_to_name
from permissions.models import Permission from permissions.models import Permission
from .events import HISTORY_DOCUMENT_EDITED from .events import event_document_edited
from .forms import (DocumentContentForm, DocumentDownloadForm, DocumentForm, from .forms import (DocumentContentForm, DocumentDownloadForm, DocumentForm,
DocumentPageForm, DocumentPageForm_edit, DocumentPageForm, DocumentPageForm_edit,
DocumentPageForm_text, DocumentPageTransformationForm, DocumentPageForm_text, DocumentPageTransformationForm,
@@ -238,7 +237,7 @@ def document_edit(request, document_id):
document.label = form.cleaned_data['document_type_available_filenames'].filename document.label = form.cleaned_data['document_type_available_filenames'].filename
document.save() document.save()
create_history(HISTORY_DOCUMENT_EDITED, document, {'user': request.user}) event_document_edited.commit(actor=request.user)
document.add_as_recent_document_for_user(request.user) document.add_as_recent_document_for_user(request.user)
messages.success(request, _(u'Document "%s" edited successfully.') % document) messages.success(request, _(u'Document "%s" edited successfully.') % document)
@@ -280,7 +279,7 @@ def document_document_type_edit(request, document_id=None, document_id_list=None
for document in documents: for document in documents:
document.set_document_type(form.cleaned_data['document_type']) document.set_document_type(form.cleaned_data['document_type'])
create_history(HISTORY_DOCUMENT_EDITED, document, {'user': request.user}) event_document_edited.commit(actor=request.user)
document.add_as_recent_document_for_user(request.user) document.add_as_recent_document_for_user(request.user)
messages.success(request, _(u'Document type changed successfully.')) messages.success(request, _(u'Document type changed successfully.'))

View File

@@ -0,0 +1 @@
from .classes import Event # NOQA

View File

@@ -0,0 +1,9 @@
from django.contrib import admin
from .models import EventType
class EventTypeAdmin(admin.ModelAdmin):
readonly_fields = ('name', 'get_label')
admin.site.register(EventType, EventTypeAdmin)

View File

@@ -0,0 +1,22 @@
from __future__ import absolute_import
from django.core import serializers
from django.db import models
from actstream import action
class Event(object):
def __init__(self, name, label):
self.name = name
self.label = label
self.event_type = None
def commit(self, actor=None, action_object=None, target=None):
model = models.get_model('events', 'EventType')
if not self.event_type:
self.event_type, created = model.objects.get_or_create(
label=self.label, name=self.name)
action.send(actor or target, actor=actor, verb=self.name, action_object=action_object, target=target)

View File

@@ -0,0 +1,23 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models
class EventTypeManager(models.Manager):
def create(self, *args, **kwargs):
label = kwargs.pop('label')
instance = super(EventTypeManager, self).create(*args, **kwargs)
self.model._labels[instance.name] = label
return instance
def get(self, *args, **kwargs):
instance = super(EventTypeManager, self).get(*args, **kwargs)
instance.label = self.model._labels[instance.name]
return instance
def get_or_create(self, *args, **kwargs):
label = kwargs.pop('label')
instance, boolean = super(EventTypeManager, self).get_or_create(*args, **kwargs)
self.model._labels[instance.name] = label
return instance, boolean

View File

@@ -0,0 +1,32 @@
# -*- 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 model 'EventType'
db.create_table(u'events_eventtype', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=64)),
))
db.send_create_signal(u'events', ['EventType'])
def backwards(self, orm):
# Deleting model 'EventType'
db.delete_table(u'events_eventtype')
models = {
u'events.eventtype': {
'Meta': {'object_name': 'EventType'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
}
}
complete_apps = ['events']

View File

View File

@@ -0,0 +1,33 @@
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext as _
from .managers import EventTypeManager
@python_2_unicode_compatible
class EventType(models.Model):
_labels = {}
name = models.CharField(max_length=64, unique=True, verbose_name=_('Name'))
objects = EventTypeManager()
def __str__(self):
return unicode(self.get_label())
def get_label(self):
try:
return self.__class__._labels[self.name]
except KeyError:
return _('Unknown or obsolete event type: {0}'.format(self.name))
#@models.permalink
#def get_absolute_url(self):
# return ('history_type_list', [self.pk])
class Meta:
verbose_name = _('Event type')
verbose_name_plural = _('Event types')

View File

@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View File

@@ -1,46 +0,0 @@
from __future__ import absolute_import
import json
import pickle
from django.db import models
from django.core import serializers
from .models import HistoryType, History
from .runtime_data import history_types_dict
def register_history_type(history_type_dict):
namespace = history_type_dict['namespace']
name = history_type_dict['name']
# Runtime
history_types_dict.setdefault(namespace, {})
history_types_dict[namespace][name] = {
'label': history_type_dict['label'],
'summary': history_type_dict.get('summary', u''),
'details': history_type_dict.get('details', u''),
'expressions': history_type_dict.get('expressions', {}),
}
def create_history(history_type_dict, source_object=None, data=None):
history_type, created = HistoryType.objects.get_or_create(namespace=history_type_dict['namespace'], name=history_type_dict['name'])
new_history = History(history_type=history_type)
if source_object:
new_history.content_object = source_object
if data:
new_dict = {}
for key, value in data.items():
new_dict[key] = {}
if isinstance(value, models.Model):
new_dict[key]['value'] = serializers.serialize('json', [value])
elif isinstance(value, models.query.QuerySet):
new_dict[key]['value'] = serializers.serialize('json', value)
else:
new_dict[key]['value'] = json.dumps(value)
new_dict[key]['type'] = pickle.dumps(type(value))
new_history.dictionary = json.dumps(new_dict)
new_history.save()

View File

@@ -10,7 +10,7 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from .runtime_data import history_types_dict #from .runtime_data import history_types_dict
class HistoryType(models.Model): class HistoryType(models.Model):
@@ -18,10 +18,11 @@ class HistoryType(models.Model):
name = models.CharField(max_length=64, verbose_name=_(u'Name')) name = models.CharField(max_length=64, verbose_name=_(u'Name'))
def __unicode__(self): def __unicode__(self):
try: return '{0}.{1}'.format(self.namespace, self.name)
return unicode(history_types_dict[self.namespace][self.name]['label']) # try:
except KeyError: # return unicode(history_types_dict[self.namespace][self.name]['label'])
return u'Obsolete history type: %s - %s' % (self.namespace, self.name) # except KeyError:
# return u'Obsolete history type: %s - %s' % (self.namespace, self.name)
def get_absolute_url(self): def get_absolute_url(self):
return reverse('history:history_type_list', args=[self.pk]) return reverse('history:history_type_list', args=[self.pk])

View File

@@ -1 +0,0 @@
history_types_dict = {}

View File

@@ -2,6 +2,8 @@ from __future__ import absolute_import
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from actstream import registry
from navigation.api import register_links from navigation.api import register_links
from navigation.links import link_spacer from navigation.links import link_spacer
from project_setup.api import register_setup from project_setup.api import register_setup
@@ -25,3 +27,6 @@ register_setup(user_setup)
register_setup(group_setup) register_setup(group_setup)
APIEndPoint('users', app_name='user_management') APIEndPoint('users', app_name='user_management')
registry.register(User)
registry.register(Group)

View File

@@ -34,7 +34,7 @@ ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = ( INSTALLED_APPS = (
# Mayan EDMS # 3rd party
'suit', 'suit',
# Django # Django
'django.contrib.admin', 'django.contrib.admin',
@@ -78,6 +78,7 @@ INSTALLED_APPS = (
'document_indexing', 'document_indexing',
'document_signatures', 'document_signatures',
'documents', 'documents',
'events',
'folders', 'folders',
'history', 'history',
'installation', 'installation',
@@ -94,6 +95,9 @@ INSTALLED_APPS = (
'tags', 'tags',
# Placed after rest_api to allow template overriding # Placed after rest_api to allow template overriding
'rest_framework_swagger', 'rest_framework_swagger',
# Must be last on Django < 1.7 as per documentation
# https://django-activity-stream.readthedocs.org/en/latest/installation.html
'actstream',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (

View File

@@ -8,6 +8,7 @@ urlpatterns = patterns('',
url(r'^', include('common.urls', namespace='common')), url(r'^', include('common.urls', namespace='common')),
url(r'^', include('main.urls', namespace='main')), url(r'^', include('main.urls', namespace='main')),
url(r'^acls/', include('acls.urls', namespace='acls')), url(r'^acls/', include('acls.urls', namespace='acls')),
url(r'^activity/', include('actstream.urls')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^api/', include('rest_api.urls')), url(r'^api/', include('rest_api.urls')),
url(r'^checkouts/', include('checkouts.urls', namespace='checkouts')), url(r'^checkouts/', include('checkouts.urls', namespace='checkouts')),

View File

@@ -2,6 +2,7 @@ celery==3.1.17
cssmin==0.2.0 cssmin==0.2.0
Django==1.6.8 Django==1.6.8
django-activity-stream==0.5.1
django-celery==3.1.16 django-celery==3.1.16
django-compressor==1.4 django-compressor==1.4
django-cors-headers==0.13 django-cors-headers==0.13