Restructured sample project for Django 2.
Refactored database and changed "app" to "samples" so name didn't conflict with "AppConfig". Replaced deprecated assignment_tag with simple_tag. Updated unit tests.master
parent
10188ec8ac
commit
f4daaeb232
|
|
@ -531,8 +531,8 @@ ordering on top of that just seemed a little much in my opinion.
|
|||
### Status
|
||||
django-admin-sortable is currently used in production.
|
||||
|
||||
### What's new in 2.1.1?
|
||||
- Touch support
|
||||
### What's new in 2.1.2?
|
||||
- Django 2 compatibility
|
||||
|
||||
### Future
|
||||
- Better template support for foreign keys that are self referential. If someone would like to take on rendering recursive sortables, that would be super.
|
||||
|
|
|
|||
|
|
@ -657,10 +657,10 @@ Status
|
|||
|
||||
django-admin-sortable is currently used in production.
|
||||
|
||||
What's new in 2.1.1?
|
||||
What's new in 2.1.2?
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Touch support
|
||||
- Django 2 compatibility
|
||||
|
||||
Future
|
||||
~~~~~~
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
VERSION = (2, 1, 1)
|
||||
VERSION = (2, 1, 2)
|
||||
DEV_N = None
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ def dynamic_regroup(parser, token):
|
|||
return DynamicRegroupNode(target, parser, expression, var_name)
|
||||
|
||||
|
||||
@register.assignment_tag
|
||||
@register.simple_tag
|
||||
def get_django_version():
|
||||
version = django.VERSION
|
||||
return {'major': version[0], 'minor': version[1]}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -93,13 +93,12 @@ STATICFILES_FINDERS = (
|
|||
SECRET_KEY = '8**a!c8$1x)p@j2pj0yq!*v+dzp24g*$918ws#x@k+gf%0%rct'
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
# Uncomment the next line for simple clickjacking protection:
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
|
|
@ -115,17 +114,14 @@ TEMPLATES = [
|
|||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [
|
||||
map_path('templates')
|
||||
map_path('templates'),
|
||||
],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.static',
|
||||
'django.template.context_processors.tz',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
|
|
@ -143,7 +139,7 @@ INSTALLED_APPS = (
|
|||
'django.contrib.admindocs',
|
||||
|
||||
'adminsortable',
|
||||
'app',
|
||||
'samples',
|
||||
)
|
||||
|
||||
# A sample logging configuration. The only tangible logging
|
||||
|
|
@ -174,3 +170,21 @@ LOGGING = {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
from django.conf.urls import include, url
|
||||
"""django2_app URL Configuration
|
||||
|
||||
# Uncomment the next two lines to enable the admin:
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/2.0/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
||||
from django.urls import path
|
||||
|
||||
urlpatterns = [
|
||||
# Examples:
|
||||
# url(r'^$', 'test_project.views.home', name='home'),
|
||||
# url(r'^test_project/', include('test_project.foo.urls')),
|
||||
|
||||
# Uncomment the admin/doc line below to enable admin documentation:
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
url(r'^admin/', admin.site.urls),
|
||||
path('admin/', admin.site.urls),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,32 +1,15 @@
|
|||
"""
|
||||
WSGI config for test_project project.
|
||||
WSGI config for django2_app project.
|
||||
|
||||
This module contains the WSGI application used by Django's development server
|
||||
and any production WSGI deployments. It should expose a module-level variable
|
||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
||||
this application via the ``WSGI_APPLICATION`` setting.
|
||||
|
||||
Usually you will have the standard Django WSGI application here, but it also
|
||||
might make sense to replace the whole Django WSGI application with a custom one
|
||||
that later delegates to the Django one. For example, you could introduce WSGI
|
||||
middleware here, or combine a Django application with an application of another
|
||||
framework.
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
|
||||
"""
|
||||
import os
|
||||
|
||||
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
|
||||
# if running multiple sites in the same mod_wsgi process. To fix this, use
|
||||
# mod_wsgi daemon mode with each site in its own daemon process, or use
|
||||
# os.environ["DJANGO_SETTINGS_MODULE"] = "test_project.settings"
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")
|
||||
|
||||
# This application object is used by any WSGI server configured to use this
|
||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
# setting points here.
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")
|
||||
application = get_wsgi_application()
|
||||
|
||||
# Apply WSGI middleware here.
|
||||
# from helloworld.wsgi import HelloWorldApplication
|
||||
# application = HelloWorldApplication(application)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from adminsortable.admin import (SortableAdmin, SortableTabularInline,
|
|||
SortableStackedInline, SortableGenericStackedInline,
|
||||
NonSortableParentAdmin)
|
||||
from adminsortable.utils import get_is_sortable
|
||||
from app.models import (Category, Widget, Project, Credit, Note, GenericNote,
|
||||
from .models import (Category, Widget, Project, Credit, Note, GenericNote,
|
||||
Component, Person, NonSortableCategory, SortableCategoryWidget,
|
||||
SortableNonInlineCategory, NonSortableCredit, NonSortableNote,
|
||||
CustomWidget, CustomWidgetComponent, BackwardCompatibleWidget)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class SamplesConfig(AppConfig):
|
||||
name = 'samples'
|
||||
|
|
@ -15,7 +15,7 @@ from django.test.client import Client
|
|||
|
||||
from adminsortable.models import SortableMixin
|
||||
from adminsortable.utils import get_is_sortable
|
||||
from app.models import Category, Person, Project
|
||||
from .models import Category, Person, Project
|
||||
|
||||
|
||||
class TestSortableModel(SortableMixin):
|
||||
|
|
@ -113,7 +113,7 @@ class SortableTestCase(TestCase):
|
|||
def test_adminsortable_change_list_view(self):
|
||||
self.client.login(username=self.user.username,
|
||||
password=self.user_raw_password)
|
||||
response = self.client.get('/admin/app/category/sort/')
|
||||
response = self.client.get('/admin/samples/category/sort/')
|
||||
self.assertEqual(response.status_code, httplib.OK,
|
||||
'Unable to reach sort view.')
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ class SortableTestCase(TestCase):
|
|||
return category1, category2, category3
|
||||
|
||||
def get_sorting_url(self, model):
|
||||
return '/admin/app/project/sort/do-sorting/{0}/'.format(
|
||||
return '/admin/samples/project/sort/do-sorting/{0}/'.format(
|
||||
model.model_type_id())
|
||||
|
||||
def get_category_indexes(self, *categories):
|
||||
|
|
@ -135,7 +135,7 @@ class SortableTestCase(TestCase):
|
|||
password=self.user_raw_password)
|
||||
self.assertTrue(logged_in, 'User is not logged in')
|
||||
|
||||
response = self.client.get('/admin/app/category/sort/')
|
||||
response = self.client.get('/admin/samples/category/sort/')
|
||||
self.assertEqual(response.status_code, httplib.OK,
|
||||
'Admin sort request failed.')
|
||||
|
||||
|
|
@ -185,8 +185,7 @@ class SortableTestCase(TestCase):
|
|||
# make a normal POST
|
||||
response = self.client.post(self.get_sorting_url(Category),
|
||||
data=self.get_category_indexes(category1, category2, category3))
|
||||
content = json.loads(response.content.decode(encoding='UTF-8'),
|
||||
'latin-1')
|
||||
content = json.loads(response.content.decode(encoding='UTF-8'))
|
||||
self.assertFalse(content.get('objects_sorted'),
|
||||
'Objects should not have been sorted. An ajax post is required.')
|
||||
|
||||
|
|
@ -202,8 +201,7 @@ class SortableTestCase(TestCase):
|
|||
response = self.client.post(self.get_sorting_url(Category),
|
||||
data=self.get_category_indexes(category3, category2, category1),
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
content = json.loads(response.content.decode(encoding='UTF-8'),
|
||||
'latin-1')
|
||||
content = json.loads(response.content.decode(encoding='UTF-8'))
|
||||
self.assertTrue(content.get('objects_sorted'),
|
||||
'Objects should have been sorted.')
|
||||
|
||||
|
|
@ -256,7 +254,7 @@ class SortableTestCase(TestCase):
|
|||
|
||||
self.client.login(username=self.user.username,
|
||||
password=self.user_raw_password)
|
||||
response = self.client.get('/admin/app/project/sort/')
|
||||
response = self.client.get('/admin/samples/project/sort/')
|
||||
self.assertEqual(response.status_code, httplib.OK,
|
||||
'Unable to reach sort view.')
|
||||
|
||||
|
|
@ -266,7 +264,7 @@ class SortableTestCase(TestCase):
|
|||
|
||||
self.client.login(username=self.staff.username,
|
||||
password=self.staff_raw_password)
|
||||
response = self.client.get('/admin/app/project/sort/')
|
||||
response = self.client.get('/admin/samples/project/sort/')
|
||||
self.assertEqual(response.status_code, httplib.FORBIDDEN,
|
||||
'Sort view must be forbidden.')
|
||||
|
||||
|
|
@ -291,8 +289,7 @@ class SortableTestCase(TestCase):
|
|||
response.status_code,
|
||||
httplib.OK,
|
||||
'Note inline must be sortable in ProjectAdmin')
|
||||
content = json.loads(response.content.decode(encoding='UTF-8'),
|
||||
'latin-1')
|
||||
content = json.loads(response.content.decode(encoding='UTF-8'))
|
||||
self.assertTrue(content.get('objects_sorted'),
|
||||
'Objects should have been sorted.')
|
||||
|
||||
Loading…
Reference in New Issue