README.md edited

This commit is contained in:
2024-12-06 10:45:08 +09:00
parent 09e4edee6b
commit 1aa387aa59
13921 changed files with 2057290 additions and 10 deletions

View File

@@ -0,0 +1,13 @@
from django.contrib import admin
from jet.tests.models import TestModel, RelatedToTestModel
class TestModelAdmin(admin.ModelAdmin):
list_display = ('field1', 'field2')
class RelatedToTestModelAdmin(admin.ModelAdmin):
pass
admin.site.register(TestModel, TestModelAdmin)
admin.site.register(RelatedToTestModel, RelatedToTestModelAdmin)

View File

@@ -0,0 +1,64 @@
from jet.dashboard import modules
from jet.dashboard.dashboard import Dashboard
class TestIndexDashboard(Dashboard):
columns = 3
init_with_context_called = False
class Media:
js = ('file.js', 'file2.js')
css = ('file.css', 'file2.css')
def init_with_context(self, context):
self.init_with_context_called = True
self.available_children.append(modules.LinkList)
self.available_children.append(modules.Feed)
# append a recent actions module
self.children.append(modules.RecentActions(
'Recent Actions',
10,
column=0,
order=1
))
# append a feed module
self.children.append(modules.Feed(
'Latest Django News',
feed_url='http://www.djangoproject.com/rss/weblog/',
limit=5,
column=1,
order=1
))
class TestAppIndexDashboard(Dashboard):
columns = 3
init_with_context_called = False
class Media:
js = ('file.js', 'file2.js')
css = ('file.css', 'file2.css')
def init_with_context(self, context):
self.init_with_context_called = True
self.available_children.append(modules.LinkList)
self.available_children.append(modules.Feed)
# append a recent actions module
self.children.append(modules.RecentActions(
'Recent Actions',
10,
column=0,
order=1
))
# append a feed module
self.children.append(modules.Feed(
'Latest Django News',
feed_url='http://www.djangoproject.com/rss/weblog/',
limit=5,
column=1,
order=1
))

View File

@@ -0,0 +1,32 @@
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class TestModel(models.Model):
field1 = models.CharField(max_length=255)
field2 = models.IntegerField()
def __str__(self):
return '%s%d' % (self.field1, self.field2)
@python_2_unicode_compatible
class RelatedToTestModel(models.Model):
field = models.ForeignKey(TestModel, on_delete=models.CASCADE)
def __str__(self):
return self.field
@python_2_unicode_compatible
class SearchableTestModel(models.Model):
field1 = models.CharField(max_length=255)
field2 = models.IntegerField()
def __str__(self):
return '%s%d' % (self.field1, self.field2)
@staticmethod
def autocomplete_search_fields():
return 'field1'

View File

@@ -0,0 +1,73 @@
import os
import django
from django.conf import global_settings
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
SECRET_KEY = '!DJANGO_JET_TESTS!'
DEBUG = True
TEMPLATE_DEBUG = DEBUG
DEBUG_PROPAGATE_EXCEPTIONS = True
ROOT_URLCONF = 'jet.tests.urls'
INSTALLED_APPS = (
'jet.dashboard',
'jet',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.admin',
'jet.tests',
)
MIDDLEWARE = MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
if django.VERSION[:2] < (1, 9):
TEMPLATE_CONTEXT_PROCESSORS = tuple(global_settings.TEMPLATE_CONTEXT_PROCESSORS) + (
'django.core.context_processors.request',
)
else:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'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',
)
},
},
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
}
}
TIME_ZONE = 'UTC'
LANGUAGE_CODE = 'en-US'
USE_I18N = True
USE_L10N = True
MEDIA_ROOT = ''
MEDIA_URL = ''
STATIC_URL = '/static/'
JET_INDEX_DASHBOARD = 'jet.tests.dashboard.TestIndexDashboard'
JET_APP_INDEX_DASHBOARD = 'jet.tests.dashboard.TestAppIndexDashboard'

