Merge branch 'feature/optimize_document_widget' into development
This commit is contained in:
@@ -3,6 +3,8 @@ import os
|
||||
import re
|
||||
import types
|
||||
import tempfile
|
||||
import string
|
||||
import random
|
||||
|
||||
from django.utils.http import urlquote as django_urlquote
|
||||
from django.utils.http import urlencode as django_urlencode
|
||||
@@ -358,8 +360,13 @@ def validate_path(path):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def encapsulate(function):
|
||||
# Workaround Django ticket 15791
|
||||
# Changeset 16045
|
||||
# http://stackoverflow.com/questions/6861601/cannot-resolve-callable-context-variable/6955045#6955045
|
||||
return lambda: function
|
||||
|
||||
|
||||
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
|
||||
return ''.join(random.choice(chars) for x in range(size))
|
||||
|
||||
@@ -14,8 +14,8 @@ from converter.literals import TRANSFORMATION_RESIZE, \
|
||||
from converter.literals import DIMENSION_SEPARATOR
|
||||
from converter.literals import FILE_FORMATS
|
||||
from converter.utils import cleanup
|
||||
from converter.office_converter import OfficeConverter
|
||||
|
||||
from converter.runtime import office_converter
|
||||
from converter.exceptions import OfficeConversionError
|
||||
|
||||
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
|
||||
|
||||
@@ -51,18 +51,19 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
|
||||
|
||||
if os.path.exists(output_filepath):
|
||||
return output_filepath
|
||||
|
||||
office_converter = OfficeConverter()
|
||||
office_converter.convert(input_filepath, mimetype=mimetype)
|
||||
|
||||
if office_converter:
|
||||
try:
|
||||
input_filepath = office_converter.output_filepath
|
||||
mimetype = 'application/pdf'
|
||||
except OfficeConverter:
|
||||
raise UnknownFileFormat('office converter exception')
|
||||
else:
|
||||
# Recycle the already detected mimetype
|
||||
mimetype = office_converter.mimetype
|
||||
office_converter.convert(input_filepath, mimetype=mimetype)
|
||||
if office_converter.exists:
|
||||
input_filepath = office_converter.output_filepath
|
||||
mimetype = 'application/pdf'
|
||||
else:
|
||||
# Recycle the already detected mimetype
|
||||
mimetype = office_converter.mimetype
|
||||
|
||||
except OfficeConversionError:
|
||||
raise UnknownFileFormat('office converter exception')
|
||||
|
||||
if size:
|
||||
transformations.append(
|
||||
@@ -98,14 +99,15 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
|
||||
|
||||
|
||||
def get_page_count(input_filepath):
|
||||
office_converter = OfficeConverter()
|
||||
office_converter.convert(input_filepath)
|
||||
if office_converter:
|
||||
try:
|
||||
input_filepath = office_converter.output_filepath
|
||||
except OfficeConverter:
|
||||
raise UnknownFileFormat('office converter exception')
|
||||
|
||||
office_converter.convert(input_filepath)
|
||||
if office_converter.exists:
|
||||
input_filepath = office_converter.output_filepath
|
||||
|
||||
except OfficeConversionError:
|
||||
raise UnknownFileFormat('office converter exception')
|
||||
|
||||
return backend.get_page_count(input_filepath)
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ DEFAULT_ZOOM_LEVEL = 100
|
||||
DEFAULT_ROTATION = 0
|
||||
DEFAULT_PAGE_NUMBER = 1
|
||||
DEFAULT_FILE_FORMAT = u'jpeg'
|
||||
DEFAULT_FILE_FORMAT_MIMETYPE = u'image/jpeg'
|
||||
|
||||
DIMENSION_SEPARATOR = u'x'
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
|
||||
from mimetype.api import get_mimetype
|
||||
from common.conf.settings import TEMPORARY_DIRECTORY
|
||||
from common.utils import id_generator
|
||||
|
||||
from converter.conf.settings import UNOCONV_PATH, UNOCONV_USE_PIPE
|
||||
from converter.exceptions import (OfficeConversionError,
|
||||
@@ -26,10 +28,13 @@ CONVERTER_OFFICE_FILE_MIMETYPES = [
|
||||
'application/vnd.oasis.opendocument.graphics',
|
||||
]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OfficeConverter(object):
|
||||
def __init__(self):
|
||||
self.backend_class = OfficeConverterBackendUnoconv
|
||||
self.backend = self.backend_class()
|
||||
self.exists = False
|
||||
self.mimetype = None
|
||||
self.encoding = None
|
||||
@@ -38,6 +43,10 @@ class OfficeConverter(object):
|
||||
return CONVERTER_OFFICE_FILE_MIMETYPES
|
||||
|
||||
def convert(self, input_filepath, mimetype=None):
|
||||
self.exists = False
|
||||
self.mimetype = None
|
||||
self.encoding = None
|
||||
|
||||
self.input_filepath = input_filepath
|
||||
|
||||
# Make sure file is of a known office format
|
||||
@@ -52,7 +61,6 @@ class OfficeConverter(object):
|
||||
self.exists = os.path.exists(self.output_filepath)
|
||||
if not self.exists:
|
||||
try:
|
||||
self.backend = self.backend_class()
|
||||
self.backend.convert(self.input_filepath, self.output_filepath)
|
||||
self.exists = True
|
||||
except OfficeBackendError, msg:
|
||||
@@ -64,11 +72,6 @@ class OfficeConverter(object):
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__unicode__())
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.exists
|
||||
|
||||
__bool__ = __nonzero__
|
||||
|
||||
|
||||
class OfficeConverterBackendUnoconv(object):
|
||||
@@ -78,9 +81,9 @@ class OfficeConverterBackendUnoconv(object):
|
||||
raise OfficeBackendError('cannot find unoconv executable')
|
||||
|
||||
def convert(self, input_filepath, output_filepath):
|
||||
"""
|
||||
'''
|
||||
Executes the program unoconv using subprocess's Popen
|
||||
"""
|
||||
'''
|
||||
self.input_filepath = input_filepath
|
||||
self.output_filepath = output_filepath
|
||||
|
||||
@@ -89,17 +92,22 @@ class OfficeConverterBackendUnoconv(object):
|
||||
|
||||
if UNOCONV_USE_PIPE:
|
||||
command.append(u'--pipe')
|
||||
command.append(u'mayan')
|
||||
command.append(u'mayan-%s' % id_generator())
|
||||
|
||||
command.append(u'--format=pdf')
|
||||
command.append(u'--output=%s' % self.output_filepath)
|
||||
command.append(self.input_filepath)
|
||||
|
||||
|
||||
try:
|
||||
logger.debug('prev environment: %s' % os.environ)
|
||||
proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
return_code = proc.wait()
|
||||
logger.debug('post environment: %s' % os.environ)
|
||||
|
||||
readline = proc.stderr.readline()
|
||||
if return_code != 0:
|
||||
raise OfficeBackendError(proc.stderr.readline())
|
||||
except OSError, msg:
|
||||
raise OfficeBackendError(msg)
|
||||
except Exception, msg:
|
||||
logger.error('Unhandled exception: %s' % msg)
|
||||
|
||||
8
apps/converter/runtime.py
Normal file
8
apps/converter/runtime.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from converter.office_converter import OfficeConverter
|
||||
from converter.exceptions import OfficeBackendError
|
||||
|
||||
|
||||
try:
|
||||
office_converter = OfficeConverter()
|
||||
except OfficeBackendError:
|
||||
office_converter = None
|
||||
@@ -18,7 +18,7 @@ from common.literals import PAGE_SIZE_DIMENSIONS, \
|
||||
PAGE_ORIENTATION_PORTRAIT, PAGE_ORIENTATION_LANDSCAPE
|
||||
from common.conf.settings import DEFAULT_PAPER_SIZE
|
||||
from converter.literals import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \
|
||||
DEFAULT_PAGE_NUMBER
|
||||
DEFAULT_PAGE_NUMBER, DEFAULT_FILE_FORMAT_MIMETYPE
|
||||
from converter.office_converter import OfficeConverter
|
||||
from filetransfers.api import serve_file
|
||||
from metadata.forms import MetadataFormSet, MetadataSelectionForm
|
||||
@@ -288,7 +288,7 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE):
|
||||
|
||||
rotation = int(request.GET.get('rotation', DEFAULT_ROTATION)) % 360
|
||||
|
||||
return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation))
|
||||
return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation), mimetype=DEFAULT_FILE_FORMAT_MIMETYPE)
|
||||
|
||||
|
||||
def document_download(request, document_id):
|
||||
|
||||
@@ -37,21 +37,79 @@ def document_html_widget(document, size='document_thumbnail', click_view=None, p
|
||||
|
||||
query_string = urlencode(query_dict)
|
||||
preview_view = u'%s?%s' % (reverse(size, args=[document.pk]), query_string)
|
||||
print 'preview_view', preview_view
|
||||
|
||||
zoomable_template = []
|
||||
if click_view:
|
||||
zoomable_template.append(u'<a %s class="%s" href="%s">' % (gallery_template, fancybox_class, u'%s?%s' % (reverse(click_view, args=[document.pk]), query_string)))
|
||||
zoomable_template.append(u'<img style="border: 1px solid black;" class="lazy-load" data-href="%s" src="%s/images/ajax-loader.gif" alt="%s" />' % (preview_view, settings.STATIC_URL, alt_text))
|
||||
zoomable_template.append(u'<noscript><img style="border: 1px solid black;" src="%s" alt="%s" /></noscript>' % (preview_view, alt_text))
|
||||
if click_view:
|
||||
zoomable_template.append(u'</a>')
|
||||
|
||||
"""
|
||||
plain_template = []
|
||||
plain_template.append(u'<img class="lazy-load" data-href="%s" src="%simages/ajax-loader.gif" alt="%s" />' % (preview_view, settings.STATIC_URL, alt_text))
|
||||
plain_template.append(u'<noscript><img src="%s" alt="%s" /></noscript>' % (preview_view, alt_text))
|
||||
|
||||
result.append(u'''
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
|
||||
$.get('%(url)s', function(data) {})
|
||||
.success(function(data) {
|
||||
if (data.result) {
|
||||
$('#document-%(pk)d-%(page)d').html('%(zoomable_template)s');
|
||||
} else {
|
||||
|
||||
$('#document-%(pk)d-%(page)d').html('%(plain_template)s');
|
||||
}
|
||||
//$('.fancybox-noscaling').live('click', function(e) {alert("CLICK");});
|
||||
|
||||
})
|
||||
.error(function(data) { alert("error"); })
|
||||
;
|
||||
});
|
||||
</script>
|
||||
''' % {
|
||||
u'url': reverse('documents-expensive-is_zoomable', args=[document.pk]),
|
||||
u'pk': document.pk,
|
||||
u'page': page if page else 1,
|
||||
u'zoomable_template': mark_safe(u''.join(zoomable_template)),
|
||||
u'plain_template': mark_safe(u''.join(plain_template)),
|
||||
}
|
||||
)
|
||||
|
||||
result.append(u'<div class="tc" id="document-%d-%d">' % (document.pk, page if page else 1))
|
||||
result.append(u'<a href="%s">' % (u'%s?%s' % (reverse(click_view, args=[document.pk]), query_string)))
|
||||
result.append(u'<img src="%s/images/ajax-loader.gif" alt="%s" />' % (settings.STATIC_URL, alt_text))
|
||||
result.append(u'<noscript><img style="border: 1px solid black;" src="%s" alt="%s" /></noscript>' % (preview_view, alt_text))
|
||||
result.append(u'</a>')
|
||||
result.append(u'</div>')
|
||||
"""
|
||||
|
||||
#Fancybox w/ jQuery live
|
||||
"""
|
||||
jQuery("a.fancybox-noscaling").live('click', function(){
|
||||
jQuery.fancybox({
|
||||
'autoDimensions' : false,
|
||||
'width' : 'auto',
|
||||
'height' : 'auto',
|
||||
'href' : $(this).attr('href'),
|
||||
'titleShow' : false,
|
||||
'transitionIn' : 'elastic',
|
||||
'transitionOut' : 'elastic',
|
||||
'easingIn' : 'easeOutBack',
|
||||
'easingOut' : 'easeInBack',
|
||||
'type' : 'image',
|
||||
'autoScale' : false
|
||||
|
||||
});
|
||||
return false;
|
||||
});
|
||||
"""
|
||||
result.append(u'<div class="tc" id="document-%d-%d">' % (document.pk, page if page else 1))
|
||||
result.extend(zoomable_template)
|
||||
result.append(u'</div>')
|
||||
|
||||
try:
|
||||
document.get_valid_image()
|
||||
result.append('<div class="tc">')
|
||||
if click_view:
|
||||
result.append('<a %s class="%s" href="%s">' % (gallery_template, fancybox_class, u'%s?%s' % (reverse(click_view, args=[document.pk]), query_string)))
|
||||
result.append('<img style="border: 1px solid black;" class="lazy-load" data-href="%s" src="%s/images/ajax-loader.gif" alt="%s" />' % (preview_view, settings.STATIC_URL, alt_text))
|
||||
result.append('<noscript><img style="border: 1px solid black;" src="%s" alt="%s" /></noscript>' % (preview_view, alt_text))
|
||||
if click_view:
|
||||
result.append('</a>')
|
||||
result.append('</div>')
|
||||
except (UnknownFileFormat, UnkownConvertError):
|
||||
result.append('<div class="tc">')
|
||||
result.append('<img class="lazy-load" data-href="%s" src="%s/images/ajax-loader.gif" alt="%s" />' % (preview_view, settings.STATIC_URL, alt_text))
|
||||
result.append('<noscript><img src="%s" alt="%s" /></noscript>' % (preview_view, alt_text))
|
||||
result.append('</div>')
|
||||
|
||||
return mark_safe(u''.join(result))
|
||||
|
||||
0
apps/rest_api/__init__.py
Normal file
0
apps/rest_api/__init__.py
Normal file
3
apps/rest_api/models.py
Normal file
3
apps/rest_api/models.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
38
apps/rest_api/resources.py
Normal file
38
apps/rest_api/resources.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from djangorestframework.resources import ModelResource
|
||||
|
||||
from documents.models import Document
|
||||
from converter.exceptions import UnknownFileFormat, UnkownConvertError
|
||||
|
||||
|
||||
class DocumentResourceSimple(ModelResource):
|
||||
model = Document
|
||||
fields = ('url', 'pk', 'document_type', 'uuid', 'date_added', 'description', 'tags', 'comments', 'expensive_methods', 'files')
|
||||
|
||||
def files(self, instance):
|
||||
return [
|
||||
{
|
||||
'version': 1,
|
||||
'mimetype': instance.file_mimetype,
|
||||
'encoding': instance.file_mime_encoding,
|
||||
'filename': instance.get_fullname(),
|
||||
'date_updated': instance.date_updated,
|
||||
'checksum': instance.checksum,
|
||||
'size': instance.size,
|
||||
'exists': instance.exists(),
|
||||
'pages': [
|
||||
{
|
||||
'page_numer': page.page_number,
|
||||
'page_label': page.page_label,
|
||||
#'content':
|
||||
}
|
||||
for page in instance.documentpage_set.all()
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
def expensive_methods(self, instance):
|
||||
return [
|
||||
{'is_zoomable': reverse('documents-expensive-is_zoomable', args=[instance.pk])},
|
||||
]
|
||||
1
apps/rest_api/tests.py
Normal file
1
apps/rest_api/tests.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
18
apps/rest_api/urls.py
Normal file
18
apps/rest_api/urls.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from django.conf.urls.defaults import patterns, url
|
||||
|
||||
from djangorestframework.views import ListModelView
|
||||
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
|
||||
|
||||
from rest_api.views import APIBase, Version_0, ReadOnlyInstanceModelView, IsZoomable, Exists, Size
|
||||
from rest_api.resources import DocumentResourceSimple
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', APIBase.as_view(), name='api-root'),
|
||||
url(r'^v0/$', Version_0.as_view(), name='api-version-0'),
|
||||
|
||||
# Version 0 alpha API calls
|
||||
url(r'^v0/document/(?P<pk>[0-9]+)/$', ReadOnlyInstanceModelView.as_view(resource=DocumentResourceSimple), name='documents-simple'),
|
||||
url(r'^v0/document/(?P<pk>[0-9]+)/expensive/is_zoomable/$', IsZoomable.as_view(), name='documents-expensive-is_zoomable'),
|
||||
url(r'^v0/document/(?P<pk>[0-9]+)/expensive/exists/$', IsZoomable.as_view(), name='documents-expensive-exists'),
|
||||
url(r'^v0/document/(?P<pk>[0-9]+)/expensive/size/$', Size.as_view(), name='documents-expensive-size'),
|
||||
)
|
||||
69
apps/rest_api/views.py
Normal file
69
apps/rest_api/views.py
Normal file
@@ -0,0 +1,69 @@
|
||||
'''Views file for the rest_api app'''
|
||||
|
||||
import logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from documents.models import Document
|
||||
from converter.exceptions import UnknownFileFormat, UnkownConvertError
|
||||
|
||||
from djangorestframework.views import View, ModelView, ListModelView, InstanceModelView
|
||||
from djangorestframework.mixins import InstanceMixin, ReadModelMixin
|
||||
from djangorestframework.response import Response
|
||||
from djangorestframework import status
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ReadOnlyInstanceModelView(InstanceModelView):
|
||||
allowed_methods = ['GET']
|
||||
|
||||
|
||||
class APIBase(View):
|
||||
"""This is the REST API for Mayan EDMS (https://github.com/rosarior/mayan/).
|
||||
|
||||
All the API calls can be navigated either through the browser or from the command line...
|
||||
|
||||
bash: curl -X GET http://127.0.0.1:8000/api/ # (Use default renderer)
|
||||
bash: curl -X GET http://127.0.0.1:8000/api/ -H 'Accept: text/plain' # (Use plaintext documentation renderer)
|
||||
|
||||
"""
|
||||
|
||||
def get(self, request):
|
||||
return [
|
||||
{'name': 'Version 0 Alpha', 'url': reverse('api-version-0')}
|
||||
]
|
||||
|
||||
|
||||
class Version_0(View):
|
||||
def get(self, request):
|
||||
return [
|
||||
{'name': 'Resources', 'resources': ['documents/<pk>']}
|
||||
]
|
||||
|
||||
|
||||
class IsZoomable(View):
|
||||
def get(self, request, pk):
|
||||
logger.info('received is_zoomable call from: %s' % (request.META['REMOTE_ADDR']))
|
||||
document = get_object_or_404(Document, pk=pk)
|
||||
try:
|
||||
document.get_image_cache_name(1) # TODO: page
|
||||
return {'result': True}
|
||||
except (UnknownFileFormat, UnkownConvertError):
|
||||
return {'result': False}
|
||||
|
||||
|
||||
class Exists(View):
|
||||
def get(self, request, pk):
|
||||
logger.info('received exists call from: %s' % (request.META['REMOTE_ADDR']))
|
||||
document = get_object_or_404(Document, pk=pk)
|
||||
return {'result': document.exists()}
|
||||
|
||||
|
||||
class Size(View):
|
||||
def get(self, request, pk):
|
||||
logger.info('received size call from: %s' % (request.META['REMOTE_ADDR']))
|
||||
document = get_object_or_404(Document, pk=pk)
|
||||
return {'result': document.size}
|
||||
4
apps/web_theme/static/web_theme_media/javascripts/jquery-1.7.min.js
vendored
Normal file
4
apps/web_theme/static/web_theme_media/javascripts/jquery-1.7.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -39,7 +39,7 @@
|
||||
{% endcompress %}
|
||||
|
||||
{% compress js %}
|
||||
<script type="text/javascript" charset="utf-8" src="{{ STATIC_URL }}web_theme_media/javascripts/jquery-1.5.2.min.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="{{ STATIC_URL }}web_theme_media/javascripts/jquery-1.7.min.js"></script>
|
||||
|
||||
{% if enable_scroll_js %}
|
||||
<script type="text/javascript" charset="utf-8" src="{{ STATIC_URL }}web_theme_media/javascripts/jquery.scrollTo.js"></script>#}
|
||||
|
||||
@@ -19,3 +19,4 @@ Pillow==1.7.4
|
||||
cssmin==0.1.4
|
||||
django-compressor==1.1
|
||||
-e git://github.com/rosarior/django-sendfile.git#egg=django-sendfile
|
||||
djangorestframework==0.2.3
|
||||
|
||||
@@ -16,3 +16,4 @@ Pillow==1.7.4
|
||||
cssmin==0.1.4
|
||||
django-compressor==1.1
|
||||
-e git://github.com/rosarior/django-sendfile.git#egg=django-sendfile
|
||||
djangorestframework==0.2.3
|
||||
|
||||
@@ -81,7 +81,8 @@ STATIC_URL = '/%s-static/' % PROJECT_NAME
|
||||
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
|
||||
# trailing slash.
|
||||
# Examples: "http://foo.com/media/", "/media/".
|
||||
ADMIN_MEDIA_PREFIX = STATIC_URL + 'grappelli/'
|
||||
#ADMIN_MEDIA_PREFIX = STATIC_URL + 'grappelli/'
|
||||
ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = 'om^a(i8^6&h+umbd2%pt91cj!qu_@oztw117rgxmn(n2lp^*c!'
|
||||
@@ -117,7 +118,7 @@ TEMPLATE_DIRS = (
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'grappelli',
|
||||
#'grappelli',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
@@ -164,6 +165,8 @@ INSTALLED_APPS = (
|
||||
'history',
|
||||
'main',
|
||||
'compressor',
|
||||
'djangorestframework',
|
||||
'rest_api',
|
||||
)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
@@ -286,7 +289,7 @@ CELERY_DISABLE_RATE_LIMITS = True
|
||||
#--------- Web theme ---------------
|
||||
WEB_THEME_ENABLE_SCROLL_JS = False
|
||||
#--------- Grappelli ----------------
|
||||
GRAPPELLI_ADMIN_TITLE = PROJECT_TITLE
|
||||
#GRAPPELLI_ADMIN_TITLE = PROJECT_TITLE
|
||||
#--------- Django -------------------
|
||||
LOGIN_URL = '/login/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
|
||||
3
urls.py
3
urls.py
@@ -15,7 +15,7 @@ urlpatterns = patterns('',
|
||||
(r'^tags/', include('tags.urls')),
|
||||
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
(r'^admin/', include(admin.site.urls)),
|
||||
(r'^grappelli/', include('grappelli.urls')),
|
||||
#(r'^grappelli/', include('grappelli.urls')),
|
||||
(r'^sentry/', include('sentry.urls')),
|
||||
(r'^comments/', include('document_comments.urls')),
|
||||
(r'^user_management/', include('user_management.urls')),
|
||||
@@ -28,6 +28,7 @@ urlpatterns = patterns('',
|
||||
(r'^sources/', include('sources.urls')),
|
||||
(r'^project_setup/', include('project_setup.urls')),
|
||||
(r'^project_tools/', include('project_tools.urls')),
|
||||
(r'^api/', include('rest_api.urls')),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user