View File

@@ -0,0 +1,89 @@
from django.contrib.auth.models import User
try:
from django.core.urlresolvers import reverse
except ImportError: # Django 1.11
from django.urls import reverse
from django.test import TestCase, Client
from jet.dashboard.dashboard import Dashboard
from jet.dashboard.modules import LinkList, RecentActions
from jet.dashboard.models import UserDashboardModule
from jet.tests.dashboard import TestIndexDashboard
class DashboardTestCase(TestCase):
class Request:
def __init__(self, user):
self.user = user
def setUp(self):
self._login()
self._init_dashboard()
def _login(self):
username = 'admin'
email = 'admin@example.com'
password = 'admin'
self.admin = Client()
self.admin_user = User.objects.create_superuser(username, email, password)
return self.admin.login(username=username, password=password)
def _init_dashboard(self):
UserDashboardModule.objects.create(
title='',
module='jet.dashboard.modules.LinkList',
app_label=None,
user=self.admin_user.pk,
column=0,
order=0
)
UserDashboardModule.objects.create(
title='',
module='jet.dashboard.modules.RecentActions',
app_label=None,
user=self.admin_user.pk,
column=0,
order=1
)
self.dashboard = TestIndexDashboard({'request': self.Request(self.admin_user)})
def test_custom_columns(self):
self.assertEqual(self.dashboard.columns, 3)
def test_init_with_context_called(self):
self.assertTrue(self.dashboard.init_with_context_called)
def test_load_modules(self):
self.assertEqual(len(self.dashboard.modules), 2)
self.assertTrue(isinstance(self.dashboard.modules[0], LinkList))
self.assertTrue(isinstance(self.dashboard.modules[1], RecentActions))
def test_media(self):
media = self.dashboard.media()
self.assertEqual(len(media.js), 2)
self.assertEqual(media.js[0], 'file.js')
self.assertEqual(media.js[1], 'file2.js')
self.assertEqual(len(media.css), 2)
self.assertEqual(media.css[0], 'file.css')
self.assertEqual(media.css[1], 'file2.css')
def test_index_dashboard_view(self):
response = self.admin.get(reverse('admin:index'))
self.assertEqual(response.status_code, 200)
self.assertTrue('dashboard' in response.context)
dashboard = response.context['dashboard']
self.assertIsInstance(dashboard, Dashboard)
self.assertIsNone(dashboard.app_label)
def test_app_index_dashboard_view(self):
app_label = 'tests'
response = self.admin.get(reverse('admin:app_list', args=(app_label,)))
self.assertEqual(response.status_code, 200)
self.assertTrue('dashboard' in response.context)
dashboard = response.context['dashboard']
self.assertIsInstance(dashboard, Dashboard)
self.assertEqual(dashboard.app_label, app_label)

View File

@@ -0,0 +1,54 @@
from django.contrib import admin
from django.test import TestCase, RequestFactory
from django.utils.encoding import smart_text
from jet.filters import RelatedFieldAjaxListFilter
from jet.tests.models import RelatedToTestModel, TestModel
try:
from django.contrib.admin.utils import get_fields_from_path
except ImportError: # Django 1.6
from django.contrib.admin.util import get_fields_from_path
class FiltersTestCase(TestCase):
def setUp(self):
self.models = []
self.factory = RequestFactory()
self.models.append(TestModel.objects.create(field1='first', field2=1))
self.models.append(TestModel.objects.create(field1='second', field2=2))
def get_related_field_ajax_list_filter_params(self):
model = RelatedToTestModel
field_path = 'field'
field = get_fields_from_path(model, field_path)[-1]
lookup_params = {}
model_admin = admin.site._registry.get(model)
return field, lookup_params, model, model_admin, field_path
def test_related_field_ajax_list_filter(self):
request = self.factory.get('url')
field, lookup_params, model, model_admin, field_path = self.get_related_field_ajax_list_filter_params()
list_filter = RelatedFieldAjaxListFilter(field, request, lookup_params, model, model_admin, field_path)
self.assertTrue(list_filter.has_output())
choices = list_filter.field_choices(field, request, model_admin)
self.assertIsInstance(choices, list)
self.assertEqual(len(choices), 0)
def test_related_field_ajax_list_filter_with_initial(self):
initial = self.models[1]
request = self.factory.get('url', {'field__id__exact': initial.pk})
field, lookup_params, model, model_admin, field_path = self.get_related_field_ajax_list_filter_params()
list_filter = RelatedFieldAjaxListFilter(field, request, lookup_params, model, model_admin, field_path)
self.assertTrue(list_filter.has_output())
choices = list_filter.field_choices(field, request, model_admin)
self.assertIsInstance(choices, list)
self.assertEqual(len(choices), 1)
self.assertEqual(choices[0], (initial.pk, smart_text(initial)))

View File

@@ -0,0 +1,68 @@
from django.test import TestCase
import pickle
from jet.ordered_set import OrderedSet
class OrderedSetTestCase(TestCase):
def test_pickle(self):
set1 = OrderedSet('abracadabra')
roundtrip = pickle.loads(pickle.dumps(set1))
self.assertEqual(roundtrip, set1)
def test_empty_pickle(self):
empty_oset = OrderedSet()
empty_roundtrip = pickle.loads(pickle.dumps(empty_oset))
self.assertEqual(empty_roundtrip, empty_oset)
def test_order(self):
set1 = OrderedSet('abracadabra')
self.assertEqual(len(set1), 5)
self.assertEqual(set1, OrderedSet(['a', 'b', 'r', 'c', 'd']))
self.assertEqual(list(reversed(set1)), ['d', 'c', 'r', 'b', 'a'])
def test_binary_operations(self):
set1 = OrderedSet('abracadabra')
set2 = OrderedSet('simsalabim')
self.assertNotEqual(set1, set2)
self.assertEqual(set1 & set2, OrderedSet(['a', 'b']))
self.assertEqual(set1 | set2, OrderedSet(['a', 'b', 'r', 'c', 'd', 's', 'i', 'm', 'l']))
self.assertEqual(set1 - set2, OrderedSet(['r', 'c', 'd']))
def test_remove(self):
set1 = OrderedSet('abracadabra')
set1.remove('a')
set1.remove('b')
self.assertEqual(set1, OrderedSet('rcd'))
self.assertNotIn('a', set1)
self.assertNotIn('b', set1)
self.assertIn('r', set1)
set1.discard('a')
set1.discard('a')
def test_remove_error(self):
set1 = OrderedSet('abracadabra')
try:
set1.remove('z')
except KeyError:
pass
def test_clear(self):
set1 = OrderedSet('abracadabra')
set1.clear()
self.assertEqual(len(set1), 0)
self.assertEqual(set1, OrderedSet())
def test_pop(self):
set1 = OrderedSet('ab')
elem = set1.pop()
self.assertEqual(elem, 'b')
elem = set1.pop()
self.assertEqual(elem, 'a')
self.assertRaises(KeyError, set1.pop)

View File

@@ -0,0 +1,102 @@
from django import forms
try:
from django.core.urlresolvers import reverse
except ImportError: # Django 1.11
from django.urls import reverse
from django.test import TestCase
from jet.templatetags.jet_tags import jet_select2_lookups, jet_next_object, jet_previous_object
from jet.tests.models import TestModel, SearchableTestModel
from django.test.client import RequestFactory
class TagsTestCase(TestCase):
def setUp(self):
self.models = []
self.searchable_models = []
self.models.append(TestModel.objects.create(field1='first', field2=1))
self.models.append(TestModel.objects.create(field1='second', field2=2))
self.searchable_models.append(SearchableTestModel.objects.create(field1='first', field2=1))
self.searchable_models.append(SearchableTestModel.objects.create(field1='second', field2=2))
def test_select2_lookups(self):
class TestForm(forms.Form):
form_field = forms.ModelChoiceField(SearchableTestModel.objects)
value = self.searchable_models[0]
form = TestForm(initial={'form_field': value.pk})
field = form['form_field']
field = jet_select2_lookups(field)
choices = [choice for choice in field.field.choices]
self.assertEqual(len(choices), 1)
self.assertEqual(choices[0][0], value.pk)
def test_select2_lookups_posted(self):
class TestForm(forms.Form):
form_field = forms.ModelChoiceField(SearchableTestModel.objects)
value = self.searchable_models[0]
form = TestForm(data={'form_field': value.pk})
field = form['form_field']
field = jet_select2_lookups(field)
choices = [choice for choice in field.field.choices]
self.assertEqual(len(choices), 1)
self.assertEqual(choices[0][0], value.pk)
def test_non_select2_lookups(self):
class TestForm(forms.Form):
form_field = forms.ModelChoiceField(TestModel.objects)
value = self.searchable_models[0]
form = TestForm(initial={'form_field': value.pk})
field = form['form_field']
field = jet_select2_lookups(field)
choices = [choice for choice in field.field.choices]
self.assertEqual(len(choices), len(self.models) + 1)
def test_jet_sibling_object_next_url(self):
instance = self.models[0]
ordering_field = 1 # field1 in list_display
preserved_filters = '_changelist_filters=o%%3D%d' % ordering_field
expected_url = reverse('admin:%s_%s_change' % (
TestModel._meta.app_label,
TestModel._meta.model_name
), args=(self.models[1].pk,)) + '?' + preserved_filters
context = {
'original': instance,
'preserved_filters': preserved_filters,
'request': RequestFactory().get(expected_url),
}
actual_url = jet_next_object(context)['url']
self.assertEqual(actual_url, expected_url)
def test_jet_sibling_object_previous_url(self):
instance = self.models[0]
ordering_field = 1 # field1 in list_display
preserved_filters = '_changelist_filters=o%%3D%d' % ordering_field
changelist_url = reverse('admin:%s_%s_change' % (
TestModel._meta.app_label,
TestModel._meta.model_name
), args=(self.models[1].pk,)) + '?' + preserved_filters
context = {
'original': instance,
'preserved_filters': preserved_filters,
'request': RequestFactory().get(changelist_url),
}
previous_object = jet_previous_object(context)
expected_object = None
self.assertEqual(previous_object, expected_object)

View File

@@ -0,0 +1,70 @@
from datetime import datetime, date
import json
from django.contrib.admin import AdminSite
from django.test import TestCase
from jet.tests.models import TestModel
from jet.utils import JsonResponse, get_model_instance_label, get_app_list, get_admin_site, LazyDateTimeEncoder
class UtilsTestCase(TestCase):
def test_json_response(self):
response = JsonResponse({'str': 'string', 'int': 1})
response_dict = json.loads(response.content.decode())
expected_dict = {"int": 1, "str": "string"}
self.assertEqual(response_dict, expected_dict)
self.assertEqual(response.get('Content-Type'), 'application/json')
def test_get_model_instance_label(self):
field1 = 'value'
field2 = 2
pinned_application = TestModel.objects.create(field1=field1, field2=field2)
self.assertEqual(get_model_instance_label(pinned_application), '%s%d' % (field1, field2))
def test_get_app_list(self):
class User:
is_active = True
is_staff = True
def has_module_perms(self, app):
return True
def has_perm(self, object):
return True
class Request:
user = User()
app_list = get_app_list({
'request': Request(),
'user': None
})
self.assertIsInstance(app_list, list)
for app in app_list:
self.assertIsInstance(app, dict)
self.assertIsNotNone(app, app.get('models'))
self.assertIsNotNone(app, app.get('app_url'))
self.assertIsNotNone(app, app.get('app_label'))
for model in app['models']:
self.assertIsNotNone(app, model.get('object_name'))
self.assertIsNotNone(app, model.get('name'))
def test_get_admin_site(self):
admin_site = get_admin_site({})
self.assertIsInstance(admin_site, AdminSite)
def test_lazy_date_time_encoder_dates(self):
encoder = LazyDateTimeEncoder()
ts = datetime.now()
self.assertEqual(encoder.encode(ts), '"%s"' % ts.isoformat())
ts = date(2015, 5, 3)
self.assertEqual(encoder.encode(ts), '"%s"' % ts.isoformat())
def test_lazy_date_time_encoder_dict(self):
encoder = LazyDateTimeEncoder()
self.assertEqual(encoder.encode({'key': 1}), '{"key": 1}')

View File

@@ -0,0 +1,229 @@
import json
from django.contrib.auth.models import User
try:
from django.core.urlresolvers import reverse
except ImportError: # Django 1.11
from django.urls import reverse
from django.test import TestCase, Client
from jet.dashboard.modules import LinkList
from jet.models import Bookmark
from jet.dashboard.models import UserDashboardModule
class ViewsTestCase(TestCase):
def setUp(self):
self.assertTrue(self._login())
def _login(self):
username = 'admin'
email = 'admin@example.com'
password = 'admin'
self.admin = Client()
self.admin_user = User.objects.create_superuser(username, email, password)
return self.admin.login(username=username, password=password)
def test_module_update_view(self):
title = 'Quick links Test'
new_title = title + '2'
new_layout = 'stacked'
module = UserDashboardModule.objects.create(
title=title,
module='jet.dashboard.modules.LinkList',
app_label=None,
user=self.admin_user.pk,
column=0,
order=0,
settings='{"layout": "inline"}',
children='[]'
)
response = self.admin.get(reverse('jet-dashboard:update_module', kwargs={'pk': module.pk}))
self.assertEqual(response.status_code, 200)
self.assertTrue(response.context['module'] is not None)
self.assertTrue(isinstance(response.context['module'], LinkList))
self.assertEqual(response.context['module'].title, title)
post = {
'title': new_title,
'layout': new_layout,
'children-TOTAL_FORMS': '2',
'children-INITIAL_FORMS': '1',
'children-MIN_NUM_FORMS': '0',
'children-MAX_NUM_FORMS': '1000',
'children-0-url': 'http://docs.djangoproject.com/',
'children-0-title': 'Django documentation',
'children-0-external': 'on',
'children-1-url': '',
'children-1-title': '',
'children-__prefix__-url': '',
'children-__prefix__-title': '',
'_save': 'Save'
}
self.admin.post(reverse('jet-dashboard:update_module', kwargs={'pk': module.pk}), post)
self.assertEqual(response.status_code, 200)
module = UserDashboardModule.objects.get(pk=module.pk)
settings = json.loads(module.settings)
self.assertEqual(module.title, new_title)
self.assertEqual(settings['layout'], new_layout)
module.delete()
def test_add_bookmark_view(self):
url = 'http://test.com/'
title = 'Title'
response = self.admin.post(reverse('jet:add_bookmark'), {'url': url, 'title': title})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertNotEqual(response['id'], None)
bookmark = Bookmark.objects.get(pk=response['id'])
self.assertNotEqual(bookmark, None)
self.assertEqual(bookmark.title, title)
self.assertEqual(bookmark.url, url)
def test_add_bookmark_view_unauthorized(self):
url = 'http://test.com/'
title = 'Title'
response = self.client.post(reverse('jet:add_bookmark'), {'url': url, 'title': title})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertTrue(response['error'])
def test_remove_bookmark_view(self):
url = 'http://test.com/'
title = 'Title'
bookmark = Bookmark.objects.create(url=url, title=title, user=self.admin_user.pk)
response = self.admin.post(reverse('jet:remove_bookmark'), {'id': bookmark.id})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertFalse(Bookmark.objects.filter(pk=bookmark.pk).exists())
def test_toggle_application_pin_view(self):
app_label = 'test_app'
response = self.admin.post(reverse('jet:toggle_application_pin'), {'app_label': app_label})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertTrue(response['pinned'])
response = self.admin.post(reverse('jet:toggle_application_pin'), {'app_label': app_label})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertFalse(response['pinned'])
def test_update_dashboard_modules_view(self):
app_label = None
module_0 = UserDashboardModule.objects.create(
title='',
module='jet.dashboard.modules.LinkList',
app_label=app_label,
user=self.admin_user.pk,
column=0,
order=0
)
module_1 = UserDashboardModule.objects.create(
title='',
module='jet.dashboard.modules.LinkList',
app_label=app_label,
user=self.admin_user.pk,
column=0,
order=1
)
response = self.admin.post(reverse('jet-dashboard:update_dashboard_modules'), {
'app_label': '',
'modules': json.dumps([
{'id': module_0.pk, 'column': 0, 'order': 1},
{'id': module_1.pk, 'column': 0, 'order': 0}
])
})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
module_0 = UserDashboardModule.objects.get(pk=module_0.pk)
module_1 = UserDashboardModule.objects.get(pk=module_1.pk)
self.assertEqual(module_0.order, 1)
self.assertEqual(module_1.order, 0)
module_0.delete()
module_1.delete()
def test_add_user_dashboard_module_view(self):
response = self.admin.post(reverse('jet-dashboard:add_user_dashboard_module'), {
'app_label': '',
'type': 'available_children',
'module': 0
})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertNotEqual(response['id'], None)
module = UserDashboardModule.objects.get(pk=response['id'])
self.assertNotEqual(module, None)
def test_add_user_app_dashboard_module_view(self):
app_label = 'auth'
response = self.admin.post(reverse('jet-dashboard:add_user_dashboard_module'), {
'app_label': app_label,
'type': 'available_children',
'module': 0
})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertNotEqual(response['id'], None)
module = UserDashboardModule.objects.get(pk=response['id'])
self.assertNotEqual(module, None)
self.assertEqual(module.app_label, app_label)
def test_update_dashboard_module_collapse_view(self):
module = UserDashboardModule.objects.create(
title='',
module='jet.dashboard.modules.LinkList',
app_label=None,
user=self.admin_user.pk,
column=0,
order=0
)
response = self.admin.post(reverse('jet-dashboard:update_dashboard_module_collapse'), {
'id': module.pk, 'collapsed': True
})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertTrue(response['collapsed'])
module = UserDashboardModule.objects.get(pk=module.pk)
response = self.admin.post(reverse('jet-dashboard:update_dashboard_module_collapse'), {
'id': module.pk, 'collapsed': False
})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertFalse(response['collapsed'])
module.delete()
def test_remove_dashboard_module_view(self):
module = UserDashboardModule.objects.create(
title='',
module='jet.dashboard.modules.LinkList',
app_label=None,
user=self.admin_user.pk,
column=0,
order=0
)
response = self.admin.post(reverse('jet-dashboard:remove_dashboard_module'), {'id': module.pk})
self.assertEqual(response.status_code, 200)
response = json.loads(response.content.decode())
self.assertFalse(response['error'])
self.assertFalse(UserDashboardModule.objects.filter(pk=module.pk).exists())

View File

@@ -0,0 +1,27 @@
import django
from django.conf.urls import include, url
from django.contrib import admin
admin.autodiscover()
try:
from django.urls import path
urlpatterns = [
url(r'^jet/', include('jet.urls', 'jet')),
url(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
path('admin/', admin.site.urls),
]
except ImportError: # Django < 2.0
urlpatterns = [
url(r'^jet/', include('jet.urls', 'jet')),
url(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
]
if django.VERSION[:2] < (1, 8):
from django.conf.urls import patterns
urlpatterns = patterns('', *urlpatterns)